1
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
4
COPYING CONDITIONS NOTICE:
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of version 2 of the GNU General Public License as
8
published by the Free Software Foundation, and provided that the
9
following conditions are met:
11
* Redistributions of source code must retain this COPYING
12
CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
13
DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
14
PATENT MARKING NOTICE (below), and the PATENT RIGHTS
17
* Redistributions in binary form must reproduce this COPYING
18
CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
19
DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
20
PATENT MARKING NOTICE (below), and the PATENT RIGHTS
21
GRANT (below) in the documentation and/or other materials
22
provided with the distribution.
24
You should have received a copy of the GNU General Public License
25
along with this program; if not, write to the Free Software
26
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31
TokuDB, Tokutek Fractal Tree Indexing Library.
32
Copyright (C) 2007-2013 Tokutek, Inc.
36
This program is distributed in the hope that it will be useful, but
37
WITHOUT ANY WARRANTY; without even the implied warranty of
38
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39
General Public License for more details.
41
UNIVERSITY PATENT NOTICE:
43
The technology is licensed by the Massachusetts Institute of
44
Technology, Rutgers State University of New Jersey, and the Research
45
Foundation of State University of New York at Stony Brook under
46
United States of America Serial No. 11/760379 and to the patents
47
and/or patent applications resulting from it.
49
PATENT MARKING NOTICE:
51
This software is covered by US Patent No. 8,185,551.
52
This software is covered by US Patent No. 8,489,638.
56
"THIS IMPLEMENTATION" means the copyrightable works distributed by
57
Tokutek as part of the Fractal Tree project.
59
"PATENT CLAIMS" means the claims of patents that are owned or
60
licensable by Tokutek, both currently or in the future; and that in
61
the absence of this license would be infringed by THIS
62
IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
64
"PATENT CHALLENGE" shall mean a challenge to the validity,
65
patentability, enforceability and/or non-infringement of any of the
66
PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
68
Tokutek hereby grants to you, for the term and geographical scope of
69
the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
70
irrevocable (except as stated in this section) patent license to
71
make, have made, use, offer to sell, sell, import, transfer, and
72
otherwise run, modify, and propagate the contents of THIS
73
IMPLEMENTATION, where such license applies only to the PATENT
74
CLAIMS. This grant does not include claims that would be infringed
75
only as a consequence of further modifications of THIS
76
IMPLEMENTATION. If you or your agent or licensee institute or order
77
or agree to the institution of patent litigation against any entity
78
(including a cross-claim or counterclaim in a lawsuit) alleging that
79
THIS IMPLEMENTATION constitutes direct or contributory patent
80
infringement, or inducement of patent infringement, then any rights
81
granted to you under this License shall terminate as of the date
82
such litigation is filed. If you or your agent or exclusive
83
licensee institute or order or agree to the institution of a PATENT
84
CHALLENGE, then Tokutek may terminate any rights granted to you
88
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
95
#include <toku_pthread.h>
101
#include "threaded_stress_test_helpers.h"
104
toku_mutex_t fops_lock;
105
toku_mutex_t hi_lock;
107
uint8_t hi_gid[DB_GID_SIZE];
111
hi_put_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_key_arrays, DBT_ARRAY *dest_val_arrays, const DBT *src_key, const DBT *src_val) {
112
toku_dbt_array_resize(dest_key_arrays, 1);
113
toku_dbt_array_resize(dest_val_arrays, 1);
114
DBT *dest_key = &dest_key_arrays->dbts[0];
115
DBT *dest_val = &dest_val_arrays->dbts[0];
116
lazy_assert(src_db != NULL && dest_db != NULL);
118
if (dest_key->data) {
119
toku_free(dest_key->data);
120
dest_key->data = NULL;
122
if (dest_val->data) {
123
toku_free(dest_val->data);
124
dest_val->data = NULL;
126
dest_key->data = toku_xmemdup(src_key->data, src_key->size);
127
dest_key->size = src_key->size;
128
dest_val->data = toku_xmemdup(src_val->data, src_val->size);
129
dest_val->size = src_val->size;
135
hi_del_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_key_arrays, const DBT *src_key, const DBT* UU(src_data)) {
136
toku_dbt_array_resize(dest_key_arrays, 1);
137
DBT *dest_key = &dest_key_arrays->dbts[0];
138
lazy_assert(src_db != NULL && dest_db != NULL);
139
if (dest_key->data) {
140
toku_free(dest_key->data);
141
dest_key->data = NULL;
143
dest_key->data = toku_xmemdup(src_key->data, src_key->size);
144
dest_key->size = src_key->size;
150
static int hi_inserts(DB_TXN* UU(txn), ARG arg, void* UU(operation_extra), void *stats_extra) {
152
DB_TXN* hi_txn = NULL;
153
toku_mutex_lock(&fops_lock);
154
DB_ENV* env = arg->env;
155
DB* db = arg->dbp[0];
159
DBT_ARRAY dest_keys[2];
160
DBT_ARRAY dest_vals[2];
161
for (int j = 0; j < 2; j++) {
162
toku_dbt_array_init(&dest_keys[j], 1);
163
toku_dbt_array_init(&dest_vals[j], 1);
167
uint8_t keybuf[arg->cli->key_size];
168
uint8_t valbuf[arg->cli->val_size];
169
dbt_init(&key, keybuf, sizeof keybuf);
170
dbt_init(&val, valbuf, sizeof valbuf);
173
r = env->txn_begin(env, NULL, &hi_txn, 0);
175
for (i = 0; i < 1000; i++) {
177
toku_mutex_lock(&hi_lock);
180
int num_dbs = hot_db ? 2 : 1;
181
// do a random insertion. the assertion comes from the fact
182
// that the code used to generate a random key and mod it
183
// by the table size manually. fill_key_buf_random will
184
// do this iff arg->bounded_element_range is true.
185
invariant(arg->bounded_element_range);
186
fill_key_buf_random(arg->random_data, keybuf, arg);
187
fill_val_buf_random(arg->random_data, valbuf, arg->cli);
188
r = env->put_multiple(
200
toku_mutex_unlock(&hi_lock);
206
for (int j = 0; j < 2; j++) {
207
toku_dbt_array_destroy(&dest_keys[j]);
208
toku_dbt_array_destroy(&dest_vals[j]);
210
increment_counter(stats_extra, PUTS, i);
212
uint32_t *hi_gid_count_p = cast_to_typeof(hi_gid_count_p) hi_gid; // make gcc --happy about -Wstrict-aliasing
213
*hi_gid_count_p = gid_count;
214
int rr = hi_txn->prepare(hi_txn, hi_gid);
216
if (r || (random() % 2)) {
217
rr = hi_txn->abort(hi_txn);
221
rr = hi_txn->commit(hi_txn, 0);
224
toku_mutex_unlock(&fops_lock);
228
static int indexer_maybe_quit_poll(void *UU(poll_extra), float UU(progress)) {
229
return run_test ? 0 : TOKUDB_CANCELED;
232
static int hi_create_index(DB_TXN* UU(txn), ARG arg, void* UU(operation_extra), void* UU(stats_extra)) {
234
DB_TXN* hi_txn = NULL;
235
DB_ENV* env = arg->env;
236
DB* db = arg->dbp[0];
237
DB_INDEXER* indexer = NULL;
238
r = env->txn_begin(env, NULL, &hi_txn, 0);
240
toku_mutex_lock(&hi_lock);
241
assert(hot_db == NULL);
242
db_create(&hot_db, env, 0);
244
r = hot_db->set_flags(hot_db, 0);
246
r = hot_db->set_pagesize(hot_db, arg->cli->env_args.node_size);
248
r = hot_db->set_readpagesize(hot_db, arg->cli->env_args.basement_node_size);
250
r = hot_db->open(hot_db, NULL, "hotindex_db", NULL, DB_BTREE, DB_CREATE | DB_IS_HOT_INDEX, 0666);
252
uint32_t db_flags = 0;
253
uint32_t indexer_flags = 0;
255
r = env->create_indexer(
266
toku_mutex_unlock(&hi_lock);
268
r = indexer->set_poll_function(indexer, indexer_maybe_quit_poll, nullptr);
271
r = indexer->build(indexer);
272
CKERR2s(r, 0, TOKUDB_CANCELED);
274
toku_mutex_lock(&hi_lock);
275
r = indexer->close(indexer);
277
toku_mutex_unlock(&hi_lock);
279
r = hi_txn->commit(hi_txn, 0);
283
// now do a scan to make sure hot index is good
284
DB_TXN* scan_txn = NULL;
285
DBC* main_cursor = NULL;
286
DBC* hi_cursor = NULL;
287
r = env->txn_begin(env, NULL, &scan_txn, DB_TXN_SNAPSHOT);
289
r = db->cursor(db, scan_txn, &main_cursor, 0);
291
r = db->cursor(hot_db, scan_txn, &hi_cursor, 0);
293
DBT key1, key2, val1, val2;
294
memset(&key1, 0, sizeof key1);
295
memset(&val1, 0, sizeof val1);
296
memset(&key2, 0, sizeof key2);
297
memset(&val2, 0, sizeof val2);
299
while(r != DB_NOTFOUND) {
300
if (count++ % 256 == 0 && !run_test) {
304
// get next from both cursors and assert they are equal
305
int r1 = main_cursor->c_get(
311
int r2 = hi_cursor->c_get(
319
if (r != DB_NOTFOUND) {
320
assert(key1.size == key2.size);
321
assert(val1.size == val2.size);
322
assert(memcmp(key1.data, key2.data, key1.size) == 0);
323
assert(memcmp(val1.data, val2.data, val1.size) == 0);
326
CKERR2s(r, DB_NOTFOUND, TOKUDB_CANCELED);
327
r = main_cursor->c_close(main_cursor);
328
r = hi_cursor->c_close(hi_cursor);
330
r = scan_txn->commit(scan_txn, 0);
333
// grab lock and close hot_db, set it to NULL
334
toku_mutex_lock(&hi_lock);
335
r = hot_db->close(hot_db, 0);
338
toku_mutex_unlock(&hi_lock);
340
toku_mutex_lock(&fops_lock);
341
r = env->dbremove(env, NULL, "hotindex_db", NULL, 0);
342
toku_mutex_unlock(&fops_lock);
348
// purpose of this stress test is to do a bunch of splitting and merging
349
// and run db->verify periodically to make sure the db is in a
353
stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) {
354
if (verbose) printf("starting creation of pthreads\n");
355
const int num_threads = 2;
356
struct arg myargs[num_threads];
357
for (int i = 0; i < num_threads; i++) {
358
arg_init(&myargs[i], dbp, env, cli_args);
360
myargs[0].operation = hi_inserts;
361
myargs[1].operation = hi_create_index;
363
run_workers(myargs, num_threads, cli_args->num_seconds, false, cli_args);
367
test_main(int argc, char *const argv[]) {
369
memset(hi_gid, 0, sizeof(hi_gid));
370
toku_mutex_init(&hi_lock, NULL);
371
toku_mutex_init(&fops_lock, NULL);
373
struct cli_args args = get_default_args();
374
// let's make default checkpointing period really slow
375
args.num_ptquery_threads = 0;
376
parse_stress_test_args(argc, argv, &args);
378
args.crash_on_operation_failure = false;
379
args.env_args.generate_del_callback = hi_del_callback;
380
args.env_args.generate_put_callback = hi_put_callback;
381
stress_test_main(&args);
382
toku_mutex_destroy(&hi_lock);
383
toku_mutex_destroy(&fops_lock);