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