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