diff options
Diffstat (limited to 'storage/tokudb/PerconaFT/ft/tests/orthopush-flush.cc')
-rw-r--r-- | storage/tokudb/PerconaFT/ft/tests/orthopush-flush.cc | 1219 |
1 files changed, 1219 insertions, 0 deletions
diff --git a/storage/tokudb/PerconaFT/ft/tests/orthopush-flush.cc b/storage/tokudb/PerconaFT/ft/tests/orthopush-flush.cc new file mode 100644 index 00000000000..055a38e5f6d --- /dev/null +++ b/storage/tokudb/PerconaFT/ft/tests/orthopush-flush.cc @@ -0,0 +1,1219 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of PerconaFT. + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + PerconaFT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + PerconaFT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include "test.h" + + +#include "ule.h" + +static TOKUTXN const null_txn = 0; +static const char *fname = TOKU_TEST_FILENAME; +static txn_gc_info non_mvcc_gc_info(nullptr, TXNID_NONE, TXNID_NONE, false); +static toku::comparator dummy_cmp; + +// generate size random bytes into dest +static void +rand_bytes(void *dest, int size) +{ + long *l; + for (CAST_FROM_VOIDP(l, dest); (unsigned int) size >= (sizeof *l); ++l, size -= (sizeof *l)) { + *l = random(); + } + for (char *c = (char *) l; size > 0; ++c, --size) { + *c = random() & 0xff; + } +} + +// generate size random bytes into dest, with a lot less entropy (every +// group of 4 bytes is the same) +static void +rand_bytes_limited(void *dest, int size) +{ + long *l; + for (CAST_FROM_VOIDP(l, dest); (size_t) size >= (sizeof *l); ++l, size -= (sizeof *l)) { + char c = random() & 0xff; + for (char *p = (char *) l; (size_t) (p - (char *) l) < (sizeof *l); ++p) { + *p = c; + } + } + char c = random() & 0xff; + for (char *p = (char *) l; size > 0; ++p, --size) { + *p = c; + } +} + +// generate a random message with xids and a key starting with pfx, insert +// it in bnc, and save it in output params save and is_fresh_out +static void +insert_random_message(NONLEAF_CHILDINFO bnc, ft_msg **save, bool *is_fresh_out, XIDS xids, int pfx) +{ + int keylen = (random() % 128) + 16; + int vallen = (random() % 128) + 16; + void *key = toku_xmalloc(keylen + (sizeof pfx)); + void *val = toku_xmalloc(vallen); + *(int *) key = pfx; + rand_bytes((char *) key + (sizeof pfx), keylen); + rand_bytes(val, vallen); + MSN msn = next_dummymsn(); + bool is_fresh = (random() & 0x100) == 0; + + DBT keydbt, valdbt; + toku_fill_dbt(&keydbt, key, keylen + (sizeof pfx)); + toku_fill_dbt(&valdbt, val, vallen); + *save = new ft_msg(&keydbt, &valdbt, FT_INSERT, msn, xids); + *is_fresh_out = is_fresh; + + toku_bnc_insert_msg(bnc, key, keylen + (sizeof pfx), val, vallen, + FT_INSERT, msn, xids, is_fresh, + dummy_cmp); +} + +// generate a random message with xids and a key starting with pfx, insert +// it into blb, and save it in output param save +static void +insert_random_message_to_bn( + FT_HANDLE t, + BASEMENTNODE blb, + void** keyp, + uint32_t* keylenp, + LEAFENTRY *save, + XIDS xids, + int pfx + ) +{ + int keylen = (random() % 16) + 16; + int vallen = (random() % 128) + 16; + uint32_t *pfxp; + char key[(sizeof *pfxp) + keylen]; + char val[vallen]; + pfxp = (uint32_t *) &key[0]; + *pfxp = pfx; + char *randkeyp = &key[sizeof *pfxp]; + rand_bytes_limited(randkeyp, keylen); + rand_bytes(val, vallen); + MSN msn = next_dummymsn(); + + DBT keydbt_s, *keydbt, valdbt_s, *valdbt; + keydbt = &keydbt_s; + valdbt = &valdbt_s; + toku_fill_dbt(keydbt, key, (sizeof *pfxp) + keylen); + toku_fill_dbt(valdbt, val, vallen); + *keylenp = keydbt->size; + *keyp = toku_xmemdup(keydbt->data, keydbt->size); + ft_msg msg(keydbt, valdbt, FT_INSERT, msn, xids); + int64_t numbytes; + toku_le_apply_msg(msg, NULL, NULL, 0, keydbt->size, &non_mvcc_gc_info, save, &numbytes); + toku_ft_bn_apply_msg(t->ft->cmp, t->ft->update_fun, blb, msg, &non_mvcc_gc_info, NULL, NULL); + if (msn.msn > blb->max_msn_applied.msn) { + blb->max_msn_applied = msn; + } +} + +// generate a random message with xids and a key starting with pfx, insert +// it into blb1 and also into blb2, and save it in output param save +// +// used for making two leaf nodes the same in order to compare the result +// of 'maybe_apply' and a normal buffer flush +static void +insert_same_message_to_bns( + FT_HANDLE t, + BASEMENTNODE blb1, + BASEMENTNODE blb2, + void** keyp, + uint32_t* keylenp, + LEAFENTRY *save, + XIDS xids, + int pfx + ) +{ + int keylen = (random() % 16) + 16; + int vallen = (random() % 128) + 16; + uint32_t *pfxp; + char key[(sizeof *pfxp) + keylen]; + char val[vallen]; + pfxp = (uint32_t *) &key[0]; + *pfxp = pfx; + char *randkeyp = &key[sizeof *pfxp]; + rand_bytes_limited(randkeyp, keylen); + rand_bytes(val, vallen); + MSN msn = next_dummymsn(); + + DBT keydbt_s, *keydbt, valdbt_s, *valdbt; + keydbt = &keydbt_s; + valdbt = &valdbt_s; + toku_fill_dbt(keydbt, key, (sizeof *pfxp) + keylen); + toku_fill_dbt(valdbt, val, vallen); + *keylenp = keydbt->size; + *keyp = toku_xmemdup(keydbt->data, keydbt->size); + ft_msg msg(keydbt, valdbt, FT_INSERT, msn, xids); + int64_t numbytes; + toku_le_apply_msg(msg, NULL, NULL, 0, keydbt->size, &non_mvcc_gc_info, save, &numbytes); + toku_ft_bn_apply_msg(t->ft->cmp, t->ft->update_fun, blb1, msg, &non_mvcc_gc_info, NULL, NULL); + if (msn.msn > blb1->max_msn_applied.msn) { + blb1->max_msn_applied = msn; + } + toku_ft_bn_apply_msg(t->ft->cmp, t->ft->update_fun, blb2, msg, &non_mvcc_gc_info, NULL, NULL); + if (msn.msn > blb2->max_msn_applied.msn) { + blb2->max_msn_applied = msn; + } +} + +struct orthopush_flush_update_fun_extra { + DBT new_val; + int *num_applications; +}; + +static int +orthopush_flush_update_fun(DB * UU(db), const DBT *UU(key), const DBT *UU(old_val), const DBT *extra, + void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra) { + struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(e, extra->data); + (*e->num_applications)++; + set_val(&e->new_val, set_extra); + return 0; +} + +// generate a random update message with xids and a key starting with pfx, +// insert it into blb, and save it in output param save, and update the +// max msn so far in max_msn +// +// the update message will overwrite the value with something generated +// here, and add one to the int pointed to by applied +static void +insert_random_update_message(NONLEAF_CHILDINFO bnc, ft_msg **save, bool is_fresh, XIDS xids, int pfx, int *applied, MSN *max_msn) +{ + int keylen = (random() % 16) + 16; + int vallen = (random() % 16) + 16; + void *key = toku_xmalloc(keylen + (sizeof pfx)); + struct orthopush_flush_update_fun_extra *XMALLOC(update_extra); + *(int *) key = pfx; + rand_bytes_limited((char *) key + (sizeof pfx), keylen); + toku_fill_dbt(&update_extra->new_val, toku_xmalloc(vallen), vallen); + rand_bytes(update_extra->new_val.data, vallen); + update_extra->num_applications = applied; + MSN msn = next_dummymsn(); + + DBT keydbt, valdbt; + toku_fill_dbt(&keydbt, key, keylen + (sizeof pfx)); + toku_fill_dbt(&valdbt, update_extra, sizeof *update_extra); + *save = new ft_msg(&keydbt, &valdbt, FT_UPDATE, msn, xids); + + toku_bnc_insert_msg(bnc, key, keylen + (sizeof pfx), + update_extra, sizeof *update_extra, + FT_UPDATE, msn, xids, is_fresh, + dummy_cmp); + if (msn.msn > max_msn->msn) { + *max_msn = msn; + } +} + +// flush from one internal node to another, where both only have one +// buffer +static void +flush_to_internal(FT_HANDLE t) { + int r; + + ft_msg **MALLOC_N(4096,parent_messages); // 128k / 32 = 4096 + ft_msg **MALLOC_N(4096,child_messages); + bool *MALLOC_N(4096,parent_messages_is_fresh); + bool *MALLOC_N(4096,child_messages_is_fresh); + memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0])); + memset(child_messages_is_fresh, 0, 4096*(sizeof child_messages_is_fresh[0])); + + XIDS xids_0 = toku_xids_get_root_xids(); + XIDS xids_123, xids_234; + r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123); + CKERR(r); + r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234); + CKERR(r); + + NONLEAF_CHILDINFO child_bnc = toku_create_empty_nl(); + int i; + for (i = 0; toku_bnc_memory_used(child_bnc) < 128*1024; ++i) { + insert_random_message(child_bnc, &child_messages[i], &child_messages_is_fresh[i], xids_123, 0); + } + int num_child_messages = i; + + NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl(); + for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) { + insert_random_message(parent_bnc, &parent_messages[i], &parent_messages_is_fresh[i], xids_234, 0); + } + int num_parent_messages = i; + + FTNODE XMALLOC(child); + BLOCKNUM blocknum = { 42 }; + toku_initialize_empty_ftnode(child, blocknum, 1, 1, FT_LAYOUT_VERSION, 0); + destroy_nonleaf_childinfo(BNC(child, 0)); + set_BNC(child, 0, child_bnc); + BP_STATE(child, 0) = PT_AVAIL; + + toku_bnc_flush_to_child(t->ft, parent_bnc, child, TXNID_NONE); + + int parent_messages_present[num_parent_messages]; + int child_messages_present[num_child_messages]; + memset(parent_messages_present, 0, sizeof parent_messages_present); + memset(child_messages_present, 0, sizeof child_messages_present); + + struct checkit_fn { + int num_parent_messages; + ft_msg **parent_messages; + int *parent_messages_present; + bool *parent_messages_is_fresh; + int num_child_messages; + ft_msg **child_messages; + int *child_messages_present; + bool *child_messages_is_fresh; + checkit_fn(int np, ft_msg **pm, int *npp, bool *pmf, int nc, ft_msg **cm, int *ncp, bool *cmf) : + num_parent_messages(np), parent_messages(pm), parent_messages_present(npp), parent_messages_is_fresh(pmf), + num_child_messages(nc), child_messages(cm), child_messages_present(ncp), child_messages_is_fresh(cmf) { + } + int operator()(const ft_msg &msg, bool is_fresh) { + DBT keydbt; + DBT valdbt; + toku_fill_dbt(&keydbt, msg.kdbt()->data, msg.kdbt()->size); + toku_fill_dbt(&valdbt, msg.vdbt()->data, msg.vdbt()->size); + int found = 0; + MSN msn = msg.msn(); + enum ft_msg_type type = msg.type(); + XIDS xids = msg.xids(); + for (int k = 0; k < num_parent_messages; ++k) { + if (dummy_cmp(&keydbt, parent_messages[k]->kdbt()) == 0 && + msn.msn == parent_messages[k]->msn().msn) { + assert(parent_messages_present[k] == 0); + assert(found == 0); + assert(dummy_cmp(&valdbt, parent_messages[k]->vdbt()) == 0); + assert(type == parent_messages[k]->type()); + assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(parent_messages[k]->xids())); + assert(parent_messages_is_fresh[k] == is_fresh); + parent_messages_present[k]++; + found++; + } + } + for (int k = 0; k < num_child_messages; ++k) { + if (dummy_cmp(&keydbt, child_messages[k]->kdbt()) == 0 && + msn.msn == child_messages[k]->msn().msn) { + assert(child_messages_present[k] == 0); + assert(found == 0); + assert(dummy_cmp(&valdbt, child_messages[k]->vdbt()) == 0); + assert(type == child_messages[k]->type()); + assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(child_messages[k]->xids())); + assert(child_messages_is_fresh[k] == is_fresh); + child_messages_present[k]++; + found++; + } + } + assert(found == 1); + return 0; + } + } checkit(num_parent_messages, parent_messages, parent_messages_present, parent_messages_is_fresh, + num_child_messages, child_messages, child_messages_present, child_messages_is_fresh); + child_bnc->msg_buffer.iterate(checkit); + + for (i = 0; i < num_parent_messages; ++i) { + assert(parent_messages_present[i] == 1); + } + for (i = 0; i < num_child_messages; ++i) { + assert(child_messages_present[i] == 1); + } + + toku_xids_destroy(&xids_0); + toku_xids_destroy(&xids_123); + toku_xids_destroy(&xids_234); + + for (i = 0; i < num_parent_messages; ++i) { + toku_free(parent_messages[i]->kdbt()->data); + toku_free(parent_messages[i]->vdbt()->data); + delete parent_messages[i]; + } + for (i = 0; i < num_child_messages; ++i) { + toku_free(child_messages[i]->kdbt()->data); + toku_free(child_messages[i]->vdbt()->data); + delete child_messages[i]; + } + destroy_nonleaf_childinfo(parent_bnc); + toku_ftnode_free(&child); + toku_free(parent_messages); + toku_free(child_messages); + toku_free(parent_messages_is_fresh); + toku_free(child_messages_is_fresh); +} + +// flush from one internal node to another, where the child has 8 buffers +static void +flush_to_internal_multiple(FT_HANDLE t) { + int r; + + ft_msg **MALLOC_N(4096,parent_messages); // 128k / 32 = 4096 + ft_msg **MALLOC_N(4096,child_messages); + bool *MALLOC_N(4096,parent_messages_is_fresh); + bool *MALLOC_N(4096,child_messages_is_fresh); + memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0])); + memset(child_messages_is_fresh, 0, 4096*(sizeof child_messages_is_fresh[0])); + + XIDS xids_0 = toku_xids_get_root_xids(); + XIDS xids_123, xids_234; + r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123); + CKERR(r); + r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234); + CKERR(r); + + NONLEAF_CHILDINFO child_bncs[8]; + ft_msg *childkeys[7]; + int i; + for (i = 0; i < 8; ++i) { + child_bncs[i] = toku_create_empty_nl(); + if (i < 7) { + childkeys[i] = NULL; + } + } + int total_size = 0; + for (i = 0; total_size < 128*1024; ++i) { + total_size -= toku_bnc_memory_used(child_bncs[i%8]); + insert_random_message(child_bncs[i%8], &child_messages[i], &child_messages_is_fresh[i], xids_123, i%8); + total_size += toku_bnc_memory_used(child_bncs[i%8]); + if (i % 8 < 7) { + if (childkeys[i%8] == NULL || dummy_cmp(child_messages[i]->kdbt(), childkeys[i%8]->kdbt()) > 0) { + childkeys[i%8] = child_messages[i]; + } + } + } + int num_child_messages = i; + + NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl(); + for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) { + insert_random_message(parent_bnc, &parent_messages[i], &parent_messages_is_fresh[i], xids_234, 0); + } + int num_parent_messages = i; + + FTNODE XMALLOC(child); + BLOCKNUM blocknum = { 42 }; + toku_initialize_empty_ftnode(child, blocknum, 1, 8, FT_LAYOUT_VERSION, 0); + for (i = 0; i < 8; ++i) { + destroy_nonleaf_childinfo(BNC(child, i)); + set_BNC(child, i, child_bncs[i]); + BP_STATE(child, i) = PT_AVAIL; + if (i < 7) { + child->pivotkeys.insert_at(childkeys[i]->kdbt(), i); + } + } + + toku_bnc_flush_to_child(t->ft, parent_bnc, child, TXNID_NONE); + + int total_messages = 0; + for (i = 0; i < 8; ++i) { + total_messages += toku_bnc_n_entries(BNC(child, i)); + } + assert(total_messages == num_parent_messages + num_child_messages); + int parent_messages_present[num_parent_messages]; + int child_messages_present[num_child_messages]; + memset(parent_messages_present, 0, sizeof parent_messages_present); + memset(child_messages_present, 0, sizeof child_messages_present); + + for (int j = 0; j < 8; ++j) { + struct checkit_fn { + int num_parent_messages; + ft_msg **parent_messages; + int *parent_messages_present; + bool *parent_messages_is_fresh; + int num_child_messages; + ft_msg **child_messages; + int *child_messages_present; + bool *child_messages_is_fresh; + checkit_fn(int np, ft_msg **pm, int *npp, bool *pmf, int nc, ft_msg **cm, int *ncp, bool *cmf) : + num_parent_messages(np), parent_messages(pm), parent_messages_present(npp), parent_messages_is_fresh(pmf), + num_child_messages(nc), child_messages(cm), child_messages_present(ncp), child_messages_is_fresh(cmf) { + } + int operator()(const ft_msg &msg, bool is_fresh) { + DBT keydbt; + DBT valdbt; + toku_fill_dbt(&keydbt, msg.kdbt()->data, msg.kdbt()->size); + toku_fill_dbt(&valdbt, msg.vdbt()->data, msg.vdbt()->size); + int found = 0; + MSN msn = msg.msn(); + enum ft_msg_type type = msg.type(); + XIDS xids = msg.xids(); + for (int _i = 0; _i < num_parent_messages; ++_i) { + if (dummy_cmp(&keydbt, parent_messages[_i]->kdbt()) == 0 && + msn.msn == parent_messages[_i]->msn().msn) { + assert(parent_messages_present[_i] == 0); + assert(found == 0); + assert(dummy_cmp(&valdbt, parent_messages[_i]->vdbt()) == 0); + assert(type == parent_messages[_i]->type()); + assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(parent_messages[_i]->xids())); + assert(parent_messages_is_fresh[_i] == is_fresh); + parent_messages_present[_i]++; + found++; + } + } + for (int _i = 0; _i < num_child_messages; ++_i) { + if (dummy_cmp(&keydbt, child_messages[_i]->kdbt()) == 0 && + msn.msn == child_messages[_i]->msn().msn) { + assert(child_messages_present[_i] == 0); + assert(found == 0); + assert(dummy_cmp(&valdbt, child_messages[_i]->vdbt()) == 0); + assert(type == child_messages[_i]->type()); + assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(child_messages[_i]->xids())); + assert(child_messages_is_fresh[_i] == is_fresh); + child_messages_present[_i]++; + found++; + } + } + assert(found == 1); + return 0; + } + } checkit(num_parent_messages, parent_messages, parent_messages_present, parent_messages_is_fresh, + num_child_messages, child_messages, child_messages_present, child_messages_is_fresh); + child_bncs[j]->msg_buffer.iterate(checkit); + } + + for (i = 0; i < num_parent_messages; ++i) { + assert(parent_messages_present[i] == 1); + } + for (i = 0; i < num_child_messages; ++i) { + assert(child_messages_present[i] == 1); + } + + toku_xids_destroy(&xids_0); + toku_xids_destroy(&xids_123); + toku_xids_destroy(&xids_234); + + for (i = 0; i < num_parent_messages; ++i) { + toku_free(parent_messages[i]->kdbt()->data); + toku_free(parent_messages[i]->vdbt()->data); + delete parent_messages[i]; + } + for (i = 0; i < num_child_messages; ++i) { + toku_free(child_messages[i]->kdbt()->data); + toku_free(child_messages[i]->vdbt()->data); + delete child_messages[i]; + } + destroy_nonleaf_childinfo(parent_bnc); + toku_ftnode_free(&child); + toku_free(parent_messages); + toku_free(child_messages); + toku_free(parent_messages_is_fresh); + toku_free(child_messages_is_fresh); +} + +// flush from one internal node to a leaf node, which has 8 basement +// nodes +// +// if make_leaf_up_to_date is true, then apply the messages that are stale +// in the parent to the leaf before doing the flush, otherwise assume the +// leaf was just read off disk +// +// if use_flush is true, use a buffer flush, otherwise, use maybe_apply +static void +flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) { + int r; + + ft_msg **MALLOC_N(4096,parent_messages); // 128k / 32 = 4096 + LEAFENTRY* child_messages = NULL; + XMALLOC_N(4096,child_messages); + void** key_pointers = NULL; + XMALLOC_N(4096, key_pointers); + uint32_t* keylens = NULL; + XMALLOC_N(4096, keylens); + bool *MALLOC_N(4096,parent_messages_is_fresh); + memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0])); + int *MALLOC_N(4096,parent_messages_applied); + memset(parent_messages_applied, 0, 4096*(sizeof parent_messages_applied[0])); + + XIDS xids_0 = toku_xids_get_root_xids(); + XIDS xids_123, xids_234; + r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123); + CKERR(r); + r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234); + CKERR(r); + + BASEMENTNODE child_blbs[8]; + DBT childkeys[7]; + int i; + for (i = 0; i < 8; ++i) { + child_blbs[i] = toku_create_empty_bn(); + if (i < 7) { + toku_init_dbt(&childkeys[i]); + } + } + + FTNODE child = NULL; + XMALLOC(child); + BLOCKNUM blocknum = { 42 }; + toku_initialize_empty_ftnode(child, blocknum, 0, 8, FT_LAYOUT_VERSION, 0); + for (i = 0; i < 8; ++i) { + destroy_basement_node(BLB(child, i)); + set_BLB(child, i, child_blbs[i]); + BP_STATE(child, i) = PT_AVAIL; + } + + int total_size = 0; + for (i = 0; total_size < 128*1024; ++i) { + total_size -= child_blbs[i%8]->data_buffer.get_memory_size(); + insert_random_message_to_bn(t, child_blbs[i%8], &key_pointers[i], &keylens[i], &child_messages[i], xids_123, i%8); + total_size += child_blbs[i%8]->data_buffer.get_memory_size(); + if (i % 8 < 7) { + DBT keydbt; + if (childkeys[i%8].size == 0 || dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) > 0) { + toku_fill_dbt(&childkeys[i%8], key_pointers[i], keylens[i]); + } + } + } + int num_child_messages = i; + + for (i = 0; i < num_child_messages; ++i) { + DBT keydbt; + if (i % 8 < 7) { + assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) <= 0); + } + } + + { + int num_stale = random() % 2000; + memset(&parent_messages_is_fresh[num_stale], true, (4096 - num_stale) * (sizeof parent_messages_is_fresh[0])); + } + NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl(); + MSN max_parent_msn = MIN_MSN; + for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) { + insert_random_update_message(parent_bnc, &parent_messages[i], parent_messages_is_fresh[i], xids_234, i%8, &parent_messages_applied[i], &max_parent_msn); + } + int num_parent_messages = i; + + for (i = 0; i < 7; ++i) { + child->pivotkeys.insert_at(&childkeys[i], i); + } + + if (make_leaf_up_to_date) { + for (i = 0; i < num_parent_messages; ++i) { + if (!parent_messages_is_fresh[i]) { + toku_ft_leaf_apply_msg(t->ft->cmp, t->ft->update_fun, child, -1, *parent_messages[i], &non_mvcc_gc_info, NULL, NULL); + } + } + for (i = 0; i < 8; ++i) { + BLB(child, i)->stale_ancestor_messages_applied = true; + } + } else { + for (i = 0; i < 8; ++i) { + BLB(child, i)->stale_ancestor_messages_applied = false; + } + } + + for (i = 0; i < num_parent_messages; ++i) { + if (make_leaf_up_to_date && !parent_messages_is_fresh[i]) { + assert(parent_messages_applied[i] == 1); + } else { + assert(parent_messages_applied[i] == 0); + } + } + + if (use_flush) { + toku_bnc_flush_to_child(t->ft, parent_bnc, child, TXNID_NONE); + destroy_nonleaf_childinfo(parent_bnc); + } else { + FTNODE XMALLOC(parentnode); + BLOCKNUM parentblocknum = { 17 }; + toku_initialize_empty_ftnode(parentnode, parentblocknum, 1, 1, FT_LAYOUT_VERSION, 0); + destroy_nonleaf_childinfo(BNC(parentnode, 0)); + set_BNC(parentnode, 0, parent_bnc); + BP_STATE(parentnode, 0) = PT_AVAIL; + parentnode->max_msn_applied_to_node_on_disk = max_parent_msn; + struct ancestors ancestors = { .node = parentnode, .childnum = 0, .next = NULL }; + bool msgs_applied; + toku_apply_ancestors_messages_to_node(t, child, &ancestors, pivot_bounds::infinite_bounds(), &msgs_applied, -1); + + struct checkit_fn { + int operator()(const ft_msg &UU(msg), bool is_fresh) { + assert(!is_fresh); + return 0; + } + } checkit; + parent_bnc->msg_buffer.iterate(checkit); + invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size() + == (uint32_t) num_parent_messages); + + toku_ftnode_free(&parentnode); + } + + int total_messages = 0; + for (i = 0; i < 8; ++i) { + total_messages += BLB_DATA(child, i)->num_klpairs(); + } + assert(total_messages <= num_parent_messages + num_child_messages); + + for (i = 0; i < num_parent_messages; ++i) { + assert(parent_messages_applied[i] == 1); + } + + int parent_messages_present[num_parent_messages]; + int child_messages_present[num_child_messages]; + memset(parent_messages_present, 0, sizeof parent_messages_present); + memset(child_messages_present, 0, sizeof child_messages_present); + for (int j = 0; j < 8; ++j) { + uint32_t len = BLB_DATA(child, j)->num_klpairs(); + for (uint32_t idx = 0; idx < len; ++idx) { + LEAFENTRY le; + DBT keydbt, valdbt; + { + uint32_t keylen, vallen; + void *keyp = NULL; + void *valp = NULL; + r = BLB_DATA(child, j)->fetch_klpair(idx, &le, &keylen, &keyp); + assert_zero(r); + valp = le_latest_val_and_len(le, &vallen); + toku_fill_dbt(&keydbt, keyp, keylen); + toku_fill_dbt(&valdbt, valp, vallen); + } + int found = 0; + for (i = num_parent_messages - 1; i >= 0; --i) { + if (dummy_cmp(&keydbt, parent_messages[i]->kdbt()) == 0) { + if (found == 0) { + struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(e, parent_messages[i]->vdbt()->data); + assert(dummy_cmp(&valdbt, &e->new_val) == 0); + found++; + } + assert(parent_messages_present[i] == 0); + parent_messages_present[i]++; + } + } + for (i = j + (~7 & (num_child_messages - 1)); i >= 0; i -= 8) { + if (i >= num_child_messages) { continue; } + DBT childkeydbt, childvaldbt; + { + uint32_t vallen; + void *valp = le_latest_val_and_len(child_messages[i], &vallen); + toku_fill_dbt(&childkeydbt, key_pointers[i], keylens[i]); + toku_fill_dbt(&childvaldbt, valp, vallen); + } + if (dummy_cmp(&keydbt, &childkeydbt) == 0) { + if (found == 0) { + assert(dummy_cmp(&valdbt, &childvaldbt) == 0); + found++; + } + assert(child_messages_present[i] == 0); + child_messages_present[i]++; + } + } + } + } + + for (i = 0; i < num_parent_messages; ++i) { + assert(parent_messages_present[i] == 1); + } + for (i = 0; i < num_child_messages; ++i) { + assert(child_messages_present[i] == 1); + } + + toku_xids_destroy(&xids_0); + toku_xids_destroy(&xids_123); + toku_xids_destroy(&xids_234); + + for (i = 0; i < num_parent_messages; ++i) { + toku_free(parent_messages[i]->kdbt()->data); + struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(extra, parent_messages[i]->vdbt()->data); + toku_free(extra->new_val.data); + toku_free(parent_messages[i]->vdbt()->data); + delete parent_messages[i]; + } + for (i = 0; i < num_child_messages; ++i) { + toku_free(child_messages[i]); + toku_free(key_pointers[i]); + } + toku_ftnode_free(&child); + toku_free(parent_messages); + toku_free(key_pointers); + toku_free(keylens); + toku_free(child_messages); + toku_free(parent_messages_is_fresh); + toku_free(parent_messages_applied); +} + +// flush from one internal node to a leaf node, which has 8 basement +// nodes, but only using maybe_apply, and with actual pivot bounds +// +// if make_leaf_up_to_date is true, then apply the messages that are stale +// in the parent to the leaf before doing the flush, otherwise assume the +// leaf was just read off disk +static void +flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) { + int r; + + ft_msg **MALLOC_N(4096,parent_messages); // 128k / 32 = 4k + LEAFENTRY* child_messages = NULL; + XMALLOC_N(4096,child_messages); + void** key_pointers = NULL; + XMALLOC_N(4096, key_pointers); + uint32_t* keylens = NULL; + XMALLOC_N(4096, keylens); + bool *MALLOC_N(4096,parent_messages_is_fresh); + memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0])); + int *MALLOC_N(4096,parent_messages_applied); + memset(parent_messages_applied, 0, 4096*(sizeof parent_messages_applied[0])); + + XIDS xids_0 = toku_xids_get_root_xids(); + XIDS xids_123, xids_234; + r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123); + CKERR(r); + r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234); + CKERR(r); + + BASEMENTNODE child_blbs[8]; + DBT childkeys[8]; + int i; + for (i = 0; i < 8; ++i) { + child_blbs[i] = toku_create_empty_bn(); + toku_init_dbt(&childkeys[i]); + } + + FTNODE XMALLOC(child); + BLOCKNUM blocknum = { 42 }; + toku_initialize_empty_ftnode(child, blocknum, 0, 8, FT_LAYOUT_VERSION, 0); + for (i = 0; i < 8; ++i) { + destroy_basement_node(BLB(child, i)); + set_BLB(child, i, child_blbs[i]); + BP_STATE(child, i) = PT_AVAIL; + } + + int total_size = 0; + for (i = 0; total_size < 128*1024; ++i) { + total_size -= child_blbs[i%8]->data_buffer.get_memory_size(); + insert_random_message_to_bn(t, child_blbs[i%8], &key_pointers[i], &keylens[i], &child_messages[i], xids_123, i%8); + total_size += child_blbs[i%8]->data_buffer.get_memory_size(); + DBT keydbt; + if (childkeys[i%8].size == 0 || dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) > 0) { + toku_fill_dbt(&childkeys[i%8], key_pointers[i], keylens[i]); + } + } + int num_child_messages = i; + + for (i = 0; i < num_child_messages; ++i) { + DBT keydbt; + assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) <= 0); + } + + { + int num_stale = random() % 2000; + memset(&parent_messages_is_fresh[num_stale], true, (4096 - num_stale) * (sizeof parent_messages_is_fresh[0])); + } + NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl(); + MSN max_parent_msn = MIN_MSN; + for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) { + insert_random_update_message(parent_bnc, &parent_messages[i], parent_messages_is_fresh[i], xids_234, i%8, &parent_messages_applied[i], &max_parent_msn); + } + int num_parent_messages = i; + + for (i = 0; i < 7; ++i) { + child->pivotkeys.insert_at(&childkeys[i], i); + } + + if (make_leaf_up_to_date) { + for (i = 0; i < num_parent_messages; ++i) { + if (dummy_cmp(parent_messages[i]->kdbt(), &childkeys[7]) <= 0 && + !parent_messages_is_fresh[i]) { + toku_ft_leaf_apply_msg(t->ft->cmp, t->ft->update_fun, child, -1, *parent_messages[i], &non_mvcc_gc_info, NULL, NULL); + } + } + for (i = 0; i < 8; ++i) { + BLB(child, i)->stale_ancestor_messages_applied = true; + } + } else { + for (i = 0; i < 8; ++i) { + BLB(child, i)->stale_ancestor_messages_applied = false; + } + } + + for (i = 0; i < num_parent_messages; ++i) { + if (make_leaf_up_to_date && + dummy_cmp(parent_messages[i]->kdbt(), &childkeys[7]) <= 0 && + !parent_messages_is_fresh[i]) { + assert(parent_messages_applied[i] == 1); + } else { + assert(parent_messages_applied[i] == 0); + } + } + + FTNODE XMALLOC(parentnode); + BLOCKNUM parentblocknum = { 17 }; + toku_initialize_empty_ftnode(parentnode, parentblocknum, 1, 1, FT_LAYOUT_VERSION, 0); + destroy_nonleaf_childinfo(BNC(parentnode, 0)); + set_BNC(parentnode, 0, parent_bnc); + BP_STATE(parentnode, 0) = PT_AVAIL; + parentnode->max_msn_applied_to_node_on_disk = max_parent_msn; + struct ancestors ancestors = { .node = parentnode, .childnum = 0, .next = NULL }; + DBT lbe, ubi; + toku_init_dbt(&lbe); + toku_clone_dbt(&ubi, childkeys[7]); + const pivot_bounds bounds(lbe, ubi); + bool msgs_applied; + toku_apply_ancestors_messages_to_node(t, child, &ancestors, bounds, &msgs_applied, -1); + + struct checkit_fn { + DBT *childkeys; + int num_parent_messages; + ft_msg **parent_messages; + bool *parent_messages_is_fresh; + checkit_fn(DBT *ck, int np, ft_msg **pm, bool *pmf) : + childkeys(ck), num_parent_messages(np), parent_messages(pm), parent_messages_is_fresh(pmf) { + } + int operator()(const ft_msg &msg, bool is_fresh) { + DBT keydbt; + toku_fill_dbt(&keydbt, msg.kdbt()->data, msg.kdbt()->size); + MSN msn = msg.msn(); + if (dummy_cmp(&keydbt, &childkeys[7]) > 0) { + for (int _i = 0; _i < num_parent_messages; ++_i) { + if (dummy_cmp(&keydbt, parent_messages[_i]->kdbt()) == 0 && + msn.msn == parent_messages[_i]->msn().msn) { + assert(is_fresh == parent_messages_is_fresh[_i]); + break; + } + } + } else { + assert(!is_fresh); + } + return 0; + } + } checkit(childkeys, num_parent_messages, parent_messages, parent_messages_is_fresh); + parent_bnc->msg_buffer.iterate(checkit); + + toku_ftnode_free(&parentnode); + + int total_messages = 0; + for (i = 0; i < 8; ++i) { + total_messages += BLB_DATA(child, i)->num_klpairs(); + } + assert(total_messages <= num_parent_messages + num_child_messages); + + for (i = 0; i < num_parent_messages; ++i) { + if (dummy_cmp(parent_messages[i]->kdbt(), &childkeys[7]) <= 0) { + assert(parent_messages_applied[i] == 1); + } else { + assert(parent_messages_applied[i] == 0); + } + } + + toku_xids_destroy(&xids_0); + toku_xids_destroy(&xids_123); + toku_xids_destroy(&xids_234); + + for (i = 0; i < num_parent_messages; ++i) { + toku_free(parent_messages[i]->kdbt()->data); + struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(extra, parent_messages[i]->vdbt()->data); + toku_free(extra->new_val.data); + toku_free(parent_messages[i]->vdbt()->data); + delete parent_messages[i]; + } + for (i = 0; i < num_child_messages; ++i) { + toku_free(child_messages[i]); + toku_free(key_pointers[i]); + } + toku_free(ubi.data); + toku_ftnode_free(&child); + toku_free(parent_messages); + toku_free(key_pointers); + toku_free(keylens); + toku_free(child_messages); + toku_free(parent_messages_is_fresh); + toku_free(parent_messages_applied); +} + +// create identical leaf nodes and then buffer flush to one and +// maybe_apply to the other, and compare the results, they should be the +// same. +// +// if make_leaf_up_to_date is true, then apply the messages that are stale +// in the parent to the leaf before doing the flush, otherwise assume the +// leaf was just read off disk +static void +compare_apply_and_flush(FT_HANDLE t, bool make_leaf_up_to_date) { + int r; + + ft_msg **MALLOC_N(4096,parent_messages); // 128k / 32 = 4k + LEAFENTRY* child_messages = NULL; + XMALLOC_N(4096,child_messages); + void** key_pointers = NULL; + XMALLOC_N(4096, key_pointers); + uint32_t* keylens = NULL; + XMALLOC_N(4096, keylens); + bool *MALLOC_N(4096,parent_messages_is_fresh); + memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0])); + int *MALLOC_N(4096,parent_messages_applied); + memset(parent_messages_applied, 0, 4096*(sizeof parent_messages_applied[0])); + + XIDS xids_0 = toku_xids_get_root_xids(); + XIDS xids_123, xids_234; + r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123); + CKERR(r); + r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234); + CKERR(r); + + BASEMENTNODE child1_blbs[8], child2_blbs[8]; + DBT child1keys[7], child2keys[7]; + int i; + for (i = 0; i < 8; ++i) { + child1_blbs[i] = toku_create_empty_bn(); + child2_blbs[i] = toku_create_empty_bn(); + if (i < 7) { + toku_init_dbt(&child1keys[i]); + toku_init_dbt(&child2keys[i]); + } + } + + FTNODE XMALLOC(child1), XMALLOC(child2); + BLOCKNUM blocknum = { 42 }; + toku_initialize_empty_ftnode(child1, blocknum, 0, 8, FT_LAYOUT_VERSION, 0); + toku_initialize_empty_ftnode(child2, blocknum, 0, 8, FT_LAYOUT_VERSION, 0); + for (i = 0; i < 8; ++i) { + destroy_basement_node(BLB(child1, i)); + set_BLB(child1, i, child1_blbs[i]); + BP_STATE(child1, i) = PT_AVAIL; + destroy_basement_node(BLB(child2, i)); + set_BLB(child2, i, child2_blbs[i]); + BP_STATE(child2, i) = PT_AVAIL; + } + + int total_size = 0; + for (i = 0; total_size < 128*1024; ++i) { + total_size -= child1_blbs[i%8]->data_buffer.get_memory_size(); + insert_same_message_to_bns(t, child1_blbs[i%8], child2_blbs[i%8], &key_pointers[i], &keylens[i], &child_messages[i], xids_123, i%8); + total_size += child1_blbs[i%8]->data_buffer.get_memory_size(); + if (i % 8 < 7) { + DBT keydbt; + if (child1keys[i%8].size == 0 || dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &child1keys[i%8]) > 0) { + toku_fill_dbt(&child1keys[i%8], key_pointers[i], keylens[i]); + toku_fill_dbt(&child2keys[i%8], key_pointers[i], keylens[i]); + } + } + } + int num_child_messages = i; + + for (i = 0; i < num_child_messages; ++i) { + DBT keydbt; + if (i % 8 < 7) { + assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &child1keys[i%8]) <= 0); + assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &child2keys[i%8]) <= 0); + } + } + + { + int num_stale = random() % 2000; + memset(&parent_messages_is_fresh[num_stale], true, (4096 - num_stale) * (sizeof parent_messages_is_fresh[0])); + } + NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl(); + MSN max_parent_msn = MIN_MSN; + for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) { + insert_random_update_message(parent_bnc, &parent_messages[i], parent_messages_is_fresh[i], xids_234, i%8, &parent_messages_applied[i], &max_parent_msn); + } + int num_parent_messages = i; + + for (i = 0; i < 7; ++i) { + child1->pivotkeys.insert_at(&child1keys[i], i); + child2->pivotkeys.insert_at(&child2keys[i], i); + } + + if (make_leaf_up_to_date) { + for (i = 0; i < num_parent_messages; ++i) { + if (!parent_messages_is_fresh[i]) { + toku_ft_leaf_apply_msg(t->ft->cmp, t->ft->update_fun, child1, -1, *parent_messages[i], &non_mvcc_gc_info, NULL, NULL); + toku_ft_leaf_apply_msg(t->ft->cmp, t->ft->update_fun, child2, -1, *parent_messages[i], &non_mvcc_gc_info, NULL, NULL); + } + } + for (i = 0; i < 8; ++i) { + BLB(child1, i)->stale_ancestor_messages_applied = true; + BLB(child2, i)->stale_ancestor_messages_applied = true; + } + } else { + for (i = 0; i < 8; ++i) { + BLB(child1, i)->stale_ancestor_messages_applied = false; + BLB(child2, i)->stale_ancestor_messages_applied = false; + } + } + + toku_bnc_flush_to_child(t->ft, parent_bnc, child1, TXNID_NONE); + + FTNODE XMALLOC(parentnode); + BLOCKNUM parentblocknum = { 17 }; + toku_initialize_empty_ftnode(parentnode, parentblocknum, 1, 1, FT_LAYOUT_VERSION, 0); + destroy_nonleaf_childinfo(BNC(parentnode, 0)); + set_BNC(parentnode, 0, parent_bnc); + BP_STATE(parentnode, 0) = PT_AVAIL; + parentnode->max_msn_applied_to_node_on_disk = max_parent_msn; + struct ancestors ancestors = { .node = parentnode, .childnum = 0, .next = NULL }; + bool msgs_applied; + toku_apply_ancestors_messages_to_node(t, child2, &ancestors, pivot_bounds::infinite_bounds(), &msgs_applied, -1); + + struct checkit_fn { + int operator()(const ft_msg &UU(msg), bool is_fresh) { + assert(!is_fresh); + return 0; + } + } checkit; + parent_bnc->msg_buffer.iterate(checkit); + invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size() + == (uint32_t) num_parent_messages); + + toku_ftnode_free(&parentnode); + + for (int j = 0; j < 8; ++j) { + bn_data* first = BLB_DATA(child1, j); + bn_data* second = BLB_DATA(child2, j); + uint32_t len = first->num_klpairs(); + assert(len == second->num_klpairs()); + for (uint32_t idx = 0; idx < len; ++idx) { + LEAFENTRY le1, le2; + DBT key1dbt, val1dbt, key2dbt, val2dbt; + { + uint32_t keylen, vallen; + void *keyp = NULL; + r = first->fetch_klpair(idx, &le1, &keylen, &keyp); + assert_zero(r); + void *valp = le_latest_val_and_len(le1, &vallen); + toku_fill_dbt(&key1dbt, keyp, keylen); + toku_fill_dbt(&val1dbt, valp, vallen); + } + { + uint32_t keylen, vallen; + void *keyp = NULL; + r = second->fetch_klpair(idx, &le2, &keylen, &keyp); + assert_zero(r); + void *valp = le_latest_val_and_len(le2, &vallen); + toku_fill_dbt(&key2dbt, keyp, keylen); + toku_fill_dbt(&val2dbt, valp, vallen); + } + assert(dummy_cmp(&key1dbt, &key2dbt) == 0); + assert(dummy_cmp(&val1dbt, &val2dbt) == 0); + } + } + + toku_xids_destroy(&xids_0); + toku_xids_destroy(&xids_123); + toku_xids_destroy(&xids_234); + + for (i = 0; i < num_parent_messages; ++i) { + toku_free(parent_messages[i]->kdbt()->data); + struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(extra, parent_messages[i]->vdbt()->data); + toku_free(extra->new_val.data); + toku_free(parent_messages[i]->vdbt()->data); + delete parent_messages[i]; + } + for (i = 0; i < num_child_messages; ++i) { + toku_free(key_pointers[i]); + toku_free(child_messages[i]); + } + toku_ftnode_free(&child1); + toku_ftnode_free(&child2); + toku_free(parent_messages); + toku_free(key_pointers); + toku_free(keylens); + toku_free(child_messages); + toku_free(parent_messages_is_fresh); + toku_free(parent_messages_applied); +} + +static void +parse_args(int argc, const char *argv[]) { + const char *progname=argv[0]; + argc--; argv++; + while (argc>0) { + if (strcmp(argv[0],"-v")==0) { + verbose=1; + } else if (strcmp(argv[0],"-q")==0) { + verbose=0; + } else { + fprintf(stderr, "Usage:\n %s [-v] [-q]\n", progname); + exit(1); + } + argc--; argv++; + } +} + +static int cmp_fn(DB *db __attribute__((unused)), + const DBT *a, const DBT *b) { + int c; + if (a->size > b->size) { + c = memcmp(a->data, b->data, b->size); + } else if (a->size < b->size) { + c = memcmp(a->data, b->data, a->size); + } else { + return memcmp(a->data, b->data, a->size); + } + if (c == 0) { + c = a->size - b->size; + } + return c; +} + +int +test_main (int argc, const char *argv[]) { + parse_args(argc, argv); + + dummy_cmp.create(cmp_fn, nullptr); + + initialize_dummymsn(); + int r; + CACHETABLE ct; + toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr); + unlink(fname); + FT_HANDLE t; + r = toku_open_ft_handle(fname, 1, &t, 128*1024, 4096, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0); + toku_ft_set_update(t, orthopush_flush_update_fun); + // HACK + t->ft->update_fun = orthopush_flush_update_fun; + + for (int i = 0; i < 10; ++i) { + flush_to_internal(t); + } + for (int i = 0; i < 10; ++i) { + flush_to_internal_multiple(t); + } + for (int i = 0; i < 3; ++i) { + flush_to_leaf(t, false, false); + flush_to_leaf(t, false, true); + flush_to_leaf(t, true, false); + flush_to_leaf(t, true, true); + } + for (int i = 0; i < 10; ++i) { + flush_to_leaf_with_keyrange(t, false); + flush_to_leaf_with_keyrange(t, true); + compare_apply_and_flush(t, false); + compare_apply_and_flush(t, true); + } + + r = toku_close_ft_handle_nolsn(t, 0); assert(r==0); + toku_cachetable_close(&ct); + + dummy_cmp.destroy(); + + return 0; +} |