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 #include <stdio.h>
41
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <memory.h>
45 #include <sys/stat.h>
46 #include <db.h>
47
48
49 #define N_TXNS 4
50
51 static void
test_txn_abort(int n,int which_guys_to_abort)52 test_txn_abort (int n, int which_guys_to_abort) {
53 if (verbose>1) printf("test_txn_abort(%d,%x)\n", n, which_guys_to_abort);
54
55 int r;
56 toku_os_recursive_delete(TOKU_TEST_FILENAME);
57 toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
58
59 DB_ENV *env;
60 r = db_env_create(&env, 0); assert(r == 0);
61 r = env->open(env, TOKU_TEST_FILENAME, DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
62 if (r != 0) printf("%s:%d:%d:%s\n", __FILE__, __LINE__, r, db_strerror(r));
63 assert(r == 0);
64
65 DB *db;
66 {
67 DB_TXN *txn;
68 r = env->txn_begin(env, 0, &txn, 0); assert(r == 0);
69
70 r = db_create(&db, env, 0); assert(r == 0);
71 r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
72 r = txn->commit(txn, 0); assert(r == 0);
73 }
74 {
75 DB_TXN *txns[N_TXNS];
76 {
77 int j;
78 for (j=0; j<N_TXNS; j++) {
79 r = env->txn_begin(env, 0, &txns[j], 0); assert(r == 0);
80 }
81 }
82
83 {
84 int i;
85 for (i=0; i<n; i++) {
86 int j;
87 for (j=N_TXNS; j>0; j--) {
88 if (i%j==0) { // This is guaranteed to be true when j==1, so someone will do it.
89 DBT key, val;
90 r = db->put(db, txns[j-1], dbt_init(&key, &i, sizeof i), dbt_init(&val, &i, sizeof i), 0);
91 if (r != 0) printf("%s:%d:%d:%s\n", __FILE__, __LINE__, r, db_strerror(r));
92 assert(r == 0);
93 goto didit;
94 }
95 }
96 toku_hard_crash_on_purpose();
97 didit: ;
98 }
99 }
100 {
101 int j;
102 for (j=0; j<N_TXNS; j++) {
103 if (which_guys_to_abort&(1<<j)) {
104 r = txns[j]->abort(txns[j]);
105 } else {
106 r = txns[j]->commit(txns[j], 0);
107 }
108 if (r != 0) printf("%s:%d:abort:%d\n", __FILE__, __LINE__, r);
109 assert(r == 0);
110 }
111 }
112 }
113 {
114 DB_TXN *txn;
115 int i;
116 r = env->txn_begin(env, 0, &txn, 0); assert(r==0);
117 if (verbose>1) printf("Now see what's there: which_guys_to_abort=%x: ", which_guys_to_abort);
118 for (i=0; i<n; i++) {
119 DBT key,val;
120 memset(&val, 0, sizeof val);
121 r = db->get(db, txn, dbt_init(&key, &i, sizeof i), &val, 0);
122 if (r==0) { if (verbose>1) printf(" %d", i); }
123 }
124 if (verbose>1) printf("\n");
125 for (i=0; i<n; i++) {
126 DBT key,val;
127 memset(&val, 0, sizeof val);
128 r = db->get(db, txn, dbt_init(&key, &i, sizeof i), &val, 0);
129 int j;
130 for (j=N_TXNS; j>0; j--) {
131 if (i%j==0) {
132 if (which_guys_to_abort&(1<<(j-1))) assert(r==DB_NOTFOUND);
133 else assert(r==0);
134 break;
135 }
136 }
137 }
138 r = txn->commit(txn, 0); assert(r==0);
139 }
140
141 r = db->close(db, 0); assert(r == 0);
142 r = env->close(env, 0); assert(r == 0);
143 }
144
145 int
test_main(int argc,char * const argv[])146 test_main(int argc, char *const argv[]) {
147 int i,j;
148 for (i = 1; i < argc; i++) {
149 const char *arg = argv[i];
150 if (strcmp(arg, "-v") == 0 || strcmp(arg, "--verbose") == 0) {
151 verbose++;
152 continue;
153 }
154 }
155 if (verbose>0) printf("%s:", __FILE__);
156 if (verbose==1) printf("\n");
157 for (j=0; j<(1<<N_TXNS); j++)
158 for (i=1; i<100; i*=2)
159 test_txn_abort(i, j);
160 if (verbose>0) printf("OK\n");
161 return 0;
162 }
163