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 "ft-flusher-internal.h"
47 #include "cachetable/checkpoint.h"
48 
49 static TOKUTXN const null_txn = 0;
50 
51 enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
52 
53 static void
doit(void)54 doit (void) {
55     BLOCKNUM node_leaf[3];
56     BLOCKNUM node_root;
57 
58     CACHETABLE ct;
59     FT_HANDLE t;
60 
61     int r;
62 
63     toku_cachetable_create(&ct, 500*1024*1024, ZERO_LSN, nullptr);
64     unlink(TOKU_TEST_FILENAME);
65     r = toku_open_ft_handle(TOKU_TEST_FILENAME, 1, &t, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
66     assert(r==0);
67 
68     toku_testsetup_initialize();  // must precede any other toku_testsetup calls
69 
70     r = toku_testsetup_leaf(t, &node_leaf[0], 1, NULL, NULL);
71     assert(r==0);
72     r = toku_testsetup_leaf(t, &node_leaf[1], 1, NULL, NULL);
73     assert(r==0);
74     r = toku_testsetup_leaf(t, &node_leaf[2], 1, NULL, NULL);
75     assert(r==0);
76 
77     int keylens[2];
78     keylens[0] = 2;
79     keylens[1] = 2;
80     char first[2];
81     first[0] = 'f';
82     first[1] = 0;
83     char second[2];
84     second[0] = 'p';
85     second[1] = 0;
86 
87     char* keys[2];
88     keys[0] = first;
89     keys[1] = second;
90     r = toku_testsetup_nonleaf(t, 1, &node_root, 3, node_leaf, keys, keylens);
91     assert(r==0);
92 
93     r = toku_testsetup_root(t, node_root);
94     assert(r==0);
95 
96 
97     r = toku_testsetup_insert_to_nonleaf(
98         t,
99         node_root,
100         FT_INSERT,
101         "a",
102         2,
103         NULL,
104         0
105         );
106     r = toku_testsetup_insert_to_nonleaf(
107         t,
108         node_root,
109         FT_INSERT,
110         "m",
111         2,
112         NULL,
113         0
114         );
115 
116     r = toku_testsetup_insert_to_nonleaf(
117         t,
118         node_root,
119         FT_INSERT,
120         "z",
121         2,
122         NULL,
123         0
124         );
125 
126 
127     // at this point, we have inserted three messages into
128     // the root, one in each buffer, let's verify this.
129 
130     FTNODE node = NULL;
131     ftnode_fetch_extra bfe;
132     bfe.create_for_min_read(t->ft);
133     toku_pin_ftnode(
134         t->ft,
135         node_root,
136         toku_cachetable_hash(t->ft->cf, node_root),
137         &bfe,
138         PL_WRITE_EXPENSIVE,
139         &node,
140         true
141         );
142     assert(node->height == 1);
143     assert(node->n_children == 3);
144     assert(toku_bnc_nbytesinbuf(BNC(node, 0)) > 0);
145     assert(toku_bnc_nbytesinbuf(BNC(node, 1)) > 0);
146     assert(toku_bnc_nbytesinbuf(BNC(node, 2)) > 0);
147     toku_unpin_ftnode(t->ft, node);
148 
149     // now let's run a hot optimize, that should only flush the middle buffer
150     DBT left;
151     toku_fill_dbt(&left, "g", 2);
152     DBT right;
153     toku_fill_dbt(&right, "n", 2);
154     uint64_t loops_run = 0;
155     r = toku_ft_hot_optimize(t, &left, &right, NULL, NULL, &loops_run);
156     assert(r==0);
157 
158     // at this point, we have should have flushed
159     // only the middle buffer, let's verify this.
160     node = NULL;
161     bfe.create_for_min_read(t->ft);
162     toku_pin_ftnode(
163         t->ft,
164         node_root,
165         toku_cachetable_hash(t->ft->cf, node_root),
166         &bfe,
167         PL_WRITE_EXPENSIVE,
168         &node,
169         true
170         );
171     assert(node->height == 1);
172     assert(node->n_children == 3);
173     assert(toku_bnc_nbytesinbuf(BNC(node, 0)) > 0);
174     assert(toku_bnc_nbytesinbuf(BNC(node, 1)) == 0);
175     assert(toku_bnc_nbytesinbuf(BNC(node, 2)) > 0);
176     toku_unpin_ftnode(t->ft, node);
177 
178     r = toku_close_ft_handle_nolsn(t, 0);    assert(r==0);
179     toku_cachetable_close(&ct);
180 }
181 
182 int
test_main(int argc,const char * argv[])183 test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
184     default_parse_args(argc, argv);
185     doit();
186     return 0;
187 }
188