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 #define kv_pair_funcs 1 // pull in kv_pair generators from test.h
40 
41 #include "test.h"
42 #include "toku_pthread.h"
43 #include <db.h>
44 #include <sys/stat.h>
45 #include "ydb-internal.h"
46 
47 #include "test_kv_gen.h"
48 /*
49  */
50 
51 DB_ENV *env;
52 enum {MAX_NAME=128};
53 enum {ROWS_PER_TRANSACTION=10000};
54 int NUM_DBS=5;
55 int NUM_ROWS=100000;
56 int CHECK_RESULTS=0;
57 int optimize=0;
58 int littlenode = 0;
59 enum { old_default_cachesize=1024 }; // MB
60 int CACHESIZE=old_default_cachesize;
61 int ALLOW_DUPS=0;
62 
63 static struct timeval starttime;
UU()64 static double UU() elapsed_time (void) {
65     struct timeval now;
66     gettimeofday(&now, NULL);
67     return now.tv_sec - starttime.tv_sec + 1e-6*(now.tv_usec - starttime.tv_usec);
68 }
69 
preload_dbs(DB ** dbs)70 static void preload_dbs(DB **dbs)
71 {
72     gettimeofday(&starttime, NULL);
73     int r;
74     DB_TXN    *txn;
75 
76     DBT skey, sval;
77     DBT key, val;
78     dbt_init_realloc(&key);
79     dbt_init_realloc(&val);
80     unsigned int k, v;
81     if ( verbose ) { printf("loading");fflush(stdout); }
82     int outer_loop_num = ( NUM_ROWS <= ROWS_PER_TRANSACTION ) ? 1 : (NUM_ROWS / ROWS_PER_TRANSACTION);
83     for(int x=0;x<outer_loop_num;x++) {
84         r = env->txn_begin(env, NULL, &txn, 0);                                                              CKERR(r);
85         for(int i=1;i<=ROWS_PER_TRANSACTION;i++) {
86             k = i + (x*ROWS_PER_TRANSACTION);
87             v = generate_val(k, 0);
88             dbt_init(&skey, &k, sizeof(unsigned int));
89             dbt_init(&sval, &v, sizeof(unsigned int));
90 
91             for(int db = 0;db < NUM_DBS;db++) {
92                 put_multiple_generate(dbs[db], // dest_db
93                                       NULL, // src_db, ignored
94                                       &key, &val, // dest_key, dest_val
95                                       &skey, &sval, // src_key, src_val
96                                       NULL); // extra, ignored
97 
98                 r = dbs[db]->put(dbs[db], txn, &key, &val, 0);                                               CKERR(r);
99                 if (key.flags == 0) { dbt_init_realloc(&key); }
100                 if (val.flags == 0) { dbt_init_realloc(&val); }
101             }
102         }
103         r = txn->commit(txn, 0);                                                                             CKERR(r);
104         if ( verbose ) {printf(".");fflush(stdout);}
105     }
106     if ( key.flags ) { toku_free(key.data); key.data = NULL; }
107     if ( val.flags ) { toku_free(val.data); key.data = NULL; }
108 
109     if (optimize) {
110         if (verbose) { printf("\noptimizing");fflush(stdout);}
111         do_hot_optimize_on_dbs(env, dbs, NUM_DBS);
112     }
113 
114     if ( CHECK_RESULTS) {
115         if ( verbose ) {printf("\nchecking");fflush(stdout);}
116         check_results(env, dbs, NUM_DBS, NUM_ROWS);
117     }
118     if ( verbose) {printf("\ndone\n");fflush(stdout);}
119 }
120 
121 
122 char *free_me = NULL;
123 const char *env_dir = TOKU_TEST_FILENAME; // the default env_dir.
124 
run_test(void)125 static void run_test(void)
126 {
127     int r;
128     {
129 	int len = strlen(env_dir) + 20;
130 	char syscmd[len];
131 	r = snprintf(syscmd, len, "rm -rf %s", env_dir);
132 	assert(r<len);
133 	r = system(syscmd);                                                                                   CKERR(r);
134     }
135     r = toku_os_mkdir(env_dir, S_IRWXU+S_IRWXG+S_IRWXO);                                                      CKERR(r);
136 
137     r = db_env_create(&env, 0);                                                                               CKERR(r);
138 //    r = env->set_default_bt_compare(env, uint_dbt_cmp);                                                       CKERR(r);
139 //    r = env->set_default_dup_compare(env, uint_dbt_cmp);                                                      CKERR(r);
140 //    if ( verbose ) printf("CACHESIZE = %d MB\n", CACHESIZE);
141 //    r = env->set_cachesize(env, CACHESIZE / 1024, (CACHESIZE % 1024)*1024*1024, 1);                           CKERR(r);
142 //    CKERR(r);
143     int envflags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE | DB_PRIVATE;
144     r = env->open(env, env_dir, envflags, S_IRWXU+S_IRWXG+S_IRWXO);                                            CKERR(r);
145     env->set_errfile(env, stderr);
146     r = env->checkpointing_set_period(env, 0);                                                                CKERR(r);
147 
148     DBT desc;
149     dbt_init(&desc, "foo", sizeof("foo"));
150     char name[MAX_NAME*2];
151 
152     DB **dbs = (DB**)toku_malloc(sizeof(DB*) * NUM_DBS);
153     assert(dbs != NULL);
154     int idx[MAX_DBS];
155     for(int i=0;i<NUM_DBS;i++) {
156         idx[i] = i;
157         r = db_create(&dbs[i], env, 0);                                                                       CKERR(r);
158 	if (littlenode) {
159 	    r=dbs[i]->set_pagesize(dbs[i], 4096);
160 	    CKERR(0);
161 	}
162         dbs[i]->app_private = &idx[i];
163         snprintf(name, sizeof(name), "db_%04x", i);
164         r = dbs[i]->open(dbs[i], NULL, name, NULL, DB_BTREE, DB_CREATE, 0666);                                CKERR(r);
165         IN_TXN_COMMIT(env, NULL, txn_desc, 0, {
166                 { int chk_r = dbs[i]->change_descriptor(dbs[i], txn_desc, &desc, 0); CKERR(chk_r); }
167         });
168     }
169 
170     generate_permute_tables();
171 
172     // -------------------------- //
173     preload_dbs(dbs);
174     // -------------------------- //
175 
176     for(int i=0;i<NUM_DBS;i++) {
177         r = dbs[i]->close(dbs[i], 0);                                                                         CKERR(r);
178         dbs[i] = NULL;
179     }
180 
181     if (verbose >= 2)
182 	print_engine_status(env);
183     r = env->close(env, 0);                                                                                   CKERR(r);
184     toku_free(dbs);
185 
186     /*********** DO NOT TRIM LOGFILES: Trimming logfiles defeats purpose of upgrade tests which must handle untrimmed logfiles.
187     // reopen, then close environment to trim logfiles
188     r = db_env_create(&env, 0);                                                                               CKERR(r);
189     r = env->open(env, env_dir, envflags, S_IRWXU+S_IRWXG+S_IRWXO);                                           CKERR(r);
190     r = env->close(env, 0);                                                                                   CKERR(r);
191     ***********/
192 
193 }
194 
195 // ------------ infrastructure ----------
196 static void do_args(int argc, char * const argv[]);
197 
test_main(int argc,char * const argv[])198 int test_main(int argc, char * const argv[]) {
199     do_args(argc, argv);
200     run_test();
201     if (free_me) toku_free(free_me);
202     return 0;
203 }
204 
do_args(int argc,char * const argv[])205 static void do_args(int argc, char * const argv[]) {
206     int resultcode;
207     char *cmd = argv[0];
208     argc--; argv++;
209 
210     while (argc>0) {
211 	if (strcmp(argv[0], "-v")==0) {
212 	    verbose++;
213 	} else if (strcmp(argv[0],"-q")==0) {
214 	    verbose--;
215 	    if (verbose<0) verbose=0;
216         } else if (strcmp(argv[0], "-h")==0) {
217 	    resultcode=0;
218 	do_usage:
219 	    fprintf(stderr, "Usage: -h -c -n -d <num_dbs> -r <num_rows> %s\n", cmd);
220 	    exit(resultcode);
221         } else if (strcmp(argv[0], "-d")==0) {
222             argc--; argv++;
223             NUM_DBS = atoi(argv[0]);
224             if ( NUM_DBS > MAX_DBS ) {
225                 fprintf(stderr, "max value for -d field is %d\n", MAX_DBS);
226                 resultcode=1;
227                 goto do_usage;
228             }
229         } else if (strcmp(argv[0], "-r")==0) {
230             argc--; argv++;
231             NUM_ROWS = atoi(argv[0]);
232         } else if (strcmp(argv[0], "-c")==0) {
233             CHECK_RESULTS = 1;
234         } else if (strcmp(argv[0], "-n")==0) {
235             littlenode = 1;
236         } else if (strcmp(argv[0], "-o")==0) {
237             optimize = 1;
238 	} else {
239 	    fprintf(stderr, "Unknown arg: %s\n", argv[0]);
240 	    resultcode=1;
241 	    goto do_usage;
242 	}
243 	argc--;
244 	argv++;
245     }
246 }
247