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