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