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