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 // verify that DB_RUNRECOVERY is returned when there is a missing db file
40
41 #include <sys/stat.h>
42 #include "test.h"
43
44
45 const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE;
46
47 #define NAMEA "a.db"
48 const char *namea=NAMEA;
49 #define NAMEB "b.db"
50 #define NAMEB_HINT "b_db"
51 const char *nameb=NAMEB;
52
run_test(void)53 static void run_test (void) {
54 int r;
55 toku_os_recursive_delete(TOKU_TEST_FILENAME);
56 toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
57 DB_ENV *env;
58
59 r = db_env_create(&env, 0); CKERR(r);
60 db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
61 r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
62
63 DB *dba;
64 r = db_create(&dba, env, 0); CKERR(r);
65 r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
66 r = dba->close(dba, 0); CKERR(r);
67
68 DB *dbb;
69 r = db_create(&dbb, env, 0); CKERR(r);
70 r = dbb->open(dbb, NULL, nameb, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
71 r = dbb->close(dbb, 0); CKERR(r);
72
73 r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r);
74
75 DB_TXN *txn;
76 r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
77
78 r = db_create(&dba, env, 0); CKERR(r);
79 r = dba->open(dba, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r);
80
81 r = db_create(&dbb, env, 0); CKERR(r);
82 r = dbb->open(dbb, NULL, nameb, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r);
83
84 r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r);
85
86 r = txn->commit(txn, 0); CKERR(r);
87
88 toku_hard_crash_on_purpose();
89 }
90
run_recover(void)91 static void run_recover (void) {
92 DB_ENV *env;
93 int r;
94
95 char saveddbs[TOKU_PATH_MAX+1];
96 toku_path_join(saveddbs, 2, TOKU_TEST_FILENAME, "saveddbs");
97 toku_os_recursive_delete(saveddbs);
98 r = toku_os_mkdir(saveddbs, S_IRWXU+S_IRWXG+S_IRWXO);
99 CKERR(r);
100
101 char glob[TOKU_PATH_MAX+1];
102 toku_path_join(glob, 2, TOKU_TEST_FILENAME, NAMEB_HINT "*.tokudb");
103 char cmd[2 * TOKU_PATH_MAX + sizeof("mv ")];
104 snprintf(cmd, sizeof(cmd), "mv %s %s", glob, saveddbs);
105 r = system(cmd);
106 CKERR(r);
107
108 r = db_env_create(&env, 0); CKERR(r);
109 db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
110 r = env->open(env, TOKU_TEST_FILENAME, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO);
111 assert(r == DB_RUNRECOVERY);
112
113 snprintf(cmd, sizeof(cmd), "rm -rf %s", glob);
114 r = system(cmd);
115 CKERR(r);
116
117 snprintf(cmd, sizeof(cmd), "mv %s/*.tokudb %s", saveddbs, TOKU_TEST_FILENAME);
118 r = system(cmd);
119 CKERR(r);
120
121 r = env->open(env, TOKU_TEST_FILENAME, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
122 r = env->close(env, 0); CKERR(r);
123 exit(0);
124 }
125
run_no_recover(void)126 static void run_no_recover (void) {
127 DB_ENV *env;
128 int r;
129
130 r = db_env_create(&env, 0); CKERR(r);
131 db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
132 r = env->open(env, TOKU_TEST_FILENAME, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
133 r = env->close(env, 0); CKERR(r);
134 exit(0);
135 }
136
137 const char *cmd;
138
139 bool do_test=false, do_recover=false, do_recover_only=false, do_no_recover = false;
140
test_parse_args(int argc,char * const argv[])141 static void test_parse_args (int argc, char * const argv[]) {
142 int resultcode;
143 cmd = argv[0];
144 argc--; argv++;
145 while (argc>0) {
146 if (strcmp(argv[0], "-v") == 0) {
147 verbose++;
148 } else if (strcmp(argv[0],"-q")==0) {
149 verbose--;
150 if (verbose<0) verbose=0;
151 } else if (strcmp(argv[0], "--test")==0) {
152 do_test=true;
153 } else if (strcmp(argv[0], "--recover") == 0) {
154 do_recover=true;
155 } else if (strcmp(argv[0], "--recover-only") == 0) {
156 do_recover_only=true;
157 } else if (strcmp(argv[0], "--no-recover") == 0) {
158 do_no_recover=true;
159 } else if (strcmp(argv[0], "-h")==0) {
160 resultcode=0;
161 do_usage:
162 fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd);
163 exit(resultcode);
164 } else {
165 fprintf(stderr, "Unknown arg: %s\n", argv[0]);
166 resultcode=1;
167 goto do_usage;
168 }
169 argc--;
170 argv++;
171 }
172 }
173
test_main(int argc,char * const argv[])174 int test_main (int argc, char * const argv[]) {
175 test_parse_args(argc, argv);
176 if (do_test) {
177 run_test();
178 } else if (do_recover) {
179 run_recover();
180 } else if (do_recover_only) {
181 run_recover();
182 } else if (do_no_recover) {
183 run_no_recover();
184 }
185 return 0;
186 }
187