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 "locktree_unit_test.h"
40
41 namespace toku {
42
43 // test simple, non-overlapping read locks and then write locks
test_simple_lock(void)44 void locktree_unit_test::test_simple_lock(void) {
45 locktree_manager mgr;
46 mgr.create(nullptr, nullptr, nullptr, nullptr);
47
48 DICTIONARY_ID dict_id = { .dictid = 1 };
49 locktree *lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
50
51 int r;
52 TXNID txnid_a = 1001;
53 TXNID txnid_b = 2001;
54 TXNID txnid_c = 3001;
55 TXNID txnid_d = 4001;
56 const DBT *one = get_dbt(1);
57 const DBT *two = get_dbt(2);
58 const DBT *three = get_dbt(3);
59 const DBT *four = get_dbt(4);
60
61 for (int test_run = 0; test_run < 2; test_run++) {
62 // test_run == 0 means test with read lock
63 // test_run == 1 means test with write lock
64 #define ACQUIRE_LOCK(txn, left, right, conflicts) \
65 test_run == 0 ? lt->acquire_read_lock(txn, left, right, conflicts, false) \
66 : lt->acquire_write_lock(txn, left, right, conflicts, false)
67
68 // four txns, four points
69 r = ACQUIRE_LOCK(txnid_a, one, one, nullptr);
70 invariant(r == 0);
71 r = ACQUIRE_LOCK(txnid_b, two, two, nullptr);
72 invariant(r == 0);
73 r = ACQUIRE_LOCK(txnid_c, three, three, nullptr);
74 invariant(r == 0);
75 r = ACQUIRE_LOCK(txnid_d, four, four, nullptr);
76 invariant(r == 0);
77 locktree_test_release_lock(lt, txnid_a, one, one);
78 locktree_test_release_lock(lt, txnid_b, two, two);
79 locktree_test_release_lock(lt, txnid_c, three, three);
80 locktree_test_release_lock(lt, txnid_d, four, four);
81 invariant(no_row_locks(lt));
82
83 // two txns, two ranges
84 r = ACQUIRE_LOCK(txnid_c, one, two, nullptr);
85 invariant(r == 0);
86 r = ACQUIRE_LOCK(txnid_b, three, four, nullptr);
87 invariant(r == 0);
88 locktree_test_release_lock(lt, txnid_c, one, two);
89 locktree_test_release_lock(lt, txnid_b, three, four);
90 invariant(no_row_locks(lt));
91
92 // two txns, one range, one point
93 r = ACQUIRE_LOCK(txnid_c, three, four, nullptr);
94 invariant(r == 0);
95 r = ACQUIRE_LOCK(txnid_d, one, one, nullptr);
96 invariant(r == 0);
97 locktree_test_release_lock(lt, txnid_c, three, four);
98 locktree_test_release_lock(lt, txnid_d, one, one);
99 invariant(no_row_locks(lt));
100
101 #undef ACQUIRE_LOCK
102 }
103
104 const int64_t num_locks = 10000;
105
106 int64_t *keys = (int64_t *) toku_malloc(num_locks * sizeof(int64_t));
107 for (int64_t i = 0; i < num_locks; i++) {
108 keys[i] = i;
109 }
110 for (int64_t i = 0; i < num_locks; i++) {
111 int64_t k = rand() % num_locks;
112 int64_t tmp = keys[k];
113 keys[k] = keys[i];
114 keys[i] = tmp;
115 }
116
117
118 r = mgr.set_max_lock_memory((num_locks + 1) * 500);
119 invariant_zero(r);
120
121 DBT k;
122 k.ulen = 0;
123 k.size = sizeof(keys[0]);
124 k.flags = DB_DBT_USERMEM;
125
126 for (int64_t i = 0; i < num_locks; i++) {
127 k.data = (void *) &keys[i];
128 r = lt->acquire_read_lock(txnid_a, &k, &k, nullptr, false);
129 invariant(r == 0);
130 }
131
132 for (int64_t i = 0; i < num_locks; i++) {
133 k.data = (void *) &keys[i];
134 locktree_test_release_lock(lt, txnid_a, &k, &k);
135 }
136
137 toku_free(keys);
138
139 mgr.release_lt(lt);
140 mgr.destroy();
141 }
142
143 } /* namespace toku */
144
main(void)145 int main(void) {
146 toku::locktree_unit_test test;
147 test.test_simple_lock();
148 return 0;
149 }
150