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 "test.h"
40 #include "toku_pthread.h"
41 #include <db.h>
42 #include <sys/stat.h>
43 
44 DB_ENV *env;
45 enum {NUM_DBS=1};
46 enum {NUM_KV_PAIRS=3};
47 struct kv_pair {
48     int64_t key;
49     int64_t val;
50 };
51 struct kv_pair kv_pairs[NUM_KV_PAIRS] = {{1,4},
52                                          {2,5},
53                                          {3,6}};
54 
put_multiple_generate(DB * dest_db,DB * src_db,DBT_ARRAY * dest_keys,DBT_ARRAY * dest_vals,const DBT * src_key,const DBT * src_val)55 static int put_multiple_generate(DB *dest_db, DB *src_db, DBT_ARRAY *dest_keys, DBT_ARRAY *dest_vals, const DBT *src_key, const DBT *src_val) {
56     toku_dbt_array_resize(dest_keys, 1);
57     toku_dbt_array_resize(dest_vals, 1);
58     DBT *dest_key = &dest_keys->dbts[0];
59     DBT *dest_val = &dest_vals->dbts[0];
60     dest_key->flags = 0;
61     dest_val->flags = 0;
62 
63     (void) src_db;
64 
65     uint32_t which = (uint32_t) (intptr_t) dest_db->app_private;
66 
67     if (which == NUM_DBS) {
68 	// primary
69 	dbt_init(dest_key, src_key->data, src_key->size);
70 	dbt_init(dest_val, src_val->data, src_val->size);
71     } else {
72 	// secondaries: switch the key and val
73 	dbt_init(dest_key, src_val->data, src_val->size);
74 	dbt_init(dest_val, src_key->data, src_key->size);
75     }
76 
77 //    printf("dest_key.data = %d\n", *(int*)dest_key->data);
78 //    printf("dest_val.data = %d\n", *(int*)dest_val->data);
79 
80     return 0;
81 }
82 
poll_print(void * extra,float progress)83 static int poll_print(void *extra, float progress) {
84     (void) progress;
85     (void) extra;
86     if ( verbose ) printf("poll_print %f\n", progress);
87     return 0;
88 }
89 
90 const char *src_name="src.db";
91 
run_test(void)92 static void run_test(void)
93 {
94     int r;
95     toku_os_recursive_delete(TOKU_TEST_FILENAME);
96     r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);                          CKERR(r);
97     char logname[TOKU_PATH_MAX+1];
98     r = toku_os_mkdir(toku_path_join(logname, 2, TOKU_TEST_FILENAME, "log"), S_IRWXU+S_IRWXG+S_IRWXO);                   CKERR(r);
99 
100     r = db_env_create(&env, 0);                                                  CKERR(r);
101     r = env->set_lg_dir(env, "log");                                             CKERR(r);
102     r = env->set_default_bt_compare(env, int64_dbt_cmp);                         CKERR(r);
103     r = env->set_generate_row_callback_for_put(env, put_multiple_generate);      CKERR(r);
104     int envflags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE | DB_PRIVATE | DB_INIT_LOG;
105     r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO);               CKERR(r);
106     env->set_errfile(env, stderr);
107     //Disable auto-checkpointing
108     r = env->checkpointing_set_period(env, 0);                                   CKERR(r);
109 
110     DB *src_db = NULL;
111     r = db_create(&src_db, env, 0);                                                             CKERR(r);
112     r = src_db->open(src_db, NULL, src_name, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666);   CKERR(r);
113     src_db->app_private = (void *) NUM_DBS;
114 
115     DB_TXN *txn;
116     r = env->txn_begin(env, NULL, &txn, 0);                                      CKERR(r);
117 
118     for(int i=0;i<NUM_KV_PAIRS;i++) {
119 	DBT key, val;
120         dbt_init(&key, &kv_pairs[i].key, sizeof(kv_pairs[i].key));
121         dbt_init(&val, &kv_pairs[i].val, sizeof(kv_pairs[i].val));
122         r = src_db->put(src_db, txn, &key, &val, 0);                             CKERR(r);
123     }
124 
125     DB *dbs[NUM_DBS];
126     for (int i = 0; i < NUM_DBS; i++) {
127         r = db_create(&dbs[i], env, 0); CKERR(r);
128         char key_name[32];
129         sprintf(key_name, "key%d", i);
130         r = dbs[i]->open(dbs[i], NULL, key_name, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666);   CKERR(r);
131         dbs[i]->app_private = (void *) (intptr_t) i;
132     }
133 
134     DB_TXN *hottxn;
135     r = env->txn_begin(env, NULL, &hottxn, 0);
136     CKERR(r);
137 
138     DB_INDEXER *indexer;
139     r = env->create_indexer(env, hottxn, &indexer, src_db, NUM_DBS, dbs, NULL, 0);
140     CKERR(r);
141     r = indexer->set_error_callback(indexer, NULL, NULL);
142     CKERR(r);
143     r = indexer->set_poll_function(indexer, poll_print, NULL);
144     CKERR(r);
145 
146     // setup putm
147     DB *putm_dbs[NUM_DBS+1];
148     for (int i = 0; i < NUM_DBS; i++)
149 	putm_dbs[i] = dbs[i];
150     putm_dbs[NUM_DBS] = src_db;
151 
152     DBT putm_keys[NUM_DBS+1], putm_vals[NUM_DBS+1];
153 
154     uint32_t putm_flags[NUM_DBS+1];
155     for (int i = 0; i < NUM_DBS+1; i++)
156 	putm_flags[i] = 0;
157 
158     DBT prikey; int64_t pk;
159     dbt_init(&prikey, &pk, sizeof pk);
160 
161     DBT prival; int64_t pv;
162     dbt_init(&prival, &pv, sizeof pv);
163 
164     // putm (8,9)
165     pk = 8; pv = 9;
166     r = env_put_multiple_test_no_array(env, src_db, txn, &prikey, &prival, NUM_DBS+1, putm_dbs, putm_keys, putm_vals, putm_flags);
167     CKERR(r);
168 
169     r = indexer->build(indexer);
170     CKERR(r);
171 
172     // putm (9, 10)
173     pk = 9; pv = 10;
174     r = env_put_multiple_test_no_array(env, src_db, txn, &prikey, &prival, NUM_DBS+1, putm_dbs, putm_keys, putm_vals, putm_flags);
175     CKERR(r);
176 
177     r = indexer->close(indexer);
178     CKERR(r);
179     r = hottxn->commit(hottxn, DB_TXN_SYNC);
180     CKERR(r);
181 
182     r = txn->commit(txn, DB_TXN_SYNC);                                           CKERR(r);
183 
184     for(int i=0;i<NUM_DBS;i++) {
185         r = dbs[i]->close(dbs[i], 0);                                            CKERR(r);
186     }
187 
188     r = src_db->close(src_db, 0);                                                CKERR(r);
189     r = env->close(env, 0);                                                      CKERR(r);
190 }
191 
192 
193 // ------------ infrastructure ----------
194 static void do_args(int argc, char * const argv[]);
195 
test_main(int argc,char * const * argv)196 int test_main(int argc, char * const *argv) {
197     do_args(argc, argv);
198     run_test();
199     return 0;
200 }
201 
do_args(int argc,char * const argv[])202 static void do_args(int argc, char * const argv[]) {
203     int resultcode;
204     char *cmd = argv[0];
205     argc--; argv++;
206     while (argc>0) {
207 	if (strcmp(argv[0], "-v")==0) {
208 	    verbose++;
209 	} else if (strcmp(argv[0],"-q")==0) {
210 	    verbose--;
211 	    if (verbose<0) verbose=0;
212         } else if (strcmp(argv[0], "-h")==0) {
213 	    resultcode=0;
214 	do_usage:
215 	    fprintf(stderr, "Usage:\n%s\n", cmd);
216 	    exit(resultcode);
217 	} else {
218 	    fprintf(stderr, "Unknown arg: %s\n", argv[0]);
219 	    resultcode=1;
220 	    goto do_usage;
221 	}
222 	argc--;
223 	argv++;
224     }
225 }
226