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