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