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