From 7a48a263485a585dac1e1289c830eafd35a3d54b Mon Sep 17 00:00:00 2001 From: jannaerin Date: Tue, 3 Apr 2018 13:30:30 -0400 Subject: SERVER-34145 Persist database version on shard --- src/mongo/s/SConscript | 1 + src/mongo/s/catalog/type_shard_database.cpp | 132 +++++++++++++++++++++ src/mongo/s/catalog/type_shard_database.h | 121 +++++++++++++++++++ src/mongo/s/config_server_catalog_cache_loader.cpp | 16 ++- 4 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 src/mongo/s/catalog/type_shard_database.cpp create mode 100644 src/mongo/s/catalog/type_shard_database.h (limited to 'src/mongo/s') diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index 57e488774b3..b815dc7b38e 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -116,6 +116,7 @@ env.Library( 'catalog/type_mongos.cpp', 'catalog/type_shard.cpp', 'catalog/type_shard_collection.cpp', + 'catalog/type_shard_database.cpp', 'catalog/type_tags.cpp', 'chunk_version.cpp', 'request_types/add_shard_request_type.cpp', diff --git a/src/mongo/s/catalog/type_shard_database.cpp b/src/mongo/s/catalog/type_shard_database.cpp new file mode 100644 index 00000000000..5be668cceae --- /dev/null +++ b/src/mongo/s/catalog/type_shard_database.cpp @@ -0,0 +1,132 @@ +/** + * Copyright (C) 2018 10gen 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/s/catalog/type_shard_database.h" + +#include "mongo/base/status_with.h" +#include "mongo/bson/bsonobj.h" +#include "mongo/bson/bsonobjbuilder.h" +#include "mongo/bson/util/bson_extract.h" +#include "mongo/s/catalog/type_database.h" +#include "mongo/util/assert_util.h" + +namespace mongo { + +using std::string; + +const NamespaceString ShardDatabaseType::ConfigNS( + NamespaceString::kShardConfigDatabasesCollectionName); + +const BSONField ShardDatabaseType::name("_id"); +const BSONField ShardDatabaseType::version("version"); +const BSONField ShardDatabaseType::primary("primary"); +const BSONField ShardDatabaseType::partitioned("partitioned"); +const BSONField ShardDatabaseType::enterCriticalSectionCounter("enterCriticalSectionCounter"); + +ShardDatabaseType::ShardDatabaseType(const std::string dbName, + boost::optional version, + const ShardId primary, + bool partitioned) + : _name(dbName), _version(version), _primary(primary), _partitioned(partitioned) {} + +StatusWith ShardDatabaseType::fromBSON(const BSONObj& source) { + std::string dbName; + { + Status status = bsonExtractStringField(source, name.name(), &dbName); + if (!status.isOK()) + return status; + } + + boost::optional dbVersion = boost::none; + { + BSONObj versionField = source.getObjectField("version"); + // TODO: Parse this unconditionally once featureCompatibilityVersion 3.6 is no longer + // supported. + if (!versionField.isEmpty()) { + dbVersion = DatabaseVersion::parse(IDLParserErrorContext("DatabaseType"), versionField); + } + } + + std::string dbPrimary; + { + Status status = bsonExtractStringField(source, primary.name(), &dbPrimary); + if (!status.isOK()) + return status; + } + + bool dbPartitioned; + { + Status status = + bsonExtractBooleanFieldWithDefault(source, partitioned.name(), false, &dbPartitioned); + if (!status.isOK()) + return status; + } + + ShardDatabaseType shardDatabaseType(dbName, dbVersion, dbPrimary, dbPartitioned); + + return shardDatabaseType; +} + +BSONObj ShardDatabaseType::toBSON() const { + BSONObjBuilder builder; + + builder.append(name.name(), _name); + if (_version) { + builder.append(version.name(), _version->toBSON()); + } + builder.append(primary.name(), _primary.toString()); + builder.append(partitioned.name(), _partitioned); + + return builder.obj(); +} + +std::string ShardDatabaseType::toString() const { + return toBSON().toString(); +} + +void ShardDatabaseType::setDbVersion(boost::optional version) { + _version = version; +} + +void ShardDatabaseType::setDbName(const std::string& dbName) { + invariant(!dbName.empty()); + _name = dbName; +} + +void ShardDatabaseType::setPrimary(const ShardId& primary) { + invariant(primary.isValid()); + _primary = primary; +} + +void ShardDatabaseType::setPartitioned(bool partitioned) { + _partitioned = partitioned; +} + +} // namespace mongo diff --git a/src/mongo/s/catalog/type_shard_database.h b/src/mongo/s/catalog/type_shard_database.h new file mode 100644 index 00000000000..f8b0209636d --- /dev/null +++ b/src/mongo/s/catalog/type_shard_database.h @@ -0,0 +1,121 @@ +/** + * Copyright (C) 2018 10gen 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 +#include + +#include "mongo/db/jsobj.h" +#include "mongo/s/database_version_gen.h" +#include "mongo/s/shard_id.h" + +namespace mongo { + +class Status; +template +class StatusWith; + +/** + * This class represents the layout and contents of documents contained in the shard server's + * config.databases collection. All manipulation of documents coming from that collection should + * be done with this class. + * + * Expected shard server config.databases collection format: + * { + * "_id" : "foo", + * "version" : { + * "uuid" : UUID + * "lastMod" : 1 + * }, + * "primary": "shard0000", + * "partitioned": true, + * "enterCriticalSectionCounter" : 4 // optional + * } + * + * enterCriticalSectionCounter is currently just an OpObserver signal, thus otherwise ignored here. + */ +class ShardDatabaseType { +public: + // Name of the database collection on the shard server. + static const NamespaceString ConfigNS; + + static const BSONField name; // "_id" + static const BSONField version; + static const BSONField primary; + static const BSONField partitioned; + static const BSONField enterCriticalSectionCounter; + + ShardDatabaseType(const std::string dbName, + boost::optional version, + const ShardId primary, + bool partitioned); + + /** + * Constructs a new ShardDatabaseType object from BSON. Also does validation of the contents. + */ + static StatusWith fromBSON(const BSONObj& source); + + /** + * Returns the BSON representation of this shard database type object. + */ + BSONObj toBSON() const; + + /** + * Returns a std::string representation of the current internal state. + */ + std::string toString() const; + + const std::string& getDbName() const { + return _name; + } + void setDbName(const std::string& dbName); + + const boost::optional getDbVersion() const { + return _version; + } + void setDbVersion(boost::optional version); + + const ShardId& getPrimary() const { + return _primary; + } + void setPrimary(const ShardId& primary); + + bool getPartitioned() const { + return _partitioned; + } + void setPartitioned(bool partitioned); + +private: + std::string _name; + boost::optional _version; + ShardId _primary; + bool _partitioned; +}; + +} // namespace mongo diff --git a/src/mongo/s/config_server_catalog_cache_loader.cpp b/src/mongo/s/config_server_catalog_cache_loader.cpp index 68a6817ec83..eaa2669b072 100644 --- a/src/mongo/s/config_server_catalog_cache_loader.cpp +++ b/src/mongo/s/config_server_catalog_cache_loader.cpp @@ -200,13 +200,21 @@ void ConfigServerCatalogCacheLoader::getDatabase( stdx::function)> callbackFn) { if (MONGO_FAIL_POINT(callShardServerCallbackFn)) { - uassertStatusOK(_threadPool.schedule([ dbName, callbackFn ]() noexcept { + uassertStatusOK(_threadPool.schedule([ name = dbName.toString(), callbackFn ]() noexcept { auto opCtx = Client::getCurrent()->makeOperationContext(); - const auto dbVersion = Versioning::newDatabaseVersion(); - DatabaseType dbt(dbName.toString(), ShardId("PrimaryShard"), false, dbVersion); + auto swDbt = [&]() -> StatusWith { + try { - callbackFn(opCtx.get(), dbt); + const auto dbVersion = Versioning::newDatabaseVersion(); + DatabaseType dbt(std::move(name), ShardId("PrimaryShard"), false, dbVersion); + return dbt; + } catch (const DBException& ex) { + return ex.toStatus(); + } + }(); + + callbackFn(opCtx.get(), swDbt); })); } } -- cgit v1.2.1