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 /* Purpose of this test is to verify correct behavior of
40 * environment startup:
41 *
42 * All three of the following should exist or all three should not exist:
43 * - persistent environment
44 * - fileops directory
45 * - recovery log (if DB_INIT_LOG)
46 *
47 * If all three are missing, env->open() should create a new environment.
48 * If any one is present and any other is missing, env->open() should return ENOENT.
49 *
50 * TODO: experiment with DB_INIT_LOG off.
51 */
52
53
54 #include "test.h"
55 #include <db.h>
56
57 static DB_ENV *env;
58
59 #define FLAGS_NOLOG DB_INIT_LOCK|DB_INIT_MPOOL|DB_CREATE|DB_PRIVATE
60 #define FLAGS_LOG FLAGS_NOLOG|DB_INIT_TXN|DB_INIT_LOG
61
62 static int mode = S_IRWXU+S_IRWXG+S_IRWXO;
63
64 static void test_shutdown(void);
65
66 static void
setup(uint32_t flags)67 setup (uint32_t flags) {
68 int r;
69 if (env)
70 test_shutdown();
71 toku_os_recursive_delete(TOKU_TEST_FILENAME);
72 r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
73 CKERR(r);
74 r=db_env_create(&env, 0);
75 CKERR(r);
76 env->set_errfile(env, stderr);
77 r=env->open(env, TOKU_TEST_FILENAME, flags, mode);
78 CKERR(r);
79 }
80
81
82
83 static void
test_shutdown(void)84 test_shutdown(void) {
85 int r;
86 r=env->close(env, 0); CKERR(r);
87 env = NULL;
88 }
89
90
91 static void
reopen_env(uint32_t flags,int expected_r)92 reopen_env(uint32_t flags, int expected_r) {
93 int r;
94 if (env)
95 test_shutdown();
96 r = db_env_create(&env, 0);
97 CKERR(r);
98 r = env->open(env, TOKU_TEST_FILENAME, flags, mode);
99 CKERR2(r, expected_r);
100 }
101
102 static void
delete_persistent(void)103 delete_persistent(void) {
104 char cmd[1024];
105 sprintf(cmd, "rm -rf %s%s%s", TOKU_TEST_FILENAME, "/", "tokudb.environment");
106 int r = system(cmd);
107 CKERR(r);
108 }
109
110
111 static void
delete_directory(void)112 delete_directory(void) {
113 char cmd[1024];
114 sprintf(cmd, "rm -rf %s%s%s", TOKU_TEST_FILENAME, "/", "tokudb.directory");
115 int r = system(cmd);
116 CKERR(r);
117 }
118
119
120 static void
delete_log(void)121 delete_log(void) {
122 char cmd[1024];
123 sprintf(cmd, "rm -rf %s%s%s", TOKU_TEST_FILENAME, "/", "*.tokulog*");
124 int r = system(cmd);
125 CKERR(r);
126 }
127
128
129 static void
create_env(uint32_t flags)130 create_env(uint32_t flags) {
131 setup(flags); // create new environment
132 test_shutdown();
133 reopen_env(flags, 0); // reopen existing environment, should have log now
134 test_shutdown();
135 }
136
137
138 static void
test_env_startup(int logging)139 test_env_startup(int logging) {
140 uint32_t flags;
141
142 if (logging)
143 flags = FLAGS_LOG;
144 else
145 flags = FLAGS_NOLOG;
146
147 create_env(flags);
148
149 // delete persistent info and try to reopen
150 delete_persistent();
151 reopen_env(flags, ENOENT);
152
153 // recreate, then try to open with missing fileops directory
154 create_env(flags);
155 delete_directory();
156 reopen_env(flags, ENOENT);
157
158
159 if (logging) {
160 // recreate, then try to open with missing recovery log
161 create_env(flags);
162 delete_log();
163 reopen_env(flags, ENOENT);
164
165
166 // now try two missing items, if log can be present
167
168 // log is only item present
169 create_env(flags);
170 delete_persistent();
171 delete_directory();
172 reopen_env(flags, ENOENT);
173
174 // persistent env is only item present
175 create_env(flags);
176 delete_log();
177 delete_directory();
178 reopen_env(flags, ENOENT);
179
180 // directory is only item present
181 create_env(flags);
182 delete_persistent();
183 delete_log();
184 reopen_env(flags, ENOENT);
185 }
186
187 test_shutdown();
188 }
189
190
191 int
test_main(int argc,char * const argv[])192 test_main (int argc, char * const argv[]) {
193 parse_args(argc, argv);
194 test_env_startup(0); // transactionless env
195 test_env_startup(1); // with transactions and logging
196 return 0;
197 }
198