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