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