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