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 // The purpose of this test is force errors returned from the generate function
40
41 #define DONT_DEPRECATE_MALLOC
42 #define DONT_DEPRECATE_WRITES
43 #include "test.h"
44 #include "loader/loader.h"
45 #include "loader/loader-internal.h"
46 #include "ftloader-error-injector.h"
47 #include "memory.h"
48 #include <portability/toku_path.h>
49
50
generate(DB * dest_db,DB * src_db,DBT_ARRAY * dest_keys,DBT_ARRAY * dest_vals,const DBT * src_key,const DBT * src_val)51 static int generate(DB *dest_db, DB *src_db, DBT_ARRAY *dest_keys, DBT_ARRAY *dest_vals, const DBT *src_key, const DBT *src_val) {
52 if (verbose) printf("%s %p %p %p %p %p %p\n", __FUNCTION__, dest_db, src_db, dest_keys, dest_vals, src_key, src_val);
53 toku_dbt_array_resize(dest_keys, 1);
54 toku_dbt_array_resize(dest_vals, 1);
55 DBT *dest_key = &dest_keys->dbts[0];
56 DBT *dest_val = &dest_vals->dbts[0];
57
58 assert(dest_db == NULL); assert(src_db == NULL);
59
60 int result;
61 if (event_count_trigger == event_add_and_fetch()) {
62 event_hit();
63 result = EINVAL;
64 } else {
65 copy_dbt(dest_key, src_key);
66 copy_dbt(dest_val, src_val);
67 result = 0;
68 }
69
70 if (verbose) printf("%s %d\n", __FUNCTION__, result);
71 return result;
72 }
73
qsort_compare_ints(const void * a,const void * b)74 static int qsort_compare_ints (const void *a, const void *b) {
75 int avalue = *(int*)a;
76 int bvalue = *(int*)b;
77 if (avalue<bvalue) return -1;
78 if (avalue>bvalue) return +1;
79 return 0;
80 }
81
compare_int(DB * desc,const DBT * akey,const DBT * bkey)82 static int compare_int(DB *desc, const DBT *akey, const DBT *bkey) {
83 assert(desc == NULL);
84 assert(akey->size == sizeof (int));
85 assert(bkey->size == sizeof (int));
86 return qsort_compare_ints(akey->data, bkey->data);
87 }
88
populate_rowset(struct rowset * rowset,int seq,int nrows)89 static void populate_rowset(struct rowset *rowset, int seq, int nrows) {
90 for (int i = 0; i < nrows; i++) {
91 int k = seq * nrows + i;
92 int v = seq * nrows + i;
93 DBT key;
94 toku_fill_dbt(&key, &k, sizeof k);
95 DBT val;
96 toku_fill_dbt(&val, &v, sizeof v);
97 add_row(rowset, &key, &val);
98 }
99 }
100
test_extractor(int nrows,int nrowsets,bool expect_fail)101 static void test_extractor(int nrows, int nrowsets, bool expect_fail) {
102 if (verbose) printf("%s %d %d\n", __FUNCTION__, nrows, nrowsets);
103
104 int r;
105
106 // open the ft_loader. this runs the extractor.
107 const int N = 1;
108 FT_HANDLE fts[N];
109 DB* dbs[N];
110 const char *fnames[N];
111 ft_compare_func compares[N];
112 for (int i = 0; i < N; i++) {
113 fts[i] = NULL;
114 dbs[i] = NULL;
115 fnames[i] = "";
116 compares[i] = compare_int;
117 }
118
119 FTLOADER loader;
120 r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, fts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false, true);
121 assert(r == 0);
122
123 struct rowset *rowset[nrowsets];
124 for (int i = 0 ; i < nrowsets; i++) {
125 rowset[i] = (struct rowset *) toku_malloc(sizeof (struct rowset));
126 assert(rowset[i]);
127 init_rowset(rowset[i], toku_ft_loader_get_rowset_budget_for_testing());
128 populate_rowset(rowset[i], i, nrows);
129 }
130
131 // feed rowsets to the extractor
132 for (int i = 0; i < nrowsets; i++) {
133 r = toku_queue_enq(loader->primary_rowset_queue, rowset[i], 1, NULL);
134 assert(r == 0);
135 }
136
137 r = toku_ft_loader_finish_extractor(loader);
138 assert(r == 0);
139
140 int loader_error;
141 r = toku_ft_loader_get_error(loader, &loader_error);
142 assert(r == 0);
143
144 assert(expect_fail ? loader_error != 0 : loader_error == 0);
145
146 // abort the ft_loader. this ends the test
147 r = toku_ft_loader_abort(loader, true);
148 assert(r == 0);
149 }
150
151 static int nrows = 1;
152 static int nrowsets = 2;
153
usage(const char * progname)154 static int usage(const char *progname) {
155 fprintf(stderr, "Usage:\n %s [-h] [-v] [-q] [-s] [-r %d] [--rowsets %d]\n", progname, nrows, nrowsets);
156 return 1;
157 }
158
test_main(int argc,const char * argv[])159 int test_main (int argc, const char *argv[]) {
160 const char *progname=argv[0];
161 argc--; argv++;
162 while (argc>0) {
163 if (strcmp(argv[0],"-h")==0) {
164 return usage(progname);
165 } else if (strcmp(argv[0],"-v")==0) {
166 verbose=1;
167 } else if (strcmp(argv[0],"-q")==0) {
168 verbose=0;
169 } else if (strcmp(argv[0],"-r") == 0 && argc >= 1) {
170 argc--; argv++;
171 nrows = atoi(argv[0]);
172 } else if (strcmp(argv[0],"--nrowsets") == 0 && argc >= 1) {
173 argc--; argv++;
174 nrowsets = atoi(argv[0]);
175 } else if (strcmp(argv[0],"-s") == 0) {
176 toku_ft_loader_set_size_factor(1);
177 } else if (argc!=1) {
178 return usage(progname);
179 exit(1);
180 }
181 else {
182 break;
183 }
184 argc--; argv++;
185 }
186
187 // callibrate
188 test_extractor(nrows, nrowsets, false);
189
190 // run tests
191 int event_limit = event_count;
192 if (verbose) printf("event_limit=%d\n", event_limit);
193
194 for (int i = 1; i <= event_limit; i++) {
195 reset_event_counts();
196 event_count_trigger = i;
197 test_extractor(nrows, nrowsets, true);
198 }
199
200 return 0;
201 }
202
203