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 static TOKUTXN const null_txn = 0;
42
43 static const char *fname = TOKU_TEST_FILENAME;
44
test_dump_empty_db(void)45 static void test_dump_empty_db (void) {
46 FT_HANDLE t;
47 CACHETABLE ct;
48 int r;
49
50 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
51 unlink(fname);
52 r = toku_open_ft_handle(fname, 1, &t, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
53 assert(r==0);
54 if (verbose) { r=toku_dump_ft(stdout, t); assert(r==0); }
55 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
56 toku_cachetable_close(&ct);
57
58 }
59
60 /* Test running multiple trees in different files */
test_multiple_files_of_size(int size)61 static void test_multiple_files_of_size (int size) {
62 char n0[TOKU_PATH_MAX+1];
63 toku_path_join(n0, 2, TOKU_TEST_FILENAME, "test0.dat");
64 char n1[TOKU_PATH_MAX+1];
65 toku_path_join(n1, 2, TOKU_TEST_FILENAME, "test1.dat");
66 CACHETABLE ct;
67 FT_HANDLE t0,t1;
68 int r,i;
69 if (verbose) printf("test_multiple_files_of_size(%d)\n", size);
70 toku_os_recursive_delete(TOKU_TEST_FILENAME);
71 r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU); assert(r == 0);
72
73 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
74 r = toku_open_ft_handle(n0, 1, &t0, size, size / 4, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
75 r = toku_open_ft_handle(n1, 1, &t1, size, size / 4, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
76 for (i=0; i<10000; i++) {
77 char key[100],val[100];
78 DBT k,v;
79 snprintf(key, 100, "key%d", i);
80 snprintf(val, 100, "val%d", i);
81 toku_ft_insert(t0, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
82 snprintf(val, 100, "Val%d", i);
83 toku_ft_insert(t1, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
84 }
85 //toku_verify_ft(t0);
86 //dump_ft(t0);
87 //dump_ft(t1);
88 r = toku_verify_ft(t0); assert(r==0);
89 r = toku_verify_ft(t1); assert(r==0);
90
91 r = toku_close_ft_handle_nolsn(t0, 0); assert(r==0);
92 r = toku_close_ft_handle_nolsn(t1, 0); assert(r==0);
93 toku_cachetable_close(&ct);
94
95
96 /* Now see if the data is all there. */
97 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
98 r = toku_open_ft_handle(n0, 0, &t0, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
99 if (verbose) printf("%s:%d r=%d\n", __FILE__, __LINE__,r);
100 assert(r==0);
101 r = toku_open_ft_handle(n1, 0, &t1, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
102
103 for (i=0; i<10000; i++) {
104 char key[100],val[100];
105 snprintf(key, 100, "key%d", i);
106 snprintf(val, 100, "val%d", i);
107 ft_lookup_and_check_nodup(t0, key, val);
108 snprintf(val, 100, "Val%d", i);
109 ft_lookup_and_check_nodup(t1, key, val);
110 }
111
112 r = toku_close_ft_handle_nolsn(t0, 0); assert(r==0);
113 r = toku_close_ft_handle_nolsn(t1, 0); assert(r==0);
114 toku_cachetable_close(&ct);
115
116 toku_os_recursive_delete(TOKU_TEST_FILENAME);
117 }
118
test_multiple_files(void)119 static void test_multiple_files (void) {
120 test_multiple_files_of_size (1<<12);
121 test_multiple_files_of_size (1<<20);
122 }
123
124 /* Test to see that a single db can be opened many times. */
test_multiple_ft_handles_one_db_one_file(void)125 static void test_multiple_ft_handles_one_db_one_file (void) {
126 enum { MANYN = 2 };
127 int i, r;
128 CACHETABLE ct;
129 FT_HANDLE trees[MANYN];
130 if (verbose) printf("test_multiple_ft_handles_one_db_one_file:");
131
132 unlink(fname);
133 toku_cachetable_create(&ct, 32, ZERO_LSN, nullptr);
134 for (i=0; i<MANYN; i++) {
135 r = toku_open_ft_handle(fname, (i==0), &trees[i], 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
136 assert(r==0);
137 }
138 for (i=0; i<MANYN; i++) {
139 char k[20], v[20];
140 DBT kb, vb;
141 snprintf(k, 20, "key%d", i);
142 snprintf(v, 20, "val%d", i);
143 toku_ft_insert(trees[i], toku_fill_dbt(&kb, k, strlen(k)+1), toku_fill_dbt(&vb, v, strlen(v)+1), null_txn);
144 }
145 for (i=0; i<MANYN; i++) {
146 char k[20],vexpect[20];
147 snprintf(k, 20, "key%d", i);
148 snprintf(vexpect, 20, "val%d", i);
149 ft_lookup_and_check_nodup(trees[0], k, vexpect);
150 }
151 for (i=0; i<MANYN; i++) {
152 r=toku_close_ft_handle_nolsn(trees[i], 0); assert(r==0);
153 }
154 toku_cachetable_close(&ct);
155
156 if (verbose) printf(" ok\n");
157 }
158
159
160 /* Check to see if data can be read that was written. */
test_read_what_was_written(void)161 static void test_read_what_was_written (void) {
162 CACHETABLE ct;
163 FT_HANDLE ft;
164 int r;
165 const int NVALS=10000;
166
167 if (verbose) {
168 printf("test_read_what_was_written(): "); fflush(stdout);
169 }
170
171 unlink(fname);
172
173 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
174 r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
175 r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
176 toku_cachetable_close(&ct);
177
178 /* Now see if we can read an empty tree in. */
179 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
180 r = toku_open_ft_handle(fname, 0, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
181
182 /* See if we can put something in it. */
183 {
184 DBT k,v;
185 toku_ft_insert(ft, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn);
186 }
187
188 r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
189 toku_cachetable_close(&ct);
190
191 /* Now see if we can read it in and get the value. */
192 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
193 r = toku_open_ft_handle(fname, 0, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
194
195 ft_lookup_and_check_nodup(ft, "hello", "there");
196
197 assert(toku_verify_ft(ft)==0);
198
199 /* Now put a bunch (NVALS) of things in. */
200 {
201 int i;
202 for (i=0; i<NVALS; i++) {
203 char key[100],val[100];
204 DBT k,v;
205 snprintf(key, 100, "key%d", i);
206 snprintf(val, 100, "val%d", i);
207 if (i<600) {
208 int verify_result=toku_verify_ft(ft);;
209 assert(verify_result==0);
210 }
211 toku_ft_insert(ft, toku_fill_dbt(&k, key, strlen(key)+1), toku_fill_dbt(&v, val, strlen(val)+1), null_txn);
212 if (i<600) {
213 int verify_result=toku_verify_ft(ft);
214 if (verify_result) {
215 r = toku_dump_ft(stdout, ft);
216 assert(r==0);
217 assert(0);
218 }
219 {
220 int j;
221 for (j=0; j<=i; j++) {
222 char expectedval[100];
223 snprintf(key, 100, "key%d", j);
224 snprintf(expectedval, 100, "val%d", j);
225 ft_lookup_and_check_nodup(ft, key, expectedval);
226 }
227 }
228 }
229 }
230 }
231 if (verbose) printf("Now read them out\n");
232
233 r = toku_verify_ft(ft);
234 assert(r==0);
235 //dump_ft(ft);
236
237 /* See if we can read them all out again. */
238 {
239 int i;
240 for (i=0; i<NVALS; i++) {
241 char key[100],expectedval[100];
242 snprintf(key, 100, "key%d", i);
243 snprintf(expectedval, 100, "val%d", i);
244 ft_lookup_and_check_nodup(ft, key, expectedval);
245 }
246 }
247
248 r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
249 if (verbose) printf("%s:%d About to close %p\n", __FILE__, __LINE__, ct);
250 toku_cachetable_close(&ct);
251
252
253
254 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
255 r = toku_open_ft_handle(fname, 0, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
256
257 ft_lookup_and_check_nodup(ft, "hello", "there");
258 {
259 int i;
260 for (i=0; i<NVALS; i++) {
261 char key[100],expectedval[100];
262 snprintf(key, 100, "key%d", i);
263 snprintf(expectedval, 100, "val%d", i);
264 ft_lookup_and_check_nodup(ft, key, expectedval);
265 }
266 }
267
268 r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
269 toku_cachetable_close(&ct);
270
271
272
273
274 if (verbose) printf(" ok\n");
275 }
276
277 /* Test c_get(DB_LAST) on an empty tree */
test_cursor_last_empty(void)278 static void test_cursor_last_empty(void) {
279 CACHETABLE ct;
280 FT_HANDLE ft;
281 FT_CURSOR cursor=0;
282 int r;
283 if (verbose) printf("%s", __FUNCTION__);
284 unlink(fname);
285
286 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
287 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
288 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
289 r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
290 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
291 r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
292 {
293 struct check_pair pair = {0,0,0,0,0};
294 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_LAST);
295 assert(pair.call_count==0);
296 assert(r==DB_NOTFOUND);
297 }
298 {
299 struct check_pair pair = {0,0,0,0,0};
300 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_FIRST);
301 assert(pair.call_count==0);
302 assert(r==DB_NOTFOUND);
303 }
304 toku_ft_cursor_close(cursor);
305 r = toku_close_ft_handle_nolsn(ft, 0);
306 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
307 toku_cachetable_close(&ct);
308 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
309
310 }
311
test_cursor_next(void)312 static void test_cursor_next (void) {
313 CACHETABLE ct;
314 FT_HANDLE ft;
315 FT_CURSOR cursor=0;
316 int r;
317 DBT kbt, vbt;
318
319 unlink(fname);
320
321 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
322 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
323 r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
324 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
325 toku_ft_insert(ft, toku_fill_dbt(&kbt, "hello", 6), toku_fill_dbt(&vbt, "there", 6), null_txn);
326 toku_ft_insert(ft, toku_fill_dbt(&kbt, "byebye", 7), toku_fill_dbt(&vbt, "byenow", 7), null_txn);
327 if (verbose) printf("%s:%d calling toku_ft_cursor(...)\n", __FILE__, __LINE__);
328 r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
329 toku_init_dbt(&kbt);
330 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
331 toku_init_dbt(&vbt);
332 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
333
334 if (verbose) printf("%s:%d calling toku_ft_cursor_get(...)\n", __FILE__, __LINE__);
335 {
336 struct check_pair pair = {7, "byebye", 7, "byenow", 0};
337 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
338 if (verbose) printf("%s:%d called toku_ft_cursor_get(...)\n", __FILE__, __LINE__);
339 assert(r==0);
340 assert(pair.call_count==1);
341 }
342
343 {
344 struct check_pair pair = {6, "hello", 6, "there", 0};
345 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
346 assert(r==0);
347 assert(pair.call_count==1);
348 }
349 {
350 struct check_pair pair = {0, 0, 0, 0, 0};
351 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
352 assert(r==DB_NOTFOUND);
353 assert(pair.call_count==0);
354 }
355
356 toku_ft_cursor_close(cursor);
357 r = toku_close_ft_handle_nolsn(ft, 0);
358 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
359 toku_cachetable_close(&ct);
360 //printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
361
362
363 }
364
wrong_compare_fun(DB * UU (desc),const DBT * a,const DBT * b)365 static int wrong_compare_fun(DB* UU(desc), const DBT *a, const DBT *b) {
366 unsigned int i;
367 unsigned char *CAST_FROM_VOIDP(ad, a->data);
368 unsigned char *CAST_FROM_VOIDP(bd, b->data);
369 unsigned int siz=a->size;
370 assert(a->size==b->size);
371 //assert(db==&nonce_db); // make sure the db was passed down correctly
372 for (i=0; i<siz; i++) {
373 if (ad[siz-1-i]<bd[siz-1-i]) return -1;
374 if (ad[siz-1-i]>bd[siz-1-i]) return +1;
375 }
376 return 0;
377
378 }
379
test_wrongendian_compare(int wrong_p,unsigned int N)380 static void test_wrongendian_compare (int wrong_p, unsigned int N) {
381 CACHETABLE ct;
382 FT_HANDLE ft;
383 int r;
384 unsigned int i;
385
386 unlink(fname);
387
388
389 {
390 char a[4]={0,1,0,0};
391 char b[4]={1,0,0,0};
392 DBT at, bt;
393 assert(wrong_compare_fun(NULL, toku_fill_dbt(&at, a, 4), toku_fill_dbt(&bt, b, 4))>0);
394 assert(wrong_compare_fun(NULL, toku_fill_dbt(&at, b, 4), toku_fill_dbt(&bt, a, 4))<0);
395 }
396
397 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
398 //printf("%s:%d WRONG=%d\n", __FILE__, __LINE__, wrong_p);
399
400 if (0) { // ???? Why is this commented out?
401 r = toku_open_ft_handle(fname, 1, &ft, 1<<20, 1<<17, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, wrong_p ? wrong_compare_fun : toku_builtin_compare_fun); assert(r==0);
402 for (i=1; i<257; i+=255) {
403 unsigned char a[4],b[4];
404 b[3] = a[0] = (unsigned char)(i&255);
405 b[2] = a[1] = (unsigned char)((i>>8)&255);
406 b[1] = a[2] = (unsigned char)((i>>16)&255);
407 b[0] = a[3] = (unsigned char)((i>>24)&255);
408 DBT kbt;
409 toku_fill_dbt(&kbt, a, sizeof a);
410 DBT vbt;
411 toku_fill_dbt(&vbt, b, sizeof b);
412 if (verbose)
413 printf("%s:%d insert: %02x%02x%02x%02x -> %02x%02x%02x%02x\n", __FILE__, __LINE__,
414 ((char*)kbt.data)[0], ((char*)kbt.data)[1], ((char*)kbt.data)[2], ((char*)kbt.data)[3],
415 ((char*)vbt.data)[0], ((char*)vbt.data)[1], ((char*)vbt.data)[2], ((char*)vbt.data)[3]);
416 toku_ft_insert(ft, &kbt, &vbt, null_txn);
417 }
418 {
419 FT_CURSOR cursor=0;
420 r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
421
422 for (i=0; i<2; i++) {
423 unsigned char a[4],b[4];
424 struct check_pair pair = {4, &a, 4, &b, 0};
425 b[3] = a[0] = (unsigned char)(i&255);
426 b[2] = a[1] = (unsigned char)((i>>8)&255);
427 b[1] = a[2] = (unsigned char)((i>>16)&255);
428 b[0] = a[3] = (unsigned char)((i>>24)&255);
429 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
430 assert(r==0);
431 assert(pair.call_count==1);
432 }
433
434
435 r = toku_close_ft_handle_nolsn(ft, 0);
436 }
437 }
438
439 {
440 toku_cachetable_verify(ct);
441 r = toku_open_ft_handle(fname, 1, &ft, 1<<20, 1<<17, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, wrong_p ? wrong_compare_fun : toku_builtin_compare_fun); assert(r==0);
442 toku_cachetable_verify(ct);
443
444 for (i=0; i<N; i++) {
445 unsigned char a[4],b[4];
446 b[3] = a[0] = (unsigned char)(i&255);
447 b[2] = a[1] = (unsigned char)((i>>8)&255);
448 b[1] = a[2] = (unsigned char)((i>>16)&255);
449 b[0] = a[3] = (unsigned char)((i>>24)&255);
450 DBT kbt;
451 toku_fill_dbt(&kbt, a, sizeof a);
452 DBT vbt;
453 toku_fill_dbt(&vbt, b, sizeof b);
454 if (0) printf("%s:%d insert: %02x%02x%02x%02x -> %02x%02x%02x%02x\n", __FILE__, __LINE__,
455 ((unsigned char*)kbt.data)[0], ((unsigned char*)kbt.data)[1], ((unsigned char*)kbt.data)[2], ((unsigned char*)kbt.data)[3],
456 ((unsigned char*)vbt.data)[0], ((unsigned char*)vbt.data)[1], ((unsigned char*)vbt.data)[2], ((unsigned char*)vbt.data)[3]);
457 toku_ft_insert(ft, &kbt, &vbt, null_txn);
458 toku_cachetable_verify(ct);
459 }
460 FT_CURSOR cursor=0;
461 r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
462
463 for (i=0; i<N; i++) {
464 unsigned char a[4],b[4];
465 struct check_pair pair = {4, &a, 4, &b, 0};
466 b[3] = a[0] = (unsigned char)(i&255);
467 b[2] = a[1] = (unsigned char)((i>>8)&255);
468 b[1] = a[2] = (unsigned char)((i>>16)&255);
469 b[0] = a[3] = (unsigned char)((i>>24)&255);
470 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
471 assert(r==0);
472 assert(pair.call_count==1);
473 toku_cachetable_verify(ct);
474 }
475 toku_ft_cursor_close(cursor);
476 r = toku_close_ft_handle_nolsn(ft, 0);
477 assert(r==0);
478 }
479 toku_cachetable_close(&ct);
480
481 }
482
test_ft_cursor_keycompare(DB * desc,const DBT * a,const DBT * b)483 static int test_ft_cursor_keycompare(DB *desc __attribute__((unused)), const DBT *a, const DBT *b) {
484 return toku_keycompare(a->data, a->size, b->data, b->size);
485 }
486
test_large_kv(int bsize,int ksize,int vsize)487 static void test_large_kv(int bsize, int ksize, int vsize) {
488 FT_HANDLE t;
489 int r;
490 CACHETABLE ct;
491
492 if (verbose) printf("test_large_kv: %d %d %d\n", bsize, ksize, vsize);
493
494 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
495 unlink(fname);
496 r = toku_open_ft_handle(fname, 1, &t, bsize, bsize / 4, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
497 assert(r==0);
498
499 DBT key, val;
500 char *k, *v;
501 XCALLOC_N(ksize, k);
502 XCALLOC_N(vsize, v);
503 toku_fill_dbt(&key, k, ksize);
504 toku_fill_dbt(&val, v, vsize);
505
506 toku_ft_insert(t, &key, &val, 0);
507
508 toku_free(k);
509 toku_free(v);
510
511 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
512 toku_cachetable_close(&ct);
513 }
514
515 /*
516 * test the key and value limits
517 * the current implementation crashes when kvsize == bsize/2 rather than fails
518 */
test_ft_limits(void)519 static void test_ft_limits(void) {
520 int bsize = 1024;
521 int kvsize = 4;
522 while (kvsize < bsize/2) {
523 test_large_kv(bsize, kvsize, kvsize);
524 kvsize *= 2;
525 }
526 }
527
528 /*
529 * verify that a delete on an empty tree fails
530 */
test_ft_delete_empty(void)531 static void test_ft_delete_empty(void) {
532 if (verbose) printf("test_ft_delete_empty\n");
533
534 FT_HANDLE t;
535 int r;
536 CACHETABLE ct;
537
538 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
539 unlink(fname);
540 r = toku_open_ft_handle(fname, 1, &t, 4096, 1024, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
541 assert(r==0);
542
543 DBT key;
544 int k = toku_htonl(1);
545 toku_fill_dbt(&key, &k, sizeof k);
546 toku_ft_delete(t, &key, null_txn);
547
548 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
549 toku_cachetable_close(&ct);
550 }
551
552 /*
553 * insert n keys, delete all n keys, verify that lookups for all the keys fail,
554 * verify that a cursor walk of the tree finds nothing
555 */
test_ft_delete_present(int n)556 static void test_ft_delete_present(int n) {
557 if (verbose) printf("test_ft_delete_present:%d\n", n);
558
559 FT_HANDLE t;
560 int r;
561 CACHETABLE ct;
562 int i;
563
564 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
565 unlink(fname);
566 r = toku_open_ft_handle(fname, 1, &t, 4096, 1024, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
567 assert(r==0);
568
569 /* insert 0 .. n-1 */
570 for (i=0; i<n; i++) {
571 int k = toku_htonl(i);
572 int v = i;
573 DBT key;
574 toku_fill_dbt(&key, &k, sizeof k);
575 DBT val;
576 toku_fill_dbt(&val, &v, sizeof v);
577 toku_ft_insert(t, &key, &val, 0);
578 }
579
580 /* delete 0 .. n-1 */
581 for (i=0; i<n; i++) {
582 int k = toku_htonl(i);
583 DBT key;
584 toku_fill_dbt(&key, &k, sizeof k);
585 toku_ft_delete(t, &key, null_txn);
586 assert(r == 0);
587 }
588
589 /* lookups should all fail */
590 for (i=0; i<n; i++) {
591 int k = toku_htonl(i);
592 DBT key;
593 toku_fill_dbt(&key, &k, sizeof k);
594 struct check_pair pair = {0, 0, 0, 0, 0};
595 r = toku_ft_lookup(t, &key, lookup_checkf, &pair);
596 assert(r == DB_NOTFOUND);
597 assert(pair.call_count==0);
598 }
599
600 /* cursor should not find anything */
601 FT_CURSOR cursor=0;
602
603 r = toku_ft_cursor(t, &cursor, NULL, false, false);
604 assert(r == 0);
605
606 {
607 struct check_pair pair = {0,0,0,0,0};
608 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_FIRST);
609 assert(r != 0);
610 assert(pair.call_count==0);
611 }
612
613 toku_ft_cursor_close(cursor);
614
615 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
616 toku_cachetable_close(&ct);
617 }
618
test_ft_delete_not_present(int n)619 static void test_ft_delete_not_present(int n) {
620 if (verbose) printf("test_ft_delete_not_present:%d\n", n);
621
622 FT_HANDLE t;
623 int r;
624 CACHETABLE ct;
625 int i;
626
627 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
628 unlink(fname);
629 r = toku_open_ft_handle(fname, 1, &t, 4096, 1024, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
630 assert(r==0);
631
632 DBT key, val;
633 int k, v;
634
635 /* insert 0 .. n-1 */
636 for (i=0; i<n; i++) {
637 k = toku_htonl(i); v = i;
638 toku_fill_dbt(&key, &k, sizeof k);
639 toku_fill_dbt(&val, &v, sizeof v);
640 toku_ft_insert(t, &key, &val, 0);
641 }
642
643 /* delete 0 .. n-1 */
644 for (i=0; i<n; i++) {
645 k = toku_htonl(i);
646 toku_fill_dbt(&key, &k, sizeof k);
647 toku_ft_delete(t, &key, null_txn);
648 assert(r == 0);
649 }
650
651 /* try to delete key n+1 not in the tree */
652 k = toku_htonl(n+1);
653 toku_fill_dbt(&key, &k, sizeof k);
654 toku_ft_delete(t, &key, null_txn);
655 /* the delete may be buffered or may be executed on a leaf node, so the
656 return value depends */
657 if (verbose) printf("toku_ft_delete k=%d %d\n", k, r);
658
659 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
660 toku_cachetable_close(&ct);
661 }
662
test_ft_delete_cursor_first(int n)663 static void test_ft_delete_cursor_first(int n) {
664 if (verbose) printf("test_ft_delete_cursor_first:%d\n", n);
665
666 FT_HANDLE t;
667 int r;
668 CACHETABLE ct;
669 int i;
670
671 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
672 unlink(fname);
673 r = toku_open_ft_handle(fname, 1, &t, 4096, 1024, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
674 assert(r==0);
675
676 /* insert 0 .. n-1 */
677 for (i=0; i<n; i++) {
678 int k = toku_htonl(i);
679 int v = i;
680 DBT key;
681 toku_fill_dbt(&key, &k, sizeof k);
682 DBT val;
683 toku_fill_dbt(&val, &v, sizeof v);
684 toku_ft_insert(t, &key, &val, 0);
685 }
686
687 /* lookups 0 .. n-1 should succeed */
688 for (i=0; i<n; i++) {
689 int k = toku_htonl(i);
690 DBT key;
691 toku_fill_dbt(&key, &k, sizeof k);
692 int k2 = k;
693 int v = i;
694 struct check_pair pair = {sizeof k, &k2, sizeof v, &v, 0};
695 r = toku_ft_lookup(t, &key, lookup_checkf, &pair);
696 assert(r == 0);
697 assert(pair.call_count==1);
698 }
699
700 /* delete 0 .. n-2 */
701 for (i=0; i<n-1; i++) {
702 {
703 int k = toku_htonl(i);
704 DBT key;
705 toku_fill_dbt(&key, &k, sizeof k);
706 toku_ft_delete(t, &key, null_txn);
707 }
708
709 {
710 int k = toku_htonl(i);
711 DBT key;
712 toku_fill_dbt(&key, &k, sizeof k);
713 struct check_pair pair = {0,0,0,0,0};
714 r = toku_ft_lookup(t, &key, lookup_checkf, &pair);
715 assert(r == DB_NOTFOUND);
716 assert(pair.call_count==0);
717 }
718 }
719
720 /* lookup of 0 .. n-2 should all fail */
721 for (i=0; i<n-1; i++) {
722 int k = toku_htonl(i);
723 DBT key;
724 toku_fill_dbt(&key, &k, sizeof k);
725 struct check_pair pair = {0,0,0,0,0};
726 r = toku_ft_lookup(t, &key, lookup_checkf, &pair);
727 assert(r == DB_NOTFOUND);
728 assert(pair.call_count==0);
729 }
730
731 /* cursor should find the last key: n-1 */
732 FT_CURSOR cursor=0;
733
734 r = toku_ft_cursor(t, &cursor, NULL, false, false);
735 assert(r == 0);
736
737 {
738 int kv = toku_htonl(n-1);
739 int vv = n-1;
740 struct check_pair pair = {sizeof kv, &kv, sizeof vv, &vv, 0};
741 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_FIRST);
742 assert(r == 0);
743 assert(pair.call_count==1);
744 }
745
746 toku_ft_cursor_close(cursor);
747
748 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
749 toku_cachetable_close(&ct);
750 }
751
752 /* test for bug: insert message in a nonleaf node, delete removes the
753 insert message, but lookup finds the insert message
754
755 build a 2 level tree, and expect the last insertion to be
756 buffered. then delete and lookup. */
757
test_insert_delete_lookup(int n)758 static void test_insert_delete_lookup(int n) {
759 if (verbose) printf("test_insert_delete_lookup:%d\n", n);
760
761 FT_HANDLE t;
762 int r;
763 CACHETABLE ct;
764 int i;
765
766 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
767 unlink(fname);
768 r = toku_open_ft_handle(fname, 1, &t, 4096, 1024, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
769 assert(r==0);
770
771 /* insert 0 .. n-1 */
772 for (i=0; i<n; i++) {
773 int k = toku_htonl(i);
774 int v = i;
775 DBT key;
776 toku_fill_dbt(&key, &k, sizeof k);
777 DBT val;
778 toku_fill_dbt(&val, &v, sizeof v);
779 toku_ft_insert(t, &key, &val, 0);
780 }
781
782 if (n > 0) {
783 {
784 int k = toku_htonl(n-1);
785 DBT key;
786 toku_fill_dbt(&key, &k, sizeof k);
787 toku_ft_delete(t, &key, null_txn);
788 }
789 {
790 int k = toku_htonl(n-1);
791 DBT key;
792 toku_fill_dbt(&key, &k, sizeof k);
793 struct check_pair pair = {0,0,0,0,0};
794 r = toku_ft_lookup(t, &key, lookup_checkf, &pair);
795 assert(r == DB_NOTFOUND);
796 assert(pair.call_count==0);
797 }
798 }
799
800 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
801 toku_cachetable_close(&ct);
802 }
803
804 /* insert <0,0>, <0,1>, .. <0,n>
805 delete_both <0,i> for all even i
806 verify <0,i> exists for all odd i */
807
808
test_ft_delete(void)809 static void test_ft_delete(void) {
810 test_ft_delete_empty();
811 test_ft_delete_present(1);
812 test_ft_delete_present(100);
813 test_ft_delete_present(500);
814 test_ft_delete_not_present(1);
815 test_ft_delete_not_present(100);
816 test_ft_delete_not_present(500);
817 test_ft_delete_cursor_first(1);
818 test_ft_delete_cursor_first(100);
819 test_ft_delete_cursor_first(500);
820 test_ft_delete_cursor_first(10000);
821 test_insert_delete_lookup(2);
822 test_insert_delete_lookup(512);
823 }
824
test_new_ft_cursor_create_close(void)825 static void test_new_ft_cursor_create_close (void) {
826 int r;
827 FT_HANDLE ft=0;
828 int n = 8;
829 FT_CURSOR cursors[n];
830
831 toku_ft_handle_create(&ft);
832
833 int i;
834 for (i=0; i<n; i++) {
835 r = toku_ft_cursor(ft, &cursors[i], NULL, false, false); assert(r == 0);
836 }
837
838 for (i=0; i<n; i++) {
839 toku_ft_cursor_close(cursors[i]);
840 }
841
842 r = toku_close_ft_handle_nolsn(ft, 0); assert(r == 0);
843 }
844
test_new_ft_cursor_first(int n)845 static void test_new_ft_cursor_first(int n) {
846 if (verbose) printf("test_ft_cursor_first:%d\n", n);
847
848 FT_HANDLE t=0;
849 int r;
850 CACHETABLE ct;
851 int i;
852
853 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
854 unlink(fname);
855 toku_ft_handle_create(&t);
856 toku_ft_handle_set_nodesize(t, 4096);
857 r = toku_ft_handle_open(t, fname, 1, 1, ct, null_txn); assert(r==0);
858
859 DBT key, val;
860 int k, v;
861
862 for (i=0; i<n; i++) {
863 k = toku_htonl(i); v = toku_htonl(i);
864 toku_ft_insert(t, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
865 }
866
867 FT_CURSOR cursor=0;
868
869 r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
870
871 toku_init_dbt(&key); key.flags = DB_DBT_REALLOC;
872 toku_init_dbt(&val); val.flags = DB_DBT_REALLOC;
873
874 for (i=0; ; i++) {
875 int kv = toku_htonl(i);
876 int vv = toku_htonl(i);
877 struct check_pair pair = {sizeof kv, &kv, sizeof vv, &vv, 0};
878 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_FIRST);
879 if (r != 0) {
880 assert(pair.call_count==0);
881 break;
882 }
883 assert(pair.call_count==1);
884
885 r = toku_ft_cursor_delete(cursor, 0, null_txn); assert(r == 0);
886 }
887 assert(i == n);
888
889 if (key.data) toku_free(key.data);
890 if (val.data) toku_free(val.data);
891
892 toku_ft_cursor_close(cursor);
893 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
894 toku_cachetable_close(&ct);
895 }
896
test_new_ft_cursor_last(int n)897 static void test_new_ft_cursor_last(int n) {
898 if (verbose) printf("test_ft_cursor_last:%d\n", n);
899
900 FT_HANDLE t=0;
901 int r;
902 CACHETABLE ct;
903 int i;
904
905 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
906 unlink(fname);
907 toku_ft_handle_create(&t);
908 toku_ft_handle_set_nodesize(t, 4096);
909 r = toku_ft_handle_open(t, fname, 1, 1, ct, null_txn); assert(r==0);
910
911 DBT key, val;
912 int k, v;
913
914 for (i=0; i<n; i++) {
915 k = toku_htonl(i); v = toku_htonl(i);
916 toku_ft_insert(t, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
917 }
918
919 FT_CURSOR cursor=0;
920
921 r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
922
923 toku_init_dbt(&key); key.flags = DB_DBT_REALLOC;
924 toku_init_dbt(&val); val.flags = DB_DBT_REALLOC;
925
926 for (i=n-1; ; i--) {
927 int kk = toku_htonl(i);
928 int vv = toku_htonl(i);
929 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
930 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_LAST);
931 if (r != 0) {
932 assert(pair.call_count==0);
933 break;
934 }
935 assert(pair.call_count==1);
936
937 //if (n==512 && i<=360) { printf("i=%d\n", i); toku_dump_ft(stdout, t); }
938 r = toku_ft_cursor_delete(cursor, 0, null_txn); assert(r == 0);
939 }
940 assert(i == -1);
941
942 if (key.data) toku_free(key.data);
943 if (val.data) toku_free(val.data);
944
945 toku_ft_cursor_close(cursor);
946 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
947 toku_cachetable_close(&ct);
948 }
949
test_new_ft_cursor_next(int n)950 static void test_new_ft_cursor_next(int n) {
951 if (verbose) printf("test_ft_cursor_next:%d\n", n);
952
953 FT_HANDLE t=0;
954 int r;
955 CACHETABLE ct;
956 int i;
957
958 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
959 unlink(fname);
960 toku_ft_handle_create(&t);
961 toku_ft_handle_set_nodesize(t, 4096);
962 r = toku_ft_handle_open(t, fname, 1, 1, ct, null_txn); assert(r==0);
963
964 for (i=0; i<n; i++) {
965 DBT key, val;
966 int k = toku_htonl(i);
967 int v = toku_htonl(i);
968 toku_ft_insert(t, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
969 }
970
971 FT_CURSOR cursor=0;
972
973 r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
974
975 for (i=0; ; i++) {
976 int kk = toku_htonl(i);
977 int vv = toku_htonl(i);
978 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
979 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
980 if (r != 0) {
981 assert(pair.call_count ==0);
982 break;
983 }
984 assert(pair.call_count==1);
985 }
986 assert(i == n);
987
988 toku_ft_cursor_close(cursor);
989 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
990 toku_cachetable_close(&ct);
991 }
992
test_new_ft_cursor_prev(int n)993 static void test_new_ft_cursor_prev(int n) {
994 if (verbose) printf("test_ft_cursor_prev:%d\n", n);
995
996 FT_HANDLE t=0;
997 int r;
998 CACHETABLE ct;
999 int i;
1000
1001 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
1002 unlink(fname);
1003 toku_ft_handle_create(&t);
1004 toku_ft_handle_set_nodesize(t, 4096);
1005 r = toku_ft_handle_open(t, fname, 1, 1, ct, null_txn); assert(r==0);
1006
1007 for (i=0; i<n; i++) {
1008 DBT key, val;
1009 int k = toku_htonl(i);
1010 int v = toku_htonl(i);
1011 toku_ft_insert(t, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
1012 }
1013
1014 FT_CURSOR cursor=0;
1015
1016 r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
1017
1018 for (i=n-1; ; i--) {
1019 int kk = toku_htonl(i);
1020 int vv = toku_htonl(i);
1021 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
1022 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_PREV);
1023 if (r != 0) {
1024 assert(pair.call_count==0);
1025 break;
1026 }
1027 assert(pair.call_count==1);
1028 }
1029 assert(i == -1);
1030
1031 toku_ft_cursor_close(cursor);
1032 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
1033 toku_cachetable_close(&ct);
1034 }
1035
test_new_ft_cursor_current(int n)1036 static void test_new_ft_cursor_current(int n) {
1037 if (verbose) printf("test_ft_cursor_current:%d\n", n);
1038
1039 FT_HANDLE t=0;
1040 int r;
1041 CACHETABLE ct;
1042 int i;
1043
1044 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
1045 unlink(fname);
1046 toku_ft_handle_create(&t);
1047 toku_ft_handle_set_nodesize(t, 4096);
1048 r = toku_ft_handle_open(t, fname, 1, 1, ct, null_txn); assert(r==0);
1049
1050 for (i=0; i<n; i++) {
1051 int k = toku_htonl(i);
1052 int v = toku_htonl(i);
1053 DBT key, val;
1054 toku_ft_insert(t, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
1055 }
1056
1057 FT_CURSOR cursor=0;
1058
1059 r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
1060
1061 for (i=0; ; i++) {
1062 {
1063 int kk = toku_htonl(i);
1064 int vv = toku_htonl(i);
1065 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
1066 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_FIRST);
1067 if (r != 0) {
1068 assert(pair.call_count==0);
1069 break;
1070 }
1071 assert(pair.call_count==1);
1072 }
1073 {
1074 int kk = toku_htonl(i);
1075 int vv = toku_htonl(i);
1076 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
1077 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_CURRENT);
1078 assert(r == 0);
1079 assert(pair.call_count==1);
1080 }
1081
1082 {
1083 int kk = toku_htonl(i);
1084 int vv = toku_htonl(i);
1085 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
1086 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_CURRENT_BINDING);
1087 assert(r == 0);
1088 assert(pair.call_count==1);
1089 }
1090
1091 r = toku_ft_cursor_delete(cursor, 0, null_txn); assert(r == 0);
1092
1093 {
1094 static int count=0;
1095 count++;
1096 struct check_pair pair = {0,0,0,0,0};
1097 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_CURRENT);
1098 CKERR2(r,DB_NOTFOUND); // previous DB_KEYEMPTY
1099 assert(pair.call_count==0);
1100 }
1101
1102 {
1103 int kk = toku_htonl(i);
1104 int vv = toku_htonl(i);
1105 struct check_pair pair = {sizeof kk, &kk, sizeof vv, &vv, 0};
1106 r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_CURRENT_BINDING);
1107 assert(r == 0);
1108 assert(pair.call_count==1);
1109 }
1110 }
1111 assert(i == n);
1112
1113 toku_ft_cursor_close(cursor);
1114 r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
1115 toku_cachetable_close(&ct);
1116 }
1117
test_new_ft_cursor_set_range(int n)1118 static void test_new_ft_cursor_set_range(int n) {
1119 if (verbose) printf("test_ft_cursor_set_range:%d\n", n);
1120
1121 int r;
1122 CACHETABLE ct;
1123 FT_HANDLE ft=0;
1124 FT_CURSOR cursor=0;
1125
1126 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
1127 unlink(fname);
1128 toku_ft_handle_create(&ft);
1129 toku_ft_handle_set_nodesize(ft, 4096);
1130 r = toku_ft_handle_open(ft, fname, 1, 1, ct, null_txn); assert(r==0);
1131
1132 int i;
1133
1134 /* insert keys 0, 10, 20 .. 10*(n-1) */
1135 int max_key = 10*(n-1);
1136 for (i=0; i<n; i++) {
1137 DBT key, val;
1138 int k = toku_htonl(10*i);
1139 int v = 10*i;
1140 toku_ft_insert(ft, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
1141 }
1142
1143 r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
1144
1145 /* pick random keys v in 0 <= v < 10*n, the cursor should point
1146 to the smallest key in the tree that is >= v */
1147 for (i=0; i<n; i++) {
1148
1149 int v = random() % (10*n);
1150 int k = toku_htonl(v);
1151 DBT key;
1152 toku_fill_dbt(&key, &k, sizeof k);
1153
1154 int vv = (((v+9)/10)*10); // This is the value we should actually find.
1155
1156 struct check_pair pair = {sizeof k, NULL, // NULL data means don't check it
1157 sizeof vv, &vv,
1158 0};
1159 r = toku_ft_cursor_get(cursor, &key, lookup_checkf, &pair, DB_SET_RANGE);
1160 if (v > max_key) {
1161 /* there is no smallest key if v > the max key */
1162 assert(r == DB_NOTFOUND);
1163 assert(pair.call_count==0);
1164 } else {
1165 assert(r == 0);
1166 assert(pair.call_count==1);
1167 }
1168 }
1169
1170 toku_ft_cursor_close(cursor);
1171
1172 r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
1173
1174 toku_cachetable_close(&ct);
1175 }
1176
test_new_ft_cursor_set(int n,int cursor_op,DB * db)1177 static void test_new_ft_cursor_set(int n, int cursor_op, DB *db) {
1178 if (verbose) printf("test_ft_cursor_set:%d %d %p\n", n, cursor_op, db);
1179
1180 int r;
1181 CACHETABLE ct;
1182 FT_HANDLE ft;
1183 FT_CURSOR cursor=0;
1184
1185 unlink(fname);
1186
1187 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
1188
1189 r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare); assert(r==0);
1190
1191 int i;
1192
1193 /* insert keys 0, 10, 20 .. 10*(n-1) */
1194 for (i=0; i<n; i++) {
1195 DBT key, val;
1196 int k = toku_htonl(10*i);
1197 int v = 10*i;
1198 toku_ft_insert(ft, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
1199 }
1200
1201 r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
1202
1203 /* set cursor to random keys in set { 0, 10, 20, .. 10*(n-1) } */
1204 for (i=0; i<n; i++) {
1205
1206 int v = 10*(random() % n);
1207 int k = toku_htonl(v);
1208 DBT key;
1209 toku_fill_dbt(&key, &k, sizeof k);
1210 struct check_pair pair = {sizeof k, &k, sizeof v, &v, 0};
1211 r = toku_ft_cursor_get(cursor, &key, lookup_checkf, &pair, cursor_op);
1212 assert(r == 0);
1213 assert(pair.call_count==1);
1214 if (cursor_op == DB_SET) assert(key.data == &k);
1215 }
1216
1217 /* try to set cursor to keys not in the tree, all should fail */
1218 for (i=0; i<10*n; i++) {
1219 if (i % 10 == 0)
1220 continue;
1221 int k = toku_htonl(i);
1222 DBT key;
1223 toku_fill_dbt(&key, &k, sizeof k);
1224 struct check_pair pair = {0,0,0,0,0};
1225 r = toku_ft_cursor_get(cursor, &key, lookup_checkf, &pair, DB_SET);
1226 assert(r == DB_NOTFOUND);
1227 assert(pair.call_count==0);
1228 assert(key.data == &k);
1229 }
1230
1231 toku_ft_cursor_close(cursor);
1232
1233 r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
1234
1235 toku_cachetable_close(&ct);
1236 }
1237
test_new_ft_cursors(void)1238 static void test_new_ft_cursors(void) {
1239 test_new_ft_cursor_create_close();
1240 test_new_ft_cursor_first(8);
1241 test_new_ft_cursor_last(8);
1242 test_new_ft_cursor_last(512);
1243 test_new_ft_cursor_next(8);
1244 test_new_ft_cursor_prev(8);
1245 test_new_ft_cursor_current(8);
1246 test_new_ft_cursor_next(512);
1247 test_new_ft_cursor_set_range(512);
1248 test_new_ft_cursor_set(512, DB_SET, 0);
1249 }
1250
ft_blackbox_test(void)1251 static void ft_blackbox_test (void) {
1252
1253 test_wrongendian_compare(0, 2);
1254 test_wrongendian_compare(1, 2);
1255 test_wrongendian_compare(1, 257);
1256 test_wrongendian_compare(1, 1000);
1257 test_new_ft_cursors();
1258
1259 test_read_what_was_written(); if (verbose) printf("did read_what_was_written\n");
1260 test_cursor_next();
1261 test_cursor_last_empty();
1262 test_multiple_ft_handles_one_db_one_file();
1263 test_dump_empty_db();
1264
1265
1266 if (verbose) printf("test_multiple_files\n");
1267 test_multiple_files();
1268
1269 test_ft_limits();
1270
1271 test_ft_delete();
1272 }
1273
1274 int
test_main(int argc,const char * argv[])1275 test_main (int argc , const char *argv[]) {
1276 default_parse_args(argc, argv);
1277
1278 ft_blackbox_test();
1279 if (verbose) printf("test ok\n");
1280 return 0;
1281 }
1282