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
40 #define kv_pair_funcs 1 // pull in kv_pair generators from test.h
41
42 #include "test.h"
43 #include "toku_pthread.h"
44 #include <db.h>
45 #include <sys/stat.h>
46 #include "ydb-internal.h"
47
48 #include "test_kv_gen.h"
49
50 /*
51 */
52
53 DB_ENV *env;
54 enum {MAX_NAME=128};
55 int NUM_DBS=5;
56 int NUM_ROWS=100000;
57 int SRC_VERSION = 4;
58 int littlenode = 0;
59 int flat = 0;
60
61 #define OLDDATADIR "../../../../tokudb.data/"
62
63 char *env_dir = TOKU_TEST_FILENAME; // the default env_dir.
64 char *db_v5_dir = "dir.preload-db.c.tdb";
65 char *db_v4_dir = OLDDATADIR "env_preload.4.2.0.cleanshutdown";
66 char *db_v4_dir_node4k = OLDDATADIR "env_preload.4.2.0.node4k.cleanshutdown";
67 char *db_v4_dir_flat = OLDDATADIR "env_preload.4.2.0.flat.cleanshutdown";
68
69 // HACK: Newer versions of the database/ft to use with this old
70 // upgrade test code.
71 char *db_v6_dir = OLDDATADIR "env_preload.5.0.8.cleanshutdown";
72 char *db_v6_dir_node4k = OLDDATADIR "env_preload.5.0.8.node4k.cleanshutdown";
73 char *db_v6_dir_flat = OLDDATADIR "env_preload.5.0.8.flat.cleanshutdown";
74
75 char *db_v7_dir = OLDDATADIR "env_preload.5.2.7.cleanshutdown";
76 char *db_v7_dir_node4k = OLDDATADIR "env_preload.5.2.7.node4k.cleanshutdown";
77 char *db_v7_dir_flat = OLDDATADIR "env_preload.5.2.7.flat.cleanshutdown";
78
79
80 // should put this in test.h:
81 static __attribute__((__unused__)) int
char_dbt_cmp(const DBT * a,const DBT * b)82 char_dbt_cmp (const DBT *a, const DBT *b) {
83 int rval = 0;
84 assert(a && b);
85 if (a->size < b->size) rval = -1;
86 else if (a->size > b->size) rval = 1;
87 else if (a->size) { // if both strings are of size zero, return 0
88 rval = strcmp((char*)a->data, (char*)b->data);
89 }
90 return rval;
91 }
92
93
upgrade_test_1(DB ** dbs)94 static void upgrade_test_1(DB **dbs) {
95 int r;
96 // open the DBS
97 {
98 DBT desc;
99 dbt_init(&desc, "foo", sizeof("foo"));
100 char name[MAX_NAME*2];
101
102 int idx[MAX_DBS];
103 for(int i=0;i<NUM_DBS;i++) {
104 idx[i] = i;
105 r = db_create(&dbs[i], env, 0); CKERR(r);
106 dbs[i]->app_private = &idx[i];
107 snprintf(name, sizeof(name), "db_%04x", i);
108 r = dbs[i]->open(dbs[i], NULL, name, NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r);
109 r = char_dbt_cmp(&desc, &(dbs[i]->descriptor->dbt));
110 CKERR(r); // verify that upgraded descriptor is same as original
111 }
112 }
113
114 // read and verify all rows
115 {
116 if ( verbose ) {printf("checking");fflush(stdout);}
117 check_results(env, dbs, NUM_DBS, NUM_ROWS);
118 if ( verbose) {printf("\ndone\n");fflush(stdout);}
119 }
120 // close
121 {
122 for(int i=0;i<NUM_DBS;i++) {
123 r = dbs[i]->close(dbs[i], 0); CKERR(r);
124 dbs[i] = NULL;
125 }
126 }
127 }
128
setup(void)129 static void setup(void) {
130 int r;
131 int len = 256;
132 char syscmd[len];
133 char * src_db_dir;
134
135 if ( SRC_VERSION == 4 ) {
136 if (flat)
137 src_db_dir = db_v4_dir_flat;
138 else if (littlenode)
139 src_db_dir = db_v4_dir_node4k;
140 else
141 src_db_dir = db_v4_dir;
142 }
143 else if ( SRC_VERSION == 5 ) {
144 src_db_dir = db_v5_dir;
145 }
146 else if (SRC_VERSION == 6) {
147 if (flat) {
148 src_db_dir = db_v6_dir_flat;
149 } else if (littlenode) {
150 src_db_dir = db_v6_dir_node4k;
151 } else {
152 src_db_dir = db_v6_dir;
153 }
154 }
155 else if (SRC_VERSION == 7) {
156 if (flat) {
157 src_db_dir = db_v7_dir_flat;
158 } else if (littlenode) {
159 src_db_dir = db_v7_dir_node4k;
160 } else {
161 src_db_dir = db_v7_dir;
162 }
163 }
164 else {
165 fprintf(stderr, "unsupported PerconaFT version %d to upgrade\n", SRC_VERSION);
166 assert(0);
167 }
168
169 r = snprintf(syscmd, len, "rm -rf %s", env_dir);
170 assert(r<len);
171 r = system(syscmd);
172 CKERR(r);
173
174 r = snprintf(syscmd, len, "cp -r %s %s", src_db_dir, env_dir);
175 assert(r<len);
176 r = system(syscmd);
177 CKERR(r);
178 generate_permute_tables();
179
180 }
181
run_test(void)182 static void run_test(void)
183 {
184 int r;
185 r = db_env_create(&env, 0); CKERR(r);
186 if (littlenode) {
187 r = env->set_cachesize(env, 0, 512*1024, 1); CKERR(r);
188 }
189 r = env->set_redzone(env, 0); CKERR(r);
190 int envflags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE | DB_PRIVATE;
191 r = env->open(env, env_dir, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
192 env->set_errfile(env, stderr);
193 r = env->checkpointing_set_period(env, 1); CKERR(r);
194
195 DB **dbs = (DB**)toku_malloc(sizeof(DB*) * NUM_DBS);
196 assert(dbs != NULL);
197
198 // --------------------------
199 upgrade_test_1(dbs);
200 // --------------------------
201
202 if (verbose >= 2)
203 print_engine_status(env);
204 r = env->close(env, 0); CKERR(r);
205 toku_free(dbs);
206
207 }
208
209 // ------------ infrastructure ----------
210 static void do_args(int argc, char * const argv[]);
211
test_main(int argc,char * const * argv)212 int test_main(int argc, char * const *argv) {
213 do_args(argc, argv);
214 if (SRC_VERSION == 4) {
215 littlenode = 1; // 4k nodes, small cache
216 }
217 setup();
218 run_test(); // read, upgrade, write back to disk
219 run_test(); // read and verify
220 return 0;
221 }
222
do_args(int argc,char * const argv[])223 static void do_args(int argc, char * const argv[]) {
224 int resultcode;
225 char *cmd = argv[0];
226 argc--; argv++;
227
228 while (argc>0) {
229 if (strcmp(argv[0], "-v")==0) {
230 verbose++;
231 } else if (strcmp(argv[0],"-q")==0) {
232 verbose--;
233 if (verbose<0) verbose=0;
234 } else if (strcmp(argv[0], "-h")==0) {
235 resultcode=0;
236 do_usage:
237 fprintf(stderr, "Usage: -h -d <num_dbs> -r <num_rows> %s\n", cmd);
238 exit(resultcode);
239 } else if (strcmp(argv[0], "-d")==0) {
240 argc--; argv++;
241 NUM_DBS = atoi(argv[0]);
242 if ( NUM_DBS > MAX_DBS ) {
243 fprintf(stderr, "max value for -d field is %d\n", MAX_DBS);
244 resultcode=1;
245 goto do_usage;
246 }
247 } else if (strcmp(argv[0], "-r")==0) {
248 argc--; argv++;
249 NUM_ROWS = atoi(argv[0]);
250 } else if (strcmp(argv[0], "-V")==0) {
251 argc--; argv++;
252 SRC_VERSION = atoi(argv[0]);
253 } else if (strcmp(argv[0], "-f")==0) {
254 flat = 1;
255 } else {
256 fprintf(stderr, "Unknown arg: %s\n", argv[0]);
257 resultcode=1;
258 goto do_usage;
259 }
260 argc--;
261 argv++;
262 }
263 }
264