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 // test delboth commit before checkpoint
40
41 #include "test.h"
42
43
44 const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE;
45 const char *namea="a.db";
46
47 static void
run_test(bool do_commit,bool do_abort)48 run_test (bool do_commit, bool do_abort) {
49 int r;
50
51 toku_os_recursive_delete(TOKU_TEST_FILENAME);
52 toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
53
54 DB_ENV *env;
55 r = db_env_create(&env, 0); CKERR(r);
56 r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
57
58 DB *dba;
59 r = db_create(&dba, env, 0); CKERR(r);
60 r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
61
62 // insert (i,i) pairs
63 DB_TXN *txn;
64 r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
65 for (int i=0; i<256; i++) {
66 unsigned char c = (unsigned char) i;
67 DBT k = {.data=&c, .size=sizeof c};
68 DBT v = {.data=&c, .size=sizeof c};
69 r = dba->put(dba, txn, &k, &v, 0); CKERR(r);
70 }
71 r = txn->commit(txn, 0); CKERR(r);
72
73 // delete (128,128)
74 r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
75 {
76 unsigned char c = 128;
77 DBT k = {.data=&c, .size=sizeof c};
78 r = dba->del(dba, txn, &k, 0); CKERR(r);
79 }
80
81 r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r);
82
83 if (do_commit) {
84 r = txn->commit(txn, 0); CKERR(r);
85 } else if (do_abort) {
86 r = txn->abort(txn); CKERR(r);
87
88 // force an fsync of the log
89 r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
90 r = txn->commit(txn, DB_TXN_SYNC); CKERR(r);
91 }
92 //printf("shutdown\n");
93 toku_hard_crash_on_purpose();
94 }
95
96 static void
run_recover(bool UU (did_commit))97 run_recover (bool UU(did_commit)) {
98 DB_ENV *env;
99 int r;
100 r = db_env_create(&env, 0); CKERR(r);
101 r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
102
103 // verify all but (128,128) exist
104 DB *dba;
105 r = db_create(&dba, env, 0); CKERR(r);
106 r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
107 DB_TXN *txn;
108 r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
109 DBC *ca;
110 r = dba->cursor(dba, txn, &ca, 0); CKERR(r);
111 int i;
112 for (i=0; ; i++) {
113 if (i == 128)
114 continue;
115 DBT k,v;
116 dbt_init(&k, NULL, 0);
117 dbt_init(&v, NULL, 0);
118 r = ca->c_get(ca, &k, &v, DB_NEXT);
119 if (r != 0)
120 break;
121 assert(k.size == 1 && v.size == 1);
122 unsigned char kk, vv;
123 memcpy(&kk, k.data, k.size);
124 memcpy(&vv, v.data, v.size);
125 assert(kk == i);
126 assert(vv == i);
127 }
128 assert(i == 256);
129
130 r = ca->c_close(ca); CKERR(r);
131
132 r = txn->commit(txn, 0); CKERR(r);
133
134 r = dba->close(dba, 0); CKERR(r);
135
136 r = env->close(env, 0); CKERR(r);
137 exit(0);
138 }
139
140 static void
run_recover_only(void)141 run_recover_only (void) {
142 DB_ENV *env;
143 int r;
144
145 r = db_env_create(&env, 0); CKERR(r);
146 r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
147 r = env->close(env, 0); CKERR(r);
148 exit(0);
149 }
150
151 static void
run_no_recover(void)152 run_no_recover (void) {
153 DB_ENV *env;
154 int r;
155
156 r = db_env_create(&env, 0); CKERR(r);
157 r = env->open(env, TOKU_TEST_FILENAME, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO);
158 assert(r == DB_RUNRECOVERY);
159 r = env->close(env, 0); CKERR(r);
160 exit(0);
161 }
162
163 const char *cmd;
164
165 bool do_commit=false, do_abort=false, do_explicit_abort=false, do_recover_committed=false, do_recover_aborted=false, do_recover_only=false, do_no_recover = false;
166
167 static void
x1_parse_args(int argc,char * const argv[])168 x1_parse_args (int argc, char * const argv[]) {
169 int resultcode;
170 cmd = argv[0];
171 argc--; argv++;
172 while (argc>0) {
173 if (strcmp(argv[0], "-v") == 0) {
174 verbose++;
175 } else if (strcmp(argv[0],"-q")==0) {
176 verbose--;
177 if (verbose<0) verbose=0;
178 } else if (strcmp(argv[0], "--commit")==0 || strcmp(argv[0], "--test") == 0) {
179 do_commit=true;
180 } else if (strcmp(argv[0], "--abort")==0) {
181 do_abort=true;
182 } else if (strcmp(argv[0], "--explicit-abort")==0) {
183 do_explicit_abort=true;
184 } else if (strcmp(argv[0], "--recover-committed")==0 || strcmp(argv[0], "--recover") == 0) {
185 do_recover_committed=true;
186 } else if (strcmp(argv[0], "--recover-aborted")==0) {
187 do_recover_aborted=true;
188 } else if (strcmp(argv[0], "--recover-only") == 0) {
189 do_recover_only=true;
190 } else if (strcmp(argv[0], "--no-recover") == 0) {
191 do_no_recover=true;
192 } else if (strcmp(argv[0], "-h")==0) {
193 resultcode=0;
194 do_usage:
195 fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--commit | --abort | --explicit-abort | --recover-committed | --recover-aborted } \n", cmd);
196 exit(resultcode);
197 } else {
198 fprintf(stderr, "Unknown arg: %s\n", argv[0]);
199 resultcode=1;
200 goto do_usage;
201 }
202 argc--;
203 argv++;
204 }
205 {
206 int n_specified=0;
207 if (do_commit) n_specified++;
208 if (do_abort) n_specified++;
209 if (do_explicit_abort) n_specified++;
210 if (do_recover_committed) n_specified++;
211 if (do_recover_aborted) n_specified++;
212 if (do_recover_only) n_specified++;
213 if (do_no_recover) n_specified++;
214 if (n_specified>1) {
215 printf("Specify only one of --commit or --abort or --recover-committed or --recover-aborted\n");
216 resultcode=1;
217 goto do_usage;
218 }
219 }
220 }
221
222 int
test_main(int argc,char * const argv[])223 test_main (int argc, char * const argv[])
224 {
225 x1_parse_args(argc, argv);
226 if (do_commit) {
227 run_test (true, false);
228 } else if (do_abort) {
229 run_test (false, false);
230 } else if (do_explicit_abort) {
231 run_test(false, true);
232 } else if (do_recover_committed) {
233 run_recover(true);
234 } else if (do_recover_aborted) {
235 run_recover(false);
236 } else if (do_recover_only) {
237 run_recover_only();
238 } else if (do_no_recover) {
239 run_no_recover();
240 }
241 #if 0
242 else {
243 do_test();
244 }
245 #endif
246 return 0;
247 }
248