summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency/lock_state_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/concurrency/lock_state_test.cpp')
-rw-r--r--src/mongo/db/concurrency/lock_state_test.cpp412
1 files changed, 205 insertions, 207 deletions
diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp
index 54f305f20df..cb3d87aa1ad 100644
--- a/src/mongo/db/concurrency/lock_state_test.cpp
+++ b/src/mongo/db/concurrency/lock_state_test.cpp
@@ -40,280 +40,278 @@
namespace mongo {
namespace {
- const int NUM_PERF_ITERS = 1000*1000; // numeber of iterations to use for lock perf
+const int NUM_PERF_ITERS = 1000 * 1000; // numeber of iterations to use for lock perf
}
- TEST(LockerImpl, LockNoConflict) {
- const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+TEST(LockerImpl, LockNoConflict) {
+ const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- MMAPV1LockerImpl locker;
- locker.lockGlobal(MODE_IX);
+ MMAPV1LockerImpl locker;
+ locker.lockGlobal(MODE_IX);
- ASSERT(LOCK_OK == locker.lock(resId, MODE_X));
+ ASSERT(LOCK_OK == locker.lock(resId, MODE_X));
- ASSERT(locker.isLockHeldForMode(resId, MODE_X));
- ASSERT(locker.isLockHeldForMode(resId, MODE_S));
+ ASSERT(locker.isLockHeldForMode(resId, MODE_X));
+ ASSERT(locker.isLockHeldForMode(resId, MODE_S));
- ASSERT(locker.unlock(resId));
+ ASSERT(locker.unlock(resId));
- ASSERT(locker.isLockHeldForMode(resId, MODE_NONE));
+ ASSERT(locker.isLockHeldForMode(resId, MODE_NONE));
- locker.unlockAll();
- }
+ locker.unlockAll();
+}
- TEST(LockerImpl, ReLockNoConflict) {
- const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+TEST(LockerImpl, ReLockNoConflict) {
+ const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- MMAPV1LockerImpl locker;
- locker.lockGlobal(MODE_IX);
+ MMAPV1LockerImpl locker;
+ locker.lockGlobal(MODE_IX);
- ASSERT(LOCK_OK == locker.lock(resId, MODE_S));
- ASSERT(LOCK_OK == locker.lock(resId, MODE_X));
+ ASSERT(LOCK_OK == locker.lock(resId, MODE_S));
+ ASSERT(LOCK_OK == locker.lock(resId, MODE_X));
- ASSERT(!locker.unlock(resId));
- ASSERT(locker.isLockHeldForMode(resId, MODE_X));
+ ASSERT(!locker.unlock(resId));
+ ASSERT(locker.isLockHeldForMode(resId, MODE_X));
- ASSERT(locker.unlock(resId));
- ASSERT(locker.isLockHeldForMode(resId, MODE_NONE));
+ ASSERT(locker.unlock(resId));
+ ASSERT(locker.isLockHeldForMode(resId, MODE_NONE));
- ASSERT(locker.unlockAll());
- }
+ ASSERT(locker.unlockAll());
+}
- TEST(LockerImpl, ConflictWithTimeout) {
- const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+TEST(LockerImpl, ConflictWithTimeout) {
+ const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- DefaultLockerImpl locker1;
- ASSERT(LOCK_OK == locker1.lockGlobal(MODE_IX));
- ASSERT(LOCK_OK == locker1.lock(resId, MODE_X));
+ DefaultLockerImpl locker1;
+ ASSERT(LOCK_OK == locker1.lockGlobal(MODE_IX));
+ ASSERT(LOCK_OK == locker1.lock(resId, MODE_X));
- DefaultLockerImpl locker2;
- ASSERT(LOCK_OK == locker2.lockGlobal(MODE_IX));
- ASSERT(LOCK_TIMEOUT == locker2.lock(resId, MODE_S, 0));
+ DefaultLockerImpl locker2;
+ ASSERT(LOCK_OK == locker2.lockGlobal(MODE_IX));
+ ASSERT(LOCK_TIMEOUT == locker2.lock(resId, MODE_S, 0));
- ASSERT(locker2.getLockMode(resId) == MODE_NONE);
+ ASSERT(locker2.getLockMode(resId) == MODE_NONE);
- ASSERT(locker1.unlock(resId));
+ ASSERT(locker1.unlock(resId));
- ASSERT(locker1.unlockAll());
- ASSERT(locker2.unlockAll());
- }
+ ASSERT(locker1.unlockAll());
+ ASSERT(locker2.unlockAll());
+}
- TEST(LockerImpl, ConflictUpgradeWithTimeout) {
- const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+TEST(LockerImpl, ConflictUpgradeWithTimeout) {
+ const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- DefaultLockerImpl locker1;
- ASSERT(LOCK_OK == locker1.lockGlobal(MODE_IS));
- ASSERT(LOCK_OK == locker1.lock(resId, MODE_S));
+ DefaultLockerImpl locker1;
+ ASSERT(LOCK_OK == locker1.lockGlobal(MODE_IS));
+ ASSERT(LOCK_OK == locker1.lock(resId, MODE_S));
- DefaultLockerImpl locker2;
- ASSERT(LOCK_OK == locker2.lockGlobal(MODE_IS));
- ASSERT(LOCK_OK == locker2.lock(resId, MODE_S));
+ DefaultLockerImpl locker2;
+ ASSERT(LOCK_OK == locker2.lockGlobal(MODE_IS));
+ ASSERT(LOCK_OK == locker2.lock(resId, MODE_S));
- // Try upgrading locker 1, which should block and timeout
- ASSERT(LOCK_TIMEOUT == locker1.lock(resId, MODE_X, 1));
+ // Try upgrading locker 1, which should block and timeout
+ ASSERT(LOCK_TIMEOUT == locker1.lock(resId, MODE_X, 1));
- locker1.unlockAll();
- locker2.unlockAll();
- }
+ locker1.unlockAll();
+ locker2.unlockAll();
+}
- TEST(LockerImpl, ReadTransaction) {
- DefaultLockerImpl locker;
+TEST(LockerImpl, ReadTransaction) {
+ DefaultLockerImpl locker;
- locker.lockGlobal(MODE_IS);
- locker.unlockAll();
+ locker.lockGlobal(MODE_IS);
+ locker.unlockAll();
- locker.lockGlobal(MODE_IX);
- locker.unlockAll();
+ locker.lockGlobal(MODE_IX);
+ locker.unlockAll();
- locker.lockGlobal(MODE_IX);
- locker.lockGlobal(MODE_IS);
- locker.unlockAll();
- locker.unlockAll();
- }
+ locker.lockGlobal(MODE_IX);
+ locker.lockGlobal(MODE_IS);
+ locker.unlockAll();
+ locker.unlockAll();
+}
- /**
- * Test that saveMMAPV1LockerImpl works by examining the output.
- */
- TEST(LockerImpl, saveAndRestoreGlobal) {
- Locker::LockSnapshot lockInfo;
+/**
+ * Test that saveMMAPV1LockerImpl works by examining the output.
+ */
+TEST(LockerImpl, saveAndRestoreGlobal) {
+ Locker::LockSnapshot lockInfo;
- DefaultLockerImpl locker;
+ DefaultLockerImpl locker;
- // No lock requests made, no locks held.
- locker.saveLockStateAndUnlock(&lockInfo);
- ASSERT_EQUALS(0U, lockInfo.locks.size());
+ // No lock requests made, no locks held.
+ locker.saveLockStateAndUnlock(&lockInfo);
+ ASSERT_EQUALS(0U, lockInfo.locks.size());
- // Lock the global lock, but just once.
- locker.lockGlobal(MODE_IX);
+ // Lock the global lock, but just once.
+ locker.lockGlobal(MODE_IX);
- // We've locked the global lock. This should be reflected in the lockInfo.
- locker.saveLockStateAndUnlock(&lockInfo);
- ASSERT(!locker.isLocked());
- ASSERT_EQUALS(MODE_IX, lockInfo.globalMode);
+ // We've locked the global lock. This should be reflected in the lockInfo.
+ locker.saveLockStateAndUnlock(&lockInfo);
+ ASSERT(!locker.isLocked());
+ ASSERT_EQUALS(MODE_IX, lockInfo.globalMode);
- // Restore the lock(s) we had.
- locker.restoreLockState(lockInfo);
+ // Restore the lock(s) we had.
+ locker.restoreLockState(lockInfo);
- ASSERT(locker.isLocked());
- ASSERT(locker.unlockAll());
- }
+ ASSERT(locker.isLocked());
+ ASSERT(locker.unlockAll());
+}
- /**
- * Test that we don't unlock when we have the global lock more than once.
- */
- TEST(LockerImpl, saveAndRestoreGlobalAcquiredTwice) {
- Locker::LockSnapshot lockInfo;
+/**
+ * Test that we don't unlock when we have the global lock more than once.
+ */
+TEST(LockerImpl, saveAndRestoreGlobalAcquiredTwice) {
+ Locker::LockSnapshot lockInfo;
- DefaultLockerImpl locker;
+ DefaultLockerImpl locker;
- // No lock requests made, no locks held.
- locker.saveLockStateAndUnlock(&lockInfo);
- ASSERT_EQUALS(0U, lockInfo.locks.size());
+ // No lock requests made, no locks held.
+ locker.saveLockStateAndUnlock(&lockInfo);
+ ASSERT_EQUALS(0U, lockInfo.locks.size());
- // Lock the global lock.
- locker.lockGlobal(MODE_IX);
- locker.lockGlobal(MODE_IX);
+ // Lock the global lock.
+ locker.lockGlobal(MODE_IX);
+ locker.lockGlobal(MODE_IX);
- // This shouldn't actually unlock as we're in a nested scope.
- ASSERT(!locker.saveLockStateAndUnlock(&lockInfo));
+ // This shouldn't actually unlock as we're in a nested scope.
+ ASSERT(!locker.saveLockStateAndUnlock(&lockInfo));
- ASSERT(locker.isLocked());
+ ASSERT(locker.isLocked());
- // We must unlockAll twice.
- ASSERT(!locker.unlockAll());
- ASSERT(locker.unlockAll());
- }
+ // We must unlockAll twice.
+ ASSERT(!locker.unlockAll());
+ ASSERT(locker.unlockAll());
+}
- /**
- * Tests that restoreMMAPV1LockerImpl works by locking a db and collection and saving + restoring.
- */
- TEST(LockerImpl, saveAndRestoreDBAndCollection) {
- Locker::LockSnapshot lockInfo;
+/**
+ * Tests that restoreMMAPV1LockerImpl works by locking a db and collection and saving + restoring.
+ */
+TEST(LockerImpl, saveAndRestoreDBAndCollection) {
+ Locker::LockSnapshot lockInfo;
- DefaultLockerImpl locker;
+ DefaultLockerImpl locker;
- const ResourceId resIdDatabase(RESOURCE_DATABASE, std::string("TestDB"));
- const ResourceId resIdCollection(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+ const ResourceId resIdDatabase(RESOURCE_DATABASE, std::string("TestDB"));
+ const ResourceId resIdCollection(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- // Lock some stuff.
- locker.lockGlobal(MODE_IX);
- ASSERT_EQUALS(LOCK_OK, locker.lock(resIdDatabase, MODE_IX));
- ASSERT_EQUALS(LOCK_OK, locker.lock(resIdCollection, MODE_X));
- locker.saveLockStateAndUnlock(&lockInfo);
+ // Lock some stuff.
+ locker.lockGlobal(MODE_IX);
+ ASSERT_EQUALS(LOCK_OK, locker.lock(resIdDatabase, MODE_IX));
+ ASSERT_EQUALS(LOCK_OK, locker.lock(resIdCollection, MODE_X));
+ locker.saveLockStateAndUnlock(&lockInfo);
- // Things shouldn't be locked anymore.
- ASSERT_EQUALS(MODE_NONE, locker.getLockMode(resIdDatabase));
- ASSERT_EQUALS(MODE_NONE, locker.getLockMode(resIdCollection));
+ // Things shouldn't be locked anymore.
+ ASSERT_EQUALS(MODE_NONE, locker.getLockMode(resIdDatabase));
+ ASSERT_EQUALS(MODE_NONE, locker.getLockMode(resIdCollection));
- // Restore lock state.
- locker.restoreLockState(lockInfo);
+ // Restore lock state.
+ locker.restoreLockState(lockInfo);
- // Make sure things were re-locked.
- ASSERT_EQUALS(MODE_IX, locker.getLockMode(resIdDatabase));
- ASSERT_EQUALS(MODE_X, locker.getLockMode(resIdCollection));
+ // Make sure things were re-locked.
+ ASSERT_EQUALS(MODE_IX, locker.getLockMode(resIdDatabase));
+ ASSERT_EQUALS(MODE_X, locker.getLockMode(resIdCollection));
- ASSERT(locker.unlockAll());
- }
+ ASSERT(locker.unlockAll());
+}
- TEST(LockerImpl, DefaultLocker) {
- const ResourceId resId(RESOURCE_DATABASE, std::string("TestDB"));
+TEST(LockerImpl, DefaultLocker) {
+ const ResourceId resId(RESOURCE_DATABASE, std::string("TestDB"));
- DefaultLockerImpl locker;
- ASSERT_EQUALS(LOCK_OK, locker.lockGlobal(MODE_IX));
- ASSERT_EQUALS(LOCK_OK, locker.lock(resId, MODE_X));
-
- // Make sure the flush lock IS NOT held
- Locker::LockerInfo info;
- locker.getLockerInfo(&info);
- ASSERT(!info.waitingResource.isValid());
- ASSERT_EQUALS(2U, info.locks.size());
- ASSERT_EQUALS(RESOURCE_GLOBAL, info.locks[0].resourceId.getType());
- ASSERT_EQUALS(resId, info.locks[1].resourceId);
-
- ASSERT(locker.unlockAll());
- }
+ DefaultLockerImpl locker;
+ ASSERT_EQUALS(LOCK_OK, locker.lockGlobal(MODE_IX));
+ ASSERT_EQUALS(LOCK_OK, locker.lock(resId, MODE_X));
- TEST(LockerImpl, MMAPV1Locker) {
- const ResourceId resId(RESOURCE_DATABASE, std::string("TestDB"));
+ // Make sure the flush lock IS NOT held
+ Locker::LockerInfo info;
+ locker.getLockerInfo(&info);
+ ASSERT(!info.waitingResource.isValid());
+ ASSERT_EQUALS(2U, info.locks.size());
+ ASSERT_EQUALS(RESOURCE_GLOBAL, info.locks[0].resourceId.getType());
+ ASSERT_EQUALS(resId, info.locks[1].resourceId);
- MMAPV1LockerImpl locker;
- ASSERT_EQUALS(LOCK_OK, locker.lockGlobal(MODE_IX));
- ASSERT_EQUALS(LOCK_OK, locker.lock(resId, MODE_X));
+ ASSERT(locker.unlockAll());
+}
- // Make sure the flush lock IS held
- Locker::LockerInfo info;
- locker.getLockerInfo(&info);
- ASSERT(!info.waitingResource.isValid());
- ASSERT_EQUALS(3U, info.locks.size());
- ASSERT_EQUALS(RESOURCE_GLOBAL, info.locks[0].resourceId.getType());
- ASSERT_EQUALS(RESOURCE_MMAPV1_FLUSH, info.locks[1].resourceId.getType());
- ASSERT_EQUALS(resId, info.locks[2].resourceId);
+TEST(LockerImpl, MMAPV1Locker) {
+ const ResourceId resId(RESOURCE_DATABASE, std::string("TestDB"));
- ASSERT(locker.unlockAll());
- }
+ MMAPV1LockerImpl locker;
+ ASSERT_EQUALS(LOCK_OK, locker.lockGlobal(MODE_IX));
+ ASSERT_EQUALS(LOCK_OK, locker.lock(resId, MODE_X));
+ // Make sure the flush lock IS held
+ Locker::LockerInfo info;
+ locker.getLockerInfo(&info);
+ ASSERT(!info.waitingResource.isValid());
+ ASSERT_EQUALS(3U, info.locks.size());
+ ASSERT_EQUALS(RESOURCE_GLOBAL, info.locks[0].resourceId.getType());
+ ASSERT_EQUALS(RESOURCE_MMAPV1_FLUSH, info.locks[1].resourceId.getType());
+ ASSERT_EQUALS(resId, info.locks[2].resourceId);
- // These two tests exercise single-threaded performance of uncontended lock acquisition. It
- // is not practical to run them on debug builds.
+ ASSERT(locker.unlockAll());
+}
+
+
+// These two tests exercise single-threaded performance of uncontended lock acquisition. It
+// is not practical to run them on debug builds.
#ifndef MONGO_CONFIG_DEBUG_BUILD
- TEST(Locker, PerformanceBoostSharedMutex) {
- for (int numLockers = 1; numLockers <= 64; numLockers = numLockers * 2) {
- stdx::mutex mtx;
-
- // Do some warm-up loops
- for (int i = 0; i < 1000; i++) {
- mtx.lock();
- mtx.unlock();
- }
-
- // Measure the number of loops
- //
- Timer t;
-
- for (int i = 0; i < NUM_PERF_ITERS; i++) {
- mtx.lock();
- mtx.unlock();
- }
-
- log() << numLockers
- << " locks took: "
- << static_cast<double>(t.micros()) * 1000.0 / static_cast<double>(NUM_PERF_ITERS)
- << " ns";
+TEST(Locker, PerformanceBoostSharedMutex) {
+ for (int numLockers = 1; numLockers <= 64; numLockers = numLockers * 2) {
+ stdx::mutex mtx;
+
+ // Do some warm-up loops
+ for (int i = 0; i < 1000; i++) {
+ mtx.lock();
+ mtx.unlock();
+ }
+
+ // Measure the number of loops
+ //
+ Timer t;
+
+ for (int i = 0; i < NUM_PERF_ITERS; i++) {
+ mtx.lock();
+ mtx.unlock();
}
+
+ log() << numLockers << " locks took: "
+ << static_cast<double>(t.micros()) * 1000.0 / static_cast<double>(NUM_PERF_ITERS)
+ << " ns";
}
+}
+
+TEST(Locker, PerformanceLocker) {
+ for (int numLockers = 1; numLockers <= 64; numLockers = numLockers * 2) {
+ std::vector<std::shared_ptr<LockerForTests>> lockers(numLockers);
+ for (int i = 0; i < numLockers; i++) {
+ lockers[i].reset(new LockerForTests(MODE_S));
+ }
+
+ DefaultLockerImpl locker;
+
+ // Do some warm-up loops
+ for (int i = 0; i < 1000; i++) {
+ locker.lockGlobal(MODE_IS);
+ locker.unlockAll();
+ }
- TEST(Locker, PerformanceLocker) {
- for (int numLockers = 1; numLockers <= 64; numLockers = numLockers * 2) {
- std::vector<std::shared_ptr<LockerForTests> > lockers(numLockers);
- for (int i = 0; i < numLockers; i++) {
- lockers[i].reset(new LockerForTests(MODE_S));
- }
-
- DefaultLockerImpl locker;
-
- // Do some warm-up loops
- for (int i = 0; i < 1000; i++) {
- locker.lockGlobal(MODE_IS);
- locker.unlockAll();
- }
-
- // Measure the number of loops
- Timer t;
-
- for (int i = 0; i < NUM_PERF_ITERS; i++) {
- locker.lockGlobal(MODE_IS);
- locker.unlockAll();
- }
-
- log() << numLockers
- << " locks took: "
- << static_cast<double>(t.micros()) * 1000.0 / static_cast<double>(NUM_PERF_ITERS)
- << " ns";
+ // Measure the number of loops
+ Timer t;
+
+ for (int i = 0; i < NUM_PERF_ITERS; i++) {
+ locker.lockGlobal(MODE_IS);
+ locker.unlockAll();
}
+
+ log() << numLockers << " locks took: "
+ << static_cast<double>(t.micros()) * 1000.0 / static_cast<double>(NUM_PERF_ITERS)
+ << " ns";
}
+}
#endif // MONGO_CONFIG_DEBUG_BUILD
-} // namespace mongo
+} // namespace mongo