1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6 
7 
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9 
10     PerconaFT is free software: you can redistribute it and/or modify
11     it under the terms of the GNU General Public License, version 2,
12     as published by the Free Software Foundation.
13 
14     PerconaFT is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
21 
22 ----------------------------------------
23 
24     PerconaFT is free software: you can redistribute it and/or modify
25     it under the terms of the GNU Affero General Public License, version 3,
26     as published by the Free Software Foundation.
27 
28     PerconaFT is distributed in the hope that it will be useful,
29     but WITHOUT ANY WARRANTY; without even the implied warranty of
30     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31     GNU Affero General Public License for more details.
32 
33     You should have received a copy of the GNU Affero General Public License
34     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36 
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38 
39 #include "test.h"
40 
41 
42 #include "ule.h"
43 
44 static TOKUTXN const null_txn = 0;
45 static const char *fname = TOKU_TEST_FILENAME;
46 static txn_gc_info non_mvcc_gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
47 static toku::comparator dummy_cmp;
48 
49 // generate size random bytes into dest
50 static void
rand_bytes(void * dest,int size)51 rand_bytes(void *dest, int size)
52 {
53     long *l;
54     for (CAST_FROM_VOIDP(l, dest); (unsigned int) size >= (sizeof *l); ++l, size -= (sizeof *l)) {
55         *l = random();
56     }
57     for (char *c = (char *) l; size > 0; ++c, --size) {
58         *c = random() & 0xff;
59     }
60 }
61 
62 // generate size random bytes into dest, with a lot less entropy (every
63 // group of 4 bytes is the same)
64 static void
rand_bytes_limited(void * dest,int size)65 rand_bytes_limited(void *dest, int size)
66 {
67     long *l;
68     for (CAST_FROM_VOIDP(l, dest); (size_t) size >= (sizeof *l); ++l, size -= (sizeof *l)) {
69         char c = random() & 0xff;
70         for (char *p = (char *) l; (size_t) (p - (char *) l) < (sizeof *l); ++p) {
71             *p = c;
72         }
73     }
74     char c = random() & 0xff;
75     for (char *p = (char *) l; size > 0; ++p, --size) {
76         *p = c;
77     }
78 }
79 
80 // generate a random message with xids and a key starting with pfx, insert
81 // it in bnc, and save it in output params save and is_fresh_out
82 static void
insert_random_message(NONLEAF_CHILDINFO bnc,ft_msg ** save,bool * is_fresh_out,XIDS xids,int pfx)83 insert_random_message(NONLEAF_CHILDINFO bnc, ft_msg **save, bool *is_fresh_out, XIDS xids, int pfx)
84 {
85     int keylen = (random() % 128) + 16;
86     int vallen = (random() % 128) + 16;
87     void *key = toku_xmalloc(keylen + (sizeof pfx));
88     void *val = toku_xmalloc(vallen);
89     *(int *) key = pfx;
90     rand_bytes((char *) key + (sizeof pfx), keylen);
91     rand_bytes(val, vallen);
92     MSN msn = next_dummymsn();
93     bool is_fresh = (random() & 0x100) == 0;
94 
95     DBT keydbt, valdbt;
96     toku_fill_dbt(&keydbt, key, keylen + (sizeof pfx));
97     toku_fill_dbt(&valdbt, val, vallen);
98     *save = new ft_msg(&keydbt, &valdbt, FT_INSERT, msn, xids);
99     *is_fresh_out = is_fresh;
100 
101     toku_bnc_insert_msg(bnc, key, keylen + (sizeof pfx), val, vallen,
102                         FT_INSERT, msn, xids, is_fresh,
103                         dummy_cmp);
104 }
105 
106 // generate a random message with xids and a key starting with pfx, insert
107 // it into blb, and save it in output param save
108 static void
insert_random_message_to_bn(FT_HANDLE t,BASEMENTNODE blb,void ** keyp,uint32_t * keylenp,LEAFENTRY * save,XIDS xids,int pfx)109 insert_random_message_to_bn(
110     FT_HANDLE t,
111     BASEMENTNODE blb,
112     void** keyp,
113     uint32_t* keylenp,
114     LEAFENTRY *save,
115     XIDS xids,
116     int pfx
117     )
118 {
119     int keylen = (random() % 16) + 16;
120     int vallen = (random() % 128) + 16;
121     uint32_t *pfxp;
122     char key[(sizeof *pfxp) + keylen];
123     char val[vallen];
124     pfxp = (uint32_t *) &key[0];
125     *pfxp = pfx;
126     char *randkeyp = &key[sizeof *pfxp];
127     rand_bytes_limited(randkeyp, keylen);
128     rand_bytes(val, vallen);
129     MSN msn = next_dummymsn();
130 
131     DBT keydbt_s, *keydbt, valdbt_s, *valdbt;
132     keydbt = &keydbt_s;
133     valdbt = &valdbt_s;
134     toku_fill_dbt(keydbt, key, (sizeof *pfxp) + keylen);
135     toku_fill_dbt(valdbt, val, vallen);
136     *keylenp = keydbt->size;
137     *keyp = toku_xmemdup(keydbt->data, keydbt->size);
138     ft_msg msg(keydbt, valdbt, FT_INSERT, msn, xids);
139     int64_t numbytes;
140     toku_le_apply_msg(
141         msg,
142         NULL,
143         NULL,
144         0,
145         keydbt->size,
146         &non_mvcc_gc_info,
147         save,
148         &numbytes);
149     toku_ft_bn_apply_msg(
150         t->ft->cmp,
151         t->ft->update_fun,
152         blb,
153         msg,
154         &non_mvcc_gc_info,
155         NULL,
156         NULL,
157         NULL);
158     if (msn.msn > blb->max_msn_applied.msn) {
159         blb->max_msn_applied = msn;
160     }
161 }
162 
163 // generate a random message with xids and a key starting with pfx, insert
164 // it into blb1 and also into blb2, and save it in output param save
165 //
166 // used for making two leaf nodes the same in order to compare the result
167 // of 'maybe_apply' and a normal buffer flush
168 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)169 insert_same_message_to_bns(
170     FT_HANDLE t,
171     BASEMENTNODE blb1,
172     BASEMENTNODE blb2,
173     void** keyp,
174     uint32_t* keylenp,
175     LEAFENTRY *save,
176     XIDS xids,
177     int pfx
178     )
179 {
180     int keylen = (random() % 16) + 16;
181     int vallen = (random() % 128) + 16;
182     uint32_t *pfxp;
183     char key[(sizeof *pfxp) + keylen];
184     char val[vallen];
185     pfxp = (uint32_t *) &key[0];
186     *pfxp = pfx;
187     char *randkeyp = &key[sizeof *pfxp];
188     rand_bytes_limited(randkeyp, keylen);
189     rand_bytes(val, vallen);
190     MSN msn = next_dummymsn();
191 
192     DBT keydbt_s, *keydbt, valdbt_s, *valdbt;
193     keydbt = &keydbt_s;
194     valdbt = &valdbt_s;
195     toku_fill_dbt(keydbt, key, (sizeof *pfxp) + keylen);
196     toku_fill_dbt(valdbt, val, vallen);
197     *keylenp = keydbt->size;
198     *keyp = toku_xmemdup(keydbt->data, keydbt->size);
199     ft_msg msg(keydbt, valdbt, FT_INSERT, msn, xids);
200     int64_t numbytes;
201     toku_le_apply_msg(
202         msg,
203         NULL,
204         NULL,
205         0,
206         keydbt->size,
207         &non_mvcc_gc_info,
208         save,
209         &numbytes);
210     toku_ft_bn_apply_msg(
211         t->ft->cmp,
212         t->ft->update_fun,
213         blb1,
214         msg,
215         &non_mvcc_gc_info,
216         NULL,
217         NULL,
218         NULL);
219     if (msn.msn > blb1->max_msn_applied.msn) {
220         blb1->max_msn_applied = msn;
221     }
222     toku_ft_bn_apply_msg(
223         t->ft->cmp,
224         t->ft->update_fun,
225         blb2,
226         msg,
227         &non_mvcc_gc_info,
228         NULL,
229         NULL,
230         NULL);
231     if (msn.msn > blb2->max_msn_applied.msn) {
232         blb2->max_msn_applied = msn;
233     }
234 }
235 
236 struct orthopush_flush_update_fun_extra {
237     DBT new_val;
238     int *num_applications;
239 };
240 
241 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)242 orthopush_flush_update_fun(DB * UU(db), const DBT *UU(key), const DBT *UU(old_val), const DBT *extra,
243                            void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra) {
244     struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(e, extra->data);
245     (*e->num_applications)++;
246     set_val(&e->new_val, set_extra);
247     return 0;
248 }
249 
250 // generate a random update message with xids and a key starting with pfx,
251 // insert it into blb, and save it in output param save, and update the
252 // max msn so far in max_msn
253 //
254 // the update message will overwrite the value with something generated
255 // here, and add one to the int pointed to by applied
256 static void
insert_random_update_message(NONLEAF_CHILDINFO bnc,ft_msg ** save,bool is_fresh,XIDS xids,int pfx,int * applied,MSN * max_msn)257 insert_random_update_message(NONLEAF_CHILDINFO bnc, ft_msg **save, bool is_fresh, XIDS xids, int pfx, int *applied, MSN *max_msn)
258 {
259     int keylen = (random() % 16) + 16;
260     int vallen = (random() % 16) + 16;
261     void *key = toku_xmalloc(keylen + (sizeof pfx));
262     struct orthopush_flush_update_fun_extra *XMALLOC(update_extra);
263     *(int *) key = pfx;
264     rand_bytes_limited((char *) key + (sizeof pfx), keylen);
265     toku_fill_dbt(&update_extra->new_val, toku_xmalloc(vallen), vallen);
266     rand_bytes(update_extra->new_val.data, vallen);
267     update_extra->num_applications = applied;
268     MSN msn = next_dummymsn();
269 
270     DBT keydbt, valdbt;
271     toku_fill_dbt(&keydbt, key, keylen + (sizeof pfx));
272     toku_fill_dbt(&valdbt, update_extra, sizeof *update_extra);
273     *save = new ft_msg(&keydbt, &valdbt, FT_UPDATE, msn, xids);
274 
275     toku_bnc_insert_msg(bnc, key, keylen + (sizeof pfx),
276                         update_extra, sizeof *update_extra,
277                         FT_UPDATE, msn, xids, is_fresh,
278                         dummy_cmp);
279     if (msn.msn > max_msn->msn) {
280         *max_msn = msn;
281     }
282 }
283 
284 // flush from one internal node to another, where both only have one
285 // buffer
286 static void
flush_to_internal(FT_HANDLE t)287 flush_to_internal(FT_HANDLE t) {
288     int r;
289 
290     ft_msg **MALLOC_N(4096,parent_messages);  // 128k / 32 = 4096
291     ft_msg **MALLOC_N(4096,child_messages);
292     bool *MALLOC_N(4096,parent_messages_is_fresh);
293     bool *MALLOC_N(4096,child_messages_is_fresh);
294     memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0]));
295     memset(child_messages_is_fresh, 0, 4096*(sizeof child_messages_is_fresh[0]));
296 
297     XIDS xids_0 = toku_xids_get_root_xids();
298     XIDS xids_123, xids_234;
299     r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123);
300     CKERR(r);
301     r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234);
302     CKERR(r);
303 
304     NONLEAF_CHILDINFO child_bnc = toku_create_empty_nl();
305     int i;
306     for (i = 0; toku_bnc_memory_used(child_bnc) < 128*1024; ++i) {
307         insert_random_message(child_bnc, &child_messages[i], &child_messages_is_fresh[i], xids_123, 0);
308     }
309     int num_child_messages = i;
310 
311     NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl();
312     for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) {
313         insert_random_message(parent_bnc, &parent_messages[i], &parent_messages_is_fresh[i], xids_234, 0);
314     }
315     int num_parent_messages = i;
316 
317     FTNODE XMALLOC(child);
318     BLOCKNUM blocknum = { 42 };
319     toku_initialize_empty_ftnode(child, blocknum, 1, 1, FT_LAYOUT_VERSION, 0);
320     destroy_nonleaf_childinfo(BNC(child, 0));
321     set_BNC(child, 0, child_bnc);
322     BP_STATE(child, 0) = PT_AVAIL;
323 
324     toku_bnc_flush_to_child(t->ft, parent_bnc, child, TXNID_NONE);
325 
326     int parent_messages_present[num_parent_messages];
327     int child_messages_present[num_child_messages];
328     memset(parent_messages_present, 0, sizeof parent_messages_present);
329     memset(child_messages_present, 0, sizeof child_messages_present);
330 
331     struct checkit_fn {
332         int num_parent_messages;
333         ft_msg **parent_messages;
334         int *parent_messages_present;
335         bool *parent_messages_is_fresh;
336         int num_child_messages;
337         ft_msg **child_messages;
338         int *child_messages_present;
339         bool *child_messages_is_fresh;
340         checkit_fn(int np, ft_msg **pm, int *npp, bool *pmf, int nc, ft_msg **cm, int *ncp, bool *cmf) :
341             num_parent_messages(np), parent_messages(pm), parent_messages_present(npp), parent_messages_is_fresh(pmf),
342             num_child_messages(nc), child_messages(cm), child_messages_present(ncp), child_messages_is_fresh(cmf) {
343         }
344         int operator()(const ft_msg &msg, bool is_fresh) {
345             DBT keydbt;
346             DBT valdbt;
347             toku_fill_dbt(&keydbt, msg.kdbt()->data, msg.kdbt()->size);
348             toku_fill_dbt(&valdbt, msg.vdbt()->data, msg.vdbt()->size);
349             int found = 0;
350             MSN msn = msg.msn();
351             enum ft_msg_type type = msg.type();
352             XIDS xids = msg.xids();
353             for (int k = 0; k < num_parent_messages; ++k) {
354                 if (dummy_cmp(&keydbt, parent_messages[k]->kdbt()) == 0 &&
355                         msn.msn == parent_messages[k]->msn().msn) {
356                     assert(parent_messages_present[k] == 0);
357                     assert(found == 0);
358                     assert(dummy_cmp(&valdbt, parent_messages[k]->vdbt()) == 0);
359                     assert(type == parent_messages[k]->type());
360                     assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(parent_messages[k]->xids()));
361                     assert(parent_messages_is_fresh[k] == is_fresh);
362                     parent_messages_present[k]++;
363                     found++;
364                 }
365             }
366             for (int k = 0; k < num_child_messages; ++k) {
367                 if (dummy_cmp(&keydbt, child_messages[k]->kdbt()) == 0 &&
368                         msn.msn == child_messages[k]->msn().msn) {
369                     assert(child_messages_present[k] == 0);
370                     assert(found == 0);
371                     assert(dummy_cmp(&valdbt, child_messages[k]->vdbt()) == 0);
372                     assert(type == child_messages[k]->type());
373                     assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(child_messages[k]->xids()));
374                     assert(child_messages_is_fresh[k] == is_fresh);
375                     child_messages_present[k]++;
376                     found++;
377                 }
378             }
379             assert(found == 1);
380             return 0;
381         }
382     } checkit(num_parent_messages, parent_messages, parent_messages_present, parent_messages_is_fresh,
383               num_child_messages, child_messages, child_messages_present, child_messages_is_fresh);
384     child_bnc->msg_buffer.iterate(checkit);
385 
386     for (i = 0; i < num_parent_messages; ++i) {
387         assert(parent_messages_present[i] == 1);
388     }
389     for (i = 0; i < num_child_messages; ++i) {
390         assert(child_messages_present[i] == 1);
391     }
392 
393     toku_xids_destroy(&xids_0);
394     toku_xids_destroy(&xids_123);
395     toku_xids_destroy(&xids_234);
396 
397     for (i = 0; i < num_parent_messages; ++i) {
398         toku_free(parent_messages[i]->kdbt()->data);
399         toku_free(parent_messages[i]->vdbt()->data);
400         delete parent_messages[i];
401     }
402     for (i = 0; i < num_child_messages; ++i) {
403         toku_free(child_messages[i]->kdbt()->data);
404         toku_free(child_messages[i]->vdbt()->data);
405         delete child_messages[i];
406     }
407     destroy_nonleaf_childinfo(parent_bnc);
408     toku_ftnode_free(&child);
409     toku_free(parent_messages);
410     toku_free(child_messages);
411     toku_free(parent_messages_is_fresh);
412     toku_free(child_messages_is_fresh);
413 }
414 
415 // flush from one internal node to another, where the child has 8 buffers
416 static void
flush_to_internal_multiple(FT_HANDLE t)417 flush_to_internal_multiple(FT_HANDLE t) {
418     int r;
419 
420     ft_msg **MALLOC_N(4096,parent_messages);  // 128k / 32 = 4096
421     ft_msg **MALLOC_N(4096,child_messages);
422     bool *MALLOC_N(4096,parent_messages_is_fresh);
423     bool *MALLOC_N(4096,child_messages_is_fresh);
424     memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0]));
425     memset(child_messages_is_fresh, 0, 4096*(sizeof child_messages_is_fresh[0]));
426 
427     XIDS xids_0 = toku_xids_get_root_xids();
428     XIDS xids_123, xids_234;
429     r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123);
430     CKERR(r);
431     r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234);
432     CKERR(r);
433 
434     NONLEAF_CHILDINFO child_bncs[8];
435     ft_msg *childkeys[7];
436     int i;
437     for (i = 0; i < 8; ++i) {
438         child_bncs[i] = toku_create_empty_nl();
439         if (i < 7) {
440             childkeys[i] = NULL;
441         }
442     }
443     int total_size = 0;
444     for (i = 0; total_size < 128*1024; ++i) {
445         total_size -= toku_bnc_memory_used(child_bncs[i%8]);
446         insert_random_message(child_bncs[i%8], &child_messages[i], &child_messages_is_fresh[i], xids_123, i%8);
447         total_size += toku_bnc_memory_used(child_bncs[i%8]);
448         if (i % 8 < 7) {
449             if (childkeys[i%8] == NULL || dummy_cmp(child_messages[i]->kdbt(), childkeys[i%8]->kdbt()) > 0) {
450                 childkeys[i%8] = child_messages[i];
451             }
452         }
453     }
454     int num_child_messages = i;
455 
456     NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl();
457     for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) {
458         insert_random_message(parent_bnc, &parent_messages[i], &parent_messages_is_fresh[i], xids_234, 0);
459     }
460     int num_parent_messages = i;
461 
462     FTNODE XMALLOC(child);
463     BLOCKNUM blocknum = { 42 };
464     toku_initialize_empty_ftnode(child, blocknum, 1, 8, FT_LAYOUT_VERSION, 0);
465     for (i = 0; i < 8; ++i) {
466         destroy_nonleaf_childinfo(BNC(child, i));
467         set_BNC(child, i, child_bncs[i]);
468         BP_STATE(child, i) = PT_AVAIL;
469         if (i < 7) {
470             child->pivotkeys.insert_at(childkeys[i]->kdbt(), i);
471         }
472     }
473 
474     toku_bnc_flush_to_child(t->ft, parent_bnc, child, TXNID_NONE);
475 
476     int total_messages = 0;
477     for (i = 0; i < 8; ++i) {
478         total_messages += toku_bnc_n_entries(BNC(child, i));
479     }
480     assert(total_messages == num_parent_messages + num_child_messages);
481     int parent_messages_present[num_parent_messages];
482     int child_messages_present[num_child_messages];
483     memset(parent_messages_present, 0, sizeof parent_messages_present);
484     memset(child_messages_present, 0, sizeof child_messages_present);
485 
486     for (int j = 0; j < 8; ++j) {
487         struct checkit_fn {
488             int num_parent_messages;
489             ft_msg **parent_messages;
490             int *parent_messages_present;
491             bool *parent_messages_is_fresh;
492             int num_child_messages;
493             ft_msg **child_messages;
494             int *child_messages_present;
495             bool *child_messages_is_fresh;
496             checkit_fn(int np, ft_msg **pm, int *npp, bool *pmf, int nc, ft_msg **cm, int *ncp, bool *cmf) :
497                 num_parent_messages(np), parent_messages(pm), parent_messages_present(npp), parent_messages_is_fresh(pmf),
498                 num_child_messages(nc), child_messages(cm), child_messages_present(ncp), child_messages_is_fresh(cmf) {
499             }
500             int operator()(const ft_msg &msg, bool is_fresh) {
501                 DBT keydbt;
502                 DBT valdbt;
503                 toku_fill_dbt(&keydbt, msg.kdbt()->data, msg.kdbt()->size);
504                 toku_fill_dbt(&valdbt, msg.vdbt()->data, msg.vdbt()->size);
505                 int found = 0;
506                 MSN msn = msg.msn();
507                 enum ft_msg_type type = msg.type();
508                 XIDS xids = msg.xids();
509                 for (int _i = 0; _i < num_parent_messages; ++_i) {
510                     if (dummy_cmp(&keydbt, parent_messages[_i]->kdbt()) == 0 &&
511                             msn.msn == parent_messages[_i]->msn().msn) {
512                         assert(parent_messages_present[_i] == 0);
513                         assert(found == 0);
514                         assert(dummy_cmp(&valdbt, parent_messages[_i]->vdbt()) == 0);
515                         assert(type == parent_messages[_i]->type());
516                         assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(parent_messages[_i]->xids()));
517                         assert(parent_messages_is_fresh[_i] == is_fresh);
518                         parent_messages_present[_i]++;
519                         found++;
520                     }
521                 }
522                 for (int _i = 0; _i < num_child_messages; ++_i) {
523                     if (dummy_cmp(&keydbt, child_messages[_i]->kdbt()) == 0 &&
524                             msn.msn == child_messages[_i]->msn().msn) {
525                         assert(child_messages_present[_i] == 0);
526                         assert(found == 0);
527                         assert(dummy_cmp(&valdbt, child_messages[_i]->vdbt()) == 0);
528                         assert(type == child_messages[_i]->type());
529                         assert(toku_xids_get_innermost_xid(xids) == toku_xids_get_innermost_xid(child_messages[_i]->xids()));
530                         assert(child_messages_is_fresh[_i] == is_fresh);
531                         child_messages_present[_i]++;
532                         found++;
533                     }
534                 }
535                 assert(found == 1);
536                 return 0;
537             }
538         } checkit(num_parent_messages, parent_messages, parent_messages_present, parent_messages_is_fresh,
539                   num_child_messages, child_messages, child_messages_present, child_messages_is_fresh);
540         child_bncs[j]->msg_buffer.iterate(checkit);
541     }
542 
543     for (i = 0; i < num_parent_messages; ++i) {
544         assert(parent_messages_present[i] == 1);
545     }
546     for (i = 0; i < num_child_messages; ++i) {
547         assert(child_messages_present[i] == 1);
548     }
549 
550     toku_xids_destroy(&xids_0);
551     toku_xids_destroy(&xids_123);
552     toku_xids_destroy(&xids_234);
553 
554     for (i = 0; i < num_parent_messages; ++i) {
555         toku_free(parent_messages[i]->kdbt()->data);
556         toku_free(parent_messages[i]->vdbt()->data);
557         delete parent_messages[i];
558     }
559     for (i = 0; i < num_child_messages; ++i) {
560         toku_free(child_messages[i]->kdbt()->data);
561         toku_free(child_messages[i]->vdbt()->data);
562         delete child_messages[i];
563     }
564     destroy_nonleaf_childinfo(parent_bnc);
565     toku_ftnode_free(&child);
566     toku_free(parent_messages);
567     toku_free(child_messages);
568     toku_free(parent_messages_is_fresh);
569     toku_free(child_messages_is_fresh);
570 }
571 
572 // flush from one internal node to a leaf node, which has 8 basement
573 // nodes
574 //
575 // if make_leaf_up_to_date is true, then apply the messages that are stale
576 // in the parent to the leaf before doing the flush, otherwise assume the
577 // leaf was just read off disk
578 //
579 // if use_flush is true, use a buffer flush, otherwise, use maybe_apply
580 static void
flush_to_leaf(FT_HANDLE t,bool make_leaf_up_to_date,bool use_flush)581 flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) {
582     int r;
583 
584     ft_msg **MALLOC_N(4096,parent_messages);  // 128k / 32 = 4096
585     LEAFENTRY* child_messages = NULL;
586     XMALLOC_N(4096,child_messages);
587     void** key_pointers = NULL;
588     XMALLOC_N(4096, key_pointers);
589     uint32_t* keylens = NULL;
590     XMALLOC_N(4096, keylens);
591     bool *MALLOC_N(4096,parent_messages_is_fresh);
592     memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0]));
593     int *MALLOC_N(4096,parent_messages_applied);
594     memset(parent_messages_applied, 0, 4096*(sizeof parent_messages_applied[0]));
595 
596     XIDS xids_0 = toku_xids_get_root_xids();
597     XIDS xids_123, xids_234;
598     r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123);
599     CKERR(r);
600     r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234);
601     CKERR(r);
602 
603     BASEMENTNODE child_blbs[8];
604     DBT childkeys[7];
605     int i;
606     for (i = 0; i < 8; ++i) {
607         child_blbs[i] = toku_create_empty_bn();
608         if (i < 7) {
609             toku_init_dbt(&childkeys[i]);
610         }
611     }
612 
613     FTNODE child = NULL;
614     XMALLOC(child);
615     BLOCKNUM blocknum = { 42 };
616     toku_initialize_empty_ftnode(child, blocknum, 0, 8, FT_LAYOUT_VERSION, 0);
617     for (i = 0; i < 8; ++i) {
618         destroy_basement_node(BLB(child, i));
619         set_BLB(child, i, child_blbs[i]);
620         BP_STATE(child, i) = PT_AVAIL;
621     }
622 
623     int total_size = 0;
624     for (i = 0; total_size < 128*1024; ++i) {
625         total_size -= child_blbs[i%8]->data_buffer.get_memory_size();
626         insert_random_message_to_bn(t, child_blbs[i%8], &key_pointers[i], &keylens[i], &child_messages[i], xids_123, i%8);
627         total_size += child_blbs[i%8]->data_buffer.get_memory_size();
628         if (i % 8 < 7) {
629             DBT keydbt;
630             if (childkeys[i%8].size == 0 || dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) > 0) {
631                 toku_fill_dbt(&childkeys[i%8], key_pointers[i], keylens[i]);
632             }
633         }
634     }
635     int num_child_messages = i;
636 
637     for (i = 0; i < num_child_messages; ++i) {
638         DBT keydbt;
639         if (i % 8 < 7) {
640             assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) <= 0);
641         }
642     }
643 
644     {
645         int num_stale = random() % 2000;
646         memset(&parent_messages_is_fresh[num_stale], true, (4096 - num_stale) * (sizeof parent_messages_is_fresh[0]));
647     }
648     NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl();
649     MSN max_parent_msn = MIN_MSN;
650     for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) {
651         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);
652     }
653     int num_parent_messages = i;
654 
655     for (i = 0; i < 7; ++i) {
656         child->pivotkeys.insert_at(&childkeys[i], i);
657     }
658 
659     if (make_leaf_up_to_date) {
660         for (i = 0; i < num_parent_messages; ++i) {
661             if (!parent_messages_is_fresh[i]) {
662                 toku_ft_leaf_apply_msg(
663                     t->ft->cmp,
664                     t->ft->update_fun,
665                     child,
666                     -1,
667                     *parent_messages[i],
668                     &non_mvcc_gc_info,
669                     NULL,
670                     NULL,
671                     NULL);
672             }
673         }
674         for (i = 0; i < 8; ++i) {
675             BLB(child, i)->stale_ancestor_messages_applied = true;
676         }
677     } else {
678         for (i = 0; i < 8; ++i) {
679             BLB(child, i)->stale_ancestor_messages_applied = false;
680         }
681     }
682 
683     for (i = 0; i < num_parent_messages; ++i) {
684         if (make_leaf_up_to_date && !parent_messages_is_fresh[i]) {
685             assert(parent_messages_applied[i] == 1);
686         } else {
687             assert(parent_messages_applied[i] == 0);
688         }
689     }
690 
691     if (use_flush) {
692         toku_bnc_flush_to_child(t->ft, parent_bnc, child, TXNID_NONE);
693         destroy_nonleaf_childinfo(parent_bnc);
694     } else {
695         FTNODE XMALLOC(parentnode);
696         BLOCKNUM parentblocknum = { 17 };
697         toku_initialize_empty_ftnode(parentnode, parentblocknum, 1, 1, FT_LAYOUT_VERSION, 0);
698         destroy_nonleaf_childinfo(BNC(parentnode, 0));
699         set_BNC(parentnode, 0, parent_bnc);
700         BP_STATE(parentnode, 0) = PT_AVAIL;
701         parentnode->max_msn_applied_to_node_on_disk = max_parent_msn;
702         struct ancestors ancestors = { .node = parentnode, .childnum = 0, .next = NULL };
703         bool msgs_applied;
704         toku_apply_ancestors_messages_to_node(t, child, &ancestors, pivot_bounds::infinite_bounds(), &msgs_applied, -1);
705 
706         struct checkit_fn {
707             int operator()(const ft_msg &UU(msg), bool is_fresh) {
708                  assert(!is_fresh);
709                 return 0;
710             }
711         } checkit;
712         parent_bnc->msg_buffer.iterate(checkit);
713         invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size()
714                   == (uint32_t) num_parent_messages);
715 
716         toku_ftnode_free(&parentnode);
717     }
718 
719     int total_messages = 0;
720     for (i = 0; i < 8; ++i) {
721         total_messages += BLB_DATA(child, i)->num_klpairs();
722     }
723     assert(total_messages <= num_parent_messages + num_child_messages);
724 
725     for (i = 0; i < num_parent_messages; ++i) {
726         assert(parent_messages_applied[i] == 1);
727     }
728 
729     int parent_messages_present[num_parent_messages];
730     int child_messages_present[num_child_messages];
731     memset(parent_messages_present, 0, sizeof parent_messages_present);
732     memset(child_messages_present, 0, sizeof child_messages_present);
733     for (int j = 0; j < 8; ++j) {
734         uint32_t len = BLB_DATA(child, j)->num_klpairs();
735         for (uint32_t idx = 0; idx < len; ++idx) {
736             LEAFENTRY le;
737             DBT keydbt, valdbt;
738             {
739                 uint32_t keylen, vallen;
740                 void *keyp = NULL;
741                 void *valp = NULL;
742                 r = BLB_DATA(child, j)->fetch_klpair(idx, &le, &keylen, &keyp);
743                 assert_zero(r);
744                 valp = le_latest_val_and_len(le, &vallen);
745                 toku_fill_dbt(&keydbt, keyp, keylen);
746                 toku_fill_dbt(&valdbt, valp, vallen);
747             }
748             int found = 0;
749             for (i = num_parent_messages - 1; i >= 0; --i) {
750                 if (dummy_cmp(&keydbt, parent_messages[i]->kdbt()) == 0) {
751                     if (found == 0) {
752                         struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(e, parent_messages[i]->vdbt()->data);
753                         assert(dummy_cmp(&valdbt, &e->new_val) == 0);
754                         found++;
755                     }
756                     assert(parent_messages_present[i] == 0);
757                     parent_messages_present[i]++;
758                 }
759             }
760             for (i = j + (~7 & (num_child_messages - 1)); i >= 0; i -= 8) {
761                 if (i >= num_child_messages) { continue; }
762                 DBT childkeydbt, childvaldbt;
763                 {
764                     uint32_t vallen;
765                     void *valp = le_latest_val_and_len(child_messages[i], &vallen);
766                     toku_fill_dbt(&childkeydbt, key_pointers[i], keylens[i]);
767                     toku_fill_dbt(&childvaldbt, valp, vallen);
768                 }
769                 if (dummy_cmp(&keydbt, &childkeydbt) == 0) {
770                     if (found == 0) {
771                         assert(dummy_cmp(&valdbt, &childvaldbt) == 0);
772                         found++;
773                     }
774                     assert(child_messages_present[i] == 0);
775                     child_messages_present[i]++;
776                 }
777             }
778         }
779     }
780 
781     for (i = 0; i < num_parent_messages; ++i) {
782         assert(parent_messages_present[i] == 1);
783     }
784     for (i = 0; i < num_child_messages; ++i) {
785         assert(child_messages_present[i] == 1);
786     }
787 
788     toku_xids_destroy(&xids_0);
789     toku_xids_destroy(&xids_123);
790     toku_xids_destroy(&xids_234);
791 
792     for (i = 0; i < num_parent_messages; ++i) {
793         toku_free(parent_messages[i]->kdbt()->data);
794         struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(extra, parent_messages[i]->vdbt()->data);
795         toku_free(extra->new_val.data);
796         toku_free(parent_messages[i]->vdbt()->data);
797         delete parent_messages[i];
798     }
799     for (i = 0; i < num_child_messages; ++i) {
800         toku_free(child_messages[i]);
801         toku_free(key_pointers[i]);
802     }
803     toku_ftnode_free(&child);
804     toku_free(parent_messages);
805     toku_free(key_pointers);
806     toku_free(keylens);
807     toku_free(child_messages);
808     toku_free(parent_messages_is_fresh);
809     toku_free(parent_messages_applied);
810 }
811 
812 // flush from one internal node to a leaf node, which has 8 basement
813 // nodes, but only using maybe_apply, and with actual pivot bounds
814 //
815 // if make_leaf_up_to_date is true, then apply the messages that are stale
816 // in the parent to the leaf before doing the flush, otherwise assume the
817 // leaf was just read off disk
818 static void
flush_to_leaf_with_keyrange(FT_HANDLE t,bool make_leaf_up_to_date)819 flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) {
820     int r;
821 
822     ft_msg **MALLOC_N(4096,parent_messages);  // 128k / 32 = 4k
823     LEAFENTRY* child_messages = NULL;
824     XMALLOC_N(4096,child_messages);
825     void** key_pointers = NULL;
826     XMALLOC_N(4096, key_pointers);
827     uint32_t* keylens = NULL;
828     XMALLOC_N(4096, keylens);
829     bool *MALLOC_N(4096,parent_messages_is_fresh);
830     memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0]));
831     int *MALLOC_N(4096,parent_messages_applied);
832     memset(parent_messages_applied, 0, 4096*(sizeof parent_messages_applied[0]));
833 
834     XIDS xids_0 = toku_xids_get_root_xids();
835     XIDS xids_123, xids_234;
836     r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123);
837     CKERR(r);
838     r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234);
839     CKERR(r);
840 
841     BASEMENTNODE child_blbs[8];
842     DBT childkeys[8];
843     int i;
844     for (i = 0; i < 8; ++i) {
845         child_blbs[i] = toku_create_empty_bn();
846         toku_init_dbt(&childkeys[i]);
847     }
848 
849     FTNODE XMALLOC(child);
850     BLOCKNUM blocknum = { 42 };
851     toku_initialize_empty_ftnode(child, blocknum, 0, 8, FT_LAYOUT_VERSION, 0);
852     for (i = 0; i < 8; ++i) {
853         destroy_basement_node(BLB(child, i));
854         set_BLB(child, i, child_blbs[i]);
855         BP_STATE(child, i) = PT_AVAIL;
856     }
857 
858     int total_size = 0;
859     for (i = 0; total_size < 128*1024; ++i) {
860         total_size -= child_blbs[i%8]->data_buffer.get_memory_size();
861         insert_random_message_to_bn(t, child_blbs[i%8], &key_pointers[i], &keylens[i], &child_messages[i], xids_123, i%8);
862         total_size += child_blbs[i%8]->data_buffer.get_memory_size();
863         DBT keydbt;
864         if (childkeys[i%8].size == 0 || dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) > 0) {
865             toku_fill_dbt(&childkeys[i%8], key_pointers[i], keylens[i]);
866         }
867     }
868     int num_child_messages = i;
869 
870     for (i = 0; i < num_child_messages; ++i) {
871         DBT keydbt;
872         assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &childkeys[i%8]) <= 0);
873     }
874 
875     {
876         int num_stale = random() % 2000;
877         memset(&parent_messages_is_fresh[num_stale], true, (4096 - num_stale) * (sizeof parent_messages_is_fresh[0]));
878     }
879     NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl();
880     MSN max_parent_msn = MIN_MSN;
881     for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) {
882         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);
883     }
884     int num_parent_messages = i;
885 
886     for (i = 0; i < 7; ++i) {
887         child->pivotkeys.insert_at(&childkeys[i], i);
888     }
889 
890     if (make_leaf_up_to_date) {
891         for (i = 0; i < num_parent_messages; ++i) {
892             if (dummy_cmp(parent_messages[i]->kdbt(), &childkeys[7]) <= 0 &&
893                 !parent_messages_is_fresh[i]) {
894                 toku_ft_leaf_apply_msg(
895                     t->ft->cmp,
896                     t->ft->update_fun,
897                     child,
898                     -1,
899                     *parent_messages[i],
900                     &non_mvcc_gc_info,
901                     NULL,
902                     NULL,
903                     NULL);
904             }
905         }
906         for (i = 0; i < 8; ++i) {
907             BLB(child, i)->stale_ancestor_messages_applied = true;
908         }
909     } else {
910         for (i = 0; i < 8; ++i) {
911             BLB(child, i)->stale_ancestor_messages_applied = false;
912         }
913     }
914 
915     for (i = 0; i < num_parent_messages; ++i) {
916         if (make_leaf_up_to_date &&
917             dummy_cmp(parent_messages[i]->kdbt(), &childkeys[7]) <= 0 &&
918             !parent_messages_is_fresh[i]) {
919             assert(parent_messages_applied[i] == 1);
920         } else {
921             assert(parent_messages_applied[i] == 0);
922         }
923     }
924 
925     FTNODE XMALLOC(parentnode);
926     BLOCKNUM parentblocknum = { 17 };
927     toku_initialize_empty_ftnode(parentnode, parentblocknum, 1, 1, FT_LAYOUT_VERSION, 0);
928     destroy_nonleaf_childinfo(BNC(parentnode, 0));
929     set_BNC(parentnode, 0, parent_bnc);
930     BP_STATE(parentnode, 0) = PT_AVAIL;
931     parentnode->max_msn_applied_to_node_on_disk = max_parent_msn;
932     struct ancestors ancestors = { .node = parentnode, .childnum = 0, .next = NULL };
933     DBT lbe, ubi;
934     toku_init_dbt(&lbe);
935     toku_clone_dbt(&ubi, childkeys[7]);
936     const pivot_bounds bounds(lbe, ubi);
937     bool msgs_applied;
938     toku_apply_ancestors_messages_to_node(t, child, &ancestors, bounds, &msgs_applied, -1);
939 
940     struct checkit_fn {
941         DBT *childkeys;
942         int num_parent_messages;
943         ft_msg **parent_messages;
944         bool *parent_messages_is_fresh;
945         checkit_fn(DBT *ck, int np, ft_msg **pm, bool *pmf) :
946             childkeys(ck), num_parent_messages(np), parent_messages(pm), parent_messages_is_fresh(pmf) {
947         }
948         int operator()(const ft_msg &msg, bool is_fresh) {
949             DBT keydbt;
950             toku_fill_dbt(&keydbt, msg.kdbt()->data, msg.kdbt()->size);
951             MSN msn = msg.msn();
952             if (dummy_cmp(&keydbt, &childkeys[7]) > 0) {
953                 for (int _i = 0; _i < num_parent_messages; ++_i) {
954                     if (dummy_cmp(&keydbt, parent_messages[_i]->kdbt()) == 0 &&
955                             msn.msn == parent_messages[_i]->msn().msn) {
956                         assert(is_fresh == parent_messages_is_fresh[_i]);
957                         break;
958                     }
959                 }
960             } else {
961                 assert(!is_fresh);
962             }
963             return 0;
964         }
965     } checkit(childkeys, num_parent_messages, parent_messages, parent_messages_is_fresh);
966     parent_bnc->msg_buffer.iterate(checkit);
967 
968     toku_ftnode_free(&parentnode);
969 
970     int total_messages = 0;
971     for (i = 0; i < 8; ++i) {
972         total_messages += BLB_DATA(child, i)->num_klpairs();
973     }
974     assert(total_messages <= num_parent_messages + num_child_messages);
975 
976     for (i = 0; i < num_parent_messages; ++i) {
977         if (dummy_cmp(parent_messages[i]->kdbt(), &childkeys[7]) <= 0) {
978             assert(parent_messages_applied[i] == 1);
979         } else {
980             assert(parent_messages_applied[i] == 0);
981         }
982     }
983 
984     toku_xids_destroy(&xids_0);
985     toku_xids_destroy(&xids_123);
986     toku_xids_destroy(&xids_234);
987 
988     for (i = 0; i < num_parent_messages; ++i) {
989         toku_free(parent_messages[i]->kdbt()->data);
990         struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(extra, parent_messages[i]->vdbt()->data);
991         toku_free(extra->new_val.data);
992         toku_free(parent_messages[i]->vdbt()->data);
993         delete parent_messages[i];
994     }
995     for (i = 0; i < num_child_messages; ++i) {
996         toku_free(child_messages[i]);
997         toku_free(key_pointers[i]);
998     }
999     toku_free(ubi.data);
1000     toku_ftnode_free(&child);
1001     toku_free(parent_messages);
1002     toku_free(key_pointers);
1003     toku_free(keylens);
1004     toku_free(child_messages);
1005     toku_free(parent_messages_is_fresh);
1006     toku_free(parent_messages_applied);
1007 }
1008 
1009 // create identical leaf nodes and then buffer flush to one and
1010 // maybe_apply to the other, and compare the results, they should be the
1011 // same.
1012 //
1013 // if make_leaf_up_to_date is true, then apply the messages that are stale
1014 // in the parent to the leaf before doing the flush, otherwise assume the
1015 // leaf was just read off disk
1016 static void
compare_apply_and_flush(FT_HANDLE t,bool make_leaf_up_to_date)1017 compare_apply_and_flush(FT_HANDLE t, bool make_leaf_up_to_date) {
1018     int r;
1019 
1020     ft_msg **MALLOC_N(4096,parent_messages);  // 128k / 32 = 4k
1021     LEAFENTRY* child_messages = NULL;
1022     XMALLOC_N(4096,child_messages);
1023     void** key_pointers = NULL;
1024     XMALLOC_N(4096, key_pointers);
1025     uint32_t* keylens = NULL;
1026     XMALLOC_N(4096, keylens);
1027     bool *MALLOC_N(4096,parent_messages_is_fresh);
1028     memset(parent_messages_is_fresh, 0, 4096*(sizeof parent_messages_is_fresh[0]));
1029     int *MALLOC_N(4096,parent_messages_applied);
1030     memset(parent_messages_applied, 0, 4096*(sizeof parent_messages_applied[0]));
1031 
1032     XIDS xids_0 = toku_xids_get_root_xids();
1033     XIDS xids_123, xids_234;
1034     r = toku_xids_create_child(xids_0, &xids_123, (TXNID)123);
1035     CKERR(r);
1036     r = toku_xids_create_child(xids_0, &xids_234, (TXNID)234);
1037     CKERR(r);
1038 
1039     BASEMENTNODE child1_blbs[8], child2_blbs[8];
1040     DBT child1keys[7], child2keys[7];
1041     int i;
1042     for (i = 0; i < 8; ++i) {
1043         child1_blbs[i] = toku_create_empty_bn();
1044         child2_blbs[i] = toku_create_empty_bn();
1045         if (i < 7) {
1046             toku_init_dbt(&child1keys[i]);
1047             toku_init_dbt(&child2keys[i]);
1048         }
1049     }
1050 
1051     FTNODE XMALLOC(child1), XMALLOC(child2);
1052     BLOCKNUM blocknum = { 42 };
1053     toku_initialize_empty_ftnode(child1, blocknum, 0, 8, FT_LAYOUT_VERSION, 0);
1054     toku_initialize_empty_ftnode(child2, blocknum, 0, 8, FT_LAYOUT_VERSION, 0);
1055     for (i = 0; i < 8; ++i) {
1056         destroy_basement_node(BLB(child1, i));
1057         set_BLB(child1, i, child1_blbs[i]);
1058         BP_STATE(child1, i) = PT_AVAIL;
1059         destroy_basement_node(BLB(child2, i));
1060         set_BLB(child2, i, child2_blbs[i]);
1061         BP_STATE(child2, i) = PT_AVAIL;
1062     }
1063 
1064     int total_size = 0;
1065     for (i = 0; total_size < 128*1024; ++i) {
1066         total_size -= child1_blbs[i%8]->data_buffer.get_memory_size();
1067         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);
1068         total_size += child1_blbs[i%8]->data_buffer.get_memory_size();
1069         if (i % 8 < 7) {
1070             DBT keydbt;
1071             if (child1keys[i%8].size == 0 || dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &child1keys[i%8]) > 0) {
1072                 toku_fill_dbt(&child1keys[i%8], key_pointers[i], keylens[i]);
1073                 toku_fill_dbt(&child2keys[i%8], key_pointers[i], keylens[i]);
1074             }
1075         }
1076     }
1077     int num_child_messages = i;
1078 
1079     for (i = 0; i < num_child_messages; ++i) {
1080         DBT keydbt;
1081         if (i % 8 < 7) {
1082             assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &child1keys[i%8]) <= 0);
1083             assert(dummy_cmp(toku_fill_dbt(&keydbt, key_pointers[i], keylens[i]), &child2keys[i%8]) <= 0);
1084         }
1085     }
1086 
1087     {
1088         int num_stale = random() % 2000;
1089         memset(&parent_messages_is_fresh[num_stale], true, (4096 - num_stale) * (sizeof parent_messages_is_fresh[0]));
1090     }
1091     NONLEAF_CHILDINFO parent_bnc = toku_create_empty_nl();
1092     MSN max_parent_msn = MIN_MSN;
1093     for (i = 0; toku_bnc_memory_used(parent_bnc) < 128*1024; ++i) {
1094         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);
1095     }
1096     int num_parent_messages = i;
1097 
1098     for (i = 0; i < 7; ++i) {
1099         child1->pivotkeys.insert_at(&child1keys[i], i);
1100         child2->pivotkeys.insert_at(&child2keys[i], i);
1101     }
1102 
1103     if (make_leaf_up_to_date) {
1104         for (i = 0; i < num_parent_messages; ++i) {
1105             if (!parent_messages_is_fresh[i]) {
1106                 toku_ft_leaf_apply_msg(
1107                     t->ft->cmp,
1108                     t->ft->update_fun,
1109                     child1,
1110                     -1,
1111                     *parent_messages[i],
1112                     &non_mvcc_gc_info,
1113                     NULL,
1114                     NULL,
1115                     NULL);
1116                 toku_ft_leaf_apply_msg(
1117                     t->ft->cmp,
1118                     t->ft->update_fun,
1119                     child2,
1120                     -1,
1121                     *parent_messages[i],
1122                     &non_mvcc_gc_info,
1123                     NULL,
1124                     NULL,
1125                     NULL);
1126             }
1127         }
1128         for (i = 0; i < 8; ++i) {
1129             BLB(child1, i)->stale_ancestor_messages_applied = true;
1130             BLB(child2, i)->stale_ancestor_messages_applied = true;
1131         }
1132     } else {
1133         for (i = 0; i < 8; ++i) {
1134             BLB(child1, i)->stale_ancestor_messages_applied = false;
1135             BLB(child2, i)->stale_ancestor_messages_applied = false;
1136         }
1137     }
1138 
1139     toku_bnc_flush_to_child(t->ft, parent_bnc, child1, TXNID_NONE);
1140 
1141     FTNODE XMALLOC(parentnode);
1142     BLOCKNUM parentblocknum = { 17 };
1143     toku_initialize_empty_ftnode(parentnode, parentblocknum, 1, 1, FT_LAYOUT_VERSION, 0);
1144     destroy_nonleaf_childinfo(BNC(parentnode, 0));
1145     set_BNC(parentnode, 0, parent_bnc);
1146     BP_STATE(parentnode, 0) = PT_AVAIL;
1147     parentnode->max_msn_applied_to_node_on_disk = max_parent_msn;
1148     struct ancestors ancestors = { .node = parentnode, .childnum = 0, .next = NULL };
1149     bool msgs_applied;
1150     toku_apply_ancestors_messages_to_node(t, child2, &ancestors, pivot_bounds::infinite_bounds(), &msgs_applied, -1);
1151 
1152     struct checkit_fn {
1153         int operator()(const ft_msg &UU(msg), bool is_fresh) {
1154             assert(!is_fresh);
1155             return 0;
1156         }
1157     } checkit;
1158     parent_bnc->msg_buffer.iterate(checkit);
1159     invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size()
1160               == (uint32_t) num_parent_messages);
1161 
1162     toku_ftnode_free(&parentnode);
1163 
1164     for (int j = 0; j < 8; ++j) {
1165         bn_data* first = BLB_DATA(child1, j);
1166         bn_data* second = BLB_DATA(child2, j);
1167         uint32_t len = first->num_klpairs();
1168         assert(len == second->num_klpairs());
1169         for (uint32_t idx = 0; idx < len; ++idx) {
1170             LEAFENTRY le1, le2;
1171             DBT key1dbt, val1dbt, key2dbt, val2dbt;
1172             {
1173                 uint32_t keylen, vallen;
1174                 void *keyp = NULL;
1175                 r = first->fetch_klpair(idx, &le1, &keylen, &keyp);
1176                 assert_zero(r);
1177                 void *valp = le_latest_val_and_len(le1, &vallen);
1178                 toku_fill_dbt(&key1dbt, keyp, keylen);
1179                 toku_fill_dbt(&val1dbt, valp, vallen);
1180             }
1181             {
1182                 uint32_t keylen, vallen;
1183                 void *keyp = NULL;
1184                 r = second->fetch_klpair(idx, &le2, &keylen, &keyp);
1185                 assert_zero(r);
1186                 void *valp = le_latest_val_and_len(le2, &vallen);
1187                 toku_fill_dbt(&key2dbt, keyp, keylen);
1188                 toku_fill_dbt(&val2dbt, valp, vallen);
1189             }
1190             assert(dummy_cmp(&key1dbt, &key2dbt) == 0);
1191             assert(dummy_cmp(&val1dbt, &val2dbt) == 0);
1192         }
1193     }
1194 
1195     toku_xids_destroy(&xids_0);
1196     toku_xids_destroy(&xids_123);
1197     toku_xids_destroy(&xids_234);
1198 
1199     for (i = 0; i < num_parent_messages; ++i) {
1200         toku_free(parent_messages[i]->kdbt()->data);
1201         struct orthopush_flush_update_fun_extra *CAST_FROM_VOIDP(extra, parent_messages[i]->vdbt()->data);
1202         toku_free(extra->new_val.data);
1203         toku_free(parent_messages[i]->vdbt()->data);
1204         delete parent_messages[i];
1205     }
1206     for (i = 0; i < num_child_messages; ++i) {
1207         toku_free(key_pointers[i]);
1208         toku_free(child_messages[i]);
1209     }
1210     toku_ftnode_free(&child1);
1211     toku_ftnode_free(&child2);
1212     toku_free(parent_messages);
1213     toku_free(key_pointers);
1214     toku_free(keylens);
1215     toku_free(child_messages);
1216     toku_free(parent_messages_is_fresh);
1217     toku_free(parent_messages_applied);
1218 }
1219 
1220 static void
parse_args(int argc,const char * argv[])1221 parse_args(int argc, const char *argv[]) {
1222     const char *progname=argv[0];
1223     argc--; argv++;
1224     while (argc>0) {
1225         if (strcmp(argv[0],"-v")==0) {
1226             verbose=1;
1227         } else if (strcmp(argv[0],"-q")==0) {
1228             verbose=0;
1229         } else {
1230             fprintf(stderr, "Usage:\n %s [-v] [-q]\n", progname);
1231             exit(1);
1232         }
1233         argc--; argv++;
1234     }
1235 }
1236 
cmp_fn(DB * db,const DBT * a,const DBT * b)1237 static int cmp_fn(DB *db __attribute__((unused)),
1238                      const DBT *a, const DBT *b) {
1239     int c;
1240     if (a->size > b->size) {
1241         c = memcmp(a->data, b->data, b->size);
1242     } else if (a->size < b->size) {
1243         c = memcmp(a->data, b->data, a->size);
1244     } else {
1245         return memcmp(a->data, b->data, a->size);
1246     }
1247     if (c == 0) {
1248         c = a->size - b->size;
1249     }
1250     return c;
1251 }
1252 
1253 int
test_main(int argc,const char * argv[])1254 test_main (int argc, const char *argv[]) {
1255     parse_args(argc, argv);
1256 
1257     dummy_cmp.create(cmp_fn, nullptr);
1258 
1259     initialize_dummymsn();
1260     int r;
1261     CACHETABLE ct;
1262     toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
1263     unlink(fname);
1264     FT_HANDLE t;
1265     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);
1266     toku_ft_set_update(t, orthopush_flush_update_fun);
1267     // HACK
1268     t->ft->update_fun = orthopush_flush_update_fun;
1269 
1270     for (int i = 0; i < 10; ++i) {
1271         flush_to_internal(t);
1272     }
1273     for (int i = 0; i < 10; ++i) {
1274         flush_to_internal_multiple(t);
1275     }
1276     for (int i = 0; i < 3; ++i) {
1277         flush_to_leaf(t, false, false);
1278         flush_to_leaf(t, false, true);
1279         flush_to_leaf(t, true, false);
1280         flush_to_leaf(t, true, true);
1281     }
1282     for (int i = 0; i < 10; ++i) {
1283         flush_to_leaf_with_keyrange(t, false);
1284         flush_to_leaf_with_keyrange(t, true);
1285         compare_apply_and_flush(t, false);
1286         compare_apply_and_flush(t, true);
1287     }
1288 
1289     r = toku_close_ft_handle_nolsn(t, 0);          assert(r==0);
1290     toku_cachetable_close(&ct);
1291 
1292     dummy_cmp.destroy();
1293 
1294     return 0;
1295 }
1296