From 5e3564a89ed631e2b1372eb455a8344f21089264 Mon Sep 17 00:00:00 2001 From: Esha Maharishi Date: Thu, 22 Feb 2018 21:54:05 -0500 Subject: SERVER-33032 add a DatabaseShardingState containing the databaseVersion as a decoration on Database --- src/mongo/db/catalog/database.h | 2 +- src/mongo/db/s/SConscript | 3 + src/mongo/db/s/database_sharding_state.cpp | 85 ++++++++++++++++++++++++ src/mongo/db/s/database_sharding_state.h | 103 +++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/mongo/db/s/database_sharding_state.cpp create mode 100644 src/mongo/db/s/database_sharding_state.h diff --git a/src/mongo/db/catalog/database.h b/src/mongo/db/catalog/database.h index c025244ae7f..e5fab444357 100644 --- a/src/mongo/db/catalog/database.h +++ b/src/mongo/db/catalog/database.h @@ -51,7 +51,7 @@ namespace mongo { * The semantics for a const Database are that you can mutate individual collections but not add or * remove them. */ -class Database { +class Database : public Decorable { public: typedef StringMap CollectionMap; diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index f2fbcb15906..30c89725877 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -12,8 +12,11 @@ env.Library( target='sharding_api_d', source=[ 'collection_metadata.cpp', + 'database_sharding_state.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/util/decorable', '$BUILD_DIR/mongo/db/range_arithmetic', '$BUILD_DIR/mongo/s/sharding_routing_table', ], diff --git a/src/mongo/db/s/database_sharding_state.cpp b/src/mongo/db/s/database_sharding_state.cpp new file mode 100644 index 00000000000..40a630bc5b4 --- /dev/null +++ b/src/mongo/db/s/database_sharding_state.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (C) 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 . + * + * 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. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/db/s/database_sharding_state.h" + +#include "mongo/db/operation_context.h" + +namespace mongo { +const Database::Decoration DatabaseShardingState::get = + Database::declareDecorationWithOwner(); + +DatabaseShardingState::DatabaseShardingState(Database* db) : _db(db) {} + +void DatabaseShardingState::enterCriticalSection(OperationContext* opCtx) { + invariant(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_X)); + invariant(!_critSecSignal); + _critSecSignal = std::make_shared>(); + // TODO (SERVER-33313): call CursorManager::invalidateAll() on all collections in this database + // with 'fromMovePrimary=true' and a predicate to only invalidate the cursor if the opCtx on its + // PlanExecutor has a client dbVersion. +} + +void DatabaseShardingState::exitCriticalSection(OperationContext* opCtx, + boost::optional newDbVersion) { + invariant(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_X)); + invariant(_critSecSignal); + _critSecSignal->set(); + _critSecSignal.reset(); + _dbVersion = newDbVersion; +} + +std::shared_ptr> DatabaseShardingState::getCriticalSectionSignal() const { + return _critSecSignal; +} + +void DatabaseShardingState::setDbVersion(OperationContext* opCtx, + boost::optional newDbVersion) { + invariant(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_X)); + _dbVersion = newDbVersion; +} + +void DatabaseShardingState::checkDbVersion(OperationContext* opCtx) const { + invariant(opCtx->lockState()->isLocked()); + + if (_critSecSignal) { + // TODO (SERVER-33097): Set movePrimary critical section signal on the + // OperationShardingState (so that the operation can wait outside the DBLock for the + // movePrimary critical section to end before returning to the client). + + // TODO (SERVER-33098): throw StaleDbVersion. + } + + // TODO (SERVER-33098): check the client's dbVersion (from the OperationShardingState) against + // _dbVersion, and throw StaleDbVersion if they don't match. + return; +} + +} // namespace mongo diff --git a/src/mongo/db/s/database_sharding_state.h b/src/mongo/db/s/database_sharding_state.h new file mode 100644 index 00000000000..28c0d94df22 --- /dev/null +++ b/src/mongo/db/s/database_sharding_state.h @@ -0,0 +1,103 @@ +/** + * Copyright (C) 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 . + * + * 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. + */ + +#pragma once + +#include "mongo/base/disallow_copying.h" +#include "mongo/db/catalog/database.h" +#include "mongo/s/database_version_gen.h" + +namespace mongo { + +class OperationContext; + +/** + * Synchronizes access to this shard server's cached database version for Database. + */ +class DatabaseShardingState { + MONGO_DISALLOW_COPYING(DatabaseShardingState); + +public: + static const Database::Decoration get; + + DatabaseShardingState(Database* db); + ~DatabaseShardingState() = default; + + /** + * Assigns a new Notification to _critSecSignal and invalidates all yielded readers and writers + * on collections in Database that have a client dbVersion on their OperationContext. + * + * Invariants that _critSecSignal was null and that the caller holds the DBLock in X mode. + */ + void enterCriticalSection(OperationContext* opCtx); + + /** + * Signals and clears _critSecSignal, and sets _dbVersion to 'newDbVersion'. + * + * Invariants that _critSecSignal was not null and that the caller holds the DBLock in X mode. + */ + void exitCriticalSection(OperationContext* opCtx, + boost::optional newDbVersion); + + /** + * Returns a shared_ptr to _critSecSignal if it's non-null, otherwise nullptr. + */ + std::shared_ptr> getCriticalSectionSignal() const; + + /** + * Sets this shard server's cached dbVersion to newVersion. + * + * Invariants that the caller holds the DBLock in X mode. + */ + void setDbVersion(OperationContext* opCtx, boost::optional newVersion); + + /** + * If _critSecSignal is non-null, always throws StaleDbVersion. + * Otherwise, if there is a client dbVersion on the OperationContext, compares it with this + * shard server's cached dbVersion and throws StaleDbVersion if they do not match. + */ + void checkDbVersion(OperationContext* opCtx) const; + +private: + // The database to which this sharding state corresponds. + const Database* _db; + + // Modifying the state below requires holding the DBLock in X mode; holding the DBLock in any + // mode is acceptable for reading it. (Note: accessing this class at all requires holding the + // DBLock in some mode, since it requires having a pointer to the Database). + + // Is non-null if this shard server is in a movePrimary critical section for the database. + // Stored as shared_ptr rather than boost::optional so callers can wait on it outside a DBLock. + std::shared_ptr> _critSecSignal; + + // This shard server's cached dbVersion. If boost::none, indicates this shard server does not + // know the dbVersion. + boost::optional _dbVersion = boost::none; +}; + +} // namespace mongo -- cgit v1.2.1