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 // hot-optimize-table-tests.c
40
41 #include "test.h"
42
43 const int envflags = DB_INIT_MPOOL |
44 DB_CREATE |
45 DB_THREAD |
46 DB_INIT_LOCK |
47 DB_INIT_LOG |
48 DB_INIT_TXN |
49 DB_PRIVATE;
50
51 DB_ENV* env;
52 unsigned int leaf_hits;
53
54 // Custom Update Function for our test FT.
55 static int
update_func(DB * UU (db),const DBT * key,const DBT * old_val,const DBT * extra,void (* set_val)(const DBT * new_val,void * set_extra),void * UU (set_extra))56 update_func(DB* UU(db),
57 const DBT* key,
58 const DBT* old_val,
59 const DBT* extra,
60 void (*set_val)(const DBT* new_val, void* set_extra) __attribute__((unused)),
61 void* UU(set_extra))
62 {
63 unsigned int *x_results;
64 assert(extra->size == sizeof x_results);
65 x_results = *(unsigned int **) extra->data;
66 assert(x_results);
67 assert(old_val->size > 0);
68 unsigned int* indexptr;
69 assert(key->size == (sizeof *indexptr));
70 indexptr = (unsigned int*)key->data;
71 ++leaf_hits;
72
73 if (verbose && x_results[*indexptr] != 0) {
74 printf("x_results = %p, indexptr = %p, *indexptr = %u, x_results[*indexptr] = %u\n", x_results, indexptr, *indexptr, x_results[*indexptr]);
75 }
76
77 assert(x_results[*indexptr] == 0);
78 x_results[*indexptr]++;
79 // ++(x_results[*indexptr]);
80 // memset(&new_val, 0, sizeof(new_val));
81 // set_val(&new_val, set_extra);
82 unsigned int i = *indexptr;
83 if (verbose && ((i + 1) % 50000 == 0)) {
84 printf("applying update to %u\n", i);
85 //printf("x_results[] = %u\n", x_results[*indexptr]);
86 }
87
88 return 0;
89 }
90
91 ///
92 static void
hot_test_setup(void)93 hot_test_setup(void)
94 {
95 int r = 0;
96 // Remove any previous environment.
97 toku_os_recursive_delete(TOKU_TEST_FILENAME);
98
99 // Set up a new environment.
100 { int chk_r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
101 { int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
102 env->set_errfile(env, stderr);
103 r = env->set_default_bt_compare(env, uint_dbt_cmp);CKERR(r);
104 env->set_update(env, update_func);
105 { int chk_r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
106 }
107
108 static void
hot_test_destroy(void)109 hot_test_destroy(void)
110 {
111 { int chk_r = env->close(env, 0); CKERR(chk_r); }
112 }
113
114 ///
115 static void
hot_insert_keys(DB * db,unsigned int key_count)116 hot_insert_keys(DB* db, unsigned int key_count)
117 {
118 int r = 0;
119 DB_TXN * xact;
120 unsigned int limit = 1;
121 if (key_count > 10) {
122 limit = 100000;
123 }
124
125 // Dummy data.
126 const unsigned int DUMMY_SIZE = 100;
127 size_t size = DUMMY_SIZE;
128 char* dummy = NULL;
129 dummy = (char*)toku_xmalloc(size);
130 memset(dummy, 0, size);
131
132 // Start the transaction for insertions.
133 //
134 r = env->txn_begin(env, 0, &xact, 0); CKERR(r);
135
136 unsigned int key;
137
138 DBT key_thing;
139 DBT *keyptr = dbt_init(&key_thing, &key, sizeof(key));
140 DBT value_thing;
141 DBT *valueptr = dbt_init(&value_thing, dummy, size);
142 for (key = 0; key < key_count; ++key)
143 {
144 { int chk_r = db->put(db, xact, keyptr, valueptr, 0); CKERR(chk_r); }
145
146 // DEBUG OUTPUT
147 //
148 if (verbose && (key + 1) % limit == 0) {
149 printf("%d Elements inserted.\n", key + 1);
150 }
151 }
152
153 // Commit the insert transaction.
154 //
155 r = xact->commit(xact, 0); CKERR(r);
156
157 toku_free(dummy);
158 }
159
160 ///
161 static void
hot_create_db(DB ** db,const char * c)162 hot_create_db(DB** db, const char* c)
163 {
164 int r = 0;
165 DB_TXN* xact;
166 verbose ? printf("Creating DB.\n") : 0;
167 r = env->txn_begin(env, 0, &xact, 0); CKERR(r);
168 { int chk_r = db_create(db, env, 0); CKERR(chk_r); }
169 { int chk_r = (*db)->open((*db), xact, c, NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); }
170 r = xact->commit(xact, 0); CKERR(r);
171 verbose ? printf("DB Created.\n") : 0;
172 }
173
174 ///
175 static void
hot_test(DB * db,unsigned int size)176 hot_test(DB* db, unsigned int size)
177 {
178 int r = 0;
179 leaf_hits = 0;
180 verbose ? printf("Insert some data.\n") : 0;
181
182 // Insert our keys to assemble the tree.
183 hot_insert_keys(db, size);
184
185 // Insert Broadcast Message.
186 verbose ? printf("Insert Broadcast Message.\n") : 0;
187 unsigned int *XMALLOC_N(size, x_results);
188 memset(x_results, 0, (sizeof x_results[0]) * size);
189 DBT extra;
190 DBT *extrap = dbt_init(&extra, &x_results, sizeof x_results);
191 DB_TXN * xact;
192 r = env->txn_begin(env, 0, &xact, 0); CKERR(r);
193 r = db->update_broadcast(db, xact, extrap, 0); CKERR(r);
194 r = xact->commit(xact, 0); CKERR(r);
195
196 // Flatten the tree.
197 verbose ? printf("Calling hot optimize...\n") : 0;
198 uint64_t loops_run;
199 r = db->hot_optimize(db, NULL, NULL, NULL, NULL, &loops_run);
200 assert(r == 0);
201 verbose ? printf("HOT Finished!\n") : 0;
202 for (unsigned int i = 0; i < size; ++i) {
203 assert(x_results[i] == 1);
204 }
205 verbose ? printf("Leaves hit = %u\n", leaf_hits) :0;
206 toku_free(x_results);
207 }
208
209 ///
210 int
test_main(int argc,char * const argv[])211 test_main(int argc, char * const argv[])
212 {
213 int r = 0;
214 default_parse_args(argc, argv);
215 hot_test_setup();
216
217 // Create and Open the Database/FT
218 DB *db = NULL;
219 const unsigned int BIG = 4000000;
220 const unsigned int SMALL = 10;
221 const unsigned int NONE = 0;
222
223 hot_create_db(&db, "none.db");
224 hot_test(db, NONE);
225 r = db->close(db, 0);
226 CKERR(r);
227 hot_create_db(&db, "small.db");
228 hot_test(db, SMALL);
229 r = db->close(db, 0);
230 CKERR(r);
231 hot_create_db(&db, "big.db");
232 hot_test(db, BIG);
233 r = db->close(db, 0);
234 CKERR(r);
235
236 hot_test_destroy();
237 verbose ? printf("Exiting Test.\n") : 0;
238 return r;
239 }
240