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
41 bool pf_called;
42 bool fetch_called;
43 CACHEFILE f1;
44
45 static int
sleep_fetch(CACHEFILE f,PAIR UU (p),int UU (fd),CACHEKEY k,uint32_t fullhash,void ** value,void ** dd,PAIR_ATTR * sizep,int * dirtyp,void * extraargs)46 sleep_fetch (CACHEFILE f __attribute__((__unused__)),
47 PAIR UU(p),
48 int UU(fd),
49 CACHEKEY k __attribute__((__unused__)),
50 uint32_t fullhash __attribute__((__unused__)),
51 void **value __attribute__((__unused__)),
52 void **dd __attribute__((__unused__)),
53 PAIR_ATTR *sizep __attribute__((__unused__)),
54 int *dirtyp,
55 void *extraargs __attribute__((__unused__))
56 ) {
57 sleep(2);
58 *dirtyp = 0;
59 *value = NULL;
60 *sizep = make_pair_attr(8);
61 fetch_called = true;
62 return 0;
63 }
64
sleep_pf_req_callback(void * UU (ftnode_pv),void * UU (read_extraargs))65 static bool sleep_pf_req_callback(void* UU(ftnode_pv), void* UU(read_extraargs)) {
66 if (pf_called || fetch_called) return false;
67 return true;
68 return true;
69 }
70
sleep_pf_callback(void * UU (ftnode_pv),void * UU (disk_data),void * UU (read_extraargs),int UU (fd),PAIR_ATTR * sizep)71 static int sleep_pf_callback(void* UU(ftnode_pv), void* UU(disk_data), void* UU(read_extraargs), int UU(fd), PAIR_ATTR* sizep) {
72 sleep(2);
73 *sizep = make_pair_attr(8);
74 pf_called = true;
75 return 0;
76 }
77
run_expensive_pf(void * arg)78 static void *run_expensive_pf(void *arg) {
79 void* v1;
80 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
81 pf_called = false;
82 fetch_called = false;
83 int r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, sleep_fetch, sleep_pf_req_callback, sleep_pf_callback, false, NULL);
84 assert_zero(r);
85 assert(pf_called);
86 return arg;
87 }
88
run_expensive_fetch(void * arg)89 static void *run_expensive_fetch(void *arg) {
90 void* v1;
91 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
92 pf_called = false;
93 fetch_called = false;
94 int r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, sleep_fetch, sleep_pf_req_callback, sleep_pf_callback, false, NULL);
95 assert_zero(r);
96 assert(fetch_called);
97 return arg;
98 }
99
100
101 static void
run_test(void)102 run_test (void) {
103 const int test_limit = 12;
104 int r;
105 void *ret;
106 CACHETABLE ct;
107 toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
108 const char *fname1 = TOKU_TEST_FILENAME;
109 unlink(fname1);
110 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
111
112 void* v1;
113 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
114
115 toku_pthread_t fetch_tid;
116 fetch_called = false;
117 r = toku_pthread_create(
118 toku_uninstrumented, &fetch_tid, nullptr, run_expensive_fetch, nullptr);
119 sleep(1);
120 r = toku_cachetable_get_and_pin(f1,
121 make_blocknum(1),
122 1,
123 &v1,
124 wc,
125 sleep_fetch,
126 def_pf_req_callback,
127 def_pf_callback,
128 false,
129 NULL);
130 assert_zero(r);
131 assert(fetch_called);
132 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
133 assert(r==0);
134 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
135 assert(r==0);
136 r = toku_pthread_join(fetch_tid, &ret);
137 assert_zero(r);
138
139 // call with may_modify_node = false twice, make sure we can get it
140 r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL);
141 assert_zero(r);
142 r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL);
143 assert_zero(r);
144 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
145 assert(r==0);
146 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
147 assert(r==0);
148
149 toku_pthread_t pf_tid;
150 pf_called = false;
151 r = toku_pthread_create(
152 toku_uninstrumented, &pf_tid, nullptr, run_expensive_pf, nullptr);
153 sleep(1);
154 r = toku_cachetable_get_and_pin(f1,
155 make_blocknum(1),
156 1,
157 &v1,
158 wc,
159 sleep_fetch,
160 def_pf_req_callback,
161 def_pf_callback,
162 false,
163 NULL);
164 assert_zero(r);
165 assert(pf_called);
166 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
167 assert(r==0);
168 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
169 assert(r==0);
170
171 r = toku_pthread_join(pf_tid, &ret);
172 assert_zero(r);
173
174 toku_cachetable_verify(ct);
175 toku_cachefile_close(&f1, false, ZERO_LSN);
176 toku_cachetable_close(&ct);
177 }
178
179 int
test_main(int argc,const char * argv[])180 test_main(int argc, const char *argv[]) {
181 default_parse_args(argc, argv);
182 run_test();
183 return 0;
184 }
185