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 <unistd.h>
40 #include <stdlib.h>
41 #include <libgen.h>
42 #include <sys/time.h>
43 #include <portability/toku_path.h>
44 #include "test.h"
45
46 #include "ft-flusher.h"
47
48 #include "cachetable/checkpoint.h"
49
50 static TOKUTXN const null_txn = NULL;
51
52 static int
noop_getf(uint32_t UU (keylen),const void * UU (key),uint32_t UU (vallen),const void * UU (val),void * extra,bool UU (lock_only))53 noop_getf(uint32_t UU(keylen), const void *UU(key), uint32_t UU(vallen), const void *UU(val), void *extra, bool UU(lock_only))
54 {
55 int *CAST_FROM_VOIDP(calledp, extra);
56 (*calledp)++;
57 return 0;
58 }
59
60 static int
get_one_value(FT_HANDLE t,CACHETABLE UU (ct),void * UU (extra))61 get_one_value(FT_HANDLE t, CACHETABLE UU(ct), void *UU(extra))
62 {
63 int r;
64 int called;
65 FT_CURSOR cursor;
66
67 r = toku_ft_cursor(t, &cursor, null_txn, false, false);
68 CKERR(r);
69 called = 0;
70 r = toku_ft_cursor_first(cursor, noop_getf, &called);
71 CKERR(r);
72 assert(called == 1);
73 toku_ft_cursor_close(cursor);
74 CKERR(r);
75
76 return 0;
77 }
78
79 static int
progress(void * extra,float fraction)80 progress(void *extra, float fraction)
81 {
82 float *CAST_FROM_VOIDP(stop_at, extra);
83 if (fraction > *stop_at) {
84 return 1;
85 } else {
86 return 0;
87 }
88 }
89
90 static int
do_hot_optimize(FT_HANDLE t,CACHETABLE UU (ct),void * extra)91 do_hot_optimize(FT_HANDLE t, CACHETABLE UU(ct), void *extra)
92 {
93 float *CAST_FROM_VOIDP(fraction, extra);
94 uint64_t loops_run = 0;
95 int r = toku_ft_hot_optimize(t, NULL, NULL, progress, extra, &loops_run);
96 if (*fraction < 1.0) {
97 CKERR2(r, 1);
98 } else {
99 CKERR(r);
100 }
101 return 0;
102 }
103
104 static int
insert_something(FT_HANDLE t,CACHETABLE UU (ct),void * UU (extra))105 insert_something(FT_HANDLE t, CACHETABLE UU(ct), void *UU(extra))
106 {
107 assert(t);
108 unsigned int dummy_value = 1U << 31;
109 DBT key;
110 DBT val;
111 toku_fill_dbt(&key, &dummy_value, sizeof(unsigned int));
112 toku_fill_dbt(&val, &dummy_value, sizeof(unsigned int));
113 toku_ft_insert (t, &key, &val, 0);
114 return 0;
115 }
116
117 typedef int (*tree_cb)(FT_HANDLE t, CACHETABLE ct, void *extra);
118
119 static int
with_open_tree(const char * fname,tree_cb cb,void * cb_extra)120 with_open_tree(const char *fname, tree_cb cb, void *cb_extra)
121 {
122 int r, r2;
123 FT_HANDLE t;
124 CACHETABLE ct;
125
126 toku_cachetable_create(&ct, 16*(1<<20), ZERO_LSN, nullptr);
127 r = toku_open_ft_handle(fname,
128 0,
129 &t,
130 4*(1<<20),
131 128*(1<<10),
132 TOKU_DEFAULT_COMPRESSION_METHOD,
133 ct,
134 null_txn,
135 toku_builtin_compare_fun
136 );
137 CKERR(r);
138
139 r2 = cb(t, ct, cb_extra);
140 r = toku_verify_ft(t);
141 CKERR(r);
142 CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
143 r = toku_checkpoint(cp, NULL, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT);
144 CKERR(r);
145 r = toku_close_ft_handle_nolsn(t, 0);
146 CKERR(r);
147 toku_cachetable_close(&ct);
148
149 return r2;
150 }
151
152 #define TMPFTFMT "%s-tmpdata.ft"
153 static const char *origft_6_0 = "upgrade_test_data.ft.6.0.gz";
154 static const char *origft_5_0 = "upgrade_test_data.ft.5.0.gz";
155 static const char *origft_4_2 = "upgrade_test_data.ft.4.2.gz";
156 static const char *not_flat_4_2 = "upgrade_test_data.ft.4.2.not.flat.gz";
157
158 static int
run_test(const char * prog,const char * origft)159 run_test(const char *prog, const char *origft) {
160 int r;
161
162 char *fullprog = toku_strdup(__FILE__);
163 char *progdir = dirname(fullprog);
164
165 size_t templen = strlen(progdir) + strlen(prog) + strlen(TMPFTFMT) - 1;
166 char tempft[templen + 1];
167 snprintf(tempft, templen + 1, TMPFTFMT, prog);
168 toku_free(fullprog);
169 {
170 char origbuf[TOKU_PATH_MAX + 1];
171 char *datadir = getenv("TOKUDB_DATA");
172 toku_path_join(origbuf, 2, datadir, origft);
173 size_t len = 13 + strlen(origbuf) + strlen(tempft);
174 char buf[len + 1];
175 snprintf(buf, len + 1, "gunzip -c %s > %s", origbuf, tempft);
176 r = system(buf);
177 CKERR(r);
178 }
179
180 r = with_open_tree(tempft, get_one_value, NULL);
181 CKERR(r);
182 r = with_open_tree(tempft, insert_something, NULL);
183 CKERR(r);
184 float fraction = 0.5;
185 r = with_open_tree(tempft, do_hot_optimize, &fraction);
186 CKERR(r);
187 fraction = 1.0;
188 r = with_open_tree(tempft, do_hot_optimize, &fraction);
189 CKERR(r);
190 r = unlink(tempft);
191 CKERR(r);
192
193 return r;
194 }
195
196 int
test_main(int argc,const char * argv[])197 test_main(int argc __attribute__((__unused__)), const char *argv[])
198 {
199 int r;
200
201 r = run_test(argv[0], origft_6_0);
202 CKERR(r);
203 r = run_test(argv[0], origft_5_0);
204 CKERR(r);
205 r = run_test(argv[0], origft_4_2);
206 CKERR(r);
207
208 r = run_test(argv[0], not_flat_4_2);
209 CKERR(r);
210
211 return r;
212 }
213