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 /* The goal of this test.  Make sure that inserts stay behind deletes. */
40 
41 
42 #include "test.h"
43 
44 #include <ft-cachetable-wrappers.h>
45 #include "ft-flusher.h"
46 #include "cachetable/checkpoint.h"
47 
48 static TOKUTXN const null_txn = 0;
49 
50 enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
51 
52 CACHETABLE ct;
53 FT_HANDLE ft;
54 const char *fname = TOKU_TEST_FILENAME;
55 
update_func(DB * UU (db),const DBT * key,const DBT * old_val,const DBT * UU (extra),void (* set_val)(const DBT * new_val,void * set_extra),void * set_extra)56 static int update_func(
57     DB* UU(db),
58     const DBT* key,
59     const DBT* old_val,
60     const DBT* UU(extra),
61     void (*set_val)(const DBT *new_val, void *set_extra),
62     void *set_extra)
63 {
64     DBT new_val;
65     assert(old_val->size > 0);
66     if (verbose) {
67         printf("applying update to %s\n", (char *)key->data);
68     }
69     toku_init_dbt(&new_val);
70     set_val(&new_val, set_extra);
71     return 0;
72 }
73 
74 
75 static void
doit(void)76 doit (void) {
77     BLOCKNUM node_leaf[2];
78     BLOCKNUM node_internal, node_root;
79 
80     int r;
81 
82     toku_cachetable_create(&ct, 500*1024*1024, ZERO_LSN, nullptr);
83     unlink(fname);
84     r = toku_open_ft_handle(fname, 1, &ft, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
85     assert(r==0);
86 
87     ft->options.update_fun = update_func;
88     ft->ft->update_fun = update_func;
89 
90     toku_testsetup_initialize();  // must precede any other toku_testsetup calls
91 
92     r = toku_testsetup_leaf(ft, &node_leaf[0], 1, NULL, NULL);
93     assert(r==0);
94     r = toku_testsetup_leaf(ft, &node_leaf[1], 1, NULL, NULL);
95     assert(r==0);
96 
97     char* pivots[1];
98     pivots[0] = toku_strdup("kkkkk");
99     int pivot_len = 6;
100 
101     r = toku_testsetup_nonleaf(ft, 1, &node_internal, 2, node_leaf, pivots, &pivot_len);
102     assert(r==0);
103 
104     r = toku_testsetup_nonleaf(ft, 2, &node_root, 1, &node_internal, 0, 0);
105     assert(r==0);
106 
107     r = toku_testsetup_root(ft, node_root);
108     assert(r==0);
109 
110     //
111     // at this point we have created a tree with a root, an internal node,
112     // and two leaf nodes, the pivot being "kkkkk"
113     //
114 
115     // now we insert a row into each leaf node
116     r = toku_testsetup_insert_to_leaf (
117         ft,
118         node_leaf[0],
119         "a", // key
120         2, // keylen
121         "aa",
122         3
123         );
124     assert(r==0);
125     r = toku_testsetup_insert_to_leaf (
126         ft,
127         node_leaf[1],
128         "z", // key
129         2, // keylen
130         "zz",
131         3
132         );
133     assert(r==0);
134 
135     //
136     // now insert a bunch of dummy delete messages
137     // into the internal node, to get its cachepressure size up
138     //
139     for (int i = 0; i < 100000; i++) {
140         r = toku_testsetup_insert_to_nonleaf (
141             ft,
142             node_internal,
143             FT_DELETE_ANY,
144             "jj", // this key does not exist, so its message application should be a no-op
145             3,
146             NULL,
147             0
148             );
149         assert(r==0);
150     }
151 
152     //
153     // now insert a broadcast message into the root
154     //
155     r = toku_testsetup_insert_to_nonleaf (
156         ft,
157         node_root,
158         FT_UPDATE_BROADCAST_ALL,
159         NULL,
160         0,
161         NULL,
162         0
163         );
164     assert(r==0);
165 
166     //
167     // now let us induce a clean on the internal node
168     //
169     FTNODE node;
170     toku_pin_node_with_min_bfe(&node, node_leaf[1], ft);
171     // hack to get merge going
172     BLB_SEQINSERT(node, node->n_children-1) = false;
173     toku_unpin_ftnode(ft->ft, node);
174 
175     // now do a lookup on one of the keys, this should bring a leaf node up to date
176     DBT k;
177     struct check_pair pair = {2, "a", 0, NULL, 0};
178     r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
179     assert(r==0);
180 
181     ftnode_fetch_extra bfe;
182     bfe.create_for_min_read(ft->ft);
183     toku_pin_ftnode(
184         ft->ft,
185         node_internal,
186         toku_cachetable_hash(ft->ft->cf, node_internal),
187         &bfe,
188         PL_WRITE_EXPENSIVE,
189         &node,
190         true
191         );
192     assert(node->n_children == 2);
193     // we expect that this flushes its buffer, that
194     // a merge is not done, and that the lookup
195     // of values "a" and "z" still works
196     r = toku_ftnode_cleaner_callback(
197         node,
198         node_internal,
199         toku_cachetable_hash(ft->ft->cf, node_internal),
200         ft->ft
201         );
202 
203     // verify that node_internal's buffer is empty
204     bfe.create_for_min_read(ft->ft);
205     toku_pin_ftnode(
206         ft->ft,
207         node_internal,
208         toku_cachetable_hash(ft->ft->cf, node_internal),
209         &bfe,
210         PL_WRITE_EXPENSIVE,
211         &node,
212         true
213         );
214     // check that merge happened
215     assert(node->n_children == 1);
216     // check that buffers are empty
217     assert(toku_bnc_nbytesinbuf(BNC(node, 0)) == 0);
218     toku_unpin_ftnode(ft->ft, node);
219 
220     //
221     // now run a checkpoint to get everything clean,
222     // and to get the rebalancing to happen
223     //
224     CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
225     r = toku_checkpoint(cp, NULL, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT);
226     assert_zero(r);
227 
228     // check that lookups on the two keys is still good
229     struct check_pair pair1 = {2, "a", 0, NULL, 0};
230     r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
231     assert(r==0);
232     struct check_pair pair2 = {2, "z", 0, NULL, 0};
233     r = toku_ft_lookup(ft, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
234     assert(r==0);
235 
236 
237     r = toku_close_ft_handle_nolsn(ft, 0);    assert(r==0);
238     toku_cachetable_close(&ct);
239 
240     toku_free(pivots[0]);
241 }
242 
243 int
test_main(int argc,const char * argv[])244 test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
245     default_parse_args(argc, argv);
246     doit();
247     return 0;
248 }
249