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 uint64_t clean_val = 0;
43 uint64_t dirty_val = 0;
44
45 bool check_me;
46 bool flush_called;
47
48 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))49 flush (CACHEFILE f __attribute__((__unused__)),
50 int UU(fd),
51 CACHEKEY k __attribute__((__unused__)),
52 void *v __attribute__((__unused__)),
53 void** UU(dd),
54 void *e __attribute__((__unused__)),
55 PAIR_ATTR s __attribute__((__unused__)),
56 PAIR_ATTR* new_size __attribute__((__unused__)),
57 bool w __attribute__((__unused__)),
58 bool keep __attribute__((__unused__)),
59 bool c __attribute__((__unused__)),
60 bool UU(is_clone)
61 ) {
62 /* Do nothing */
63 if (verbose) { printf("FLUSH: %d\n", (int)k.b); }
64 //usleep (5*1024*1024);
65 // if the checkpoint is pending, assert that it is of what we made dirty
66 if (check_me) {
67 flush_called = true;
68 assert(c);
69 assert(e == &dirty_val);
70 assert(v == &dirty_val);
71 assert(keep);
72 assert(w);
73 }
74 }
75
76 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)77 fetch (CACHEFILE f __attribute__((__unused__)),
78 PAIR UU(p),
79 int UU(fd),
80 CACHEKEY k __attribute__((__unused__)),
81 uint32_t fullhash __attribute__((__unused__)),
82 void **value __attribute__((__unused__)),
83 void** UU(dd),
84 PAIR_ATTR *sizep __attribute__((__unused__)),
85 int *dirtyp,
86 void *extraargs __attribute__((__unused__))
87 ) {
88 *dirtyp = 0;
89 if (extraargs) {
90 *value = &dirty_val;
91 }
92 else {
93 *value = &clean_val;
94 }
95 *sizep = make_pair_attr(8);
96 return 0;
97 }
98
99 static void
cachetable_test(void)100 cachetable_test (void) {
101 const int test_limit = 20;
102 int r;
103 CACHETABLE ct;
104 toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
105 const char *fname1 = TOKU_TEST_FILENAME;
106 unlink(fname1);
107 CACHEFILE f1;
108 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
109 create_dummy_functions(f1);
110
111 void* v1;
112 void* v2;
113 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(&dirty_val);
114 wc.flush_callback = flush;
115 r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, fetch, def_pf_req_callback, def_pf_callback, true, &dirty_val);
116 wc.write_extraargs = NULL;
117 r = toku_cachetable_get_and_pin(f1, make_blocknum(2), 2, &v2, wc, fetch, def_pf_req_callback, def_pf_callback, true, NULL);
118
119 //
120 // Here is the test, we have two pairs, v1 is dirty, v2 is clean, but both are currently pinned
121 // Then we will begin a checkpoint, which should theoretically mark both as pending, but
122 // flush will be called only for v1, because v1 is dirty
123 //
124 CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
125 toku_cachetable_begin_checkpoint(cp, NULL);
126
127
128 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_DIRTY, make_pair_attr(8));
129 r = toku_test_cachetable_unpin(f1, make_blocknum(2), 2, CACHETABLE_CLEAN, make_pair_attr(8));
130
131 check_me = true;
132 flush_called = false;
133 toku_cachetable_end_checkpoint(
134 cp,
135 NULL,
136 NULL,
137 NULL
138 );
139 assert(r==0);
140 assert(flush_called);
141 check_me = false;
142
143 toku_cachetable_verify(ct);
144 toku_cachefile_close(&f1, false, ZERO_LSN);
145 toku_cachetable_close(&ct);
146
147
148 }
149
150 int
test_main(int argc,const char * argv[])151 test_main(int argc, const char *argv[]) {
152 default_parse_args(argc, argv);
153 cachetable_test();
154 return 0;
155 }
156