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_begin(env, NULL, &txn, 0); CKERR(chk_r); }
99 { int chk_r = db->change_descriptor(db, txn, &desc, 0); CKERR(chk_r); }
100 { int chk_r = db->close(db,0); CKERR(chk_r); }
101 { int chk_r = txn->commit(txn,0); CKERR(chk_r); }
102
103 { int chk_r = env->txn_begin(env, NULL, &txn2, 0); CKERR(chk_r); }
104 { int chk_r = db2->change_descriptor(db2, txn2, &desc, 0); CKERR(chk_r); }
105 { int chk_r = db2->close(db2,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 { int chk_r = db3->close(db3,0); CKERR(chk_r); }
111
112 toku_hard_crash_on_purpose();
113 }
114
115
run_recover(void)116 static void run_recover(void)
117 {
118 DB_ENV *env;
119 DB *db;
120 DB *db2;
121 DB *db3;
122
123 { int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
124 env->set_errfile(env, stderr);
125 { int chk_r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
126
127 { int chk_r = db_create(&db, env, 0); CKERR(chk_r); }
128 { int chk_r = db->open(db, NULL, "foo.db", NULL, DB_BTREE, DB_AUTO_COMMIT, 0666); CKERR(chk_r); }
129 assert_desc_four(db);
130 { int chk_r = db->close(db, 0); CKERR(chk_r); }
131
132 { int chk_r = db_create(&db2, env, 0); CKERR(chk_r); }
133 { int chk_r = db2->open(db2, NULL, "foo2.db", NULL, DB_BTREE, DB_AUTO_COMMIT, 0666); CKERR(chk_r); }
134 assert_desc_eight(db2);
135 { int chk_r = db2->close(db2, 0); CKERR(chk_r); }
136
137 { int chk_r = db_create(&db3, env, 0); CKERR(chk_r); }
138 { int chk_r = db3->open(db3, NULL, "foo3.db", NULL, DB_BTREE, DB_AUTO_COMMIT, 0666); CKERR(chk_r); }
139 assert_desc_eight(db3);
140 { int chk_r = db3->close(db3, 0); CKERR(chk_r); }
141
142 { int chk_r = env->close(env, 0); CKERR(chk_r); }
143 }
144
usage(void)145 static int usage(void)
146 {
147 return 1;
148 }
149
test_main(int argc,char * const argv[])150 int test_main(int argc, char * const argv[])
151 {
152 bool do_test = false;
153 bool do_recover = false;
154
155 for (int i = 1; i < argc; i++) {
156 char * const arg = argv[i];
157 if (strcmp(arg, "-v") == 0) {
158 verbose++;
159 continue;
160 }
161 if (strcmp(arg, "-q") == 0) {
162 verbose--;
163 if (verbose < 0)
164 verbose = 0;
165 continue;
166 }
167 if (strcmp(arg, "--test") == 0) {
168 do_test = true;
169 continue;
170 }
171 if (strcmp(arg, "--recover") == 0) {
172 do_recover = true;
173 continue;
174 }
175 if (strcmp(arg, "--help") == 0) {
176 return usage();
177 }
178 }
179
180 if (do_test) {
181 run_test();
182 }
183 if (do_recover) {
184 run_recover();
185 }
186
187 return 0;
188 }
189