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 evict_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     else if (!keep && !is_clone) {
74         assert(flush_completed);
75         evict_called = true;
76     }
77 }
78 
79 
80 
81 // this test verifies that a partial fetch will wait for a cloned pair to complete
82 // writing to disk
83 static void
cachetable_test(void)84 cachetable_test (void) {
85     const int test_limit = 12;
86     int r;
87     CACHETABLE ct;
88     toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
89     const char *fname1 = TOKU_TEST_FILENAME;
90     unlink(fname1);
91     CACHEFILE f1;
92     r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
93     create_dummy_functions(f1);
94 
95     void* v1;
96     CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
97     wc.clone_callback = clone_callback;
98     wc.flush_callback = flush;
99 
100     r = toku_cachetable_get_and_pin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL);
101     assert_zero(r);
102     r = toku_test_cachetable_unpin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), CACHETABLE_DIRTY, make_pair_attr(8));
103     assert_zero(r);
104 
105     flush_completed = false;
106     evict_called = false;
107     CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
108     toku_cachetable_begin_checkpoint(cp, NULL);
109     assert_zero(r);
110     r = toku_cachetable_get_and_pin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL);
111     assert_zero(r);
112     r = toku_test_cachetable_unpin_and_remove(f1, make_blocknum(1), NULL, NULL);
113     assert_zero(r);
114 
115 
116     toku_cachetable_end_checkpoint(
117         cp,
118         NULL,
119         NULL,
120         NULL
121         );
122     assert_zero(r);
123 
124 
125     toku_cachetable_verify(ct);
126     toku_cachefile_close(&f1, false, ZERO_LSN);
127     toku_cachetable_close(&ct);
128 
129 
130 }
131 
132 int
test_main(int argc,const char * argv[])133 test_main(int argc, const char *argv[]) {
134   default_parse_args(argc, argv);
135   cachetable_test();
136   return 0;
137 }
138