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