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