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 #include "test.h"
42 //
43 // Functions to create unique key/value pairs, row generators, checkers, ... for each of NUM_DBS
44 //
45
46 // a is the bit-wise permute table. For DB[i], permute bits as described in a[i] using 'twiddle32'
47 // inv is the inverse bit-wise permute of a[]. To get the original value from a twiddled value, twiddle32 (again) with inv[]
48 enum {MAX_DBS=256};
49 enum {MAGIC=311};
50 static int aa[MAX_DBS][32] UU();
51 static int inv[MAX_DBS][32] UU();
52
53 // rotate right and left functionsp
UU()54 static inline unsigned int UU()
55 rotr32(const unsigned int x, const unsigned int num) {
56 const unsigned int n = num % 32;
57 return (x >> n) | ( x << (32 - n));
58 }
UU()59 static inline unsigned int UU()
60 rotl32(const unsigned int x, const unsigned int num) {
61 const unsigned int n = num % 32;
62 return (x << n) | ( x >> (32 - n));
63 }
64
UU()65 static void UU()
66 generate_permute_tables(void) {
67 srandom(1);
68 int i, j, tmp;
69 for(int db=0;db<MAX_DBS;db++) {
70 for(i=0;i<32;i++) {
71 aa[db][i] = i;
72 }
73 for(i=0;i<32;i++) {
74 j = random() % (i + 1);
75 tmp = aa[db][j];
76 aa[db][j] = aa[db][i];
77 aa[db][i] = tmp;
78 }
79 for(i=0;i<32;i++) {
80 inv[db][aa[db][i]] = i;
81 }
82 }
83 }
84
85 // permute bits of x based on permute table bitmap
UU()86 static unsigned int UU()
87 twiddle32(unsigned int x, int db)
88 {
89 unsigned int b = 0;
90 for(int i=0;i<32;i++) {
91 b |= (( x >> i ) & 1) << aa[db][i];
92 }
93 return b;
94 }
95
96 // permute bits of x based on inverse permute table bitmap
UU()97 static unsigned int UU()
98 inv_twiddle32(unsigned int x, int db)
99 {
100 unsigned int b = 0;
101 for(int i=0;i<32;i++) {
102 b |= (( x >> i ) & 1) << inv[db][i];
103 }
104 return b;
105 }
106
107 // generate val from key, index
UU()108 static unsigned int UU()
109 generate_val(int key, int i) {
110 return rotl32((key + MAGIC), i);
111 }
UU()112 static unsigned int UU()
113 pkey_for_val(int key, int i) {
114 return rotr32(key, i) - MAGIC;
115 }
116
117
118 static int __attribute__((unused))
dummy_progress(void * UU (extra),float UU (progress))119 dummy_progress(void *UU(extra), float UU(progress))
120 {
121 return 0;
122 }
123
124 static void __attribute__((unused))
do_hot_optimize_on_dbs(DB_ENV * UU (env),DB ** dbs,int num_dbs)125 do_hot_optimize_on_dbs(DB_ENV *UU(env), DB **dbs, int num_dbs)
126 {
127 for (int i = 0; i < num_dbs; ++i) {
128 uint64_t loops_run;
129 int r = dbs[i]->hot_optimize(dbs[i], NULL, NULL, dummy_progress, NULL, &loops_run);
130 CKERR(r);
131 }
132 }
133
134 // don't check first n rows (expect to have been deleted)
UU()135 static void UU()
136 check_results_after_row_n(DB_ENV *env, DB **dbs, const int num_dbs, const int num_rows, const int first_row_to_check) {
137
138 for(int j=0;j<num_dbs;j++){
139 DBT key, val;
140 unsigned int k=0, v=0;
141 dbt_init(&key, &k, sizeof(unsigned int));
142 dbt_init(&val, &v, sizeof(unsigned int));
143 int r;
144 unsigned int pkey_for_db_key;
145
146 DB_TXN *txn;
147 r = env->txn_begin(env, NULL, &txn, 0);
148 CKERR(r);
149
150 DBC *cursor;
151 r = dbs[j]->cursor(dbs[j], txn, &cursor, 0);
152 CKERR(r);
153 for(int i=first_row_to_check; i<num_rows; i++) {
154 r = cursor->c_get(cursor, &key, &val, DB_NEXT);
155 CKERR(r);
156 k = *(unsigned int*)key.data;
157 pkey_for_db_key = (j == 0) ? k : inv_twiddle32(k, j);
158 v = *(unsigned int*)val.data;
159 // test that we have the expected keys and values
160 if ((unsigned int)pkey_for_db_key != (unsigned int)pkey_for_val(v, j))
161 printf(" DB[%d] key = %10u, val = %10u, pkey_for_db_key = %10u, pkey_for_val=%10d\n", j, v, k, pkey_for_db_key, pkey_for_val(v, j));
162 assert((unsigned int)pkey_for_db_key == (unsigned int)pkey_for_val(v, j));
163 dbt_init(&key, NULL, sizeof(unsigned int));
164 dbt_init(&val, NULL, sizeof(unsigned int));
165 }
166 if ( verbose ) {printf("."); fflush(stdout);}
167 r = cursor->c_close(cursor);
168 CKERR(r);
169 r = txn->commit(txn, 0);
170 CKERR(r);
171 }
172 if ( verbose ) {printf("ok");fflush(stdout);}
173 }
174
UU()175 static void UU()
176 check_results(DB_ENV *env, DB **dbs, const int num_dbs, const int num_rows)
177 {
178 check_results_after_row_n(env, dbs, num_dbs, num_rows, 0);
179 }
180
181
UU()182 static int UU()
183 put_multiple_generate(DB *dest_db, DB *src_db, DBT *dest_key, DBT *dest_val, const DBT *src_key, const DBT *src_val, void *extra) {
184
185 (void) src_db;
186 (void) extra;
187
188 uint32_t which = *(uint32_t*)dest_db->app_private;
189
190 if ( which == 0 ) {
191 if (dest_key->flags==DB_DBT_REALLOC) {
192 if (dest_key->data) toku_free(dest_key->data);
193 dest_key->flags = 0;
194 dest_key->ulen = 0;
195 }
196 if (dest_val->flags==DB_DBT_REALLOC) {
197 if (dest_val->data) toku_free(dest_val->data);
198 dest_val->flags = 0;
199 dest_val->ulen = 0;
200 }
201 dbt_init(dest_key, src_key->data, src_key->size);
202 dbt_init(dest_val, src_val->data, src_val->size);
203 }
204 else {
205 assert(dest_key->flags==DB_DBT_REALLOC);
206 if (dest_key->ulen < sizeof(unsigned int)) {
207 dest_key->data = toku_xrealloc(dest_key->data, sizeof(unsigned int));
208 dest_key->ulen = sizeof(unsigned int);
209 }
210 assert(dest_val->flags==DB_DBT_REALLOC);
211 if (dest_val->ulen < sizeof(unsigned int)) {
212 dest_val->data = toku_xrealloc(dest_val->data, sizeof(unsigned int));
213 dest_val->ulen = sizeof(unsigned int);
214 }
215 unsigned int *new_key = (unsigned int *)dest_key->data;
216 unsigned int *new_val = (unsigned int *)dest_val->data;
217
218 *new_key = twiddle32(*(unsigned int*)src_key->data, which);
219 *new_val = generate_val(*(unsigned int*)src_key->data, which);
220
221 dest_key->size = sizeof(unsigned int);
222 dest_val->size = sizeof(unsigned int);
223 //data is already set above
224 }
225 return 0;
226 }
227