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