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