diff options
author | Tess Avitabile <tess.avitabile@mongodb.com> | 2018-02-27 17:51:41 -0500 |
---|---|---|
committer | Tess Avitabile <tess.avitabile@mongodb.com> | 2018-03-02 17:21:41 -0500 |
commit | b1624b3fb1fe7eaf4554682d02c57abc519db819 (patch) | |
tree | 87791d227aed63623028ee51dbd6c5f585654962 /src/mongo/db/catalog_raii_test.cpp | |
parent | 70e200e98474d1a29339bf536f348257e8f83a9d (diff) | |
download | mongo-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.cpp | 204 |
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 |