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