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 /* verify that get_and_pin waits while a prefetch block is pending */
40
41 #include "test.h"
42
43 bool do_pf;
44 bool expect_pf;
45
46 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))47 flush (CACHEFILE f __attribute__((__unused__)),
48 int UU(fd),
49 CACHEKEY k __attribute__((__unused__)),
50 void *v __attribute__((__unused__)),
51 void** UU(dd),
52 void *e __attribute__((__unused__)),
53 PAIR_ATTR s __attribute__((__unused__)),
54 PAIR_ATTR* new_size __attribute__((__unused__)),
55 bool w __attribute__((__unused__)),
56 bool keep __attribute__((__unused__)),
57 bool c __attribute__((__unused__)),
58 bool UU(is_clone)
59 ) {
60 assert(w == false);
61 }
62
63 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)64 fetch (CACHEFILE f __attribute__((__unused__)),
65 PAIR UU(p),
66 int UU(fd),
67 CACHEKEY k __attribute__((__unused__)),
68 uint32_t fullhash __attribute__((__unused__)),
69 void **value __attribute__((__unused__)),
70 void** UU(dd),
71 PAIR_ATTR *sizep __attribute__((__unused__)),
72 int *dirtyp __attribute__((__unused__)),
73 void *extraargs __attribute__((__unused__))
74 ) {
75
76 if(!expect_pf) {
77 sleep(2);
78 }
79 *value = 0;
80 *sizep = make_pair_attr(2);
81 *dirtyp = 0;
82
83 return 0;
84 }
85
pf_req_callback(void * UU (ftnode_pv),void * UU (read_extraargs))86 static bool pf_req_callback(void* UU(ftnode_pv), void* UU(read_extraargs)) {
87 if (do_pf) {
88 assert(expect_pf);
89 return true;
90 }
91 else {
92 return false;
93 }
94 }
95
pf_callback(void * UU (ftnode_pv),void * UU (dd),void * UU (read_extraargs),int UU (fd),PAIR_ATTR * UU (sizep))96 static int pf_callback(void* UU(ftnode_pv), void* UU(dd), void* UU(read_extraargs), int UU(fd), PAIR_ATTR* UU(sizep)) {
97 assert(expect_pf);
98 sleep(2);
99 *sizep = make_pair_attr(2);
100 return 0;
101 }
102
tdelta_usec(struct timeval * tend,struct timeval * tstart)103 static uint64_t tdelta_usec(struct timeval *tend, struct timeval *tstart) {
104 uint64_t t = tend->tv_sec * 1000000 + tend->tv_usec;
105 t -= tstart->tv_sec * 1000000 + tstart->tv_usec;
106 return t;
107 }
108
cachetable_prefetch_maybegetandpin_test(bool do_partial_fetch)109 static void cachetable_prefetch_maybegetandpin_test (bool do_partial_fetch) {
110 const int test_limit = 2;
111 int r;
112 CACHETABLE ct;
113 toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
114 const char *fname1 = TOKU_TEST_FILENAME;
115 unlink(fname1);
116 CACHEFILE f1;
117 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
118 expect_pf = false;
119 do_pf = false;
120 CACHEKEY key = make_blocknum(0);
121 uint32_t fullhash = toku_cachetable_hash(f1, make_blocknum(0));
122 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
123 wc.flush_callback = flush;
124 if (do_partial_fetch) {
125 expect_pf = true;
126 void* value;
127 r = toku_cachetable_get_and_pin(
128 f1,
129 key,
130 fullhash,
131 &value,
132 wc,
133 fetch,
134 pf_req_callback,
135 pf_callback,
136 true,
137 0
138 );
139 assert(r==0);
140 r = toku_test_cachetable_unpin(f1, key, fullhash, CACHETABLE_CLEAN, make_pair_attr(1));
141 }
142
143 struct timeval tstart;
144 gettimeofday(&tstart, NULL);
145
146 // prefetch block 0. this will take 2 seconds.
147 do_pf = true;
148 r = toku_cachefile_prefetch(f1, key, fullhash, wc, fetch, pf_req_callback, pf_callback, 0, NULL);
149 toku_cachetable_verify(ct);
150
151 // verify that get_and_pin waits while the prefetch is in progress
152 void *v = 0;
153 do_pf = false;
154 r = toku_cachetable_get_and_pin_nonblocking(f1, key, fullhash, &v, wc, fetch, pf_req_callback, pf_callback, PL_WRITE_EXPENSIVE, NULL, NULL);
155 assert(r==TOKUDB_TRY_AGAIN);
156 r = toku_cachetable_get_and_pin(f1, key, fullhash, &v, wc, fetch, pf_req_callback, pf_callback, true, NULL);
157 assert(r == 0 && v == 0);
158 PAIR_ATTR attr;
159 r = toku_cachetable_get_attr(f1, key, fullhash, &attr);
160 assert(r == 0 && attr.size == 2);
161
162 struct timeval tend;
163 gettimeofday(&tend, NULL);
164
165 assert(tdelta_usec(&tend, &tstart) >= 1900000);
166
167 toku_cachetable_verify(ct);
168
169 r = toku_test_cachetable_unpin(f1, key, fullhash, CACHETABLE_CLEAN, make_pair_attr(1));
170 assert(r == 0);
171 toku_cachetable_verify(ct);
172
173 toku_cachefile_close(&f1, false, ZERO_LSN);
174 toku_cachetable_close(&ct);
175 }
176
177 int
test_main(int argc,const char * argv[])178 test_main(int argc, const char *argv[]) {
179 default_parse_args(argc, argv);
180 cachetable_prefetch_maybegetandpin_test(true);
181 cachetable_prefetch_maybegetandpin_test(false);
182 return 0;
183 }
184