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 // nested txn straddles the recovery turn around point in the log
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 const char *namea="a.db";
48
run_test(void)49 static void run_test (void) {
50 int r;
51
52 toku_os_recursive_delete(TOKU_TEST_FILENAME);
53 toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
54
55 DB_ENV *env;
56 r = db_env_create(&env, 0); CKERR(r);
57 r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
58
59 DB *db;
60 r = db_create(&db, env, 0); CKERR(r);
61 r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
62
63 DB_TXN *atxn;
64 r = env->txn_begin(env, NULL, &atxn, 0); CKERR(r);
65
66 DB_TXN *btxn;
67 r = env->txn_begin(env, atxn, &btxn, 0); CKERR(r);
68
69 // create a live transaction so that recovery needs to come here
70 DB_TXN *livetxn;
71 r = env->txn_begin(env, NULL, &livetxn, 0); CKERR(r);
72
73 DBT k,v;
74 dbt_init(&k, "a", 2);
75 dbt_init(&v, "b", 2);
76 r = db->put(db, btxn, &k, &v, 0); CKERR(r);
77 r = btxn->commit(btxn, 0); CKERR(r);
78
79 r = atxn->abort(atxn); CKERR(r);
80
81 r = db->close(db, 0); CKERR(r);
82
83 r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r);
84
85 // abort the process
86 toku_hard_crash_on_purpose();
87 }
88
run_recover(void)89 static void run_recover (void) {
90 DB_ENV *env;
91 int r;
92
93 // run recovery
94 r = db_env_create(&env, 0); CKERR(r);
95 r = env->open(env, TOKU_TEST_FILENAME, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
96
97 // verify the data
98 DB *db;
99 r = db_create(&db, env, 0); CKERR(r);
100 r = db->open(db, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r);
101
102 DB_TXN *txn;
103 r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
104 DBC *cursor;
105 r = db->cursor(db, txn, &cursor, 0); CKERR(r);
106 DBT k, v;
107 r = cursor->c_get(cursor, dbt_init_malloc(&k), dbt_init_malloc(&v), DB_FIRST);
108 assert(r == DB_NOTFOUND);
109 r = cursor->c_close(cursor); CKERR(r);
110 r = txn->commit(txn, 0); CKERR(r);
111
112 r = db->close(db, 0); 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 r = env->open(env, TOKU_TEST_FILENAME, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
123 r = env->close(env, 0); CKERR(r);
124 exit(0);
125 }
126
127 const char *cmd;
128
129 bool do_test=false, do_recover=false, do_recover_only=false, do_no_recover = false;
130
test_parse_args(int argc,char * const argv[])131 static void test_parse_args (int argc, char * const argv[]) {
132 int resultcode;
133 cmd = argv[0];
134 argc--; argv++;
135 while (argc>0) {
136 if (strcmp(argv[0], "-v") == 0) {
137 verbose++;
138 } else if (strcmp(argv[0],"-q")==0) {
139 verbose--;
140 if (verbose<0) verbose=0;
141 } else if (strcmp(argv[0], "--test")==0) {
142 do_test=true;
143 } else if (strcmp(argv[0], "--recover") == 0) {
144 do_recover=true;
145 } else if (strcmp(argv[0], "--recover-only") == 0) {
146 do_recover_only=true;
147 } else if (strcmp(argv[0], "--no-recover") == 0) {
148 do_no_recover=true;
149 } else if (strcmp(argv[0], "-h")==0) {
150 resultcode=0;
151 do_usage:
152 fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd);
153 exit(resultcode);
154 } else {
155 fprintf(stderr, "Unknown arg: %s\n", argv[0]);
156 resultcode=1;
157 goto do_usage;
158 }
159 argc--;
160 argv++;
161 }
162 }
163
test_main(int argc,char * const argv[])164 int test_main (int argc, char * const argv[]) {
165 test_parse_args(argc, argv);
166 if (do_test) {
167 run_test();
168 } else if (do_recover) {
169 run_recover();
170 } else if (do_recover_only) {
171 run_recover();
172 } else if (do_no_recover) {
173 run_no_recover();
174 }
175 return 0;
176 }
177