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 #pragma once
40
41 //
42 // Functions to create unique key/value pairs, row generators, checkers, ... for each of NUM_DBS
43 //
44
45 // To use, during initialization:
46 // generate_permute_tables();
47 // r = env->set_generate_row_callback_for_put(env, put_multiple_generate);
48 //
49
50
51 enum {MAX_DBS=32};
52 enum {MAGIC=311};
53
54 // a is the bit-wise permute table. For DB[i], permute bits as described in a[i] using 'twiddle32'
55 // inv is the inverse bit-wise permute of a[]. To get the original value from a twiddled value, twiddle32 (again) with inv[]
56 int a[MAX_DBS][32];
57 int inv[MAX_DBS][32];
58
59 // rotate right and left functions
UU()60 static inline uint32_t UU() rotr32(const uint32_t x, const uint32_t num) {
61 const uint32_t n = num % 32;
62 return (x >> n) | ( x << (32 - n));
63 }
UU()64 static inline uint64_t UU() rotr64(const uint64_t x, const uint64_t num) {
65 const uint64_t n = num % 64;
66 return ( x >> n ) | ( x << (64 - n));
67 }
UU()68 static inline uint32_t UU() rotl32(const uint32_t x, const uint32_t num) {
69 const uint32_t n = num % 32;
70 return (x << n) | ( x >> (32 - n));
71 }
UU()72 static inline uint64_t UU() rotl64(const uint64_t x, const uint64_t num) {
73 const uint64_t n = num % 64;
74 return ( x << n ) | ( x >> (64 - n));
75 }
76
UU()77 static void UU() generate_permute_tables(void) {
78 int i, j, tmp;
79 for(int db=0;db<MAX_DBS;db++) {
80 for(i=0;i<32;i++) {
81 a[db][i] = i;
82 }
83 for(i=0;i<32;i++) {
84 j = random() % (i + 1);
85 tmp = a[db][j];
86 a[db][j] = a[db][i];
87 a[db][i] = tmp;
88 }
89 // if(db < NUM_DBS){ printf("a[%d] = ", db); for(i=0;i<32;i++) { printf("%2d ", a[db][i]); } printf("\n");}
90 for(i=0;i<32;i++) {
91 inv[db][a[db][i]] = i;
92 }
93 }
94 }
95
96 // permute bits of x based on permute table bitmap
UU()97 static uint32_t UU() twiddle32(uint32_t x, int db)
98 {
99 uint32_t b = 0;
100 for(int i=0;i<32;i++) {
101 b |= (( x >> i ) & 1) << a[db][i];
102 }
103 return b;
104 }
105
106 // permute bits of x based on inverse permute table bitmap
UU()107 static uint32_t UU() inv_twiddle32(uint32_t x, int db)
108 {
109 uint32_t b = 0;
110 for(int i=0;i<32;i++) {
111 b |= (( x >> i ) & 1) << inv[db][i];
112 }
113 return b;
114 }
115
116 // generate val from key, index
UU()117 static uint32_t UU() generate_val(int key, int i) {
118 return rotl32((key + MAGIC), i);
119 }
UU()120 static uint32_t UU() pkey_for_val(int key, int i) {
121 return rotr32(key, i) - MAGIC;
122 }
123
124 // There is no handlerton in this test, so this function is a local replacement
125 // for the handlerton's generate_row_for_put().
UU()126 static int UU() put_multiple_generate(DB *dest_db, DB *src_db, DBT_ARRAY *dest_keys, DBT_ARRAY *dest_vals, const DBT *src_key, const DBT *src_val) {
127 toku_dbt_array_resize(dest_keys, 1);
128 toku_dbt_array_resize(dest_vals, 1);
129 DBT *dest_key = &dest_keys->dbts[0];
130 DBT *dest_val = &dest_vals->dbts[0];
131 (void) src_db;
132 (void) src_val;
133
134 uint32_t which = *(uint32_t*)dest_db->app_private;
135
136 assert(which != 0);
137 assert(dest_db != src_db);
138 {
139 assert(dest_key->flags==DB_DBT_REALLOC);
140 if (dest_key->ulen < sizeof(uint32_t)) {
141 dest_key->data = toku_xrealloc(dest_key->data, sizeof(uint32_t));
142 dest_key->ulen = sizeof(uint32_t);
143 }
144 assert(dest_val->flags==DB_DBT_REALLOC);
145 if (dest_val->ulen < sizeof(uint32_t)) {
146 dest_val->data = toku_xrealloc(dest_val->data, sizeof(uint32_t));
147 dest_val->ulen = sizeof(uint32_t);
148 }
149 uint32_t *new_key = (uint32_t *)dest_key->data;
150 uint32_t *new_val = (uint32_t *)dest_val->data;
151
152 *new_key = twiddle32(*(uint32_t*)src_key->data, which);
153 *new_val = generate_val(*(uint32_t*)src_key->data, which);
154
155 dest_key->size = sizeof(uint32_t);
156 dest_val->size = sizeof(uint32_t);
157 //data is already set above
158 }
159
160 // printf("pmg : dest_key.data = %u, dest_val.data = %u \n", *(unsigned int*)dest_key->data, *(unsigned int*)dest_val->data);
161
162 return 0;
163 }
164
UU()165 UU()
166 static int put_multiple_generate_switch(DB *dest_db, DB *src_db, DBT_ARRAY *dest_keys, DBT_ARRAY *dest_vals, const DBT *src_key, const DBT *src_val) {
167 toku_dbt_array_resize(dest_keys, 1);
168 toku_dbt_array_resize(dest_vals, 1);
169 DBT *dest_key = &dest_keys->dbts[0];
170 DBT *dest_val = &dest_vals->dbts[0];
171 dest_key->flags = 0;
172 dest_val->flags = 0;
173
174 (void) src_db;
175
176 uint32_t which = (uint32_t) (intptr_t) dest_db->app_private;
177 assert(which == 0);
178
179 // switch the key and val
180 dbt_init(dest_key, src_val->data, src_val->size);
181 dbt_init(dest_val, src_key->data, src_key->size);
182
183 // printf("dest_key.data = %d\n", *(int*)dest_key->data);
184 // printf("dest_val.data = %d\n", *(int*)dest_val->data);
185
186 return 0;
187 }
188
UU()189 static int UU() uint_cmp(const void *ap, const void *bp) {
190 unsigned int an = *(unsigned int *)ap;
191 unsigned int bn = *(unsigned int *)bp;
192 if (an < bn)
193 return -1;
194 if (an > bn)
195 return +1;
196 return 0;
197 }
198
199 float last_progress = 0.0;
UU()200 static int UU() poll_print(void *extra, float progress) {
201 if ( verbose ) {
202 if ( last_progress + 0.01 < progress ) {
203 printf(" progress : %3.0f%%\n", progress * 100.0);
204 last_progress = progress;
205 }
206 }
207 (void) extra;
208 return 0;
209 }
210
211 enum {MAX_CLIENTS=10};
UU()212 static inline UU() uint32_t key_to_put(int iter, int offset)
213 {
214 return (uint32_t)(((iter+1) * MAX_CLIENTS) + offset);
215 }
216
UU()217 static int UU() generate_initial_table(DB *db, DB_TXN *txn, uint32_t rows)
218 {
219 struct timeval start, now;
220 if ( verbose ) {
221 printf("generate_initial_table\n");
222 gettimeofday(&start,0);
223 }
224 int r = 0;
225 DBT key, val;
226 uint32_t k, v, i;
227 // create keys of stride MAX_CLIENTS
228 for (i=0; i<rows; i++)
229 {
230 k = key_to_put(i, 0);
231 v = generate_val(k, 0);
232 dbt_init(&key, &k, sizeof(k));
233 dbt_init(&val, &v, sizeof(v));
234 r = db->put(db, txn, &key, &val, 0);
235 if ( r != 0 ) break;
236 }
237 if ( verbose ) {
238 gettimeofday(&now,0);
239 int duration = (int)(now.tv_sec - start.tv_sec);
240 if ( duration > 0 )
241 printf("generate_initial_table : %u rows in %d sec = %d rows/sec\n", rows, duration, rows/duration);
242 }
243
244 return r;
245 }
246