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