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