mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 14:54:20 +01:00
784f47a841
git-svn-id: file:///svn/toku/tokudb@38549 c7de825b-a66e-492c-adef-691d508d4ae1
220 lines
5.8 KiB
C
220 lines
5.8 KiB
C
/* -*- mode: C; c-basic-offset: 4 -*- */
|
|
#ident "Copyright (c) 2007-2011 Tokutek Inc. All rights reserved."
|
|
#ident "$Id: test-merges-on-cleaner.c 38542 2012-01-06 14:06:23Z christianrober $"
|
|
/* The goal of this test. Make sure that inserts stay behind deletes. */
|
|
|
|
|
|
#include "test.h"
|
|
#include "includes.h"
|
|
#include <brt-cachetable-wrappers.h>
|
|
#include "brt-flusher.h"
|
|
#include "checkpoint.h"
|
|
|
|
static TOKUTXN const null_txn = 0;
|
|
static DB * const null_db = 0;
|
|
|
|
enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
|
|
|
|
CACHETABLE ct;
|
|
BRT brt;
|
|
int fnamelen;
|
|
char *fname;
|
|
|
|
static int update_func(
|
|
DB* UU(db),
|
|
const DBT* key,
|
|
const DBT* old_val,
|
|
const DBT* UU(extra),
|
|
void (*set_val)(const DBT *new_val, void *set_extra),
|
|
void *set_extra)
|
|
{
|
|
DBT new_val;
|
|
assert(old_val->size > 0);
|
|
if (verbose) {
|
|
printf("applying update to %s\n", (char *)key->data);
|
|
}
|
|
toku_init_dbt(&new_val);
|
|
set_val(&new_val, set_extra);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
doit (void) {
|
|
BLOCKNUM node_leaf[2];
|
|
BLOCKNUM node_internal, node_root;
|
|
|
|
int r;
|
|
|
|
fnamelen = strlen(__FILE__) + 20;
|
|
fname = toku_malloc(fnamelen);
|
|
assert(fname!=0);
|
|
|
|
snprintf(fname, fnamelen, "%s.brt", __FILE__);
|
|
r = toku_brt_create_cachetable(&ct, 500*1024*1024, ZERO_LSN, NULL_LOGGER); assert(r==0);
|
|
unlink(fname);
|
|
r = toku_open_brt(fname, 1, &brt, NODESIZE, NODESIZE/2, ct, null_txn, toku_builtin_compare_fun, null_db);
|
|
assert(r==0);
|
|
toku_free(fname);
|
|
|
|
brt->update_fun = update_func;
|
|
brt->h->update_fun = update_func;
|
|
|
|
toku_testsetup_initialize(); // must precede any other toku_testsetup calls
|
|
|
|
r = toku_testsetup_leaf(brt, &node_leaf[0], 1, NULL, NULL);
|
|
assert(r==0);
|
|
r = toku_testsetup_leaf(brt, &node_leaf[1], 1, NULL, NULL);
|
|
assert(r==0);
|
|
|
|
char* pivots[1];
|
|
pivots[0] = toku_strdup("kkkkk");
|
|
int pivot_len = 6;
|
|
|
|
r = toku_testsetup_nonleaf(brt, 1, &node_internal, 2, node_leaf, pivots, &pivot_len);
|
|
assert(r==0);
|
|
|
|
r = toku_testsetup_nonleaf(brt, 2, &node_root, 1, &node_internal, 0, 0);
|
|
assert(r==0);
|
|
|
|
r = toku_testsetup_root(brt, node_root);
|
|
assert(r==0);
|
|
|
|
//
|
|
// at this point we have created a tree with a root, an internal node,
|
|
// and two leaf nodes, the pivot being "kkkkk"
|
|
//
|
|
|
|
// now we insert a row into each leaf node
|
|
r = toku_testsetup_insert_to_leaf (
|
|
brt,
|
|
node_leaf[0],
|
|
"a", // key
|
|
2, // keylen
|
|
"aa",
|
|
3
|
|
);
|
|
assert(r==0);
|
|
r = toku_testsetup_insert_to_leaf (
|
|
brt,
|
|
node_leaf[1],
|
|
"z", // key
|
|
2, // keylen
|
|
"zz",
|
|
3
|
|
);
|
|
assert(r==0);
|
|
|
|
//
|
|
// now insert a bunch of dummy delete messages
|
|
// into the internal node, to get its cachepressure size up
|
|
//
|
|
for (int i = 0; i < 100000; i++) {
|
|
r = toku_testsetup_insert_to_nonleaf (
|
|
brt,
|
|
node_internal,
|
|
BRT_DELETE_ANY,
|
|
"jj", // this key does not exist, so its message application should be a no-op
|
|
3,
|
|
NULL,
|
|
0
|
|
);
|
|
assert(r==0);
|
|
}
|
|
|
|
//
|
|
// now insert a broadcast message into the root
|
|
//
|
|
r = toku_testsetup_insert_to_nonleaf (
|
|
brt,
|
|
node_root,
|
|
BRT_UPDATE_BROADCAST_ALL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0
|
|
);
|
|
assert(r==0);
|
|
|
|
//
|
|
// now let us induce a clean on the internal node
|
|
//
|
|
BRTNODE node;
|
|
toku_pin_node_with_min_bfe(&node, node_leaf[1], brt);
|
|
// hack to get merge going
|
|
BLB_SEQINSERT(node, node->n_children-1) = FALSE;
|
|
toku_unpin_brtnode(brt, node);
|
|
|
|
// now do a lookup on one of the keys, this should bring a leaf node up to date
|
|
DBT k;
|
|
struct check_pair pair = {2, "a", 0, NULL, 0};
|
|
r = toku_brt_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
|
|
assert(r==0);
|
|
|
|
struct brtnode_fetch_extra bfe;
|
|
fill_bfe_for_min_read(&bfe, brt->h);
|
|
toku_pin_brtnode_off_client_thread(
|
|
brt->h,
|
|
node_internal,
|
|
toku_cachetable_hash(brt->h->cf, node_internal),
|
|
&bfe,
|
|
0,
|
|
NULL,
|
|
&node
|
|
);
|
|
assert(node->n_children == 2);
|
|
// we expect that this flushes its buffer, that
|
|
// a merge is not done, and that the lookup
|
|
// of values "a" and "z" still works
|
|
r = toku_brtnode_cleaner_callback(
|
|
node,
|
|
node_internal,
|
|
toku_cachetable_hash(brt->h->cf, node_internal),
|
|
brt->h
|
|
);
|
|
|
|
// verify that node_internal's buffer is empty
|
|
fill_bfe_for_min_read(&bfe, brt->h);
|
|
toku_pin_brtnode_off_client_thread(
|
|
brt->h,
|
|
node_internal,
|
|
toku_cachetable_hash(brt->h->cf, node_internal),
|
|
&bfe,
|
|
0,
|
|
NULL,
|
|
&node
|
|
);
|
|
// check that merge happened
|
|
assert(node->n_children == 1);
|
|
// check that buffers are empty
|
|
assert(toku_bnc_nbytesinbuf(BNC(node, 0)) == 0);
|
|
toku_unpin_brtnode_off_client_thread(brt->h, node);
|
|
|
|
//
|
|
// now run a checkpoint to get everything clean,
|
|
// and to get the rebalancing to happen
|
|
//
|
|
r = toku_checkpoint(ct, NULL, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT);
|
|
assert_zero(r);
|
|
|
|
// check that lookups on the two keys is still good
|
|
struct check_pair pair1 = {2, "a", 0, NULL, 0};
|
|
r = toku_brt_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
|
|
assert(r==0);
|
|
struct check_pair pair2 = {2, "z", 0, NULL, 0};
|
|
r = toku_brt_lookup(brt, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
|
|
assert(r==0);
|
|
|
|
|
|
r = toku_close_brt(brt, 0); assert(r==0);
|
|
r = toku_cachetable_close(&ct); assert(r==0);
|
|
|
|
toku_free(pivots[0]);
|
|
}
|
|
|
|
int
|
|
test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
|
|
default_parse_args(argc, argv);
|
|
doit();
|
|
return 0;
|
|
}
|