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 // generate a tree with a single leaf node containing unsorted keys
40 // check that ft verify finds them
41
42
43 #include <ft-cachetable-wrappers.h>
44 #include "test.h"
45
46 static FTNODE
make_node(FT_HANDLE ft,int height)47 make_node(FT_HANDLE ft, int height) {
48 FTNODE node = NULL;
49 int n_children = (height == 0) ? 1 : 0;
50 toku_create_new_ftnode(ft, &node, height, n_children);
51 if (n_children) BP_STATE(node,0) = PT_AVAIL;
52 return node;
53 }
54
55 static void
append_leaf(FTNODE leafnode,void * key,size_t keylen,void * val,size_t vallen)56 append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen) {
57 assert(leafnode->height == 0);
58
59 DBT thekey;
60 toku_fill_dbt(&thekey, key, keylen);
61 DBT theval;
62 toku_fill_dbt(&theval, val, vallen);
63
64 // get an index that we can use to create a new leaf entry
65 uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
66
67 // apply an insert to the leaf node
68 MSN msn = next_dummymsn();
69 ft_msg msg(&thekey, &theval, FT_INSERT, msn, toku_xids_get_root_xids());
70 txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
71 toku_ft_bn_apply_msg_once(
72 BLB(leafnode, 0),
73 msg,
74 idx,
75 keylen,
76 NULL,
77 &gc_info,
78 NULL,
79 NULL,
80 NULL);
81
82 // don't forget to dirty the node
83 leafnode->set_dirty();
84 }
85
86 static void
populate_leaf(FTNODE leafnode,int k,int v)87 populate_leaf(FTNODE leafnode, int k, int v) {
88 append_leaf(leafnode, &k, sizeof k, &v, sizeof v);
89 }
90
91 static void
test_dup_in_leaf(int do_verify)92 test_dup_in_leaf(int do_verify) {
93 int r;
94
95 // cleanup
96 const char *fname = TOKU_TEST_FILENAME;
97 r = unlink(fname);
98 assert(r == 0 || (r == -1 && errno == ENOENT));
99
100 // create a cachetable
101 CACHETABLE ct = NULL;
102 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
103
104 // create the ft
105 TOKUTXN null_txn = NULL;
106 FT_HANDLE ft = NULL;
107 r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
108 assert(r == 0);
109
110 // discard the old root block
111 FTNODE newroot = make_node(ft, 0);
112 populate_leaf(newroot, htonl(2), 1);
113 populate_leaf(newroot, htonl(1), 2);
114
115 // set the new root to point to the new tree
116 toku_ft_set_new_root_blocknum(ft->ft, newroot->blocknum);
117
118 // unpin the new root
119 toku_unpin_ftnode(ft->ft, newroot);
120
121 if (do_verify) {
122 r = toku_verify_ft(ft);
123 assert(r != 0);
124 }
125
126 // flush to the file system
127 r = toku_close_ft_handle_nolsn(ft, 0);
128 assert(r == 0);
129
130 // shutdown the cachetable
131 toku_cachetable_close(&ct);
132 }
133
134 static int
usage(void)135 usage(void) {
136 return 1;
137 }
138
139 int
test_main(int argc,const char * argv[])140 test_main (int argc , const char *argv[]) {
141 int do_verify = 1;
142 initialize_dummymsn();
143 for (int i = 1; i < argc; i++) {
144 const char *arg = argv[i];
145 if (strcmp(arg, "-v") == 0) {
146 verbose++;
147 continue;
148 }
149 if (strcmp(arg, "-q") == 0) {
150 verbose = 0;
151 continue;
152 }
153 if (strcmp(arg, "--verify") == 0 && i+1 < argc) {
154 do_verify = atoi(argv[++i]);
155 continue;
156 }
157 return usage();
158 }
159 test_dup_in_leaf(do_verify);
160 return 0;
161 }
162