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