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 /* Idea: inflate a node by
40 * create a 2-level tree
41 * Nodes are A B C D E F G H
42 * Fill them up sequentially so they'll all be near 4MB.
43 * Close the file
44 * Insert some more to H (buffered in the root)
45 * Delete stuff from G (so that H merges with G)
46 * G ends up too big.
47 */
48
49 #include "test.h"
50
51 DB_ENV *env;
52 DB *db;
53 const char dbname[] = "foo.db";
54 const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_PRIVATE|DB_INIT_TXN;
55
56 static void
open_em(void)57 open_em (void)
58 {
59 int r;
60 r = db_env_create(&env, 0); CKERR(r);
61 r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
62 r = db_create(&db, env, 0); CKERR(r);
63 r = db->open(db, NULL, dbname, NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r);
64 }
65
66 static void
close_em(void)67 close_em (void)
68 {
69 int r;
70 r = db->close(db, 0); CKERR(r);
71 r = env->close(env, 0); CKERR(r);
72 }
73
74 static void
reopen_em(void)75 reopen_em (void)
76 {
77 close_em();
78 open_em();
79 }
80
81
82 static void
setup(void)83 setup(void)
84 {
85 int r;
86 toku_os_recursive_delete(TOKU_TEST_FILENAME);
87 toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
88 r = db_env_create(&env, 0); CKERR(r);
89 r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
90 r = db_create(&db, env, 0); CKERR(r);
91 r = db->set_pagesize(db, 8192); CKERR(r);
92 r = db->open(db, NULL, dbname, NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r);
93 }
94
95 char vdata[150];
96
97 static void
insert_n(uint32_t ah)98 insert_n (uint32_t ah) {
99 uint32_t an = htonl(ah);
100 DBT key;
101 dbt_init(&key, &an, 4);
102 DBT val;
103 dbt_init(&val, vdata, sizeof vdata);
104 int r = db->put(db, NULL, &key, &val, 0);
105 CKERR(r);
106 }
107
108 static void
delete_n(uint32_t ah)109 delete_n (uint32_t ah)
110 {
111 uint32_t an = htonl(ah);
112 DBT key;
113 dbt_init(&key, &an, 4);
114 int r = db->del(db, NULL, &key, DB_DELETE_ANY);
115 CKERR(r);
116 }
117
118 static void
get_n(uint32_t ah,int expect_r)119 get_n (uint32_t ah, int expect_r)
120 {
121 uint32_t an = htonl(ah);
122 DBT key;
123 dbt_init(&key, &an, 4);
124 DBT val;
125 dbt_init_malloc(&val);
126 int r = db->get(db, NULL, &key, &val, 0);
127 assert(r==expect_r);
128 if (r==0) toku_free(val.data);
129 }
130
131 static void
doit(void)132 doit (void)
133 {
134 uint32_t N=100;
135 for (uint32_t i=0; i<N; i++) {
136 insert_n(i<<16);
137 }
138 reopen_em();
139 for (uint32_t j=0; j<46; j++) {
140 insert_n(('.'<<16) + 1 +j);
141 }
142 for (uint32_t i=N-1; i<N; i++) {
143 delete_n(i<<16);
144 get_n(i<<16, DB_NOTFOUND);
145 }
146 reopen_em();
147 insert_n(N<<16);
148 get_n(N<<16, 0);
149 reopen_em();
150 for (uint32_t i='J'; i<N+1; i++) {
151 delete_n(i<<16);
152 get_n(i<<16, DB_NOTFOUND);
153 }
154 reopen_em();
155 reopen_em();
156 for (uint32_t j=0; j<46; j++) {
157 insert_n(('.'<<16) + 1 +j +46);
158 }
159 for (uint32_t i=0; i<13; i++) {
160 delete_n((73 - i)<< 16);
161 get_n((73-i) << 16, DB_NOTFOUND);
162 }
163 reopen_em(); // now a node is 9143 bytes
164 }
165
test_main(int argc,char * const argv[])166 int test_main (int argc __attribute__((__unused__)), char * const argv[] __attribute__((__unused__))) {
167 setup();
168 doit();
169 close_em();
170 return 0;
171 }
172