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