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 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)42 fetch (CACHEFILE f __attribute__((__unused__)),
43 PAIR UU(p),
44 int UU(fd),
45 CACHEKEY k __attribute__((__unused__)),
46 uint32_t fullhash __attribute__((__unused__)),
47 void **value __attribute__((__unused__)),
48 void** UU(dd),
49 PAIR_ATTR *sizep __attribute__((__unused__)),
50 int *dirtyp __attribute__((__unused__)),
51 void *extraargs __attribute__((__unused__))
52 ) {
53 *dirtyp = 0;
54 *sizep = make_pair_attr(0);
55 return 0;
56 }
57
58 // test simple unpin and remove
59 static void
cachetable_unpin_and_remove_test(int n)60 cachetable_unpin_and_remove_test (int n) {
61 if (verbose) printf("%s %d\n", __FUNCTION__, n);
62 const int table_limit = 2*n;
63 int r;
64 int i;
65
66 CACHETABLE ct;
67 toku_cachetable_create(&ct, table_limit, ZERO_LSN, nullptr);
68 const char *fname1 = TOKU_TEST_FILENAME;
69 unlink(fname1);
70 CACHEFILE f1;
71 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0);
72 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
73
74 // generate some random keys
75 CACHEKEY keys[n]; int nkeys = n;
76 for (i=0; i<n; i++) {
77 keys[i].b = random();
78 }
79
80 // put the keys into the cachetable
81 for (i=0; i<n; i++) {
82 uint32_t hi = toku_cachetable_hash(f1, make_blocknum(keys[i].b));
83 toku_cachetable_put(f1, make_blocknum(keys[i].b), hi, (void *)(long) keys[i].b, make_pair_attr(1),wc, put_callback_nop);
84 }
85
86 // unpin and remove
87 CACHEKEY testkeys[n];
88 for (i=0; i<n; i++) testkeys[i] = keys[i];
89 while (nkeys > 0) {
90 i = random() % nkeys;
91 uint32_t hi = toku_cachetable_hash(f1, make_blocknum(testkeys[i].b));
92 r = toku_test_cachetable_unpin_and_remove(f1, testkeys[i], NULL, NULL);
93 assert(r == 0);
94
95 toku_cachefile_verify(f1);
96
97 // verify that k is removed
98 void *v;
99 r = toku_cachetable_maybe_get_and_pin(f1, make_blocknum(testkeys[i].b), hi, PL_WRITE_EXPENSIVE, &v);
100 assert(r != 0);
101
102 testkeys[i] = testkeys[nkeys-1]; nkeys -= 1;
103 }
104
105 // verify that the cachtable is empty
106 int nentries;
107 toku_cachetable_get_state(ct, &nentries, NULL, NULL, NULL);
108 assert(nentries == 0);
109
110 toku_cachefile_close(&f1, false, ZERO_LSN);
111 toku_cachetable_close(&ct);
112 }
113
114 // test remove when the pair in being written
115 static void
cachetable_put_evict_remove_test(int n)116 cachetable_put_evict_remove_test (int n) {
117 if (verbose) printf("%s %d\n", __FUNCTION__, n);
118 const int table_limit = n-1;
119 int r;
120 int i;
121
122 CACHETABLE ct;
123 toku_cachetable_create(&ct, table_limit, ZERO_LSN, nullptr);
124 const char *fname1 = TOKU_TEST_FILENAME;
125 unlink(fname1);
126 CACHEFILE f1;
127 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0);
128 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
129
130 uint32_t hi[n];
131 for (i=0; i<n; i++)
132 hi[i] = toku_cachetable_hash(f1, make_blocknum(i));
133
134 // put 0, 1, 2, ... should evict 0
135 for (i=0; i<n; i++) {
136 toku_cachetable_put(f1, make_blocknum(i), hi[i], (void *)(long)i, make_pair_attr(1), wc, put_callback_nop);
137 r = toku_test_cachetable_unpin(f1, make_blocknum(i), hi[i], CACHETABLE_CLEAN, make_pair_attr(1));
138 assert(r == 0);
139 }
140
141 // get 0
142 void *v;
143 r = toku_cachetable_get_and_pin(f1, make_blocknum(0), hi[0], &v, wc, fetch, def_pf_req_callback, def_pf_callback, true, 0);
144 assert(r == 0);
145
146 // remove 0
147 r = toku_test_cachetable_unpin_and_remove(f1, make_blocknum(0), NULL, NULL);
148 assert(r == 0);
149
150 toku_cachefile_close(&f1, false, ZERO_LSN);
151 toku_cachetable_close(&ct);
152 }
153
154 int
test_main(int argc,const char * argv[])155 test_main(int argc, const char *argv[]) {
156 default_parse_args(argc, argv);
157 cachetable_unpin_and_remove_test(8);
158 cachetable_put_evict_remove_test(4);
159 return 0;
160 }
161