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 flush_completed;
43 bool pf_called;
44 
45 static void
clone_callback(void * UU (value_data),void ** cloned_value_data,long * clone_size,PAIR_ATTR * new_attr,bool UU (for_checkpoint),void * UU (write_extraargs))46 clone_callback(void* UU(value_data), void** cloned_value_data, long* clone_size, PAIR_ATTR* new_attr, bool UU(for_checkpoint), void* UU(write_extraargs))
47 {
48     *cloned_value_data = (void *)1;
49     *clone_size = 8;
50     new_attr->is_valid = false;
51 }
52 
53 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))54 flush (
55     CACHEFILE f __attribute__((__unused__)),
56     int UU(fd),
57     CACHEKEY k  __attribute__((__unused__)),
58     void *v     __attribute__((__unused__)),
59     void** UU(dd),
60     void *e     __attribute__((__unused__)),
61     PAIR_ATTR s      __attribute__((__unused__)),
62     PAIR_ATTR* new_size      __attribute__((__unused__)),
63     bool w      __attribute__((__unused__)),
64     bool keep   __attribute__((__unused__)),
65     bool c      __attribute__((__unused__)),
66     bool UU(is_clone)
67     )
68 {
69     if (is_clone) {
70         usleep(2*1024*1024);
71         flush_completed = true;
72     }
73 }
74 
true_pf_callback(void * UU (ftnode_pv),void * UU (dd),void * UU (read_extraargs),int UU (fd),PAIR_ATTR * sizep)75 static int true_pf_callback(void* UU(ftnode_pv), void* UU(dd), void* UU(read_extraargs), int UU(fd), PAIR_ATTR* sizep) {
76     assert(flush_completed);
77     pf_called = true;
78     *sizep = make_pair_attr(9);
79     return 0;
80 }
81 
82 
83 // this test verifies that a partial fetch will wait for a cloned pair to complete
84 // writing to disk
85 static void
cachetable_test(void)86 cachetable_test (void) {
87     const int test_limit = 12;
88     int r;
89     CACHETABLE ct;
90     toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
91     const char *fname1 = TOKU_TEST_FILENAME;
92     unlink(fname1);
93     CACHEFILE f1;
94     r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
95     create_dummy_functions(f1);
96 
97     void* v1;
98     CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
99     wc.clone_callback = clone_callback;
100     wc.flush_callback = flush;
101 
102     r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL);
103     assert_zero(r);
104     r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_DIRTY, make_pair_attr(8));
105     assert_zero(r);
106 
107     flush_completed = false;
108     CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
109     toku_cachetable_begin_checkpoint(cp, NULL);
110     assert_zero(r);
111     r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL);
112     assert_zero(r);
113     r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
114     assert_zero(r);
115 
116     pf_called = false;
117     r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL);
118     assert_zero(r);
119     assert(!pf_called);
120     toku_cachetable_pf_pinned_pair(v1, true_pf_callback, NULL, f1, make_blocknum(1), 1);
121     assert(pf_called);
122 
123     r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
124     assert_zero(r);
125     assert(pf_called);
126 
127     toku_cachetable_end_checkpoint(
128         cp,
129         NULL,
130         NULL,
131         NULL
132         );
133     assert_zero(r);
134 
135 
136     toku_cachetable_verify(ct);
137     toku_cachefile_close(&f1, false, ZERO_LSN);
138     toku_cachetable_close(&ct);
139 
140 
141 }
142 
143 int
test_main(int argc,const char * argv[])144 test_main(int argc, const char *argv[]) {
145   default_parse_args(argc, argv);
146   cachetable_test();
147   return 0;
148 }
149