summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog_raii_test.cpp
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2018-02-27 17:51:41 -0500
committerTess Avitabile <tess.avitabile@mongodb.com>2018-03-02 17:21:41 -0500
commitb1624b3fb1fe7eaf4554682d02c57abc519db819 (patch)
tree87791d227aed63623028ee51dbd6c5f585654962 /src/mongo/db/catalog_raii_test.cpp
parent70e200e98474d1a29339bf536f348257e8f83a9d (diff)
downloadmongo-b1624b3fb1fe7eaf4554682d02c57abc519db819.tar.gz
SERVER-33336 Snapshot reads should not take MODE_IX locks when autocommit=true
Diffstat (limited to 'src/mongo/db/catalog_raii_test.cpp')
-rw-r--r--src/mongo/db/catalog_raii_test.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/mongo/db/catalog_raii_test.cpp b/src/mongo/db/catalog_raii_test.cpp
new file mode 100644
index 00000000000..75d7f74ec63
--- /dev/null
+++ b/src/mongo/db/catalog_raii_test.cpp
@@ -0,0 +1,204 @@
+/**
+ * Copyright 2018 MongoDB Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
+
+#include "mongo/platform/basic.h"
+
+#include <string>
+
+#include "mongo/db/catalog_raii.h"
+#include "mongo/db/client.h"
+#include "mongo/db/concurrency/d_concurrency.h"
+#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/unittest/unittest.h"
+#include "mongo/util/log.h"
+#include "mongo/util/time_support.h"
+
+namespace mongo {
+namespace {
+
+class CatalogRAIITestFixture : public unittest::Test {
+public:
+ typedef std::pair<ServiceContext::UniqueClient, ServiceContext::UniqueOperationContext>
+ ClientAndCtx;
+
+ ClientAndCtx makeClientWithLocker(const std::string& clientName) {
+ auto client = getGlobalServiceContext()->makeClient(clientName);
+ auto opCtx = client->makeOperationContext();
+ opCtx->swapLockState(stdx::make_unique<DefaultLockerImpl>());
+ return std::make_pair(std::move(client), std::move(opCtx));
+ }
+
+ const NamespaceString nss = NamespaceString("test", "coll");
+ const Milliseconds timeoutMs = Seconds(1);
+ const ClientAndCtx client1 = makeClientWithLocker("client1");
+ const ClientAndCtx client2 = makeClientWithLocker("client2");
+};
+
+void failsWithLockTimeout(stdx::function<void()> func, Milliseconds timeoutMillis) {
+ Date_t t1 = Date_t::now();
+ try {
+ func();
+ FAIL("Should have gotten an exception due to timeout");
+ } catch (const ExceptionFor<ErrorCodes::LockTimeout>& ex) {
+ log() << ex;
+ Date_t t2 = Date_t::now();
+ ASSERT_GTE(t2 - t1, timeoutMillis);
+ }
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetDBDeadline) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_X);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_X));
+ failsWithLockTimeout(
+ [&] { AutoGetDb db(client2.second.get(), nss.db(), MODE_X, Date_t::now() + timeoutMs); },
+ timeoutMs);
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetDBGlobalLockDeadline) {
+ Lock::GlobalLock gLock1(client1.second.get(), MODE_X, Date_t::now());
+ ASSERT(gLock1.isLocked());
+ failsWithLockTimeout(
+ [&] { AutoGetDb db(client2.second.get(), nss.db(), MODE_X, Date_t::now() + timeoutMs); },
+ timeoutMs);
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetDBDeadlineNow) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_IX);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ AutoGetDb db(client2.second.get(), nss.db(), MODE_IX, Date_t::now());
+ failsWithLockTimeout(
+ [&] { AutoGetDb db(client2.second.get(), nss.db(), MODE_X, Date_t::now()); },
+ Milliseconds(0));
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetDBDeadlineMin) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_IX);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ AutoGetDb db(client2.second.get(), nss.db(), MODE_IX, Date_t::now());
+ failsWithLockTimeout(
+ [&] { AutoGetDb db(client2.second.get(), nss.db(), MODE_X, Date_t::now()); },
+ Milliseconds(0));
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetOrCreateDbDeadline) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_X);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_X));
+ failsWithLockTimeout(
+ [&] {
+ AutoGetOrCreateDb db(client2.second.get(), nss.db(), MODE_X, Date_t::now() + timeoutMs);
+ },
+ timeoutMs);
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetCollectionCollLockDeadline) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_IX);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ Lock::CollectionLock collLock1(client1.second.get()->lockState(), nss.toString(), MODE_X);
+ ASSERT(client1.second->lockState()->isCollectionLockedForMode(nss.toString(), MODE_X));
+ failsWithLockTimeout(
+ [&] {
+ AutoGetCollection coll(client2.second.get(),
+ nss,
+ MODE_IX,
+ MODE_X,
+ AutoGetCollection::ViewMode::kViewsForbidden,
+ Date_t::now() + timeoutMs);
+ },
+ timeoutMs);
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetCollectionDBLockDeadline) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_X);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_X));
+ failsWithLockTimeout(
+ [&] {
+ AutoGetCollection coll(client2.second.get(),
+ nss,
+ MODE_X,
+ MODE_X,
+ AutoGetCollection::ViewMode::kViewsForbidden,
+ Date_t::now() + timeoutMs);
+ },
+ timeoutMs);
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetCollectionGlobalLockDeadline) {
+ Lock::GlobalLock gLock1(client1.second.get(), MODE_X, Date_t::now());
+ ASSERT(client1.second->lockState()->isLocked());
+ failsWithLockTimeout(
+ [&] {
+ AutoGetCollection coll(client2.second.get(),
+ nss,
+ MODE_X,
+ MODE_X,
+ AutoGetCollection::ViewMode::kViewsForbidden,
+ Date_t::now() + timeoutMs);
+ },
+ timeoutMs);
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetCollectionDeadlineNow) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_IX);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ Lock::CollectionLock collLock1(client1.second.get()->lockState(), nss.toString(), MODE_X);
+ ASSERT(client1.second->lockState()->isCollectionLockedForMode(nss.toString(), MODE_X));
+
+ failsWithLockTimeout(
+ [&] {
+ AutoGetCollection coll(client2.second.get(),
+ nss,
+ MODE_IX,
+ MODE_X,
+ AutoGetCollection::ViewMode::kViewsForbidden,
+ Date_t::now());
+ },
+ Milliseconds(0));
+}
+
+TEST_F(CatalogRAIITestFixture, AutoGetCollectionDeadlineMin) {
+ Lock::DBLock dbLock1(client1.second.get(), nss.db(), MODE_IX);
+ ASSERT(client1.second->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ Lock::CollectionLock collLock1(client1.second.get()->lockState(), nss.toString(), MODE_X);
+ ASSERT(client1.second->lockState()->isCollectionLockedForMode(nss.toString(), MODE_X));
+
+ failsWithLockTimeout(
+ [&] {
+ AutoGetCollection coll(client2.second.get(),
+ nss,
+ MODE_IX,
+ MODE_X,
+ AutoGetCollection::ViewMode::kViewsForbidden,
+ Date_t::min());
+ },
+ Milliseconds(0));
+}
+
+} // namespace
+} // namespace mongo