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