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