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