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 #include "test.h"
40
41 // verify recovery of an update log entry which changes values at keys
42
43 static const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE;
44 uint32_t four_byte_desc = 101;
45 uint64_t eight_byte_desc = 10101;
46
assert_desc_four(DB * db)47 static void assert_desc_four (DB* db) {
48 assert(db->descriptor->dbt.size == sizeof(four_byte_desc));
49 assert(*(uint32_t *)(db->descriptor->dbt.data) == four_byte_desc);
50 }
assert_desc_eight(DB * db)51 static void assert_desc_eight (DB* db) {
52 assert(db->descriptor->dbt.size == sizeof(eight_byte_desc));
53 assert(*(uint32_t *)(db->descriptor->dbt.data) == eight_byte_desc);
54 }
55
run_test(void)56 static void run_test(void)
57 {
58 DB_ENV *env;
59 DB *db;
60 DB *db2;
61 DB *db3;
62 DB_TXN* txn;
63 DB_TXN* txn2;
64 DB_TXN* txn3;
65 DBT desc;
66 memset(&desc, 0, sizeof(desc));
67 desc.size = sizeof(four_byte_desc);
68 desc.data = &four_byte_desc;
69
70 DBT other_desc;
71 memset(&other_desc, 0, sizeof(other_desc));
72 other_desc.size = sizeof(eight_byte_desc);
73 other_desc.data = &eight_byte_desc;
74
75 toku_os_recursive_delete(TOKU_TEST_FILENAME);
76 { int chk_r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
77 { int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
78 env->set_errfile(env, stderr);
79 { int chk_r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
80
81 IN_TXN_COMMIT(env, NULL, txn_1, 0, {
82 { int chk_r = db_create(&db, env, 0); CKERR(chk_r); }
83 { int chk_r = db->open(db, txn_1, "foo.db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); }
84 });
85 IN_TXN_COMMIT(env, NULL, txn_2, 0, {
86 { int chk_r = db_create(&db2, env, 0); CKERR(chk_r); }
87 { int chk_r = db2->open(db2, txn_2, "foo2.db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); }
88 { int chk_r = db2->change_descriptor(db2, txn_2, &other_desc, 0); CKERR(chk_r); }
89 assert_desc_eight(db2);
90 });
91 IN_TXN_COMMIT(env, NULL, txn_3, 0, {
92 { int chk_r = db_create(&db3, env, 0); CKERR(chk_r); }
93 { int chk_r = db3->open(db3, txn_3, "foo3.db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); }
94 { int chk_r = db3->change_descriptor(db3, txn_3, &other_desc, 0); CKERR(chk_r); }
95 assert_desc_eight(db3);
96 });
97
98 { int chk_r = env->txn_checkpoint(env,0,0,0); CKERR(chk_r); }
99
100 { int chk_r = env->txn_begin(env, NULL, &txn, 0); CKERR(chk_r); }
101 { int chk_r = db->change_descriptor(db, txn, &desc, 0); CKERR(chk_r); }
102 { int chk_r = txn->commit(txn,0); CKERR(chk_r); }
103
104 { int chk_r = env->txn_begin(env, NULL, &txn2, 0); CKERR(chk_r); }
105 { int chk_r = db2->change_descriptor(db2, txn2, &desc, 0); CKERR(chk_r); }
106 { int chk_r = txn2->abort(txn2); CKERR(chk_r); }
107
108 { int chk_r = env->txn_begin(env, NULL, &txn3, 0); CKERR(chk_r); }
109 { int chk_r = db3->change_descriptor(db3, txn3, &desc, 0); CKERR(chk_r); }
110
111 toku_hard_crash_on_purpose();
112 }
113
114
run_recover(void)115 static void run_recover(void)
116 {
117 DB_ENV *env;
118 DB *db;
119 DB *db2;
120 DB *db3;
121
122 { int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
123 env->set_errfile(env, stderr);
124 { int chk_r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
125
126 { int chk_r = db_create(&db, env, 0); CKERR(chk_r); }
127 { int chk_r = db->open(db, NULL, "foo.db", NULL, DB_BTREE, DB_AUTO_COMMIT, 0666); CKERR(chk_r); }
128 assert_desc_four(db);
129 { int chk_r = db->close(db, 0); CKERR(chk_r); }
130
131 { int chk_r = db_create(&db2, env, 0); CKERR(chk_r); }
132 { int chk_r = db2->open(db2, NULL, "foo2.db", NULL, DB_BTREE, DB_AUTO_COMMIT, 0666); CKERR(chk_r); }
133 assert_desc_eight(db2);
134 { int chk_r = db2->close(db2, 0); CKERR(chk_r); }
135
136 { int chk_r = db_create(&db3, env, 0); CKERR(chk_r); }
137 { int chk_r = db3->open(db3, NULL, "foo3.db", NULL, DB_BTREE, DB_AUTO_COMMIT, 0666); CKERR(chk_r); }
138 assert_desc_eight(db3);
139 { int chk_r = db3->close(db3, 0); CKERR(chk_r); }
140
141 { int chk_r = env->close(env, 0); CKERR(chk_r); }
142 }
143
usage(void)144 static int usage(void)
145 {
146 return 1;
147 }
148
test_main(int argc,char * const argv[])149 int test_main(int argc, char * const argv[])
150 {
151 bool do_test = false;
152 bool do_recover = false;
153
154 for (int i = 1; i < argc; i++) {
155 char * const arg = argv[i];
156 if (strcmp(arg, "-v") == 0) {
157 verbose++;
158 continue;
159 }
160 if (strcmp(arg, "-q") == 0) {
161 verbose--;
162 if (verbose < 0)
163 verbose = 0;
164 continue;
165 }
166 if (strcmp(arg, "--test") == 0) {
167 do_test = true;
168 continue;
169 }
170 if (strcmp(arg, "--recover") == 0) {
171 do_recover = true;
172 continue;
173 }
174 if (strcmp(arg, "--help") == 0) {
175 return usage();
176 }
177 }
178
179 if (do_test) {
180 run_test();
181 }
182 if (do_recover) {
183 run_recover();
184 }
185
186 return 0;
187 }
188