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 /* Nested transactions. */
41 
42 #include <db.h>
43 #include <sys/stat.h>
44 
45 static DB_ENV *env;
46 static DB *db;
47 
insert(int i,DB_TXN * x)48 static void insert (int i, DB_TXN *x) {
49     char hello[30], there[30];
50     DBT key,data;
51     if (verbose) printf("Insert %d\n", i);
52     snprintf(hello, sizeof(hello), "hello%d", i);
53     snprintf(there, sizeof(there), "there%d", i);
54     int r = db->put(db, x,
55 		    dbt_init(&key,  hello, strlen(hello)+1),
56 		    dbt_init(&data, there, strlen(there)+1),
57 		    0);
58     CKERR(r);
59 }
60 
op_delete(int i,DB_TXN * x)61 static void op_delete (int i, DB_TXN *x) {
62     char hello[30];
63     DBT key;
64     if (verbose) printf("op_delete %d\n", i);
65     snprintf(hello, sizeof(hello), "hello%d", i);
66     int r = db->del(db, x,
67 		    dbt_init(&key,  hello, strlen(hello)+1),
68 		    0);
69     CKERR(r);
70 }
71 
lookup(int i,DB_TXN * x,int expect)72 static void lookup (int i, DB_TXN *x, int expect) {
73     char hello[30], there[30];
74     DBT key,data;
75     snprintf(hello, sizeof(hello), "hello%d", i);
76     memset(&data, 0, sizeof(data));
77     if (verbose) printf("Looking up %d (expecting %s)\n", i, expect==0 ? "to find" : "not to find");
78     int r = db->get(db, x,
79 		    dbt_init(&key,  hello, strlen(hello)+1),
80 		    &data,
81 		    0);
82     assert(expect==r);
83     if (expect==0) {
84 	CKERR(r);
85 	snprintf(there, sizeof(there), "there%d", i);
86 	assert(data.size==strlen(there)+1);
87 	assert(strcmp((char*)data.data, there)==0);
88     }
89 }
90 
91 static DB_TXN *txn, *txn2;
92 
93 static void
test_nested(void)94 test_nested (void) {
95     int r;
96     toku_os_recursive_delete(TOKU_TEST_FILENAME);
97     r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);       assert(r==0);
98 
99     r=db_env_create(&env, 0); assert(r==0);
100     env->set_errfile(env, stderr);
101     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);
102     r=db_create(&db, env, 0); CKERR(r);
103 
104     r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
105     r=db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
106     insert(0, txn);
107 
108     insert(1, txn);
109     insert(2, txn);
110     insert(3, txn);
111     lookup(0, txn, 0);
112     lookup(1, txn, 0);
113     lookup(2, txn, 0);
114     lookup(3, txn, 0);
115     r=txn->commit(txn, 0);    assert(r==0);
116 
117     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
118     op_delete(0, txn);
119     op_delete(3, txn);
120     r=env->txn_begin(env, txn, &txn2, 0); CKERR(r);
121     op_delete(1, txn2);                     CKERR(r);
122     lookup(3, txn2, DB_NOTFOUND);
123     insert(3, txn2);
124     lookup(3, txn2, 0);
125     r=txn2->commit(txn2, 0); CKERR(r);
126     lookup(0, txn, DB_NOTFOUND);
127     lookup(1, txn, DB_NOTFOUND);
128     lookup(2, txn, 0);
129     lookup(3, txn, 0);
130     r=txn->commit(txn, 0); CKERR(r);
131 
132     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
133     lookup(0, txn, DB_NOTFOUND);
134     lookup(1, txn, DB_NOTFOUND);
135     lookup(2, txn, 0);
136     r=txn->commit(txn, 0); CKERR(r);
137 
138     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
139     insert(4, txn);
140     r=txn->commit(txn, 0); CKERR(r);
141     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
142     r=env->txn_begin(env, txn, &txn2, 0); CKERR(r);
143     op_delete(4, txn2);
144     r=txn->commit(txn2, 0); CKERR(r);
145     lookup(4, txn, DB_NOTFOUND);
146     insert(4, txn);
147     r=txn->commit(txn, 0); CKERR(r);
148     lookup(4, 0, 0);
149 
150     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
151     insert(5, txn);
152     r=env->txn_begin(env, txn, &txn2, 0); CKERR(r);
153     lookup(5, txn2, 0);
154     insert(5, txn2);
155     lookup(5, txn2, 0);
156     r=txn->commit(txn2, 0); CKERR(r);
157     lookup(5, txn, 0);
158     r=env->txn_begin(env, txn, &txn2, 0); CKERR(r);
159     lookup(5, txn2, 0);
160     op_delete(5, txn2);
161     r=txn->commit(txn2, 0); CKERR(r);
162     lookup(5, txn, DB_NOTFOUND);
163     r=txn->commit(txn, 0); CKERR(r);
164 
165     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
166     insert(6, txn);
167     r=txn->commit(txn, 0); CKERR(r);
168 
169     r=env->txn_begin(env, 0, &txn, 0);    CKERR(r);
170     insert(6, txn);
171     r=env->txn_begin(env, txn, &txn2, 0); CKERR(r);
172     op_delete(6, txn2);
173     r=txn->commit(txn2, 0); CKERR(r);
174     r=txn->commit(txn, 0); CKERR(r);
175 
176     r=db->close(db, 0); CKERR(r);
177     r=env->close(env, 0); CKERR(r);
178 }
179 
180 int
test_main(int argc,char * const argv[])181 test_main (int argc, char *const argv[]) {
182     parse_args(argc, argv);
183     test_nested();
184     return 0;
185 }
186