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 /* Put some insert messages into an internal buffer (by first creating a DB, filling it up, then closing it, and reopening, and inserting a few things)
41 * Then perform a transaction that overwrites some of those internal things.
42 * Then abort the transaction.
43 * Make sure those middle things made it back into the tree.
44 */
45
46 #include <db.h>
47 #include <sys/stat.h>
48
49 static DB_ENV *env;
50 static DB *db;
51 static DB_TXN *txn;
52
53 static void
insert(int i,int j)54 insert (int i, int j) {
55 char hello[30], there[230];
56 DBT key,data;
57 snprintf(hello, sizeof(hello), "hello%d", i);
58 snprintf(there, sizeof(there), "%dthere%d %*s", j, i, 10+i%40, "padding");
59 int r = db->put(db, txn,
60 dbt_init(&key, hello, strlen(hello)+1),
61 dbt_init(&data, there, strlen(there)+1),
62 0);
63 CKERR(r);
64 }
65
66 static void
do_test_abort2(void)67 do_test_abort2 (void) {
68 int r;
69 toku_os_recursive_delete(TOKU_TEST_FILENAME);
70 r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
71
72 r=db_env_create(&env, 0); assert(r==0);
73 env->set_errfile(env, stderr);
74 r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
75 r=db_create(&db, env, 0); CKERR(r);
76 r=db->set_pagesize(db, 4096); // Use a small page
77 r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
78 r=db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
79 r=txn->commit(txn, 0); assert(r==0);
80
81 r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
82 {
83 int i;
84 for (i=0; i<1000; i++) {
85 insert(4*i, 0);
86 }
87 }
88 r=txn->commit(txn, 0); CKERR(r);
89 r=db->close(db, 0); CKERR(r);
90 r=env->close(env, 0); CKERR(r);
91
92 //printf("%s:%d\n", __FILE__, __LINE__);
93
94 // Now do a few inserts that abort.
95 r=db_env_create(&env, 0); assert(r==0);
96 env->set_errfile(env, stderr);
97 r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
98 r=db_create(&db, env, 0); CKERR(r);
99 r=env->txn_begin(env, 0, &txn, 0); CKERR(r);
100 r=db->open(db, txn, "foo.db", 0, DB_BTREE, 0, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
101 r=txn->commit(txn, 0); assert(r==0);
102
103 r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
104 insert(3, 0);
105 insert(5, 0);
106 insert(7, 0);
107 r=txn->commit(txn, 0); CKERR(r);
108
109 r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
110 insert(7, 1);
111 r=txn->abort(txn); CKERR(r);
112
113
114 //printf("%s:%d\n", __FILE__, __LINE__);
115 //r=db->close(db,0); CKERR(r); r=env->close(env, 0); CKERR(r); return;
116
117 // Don't do a lookup on "hello7", because that will force things out of the buffer.
118 r=db->close(db, 0); CKERR(r);
119 //printf("%s:%d\n", __FILE__, __LINE__);
120 r=db_create(&db, env, 0); CKERR(r);
121 r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
122 r=db->open(db, txn, "foo.db", 0, DB_BTREE, 0, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
123 r=txn->commit(txn, 0); CKERR(r);
124 //printf("%s:%d\n", __FILE__, __LINE__);
125
126 r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
127 {
128 DBT key,data;
129 memset(&data, 0, sizeof(data));
130 r = db->get(db, txn, dbt_init(&key, "hello7", strlen("hello7")+1), &data, 0);
131 CKERR(r);
132 //printf("data is %s\n", (char*)data.data);
133 assert(((char*)data.data)[0]=='0');
134 }
135 r=txn->abort(txn); CKERR(r);
136
137 r=db->close(db, 0); CKERR(r);
138 r=env->close(env, 0); CKERR(r);
139
140 }
141
142 int
test_main(int argc,char * const argv[])143 test_main (int argc, char *const argv[]) {
144 parse_args(argc, argv);
145 do_test_abort2();
146 return 0;
147 }
148