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 // test that an update calls back into the update function
40
41 #include "test.h"
42
43 const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE;
44
45 DB_ENV *env;
46
47
update_fun(DB * UU (db),const DBT * UU (key),const DBT * UU (old_val),const DBT * extra,void (* set_val)(const DBT * new_val,void * set_extra),void * set_extra)48 static int update_fun(DB *UU(db),
49 const DBT *UU(key),
50 const DBT *UU(old_val), const DBT *extra,
51 void (*set_val)(const DBT *new_val,
52 void *set_extra),
53 void *set_extra) {
54 set_val(extra, set_extra);
55 return 0;
56 }
57
58
generate_row_for_del(DB * UU (dest_db),DB * UU (src_db),DBT_ARRAY * dest_key_arrays,const DBT * UU (src_key),const DBT * UU (src_val))59 static int generate_row_for_del(
60 DB *UU(dest_db),
61 DB *UU(src_db),
62 DBT_ARRAY *dest_key_arrays,
63 const DBT *UU(src_key),
64 const DBT *UU(src_val)
65 )
66 {
67 toku_dbt_array_resize(dest_key_arrays, 1);
68 DBT *dest_key = &dest_key_arrays->dbts[0];
69 dest_key->flags = 0;
70 dest_key->size=0;
71 return 0;
72 }
73
generate_row_for_put(DB * UU (dest_db),DB * UU (src_db),DBT_ARRAY * dest_key_arrays,DBT_ARRAY * dest_val_arrays,const DBT * UU (src_key),const DBT * UU (src_val))74 static int generate_row_for_put(
75 DB *UU(dest_db),
76 DB *UU(src_db),
77 DBT_ARRAY *dest_key_arrays,
78 DBT_ARRAY *dest_val_arrays,
79 const DBT *UU(src_key),
80 const DBT *UU(src_val)
81 )
82 {
83 toku_dbt_array_resize(dest_key_arrays, 1);
84 toku_dbt_array_resize(dest_val_arrays, 1);
85 DBT *dest_key = &dest_key_arrays->dbts[0];
86 DBT *dest_val = &dest_val_arrays->dbts[0];
87 dest_key->flags = 0;
88 dest_val->flags = 0;
89
90 uint8_t src_val_data;
91 assert(src_val->size == 1);
92 src_val_data = *(uint8_t *)src_val->data;
93 assert(src_val_data == 100);
94 dest_key->size=0;
95 dest_val->size=0;
96 return 0;
97 }
98
setup(void)99 static void setup (void) {
100 toku_os_recursive_delete(TOKU_TEST_FILENAME);
101 { int chk_r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
102 { int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
103 env->set_errfile(env, stderr);
104 { int chk_r = env->set_generate_row_callback_for_put(env,generate_row_for_put); CKERR(chk_r); }
105 { int chk_r = env->set_generate_row_callback_for_del(env,generate_row_for_del); CKERR(chk_r); }
106 env->set_update(env, update_fun);
107 { int chk_r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
108 }
109
cleanup(void)110 static void cleanup (void) {
111 { int chk_r = env->close(env, 0); CKERR(chk_r); }
112 }
113
run_test(void)114 static void run_test(void) {
115 DB* db = NULL;
116 DB_LOADER* loader = NULL;
117 DBT key, val;
118 uint32_t mult_db_flags = 0;
119 uint32_t mult_dbt_flags = DB_DBT_REALLOC;
120 uint8_t key_data = 0;
121 uint8_t val_data = 0;
122
123
124 IN_TXN_COMMIT(env, NULL, txn_create, 0, {
125 { int chk_r = db_create(&db, env, 0); CKERR(chk_r); }
126 { int chk_r = db->open(db, txn_create, "foo.db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); }
127 });
128
129
130 dbt_init(&key,&key_data,sizeof(uint8_t));
131 dbt_init(&val,&val_data,sizeof(uint8_t));
132
133 val_data = 1;
134
135
136 //
137 // now do an update broadcast that will set the val to something bigger
138 //
139 val_data = 100;
140 IN_TXN_COMMIT(env, NULL, txn_broadcast, 0, {
141 { int chk_r = db->update_broadcast(db, txn_broadcast, &val, DB_IS_RESETTING_OP); CKERR(chk_r); }
142 });
143
144 //
145 // now create a loader
146 //
147 IN_TXN_COMMIT(env, NULL, txn_loader, 0, {
148 // create DB
149 { int chk_r = env->create_loader(
150 env,
151 txn_loader,
152 &loader,
153 db,
154 1,
155 &db,
156 &mult_db_flags,
157 &mult_dbt_flags,
158 0
159 ); CKERR(chk_r); }
160 { int chk_r = loader->put(loader, &key, &val); CKERR(chk_r); }
161 { int chk_r = loader->close(loader); CKERR(chk_r); }
162 });
163
164 IN_TXN_COMMIT(env, NULL, txn_update, 0, {
165 { int chk_r = db->update(db, txn_update, &key, &val, 0); CKERR(chk_r); }
166 });
167
168 { int chk_r = db->close(db, 0); CKERR(chk_r); }
169
170 }
171
test_main(int argc,char * const argv[])172 int test_main (int argc, char * const argv[]) {
173 parse_args(argc, argv);
174 setup();
175 run_test();
176 cleanup();
177 return 0;
178 }
179