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
41 static DB_TXN *txn1, *txn2, *txn3;
42 static uint64_t txnid1, txnid2, txnid3;
43
44 struct iterate_extra {
iterate_extraiterate_extra45 iterate_extra() : n(0) {
46 visited_txn[0] = false;
47 visited_txn[1] = false;
48 visited_txn[2] = false;
49 }
50 int n;
51 bool visited_txn[3];
52 };
53
iterate_callback(DB_TXN * txn,iterate_row_locks_callback iterate_locks,void * locks_extra,void * extra)54 static int iterate_callback(DB_TXN *txn,
55 iterate_row_locks_callback iterate_locks,
56 void *locks_extra, void *extra) {
57 uint64_t txnid = txn->id64(txn);
58 uint64_t client_id; void *client_extra;
59 txn->get_client_id(txn, &client_id, &client_extra);
60 iterate_extra *info = reinterpret_cast<iterate_extra *>(extra);
61 DB *db;
62 DBT left_key, right_key;
63 int r = iterate_locks(&db, &left_key, &right_key, locks_extra);
64 invariant(r == DB_NOTFOUND);
65 if (txnid == txnid1) {
66 assert(!info->visited_txn[0]);
67 invariant(client_id == 0);
68 info->visited_txn[0] = true;
69 } else if (txnid == txnid2) {
70 assert(!info->visited_txn[1]);
71 invariant(client_id == 1);
72 info->visited_txn[1] = true;
73 } else if (txnid == txnid3) {
74 assert(!info->visited_txn[2]);
75 invariant(client_id == 2);
76 info->visited_txn[2] = true;
77 }
78 info->n++;
79 return 0;
80 }
81
test_main(int UU (argc),char * const UU (argv[]))82 int test_main(int UU(argc), char *const UU(argv[])) {
83 int r;
84 const int env_flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD |
85 DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN | DB_PRIVATE;
86
87 toku_os_recursive_delete(TOKU_TEST_FILENAME);
88 r = toku_os_mkdir(TOKU_TEST_FILENAME, 0755); CKERR(r);
89
90 DB_ENV *env;
91 r = db_env_create(&env, 0); CKERR(r);
92 r = env->iterate_live_transactions(env, iterate_callback, NULL);
93 assert(r == EINVAL);
94 r = env->open(env, TOKU_TEST_FILENAME, env_flags, 0755); CKERR(r);
95
96 r = env->txn_begin(env, NULL, &txn1, 0); CKERR(r);
97 txn1->set_client_id(txn1, 0, nullptr);
98 txnid1 = txn1->id64(txn1);
99 r = env->txn_begin(env, NULL, &txn2, 0); CKERR(r);
100 txn2->set_client_id(txn2, 1, nullptr);
101 txnid2 = txn2->id64(txn2);
102 r = env->txn_begin(env, NULL, &txn3, 0); CKERR(r);
103 txn3->set_client_id(txn3, 2, nullptr);
104 txnid3 = txn3->id64(txn3);
105
106 {
107 iterate_extra e;
108 r = env->iterate_live_transactions(env, iterate_callback, &e); CKERR(r);
109 assert(e.visited_txn[0]);
110 assert(e.visited_txn[1]);
111 assert(e.visited_txn[2]);
112 assert(e.n == 3);
113 }
114
115 r = txn1->commit(txn1, 0); CKERR(r);
116 r = txn2->abort(txn2); CKERR(r);
117 {
118 iterate_extra e;
119 r = env->iterate_live_transactions(env, iterate_callback, &e); CKERR(r);
120 assert(!e.visited_txn[0]);
121 assert(!e.visited_txn[1]);
122 assert(e.visited_txn[2]);
123 assert(e.n == 1);
124 }
125
126 r = txn3->commit(txn3, 0); CKERR(r);
127 {
128 iterate_extra e;
129 r = env->iterate_live_transactions(env, iterate_callback, &e); CKERR(r);
130 assert(!e.visited_txn[0]);
131 assert(!e.visited_txn[1]);
132 assert(!e.visited_txn[2]);
133 assert(e.n == 0);
134 }
135
136 r = env->close(env, 0); CKERR(r);
137 return 0;
138 }
139