summaryrefslogtreecommitdiff
path: root/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc')
-rw-r--r--storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc134
1 files changed, 134 insertions, 0 deletions
diff --git a/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc b/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc
new file mode 100644
index 00000000000..f2bf0a2c756
--- /dev/null
+++ b/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc
@@ -0,0 +1,134 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*======
+This file is part of PerconaFT.
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
+
+----------------------------------------
+
+ PerconaFT is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License, version 3,
+ as published by the Free Software Foundation.
+
+ PerconaFT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
+======= */
+
+#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#include "test.h"
+
+#include <portability/toku_pthread.h>
+
+static DB_ENV *env;
+static DB *db;
+static DB_TXN *txn1, *txn2, *txn3;
+static const char *dname = "iterate_pending_requests_dname";
+static const int magic_key = 100;
+static int iterate_callback_called;
+toku_pthread_t thread1, thread2;
+
+// Verify the state of the world
+static int iterate_callback(DB *_db, uint64_t requesting_txnid,
+ const DBT *left_key, const DBT *right_key,
+ uint64_t blocking_txnid, uint64_t start_time, void *extra) {
+ iterate_callback_called++;
+ invariant(extra == nullptr);
+ invariant(strcmp(_db->get_dname(_db), db->get_dname(db)) == 0);
+ invariant(start_time > 0);
+ invariant(*reinterpret_cast<int *>(left_key->data) == magic_key);
+ invariant(*reinterpret_cast<int *>(right_key->data) == magic_key);
+ invariant(blocking_txnid == txn1->id64(txn1));
+ invariant(requesting_txnid == txn2->id64(txn2) || requesting_txnid == txn3->id64(txn3));
+ return 0;
+}
+
+static void acquire_lock(DB_TXN *txn, int key) {
+ int val = 0;
+ DBT k, v;
+ dbt_init(&k, &key, sizeof(int));
+ dbt_init(&v, &val, sizeof(int));
+ (void) db->put(db, txn, &k, &v, 0);
+}
+
+struct acquire_lock_extra {
+ acquire_lock_extra(DB_TXN *x, int k) :
+ txn(x), key(k) {
+ }
+ DB_TXN *txn;
+ int key;
+};
+
+static void *acquire_lock_thread(void *arg) {
+ acquire_lock_extra *info = reinterpret_cast<acquire_lock_extra *>(arg);
+ acquire_lock(info->txn, info->key);
+ return NULL;
+}
+
+int test_main(int UU(argc), char *const UU(argv[])) {
+ int r;
+ const int env_flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD |
+ DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN | DB_PRIVATE;
+
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ r = toku_os_mkdir(TOKU_TEST_FILENAME, 0755); CKERR(r);
+
+ r = db_env_create(&env, 0); CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME, env_flags, 0755); CKERR(r);
+ r = env->set_lock_timeout(env, 4000, nullptr);
+
+ r = db_create(&db, env, 0); CKERR(r);
+ r = db->open(db, NULL, dname, NULL, DB_BTREE, DB_CREATE, 0777); CKERR(r);
+
+ r = env->txn_begin(env, NULL, &txn1, DB_SERIALIZABLE); CKERR(r);
+ r = env->txn_begin(env, NULL, &txn2, DB_SERIALIZABLE); CKERR(r);
+ r = env->txn_begin(env, NULL, &txn3, DB_SERIALIZABLE); CKERR(r);
+
+ // Extremely simple test. Get lock [0, 0] on txn1, then asynchronously
+ // attempt to get that lock in txn2 and txn3. The iterate callback
+ // verifies that two waiters exist for [0, 0] and that txn1 is
+ // the blocking txn.
+
+ acquire_lock(txn1, magic_key);
+
+ acquire_lock_extra e1(txn2, magic_key);
+ r = toku_pthread_create(&thread1, NULL, acquire_lock_thread, &e1); CKERR(r);
+ acquire_lock_extra e2(txn3, magic_key);
+ r = toku_pthread_create(&thread2, NULL, acquire_lock_thread, &e2); CKERR(r);
+
+ sleep(1);
+ r = env->iterate_pending_lock_requests(env, iterate_callback, NULL); CKERR(r);
+ invariant(iterate_callback_called == 2);
+
+ void *v;
+ r = toku_pthread_join(thread1, &v); CKERR(r);
+ r = toku_pthread_join(thread2, &v); CKERR(r);
+
+ r = txn1->commit(txn1, 0); CKERR(r);
+ r = txn2->commit(txn2, 0); CKERR(r);
+ r = txn3->commit(txn3, 0); CKERR(r);
+
+ r = db->close(db, 0); CKERR(r);
+ r = env->close(env, 0); CKERR(r);
+ return 0;
+}