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 // test txn commit after db close
40
41 #include "test.h"
42 #include <sys/stat.h>
43
44 DB_ENV *null_env = NULL;
45 DB *null_db = NULL;
46 DB_TXN *null_txn = NULL;
47 DBC *null_cursor = NULL;
48
create_non_empty(int n,const char * dirname)49 static void create_non_empty(int n, const char *dirname) {
50 DB_ENV *env = null_env;
51 int r;
52 r = db_env_create(&env, 0); assert(r == 0); assert(env != NULL);
53 r = env->set_redzone(env, 0); assert(r == 0);
54 r = env->open(env,
55 dirname,
56 DB_INIT_MPOOL+DB_INIT_LOG+DB_INIT_LOCK+DB_INIT_TXN+DB_PRIVATE+DB_CREATE,
57 S_IRWXU+S_IRWXG+S_IRWXO);
58 assert(r == 0);
59
60 DB_TXN *txn = null_txn;
61 r = env->txn_begin(env, null_txn, &txn, 0); assert(r == 0); assert(txn != NULL);
62
63 DB *db = null_db;
64 r = db_create(&db, env, 0); assert(r == 0); assert(db != NULL);
65
66 r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
67 assert(r == 0);
68
69 int i;
70 for (i=n; i<2*n; i++) {
71 DBT key, val;
72 int k = toku_htonl(i);
73 r = db->put(db, txn, dbt_init(&key, &k, sizeof k), dbt_init(&val, &i, sizeof i), 0);
74 assert(r == 0);
75 }
76
77 r = db->close(db, 0); assert(r == 0); db = null_db;
78
79 r = txn->commit(txn, 0); assert(r == 0); txn = null_txn;
80
81 r = env->close(env, 0); assert(r == 0); env = null_env;
82 }
83
root_fifo_verify(DB_ENV * env,int n,int expectn)84 static void root_fifo_verify(DB_ENV *env, int n, int expectn) {
85 if (verbose) printf("%s:%d %d %d\n", __FUNCTION__, __LINE__, n, expectn);
86
87 int r;
88 DB_TXN *txn = null_txn;
89 r = env->txn_begin(env, null_txn, &txn, 0); assert(r == 0); assert(txn != NULL);
90
91 DB *db = null_db;
92 r = db_create(&db, env, 0); assert(r == 0); assert(db != NULL);
93 r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
94 assert(r == 0);
95
96 DBC *cursor = null_cursor;
97 r = db->cursor(db, txn, &cursor, 0); assert(r == 0);
98 int i;
99 for (i = 0; ; i++) {
100 DBT key, val;
101 memset(&key, 0, sizeof key); memset(&val, 0, sizeof val);
102 r = cursor->c_get(cursor, &key, &val, DB_NEXT);
103 if (r != 0) break;
104 int k;
105 assert(key.size == sizeof k);
106 memcpy(&k, key.data, key.size);
107 assert((int)toku_ntohl(k) == i);
108 }
109 assert(i == expectn);
110
111 r = cursor->c_close(cursor); assert(r == 0); cursor = null_cursor;
112
113 r = txn->commit(txn, 0); assert(r == 0); txn = null_txn;
114
115 r = db->close(db, 0); assert(r == 0); db = null_db;
116 }
117
root_fifo_41(int n,int ntxn,bool do_populate)118 static void root_fifo_41(int n, int ntxn, bool do_populate) {
119 if (verbose) printf("%s:%d %d\n", __FUNCTION__, __LINE__, n);
120 int r;
121
122 const char *dirname = TOKU_TEST_FILENAME;
123
124 // create the env
125 toku_os_recursive_delete(dirname);
126 toku_os_mkdir(dirname, S_IRWXU+S_IRWXG+S_IRWXO);
127
128 // populate
129 if (do_populate)
130 create_non_empty(n, dirname);
131
132 DB_ENV *env = null_env;
133 r = db_env_create(&env, 0); assert(r == 0); assert(env != NULL);
134 r = env->set_redzone(env, 0); assert(r == 0);
135 r = env->open(env,
136 dirname,
137 DB_INIT_MPOOL+DB_INIT_LOG+DB_INIT_LOCK+DB_INIT_TXN+DB_PRIVATE+DB_CREATE,
138 S_IRWXU+S_IRWXG+S_IRWXO);
139 assert(r == 0);
140 {
141 DB_TXN *txn;
142 DB *db = null_db;
143 r = env->txn_begin(env, null_txn, &txn, 0); CKERR(r);
144 r = db_create(&db, env, 0); CKERR(r);
145 r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
146 CKERR(r);
147 r = txn->commit(txn, 0); CKERR(r);
148 r = db->close(db, 0); CKERR(r);
149 }
150
151 DB_TXN *txn[ntxn];
152 int i;
153 for (i=0; i<ntxn; i++) {
154 r = env->txn_begin(env, null_txn, &txn[i], 0); assert(r == 0); assert(txn[i] != NULL);
155 }
156
157 for (i=0; i<n; i++) {
158 DB *db = null_db;
159 r = db_create(&db, env, 0); assert(r == 0); assert(db != NULL);
160
161 r = db->open(db, txn[i % ntxn], "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
162 assert(r == 0);
163
164 DBT key, val;
165 int k = toku_htonl(i);
166 r = db->put(db, txn[i % ntxn], dbt_init(&key, &k, sizeof k), dbt_init(&val, &i, sizeof i), 0);
167 assert(r == 0);
168
169 r = db->close(db, 0); assert(r == 0); db = null_db;
170 }
171
172 for (i=0; i<ntxn; i++) {
173 r = txn[i]->commit(txn[i], 0); assert(r == 0);
174 }
175
176 // verify the db
177 root_fifo_verify(env, n, do_populate ? 2*n : n);
178
179 // cleanup
180 r = env->close(env, 0); assert(r == 0); env = null_env;
181 }
182
parseint(char const * str)183 static int parseint (char const *str) {
184 char *end;
185 errno=0;
186 int v = strtol(str, &end, 10);
187 if (errno!=0 || *end!=0) {
188 fprintf(stderr, "This argument should be an int: %s\n", str);
189 exit(1);
190 }
191 return v;
192 }
193
test_main(int argc,char * const argv[])194 int test_main(int argc, char *const argv[]) {
195 int i;
196 int n = -1;
197 int ntxn = -1;
198 bool do_populate = false;
199
200 // parse_args(argc, argv);
201 for (i = 1; i < argc; i++) {
202 if (strcmp(argv[i], "-v") == 0) {
203 verbose = 1;
204 } else if (strcmp(argv[i], "-n") == 0) {
205 assert(i+1 < argc);
206 n = parseint(argv[++i]);
207 } else if (strcmp(argv[i], "-ntxn") == 0) {
208 assert(i+1 < argc);
209 ntxn = parseint(argv[++i]);
210 } else if (strcmp(argv[i], "-populate") == 0) {
211 do_populate = true;
212 } else {
213 fprintf(stderr, "What is this argument? %s\n", argv[i]);
214 exit(1);
215 }
216 }
217
218 if (n >= 0)
219 root_fifo_41(n, ntxn == -1 ? 1 : ntxn, do_populate);
220 else {
221 for (i=0; i<100; i++) {
222 for (ntxn=1; ntxn<=4; ntxn++) {
223 root_fifo_41(i, ntxn, false);
224 root_fifo_41(i, ntxn, true);
225 }
226 }
227 }
228 return 0;
229 }
230
231