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