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 /* Test to see if a big nested transaction (so big that it's rollbacks spill into a file)
41  * can commit properly.
42  *  Four Tests:
43  *     big child aborts, parent aborts
44  *     big child aborts, parent commits (This test)
45  *     big child commits, parent aborts
46  *     big child commits, parent commits
47  */
48 
49 #include <db.h>
50 #include <sys/stat.h>
51 
52 int N = 50000;
53 
54 static DB_ENV *env;
55 static DB *db;
56 static DB_TXN *xchild, *xparent;
57 
insert(int i,int j)58 static void insert (int i, int j) {
59     char hello[30], there[30];
60     DBT key,data;
61     if (verbose) printf("Insert %d\n", i);
62     snprintf(hello, sizeof(hello), "hello%d", i);
63     snprintf(there, sizeof(there), "there%d", j);
64     int r = db->put(db, xchild,
65 		    dbt_init(&key,  hello, strlen(hello)+1),
66 		    dbt_init(&data, there, strlen(there)+1),
67 		    0);
68     CKERR(r);
69 }
70 
lookup(int i,int expect,int expectj)71 static void lookup (int i, int expect, int expectj) {
72     char hello[30], there[30];
73     DBT key,data;
74     snprintf(hello, sizeof(hello), "hello%d", i);
75     memset(&data, 0, sizeof(data));
76     if (verbose) printf("Looking up %d (expecting %s)\n", i, expect==0 ? "to find" : "not to find");
77     int r = db->get(db, xchild,
78 		    dbt_init(&key,  hello, strlen(hello)+1),
79 		    &data,
80 		    0);
81     assert(expect==r);
82     if (expect==0) {
83 	CKERR(r);
84 	snprintf(there, sizeof(there), "there%d", expectj);
85 	assert(data.size==strlen(there)+1);
86 	assert(strcmp((char*)data.data, there)==0);
87     }
88 }
89 
90 static void
test_abort_commit(void)91 test_abort_commit (void) {
92     int i, r;
93     r=env->txn_begin(env, 0, &xchild, 0); CKERR(r);
94     for (i=0; i<N/2; i++) {
95 	insert(i*2,i*4+1);
96     }
97     r=xchild->commit(xchild, 0); CKERR(r);
98     r=env->txn_begin(env, 0, &xparent, 0);  CKERR(r);
99     r=env->txn_begin(env, xparent, &xchild, 0); CKERR(r);
100     for (i=0; i<N; i++) {
101 	insert(i, i);
102     }
103     r=xchild->abort(xchild); CKERR(r);
104     r=env->txn_begin(env, xparent, &xchild, 0); CKERR(r);
105     for (i=0; i<N; i++) {
106 	lookup(i, (i%2==0)?0:DB_NOTFOUND, i*2+1);
107     }
108     r=xchild->commit(xchild, 0); CKERR(r);
109     r=xparent->commit(xparent, 0); CKERR(r);
110     r=env->txn_begin(env, 0, &xchild, 0); CKERR(r);
111     for (i=0; i<N; i++) {
112 	lookup(i, (i%2==0)?0:DB_NOTFOUND, i*2+1);
113     }
114     r=xchild->commit(xchild, 0); CKERR(r);
115 }
116 
117 static void
setup(void)118 setup (void) {
119     DB_TXN *txn;
120     int r;
121     toku_os_recursive_delete(TOKU_TEST_FILENAME);
122     r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);       CKERR(r);
123 
124     r=db_env_create(&env, 0); CKERR(r);
125 
126     env->set_errfile(env, stderr);
127     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);
128     r=db_create(&db, env, 0); CKERR(r);
129 
130     r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
131     r=db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
132     r=txn->commit(txn, 0);    assert(r==0);
133 }
134 
135 static void
test_shutdown(void)136 test_shutdown (void) {
137     int r;
138     r=db->close(db, 0); CKERR(r);
139     r=env->close(env, 0); CKERR(r);
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     setup();
146     test_abort_commit();
147     test_shutdown();
148     return 0;
149 }
150