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 #include "test.h"
40 #include "cachetable-test.h"
41
42 bool v1_written;
43 uint64_t val1;
44 bool v2_written;
45 uint64_t val2;
46 uint64_t val3;
47 bool check_me;
48 PAIR* dest_pair;
49
50 static void
put_callback_pair(CACHEKEY UU (key),void * UU (v),PAIR p)51 put_callback_pair(
52 CACHEKEY UU(key),
53 void *UU(v),
54 PAIR p)
55 {
56 *dest_pair = p;
57 }
58
59
60 static void
flush(CACHEFILE f,int UU (fd),CACHEKEY k,void * v,void ** UU (dd),void * e,PAIR_ATTR s,PAIR_ATTR * new_size,bool w,bool keep,bool c,bool UU (is_clone))61 flush (CACHEFILE f __attribute__((__unused__)),
62 int UU(fd),
63 CACHEKEY k __attribute__((__unused__)),
64 void *v __attribute__((__unused__)),
65 void** UU(dd),
66 void *e __attribute__((__unused__)),
67 PAIR_ATTR s __attribute__((__unused__)),
68 PAIR_ATTR* new_size __attribute__((__unused__)),
69 bool w __attribute__((__unused__)),
70 bool keep __attribute__((__unused__)),
71 bool c __attribute__((__unused__)),
72 bool UU(is_clone)
73 ) {
74 /* Do nothing */
75 if (verbose) { printf("FLUSH: %d\n", (int)k.b); }
76 //usleep (5*1024*1024);
77 if(check_me) {
78 assert(c);
79 assert(keep);
80 assert(w);
81 if (v == &val1) {
82 v1_written = true;
83 }
84 else if (v == &val2) {
85 v2_written = true;
86 }
87 else {
88 assert(false);
89 }
90 }
91 }
92
93 static int
fetch(CACHEFILE f,PAIR UU (p),int UU (fd),CACHEKEY k,uint32_t fullhash,void ** value,void ** UU (dd),PAIR_ATTR * sizep,int * dirtyp,void * extraargs)94 fetch (CACHEFILE f __attribute__((__unused__)),
95 PAIR UU(p),
96 int UU(fd),
97 CACHEKEY k __attribute__((__unused__)),
98 uint32_t fullhash __attribute__((__unused__)),
99 void **value __attribute__((__unused__)),
100 void** UU(dd),
101 PAIR_ATTR *sizep __attribute__((__unused__)),
102 int *dirtyp,
103 void *extraargs __attribute__((__unused__))
104 ) {
105 *dirtyp = 0;
106 *value = extraargs;
107 *sizep = make_pair_attr(8);
108 *dest_pair = p;
109 return 0;
110 }
111
get_key_and_fullhash(CACHEKEY * cachekey,uint32_t * fullhash,void * extra)112 static void get_key_and_fullhash(CACHEKEY* cachekey, uint32_t* fullhash, void* extra) {
113 assert(extra == NULL);
114 cachekey->b = 3;
115 *fullhash = 3;
116 }
117
118
119 static void
cachetable_test(bool write_first,bool write_second,bool start_checkpoint)120 cachetable_test (bool write_first, bool write_second, bool start_checkpoint) {
121 const int test_limit = 12;
122 int r;
123 CACHETABLE ct;
124 toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
125 const char *fname1 = TOKU_TEST_FILENAME;
126 unlink(fname1);
127 CACHEFILE f1;
128 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
129 create_dummy_functions(f1);//toku_cachefile_set_userdata(ft, NULL, NULL,
130
131 void* v1;
132 void* v2;
133 PAIR dependent_pairs[2];
134 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
135 wc.flush_callback = flush;
136 dest_pair = &dependent_pairs[0];
137 r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, fetch, def_pf_req_callback, def_pf_callback, true, &val1);
138 assert(r==0);
139 dest_pair = &dependent_pairs[1];
140 r = toku_cachetable_get_and_pin(f1, make_blocknum(2), 2, &v2, wc, fetch, def_pf_req_callback, def_pf_callback, true, &val2);
141 assert(r==0);
142
143 // now we set the dirty state of these two.
144 enum cachetable_dirty cd[2];
145 cd[0] = write_first ? CACHETABLE_DIRTY : CACHETABLE_CLEAN;
146 cd[1] = write_second ? CACHETABLE_DIRTY : CACHETABLE_CLEAN;
147 CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
148 if (start_checkpoint) {
149 //
150 // should mark the v1 and v2 as pending
151 //
152 toku_cachetable_begin_checkpoint(cp, NULL);
153 }
154 //
155 // This call should cause a flush for both
156 //
157 check_me = true;
158 v1_written = false;
159 v2_written = false;
160
161 CACHEKEY put_key;
162 uint32_t put_fullhash;
163 PAIR dummy_pair;
164 dest_pair = &dummy_pair;
165 toku_cachetable_put_with_dep_pairs(
166 f1,
167 get_key_and_fullhash,
168 &val3,
169 make_pair_attr(8),
170 wc,
171 NULL,
172 2, //num_dependent_pairs
173 dependent_pairs,
174 cd,
175 &put_key,
176 &put_fullhash,
177 put_callback_pair
178 );
179 assert(put_key.b == 3);
180 assert(put_fullhash == 3);
181
182 if (start_checkpoint) {
183 assert(v1_written == write_first);
184 assert(v2_written == write_second);
185 }
186
187 check_me = false;
188 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
189 r = toku_test_cachetable_unpin(f1, make_blocknum(2), 2, CACHETABLE_CLEAN, make_pair_attr(8));
190 r = toku_test_cachetable_unpin(f1, make_blocknum(3), 3, CACHETABLE_CLEAN, make_pair_attr(8));
191
192 if (start_checkpoint) {
193 toku_cachetable_end_checkpoint(
194 cp,
195 NULL,
196 NULL,
197 NULL
198 );
199 }
200
201 toku_cachetable_verify(ct);
202 toku_cachefile_close(&f1, false, ZERO_LSN);
203 toku_cachetable_close(&ct);
204
205
206 }
207
208 int
test_main(int argc,const char * argv[])209 test_main(int argc, const char *argv[]) {
210 default_parse_args(argc, argv);
211 cachetable_test(false,false,true);
212 cachetable_test(false,true,true);
213 cachetable_test(true,false,true);
214 cachetable_test(true,true,true);
215 cachetable_test(false,false,false);
216 cachetable_test(false,true,false);
217 cachetable_test(true,false,false);
218 cachetable_test(true,true,false);
219 return 0;
220 }
221