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 // stress test for update broadcast. 10M 8-byte keys should be 2, maybe 3
40 // levels of treeness, makes sure flushes work
41
42 #include "test.h"
43
44 const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE;
45
46 DB_ENV *env;
47
48 const unsigned int NUM_KEYS = 1024;
49
50
update_fun(DB * UU (db),const DBT * UU (key),const DBT * old_val,const DBT * extra,void (* set_val)(const DBT * new_val,void * set_extra),void * set_extra)51 static int update_fun(DB *UU(db),
52 const DBT *UU(key),
53 const DBT *old_val, const DBT *extra,
54 void (*set_val)(const DBT *new_val,
55 void *set_extra),
56 void *set_extra)
57 {
58 assert(extra->size == sizeof(unsigned int));
59 assert(old_val->size == sizeof(unsigned int));
60 unsigned int e = *(unsigned int *)extra->data;
61 unsigned int ov = *(unsigned int *)old_val->data;
62 assert(e == (ov+1));
63 {
64 DBT newval;
65 set_val(dbt_init(&newval, &e, sizeof(e)), set_extra);
66 }
67 //usleep(10);
68 return 0;
69 }
70
71 static int
int_cmp(DB * UU (db),const DBT * a,const DBT * b)72 int_cmp(DB *UU(db), const DBT *a, const DBT *b) {
73 unsigned int *ap, *bp;
74 assert(a->size == sizeof(*ap));
75 CAST_FROM_VOIDP(ap, a->data);
76 assert(b->size == sizeof(*bp));
77 CAST_FROM_VOIDP(bp, b->data);
78 return (*ap > *bp) - (*ap < *bp);
79 }
80
setup(void)81 static void setup (void) {
82 toku_os_recursive_delete(TOKU_TEST_FILENAME);
83 { int chk_r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
84 { int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
85 env->set_errfile(env, stderr);
86 env->set_update(env, update_fun);
87 { int chk_r = env->set_default_bt_compare(env, int_cmp); CKERR(chk_r); }
88 { int chk_r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
89 // make a really small checkpointing period
90 { int chk_r = env->checkpointing_set_period(env,1); CKERR(chk_r); }
91 }
92
cleanup(void)93 static void cleanup (void) {
94 { int chk_r = env->close(env, 0); CKERR(chk_r); }
95 }
96
do_inserts(DB_TXN * txn,DB * db)97 static int do_inserts(DB_TXN *txn, DB *db) {
98 int r = 0;
99 DBT key, val;
100 unsigned int i, v;
101 DBT *keyp = dbt_init(&key, &i, sizeof(i));
102 DBT *valp = dbt_init(&val, &v, sizeof(v));
103 for (i = 0; i < NUM_KEYS; ++i) {
104 v = 0;
105 r = db->put(db, txn, keyp, valp, 0); CKERR(r);
106 }
107 return r;
108 }
109
do_updates(DB_TXN * txn,DB * db,unsigned int i)110 static int do_updates(DB_TXN *txn, DB *db, unsigned int i) {
111 DBT extra;
112 unsigned int e = i;
113 DBT *extrap = dbt_init(&extra, &e, sizeof(e));
114 int r = db->update_broadcast(db, txn, extrap, 0); CKERR(r);
115 return r;
116 }
117
118
test_main(int argc,char * const argv[])119 int test_main(int argc, char * const argv[]) {
120 parse_args(argc, argv);
121 setup();
122
123 DB *db;
124
125 IN_TXN_COMMIT(env, NULL, txn_1, 0, {
126 { int chk_r = db_create(&db, env, 0); CKERR(chk_r); }
127 { int chk_r = db->set_pagesize(db, 1<<8); CKERR(chk_r); }
128 { int chk_r = db->open(db, txn_1, "foo.db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); }
129
130 { int chk_r = do_inserts(txn_1, db); CKERR(chk_r); }
131 });
132
133 for(unsigned int i = 1; i < 100; i++) {
134 IN_TXN_COMMIT(env, NULL, txn_2, 0, {
135 { int chk_r = do_updates(txn_2, db, i); CKERR(chk_r); }
136 });
137 for (unsigned int curr_key = 0; curr_key < NUM_KEYS; ++curr_key) {
138 DBT key, val;
139 unsigned int *vp;
140 DBT *keyp = dbt_init(&key, &curr_key, sizeof(curr_key));
141 DBT *valp = dbt_init(&val, NULL, 0);
142 IN_TXN_COMMIT(env, NULL, txn_3, 0, {
143 { int chk_r = db->get(db, txn_3, keyp, valp, 0); CKERR(chk_r); }
144 });
145 assert(val.size == sizeof(*vp));
146 CAST_FROM_VOIDP(vp, val.data);
147 assert(*vp==i);
148 }
149 }
150
151 { int chk_r = db->close(db, 0); CKERR(chk_r); }
152
153 cleanup();
154
155 return 0;
156 }
157