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