diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-08-14 15:31:31 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-08-14 15:31:31 -0400 |
commit | 1cee34ee3907b7652abdfc7f75ca27ef421a46c4 (patch) | |
tree | 54b3e59b4a066e3b3acf4b1bc44998cebf7f6fe5 | |
parent | cec89b290906adb7d36507d20d619aaa5a6f6c16 (diff) | |
download | mongo-1cee34ee3907b7652abdfc7f75ca27ef421a46c4.tar.gz |
Revert "SERVER-19855 Include min OpTime with shard version"
This reverts commit cec89b290906adb7d36507d20d619aaa5a6f6c16.
25 files changed, 301 insertions, 520 deletions
diff --git a/src/mongo/db/repl/optime_pair.h b/src/mongo/db/repl/optime_pair.h deleted file mode 100644 index 0f301784f7e..00000000000 --- a/src/mongo/db/repl/optime_pair.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (C) 2015 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. - */ - -#pragma once - -#include "mongo/db/repl/optime.h" - -namespace mongo { -namespace repl { - -template <typename T> -struct OpTimePair { -public: - OpTimePair() = default; - explicit OpTimePair(T val) : value(std::move(val)) {} - OpTimePair(T val, OpTime ts) : value(std::move(val)), opTime(std::move(ts)) {} - - T value; - OpTime opTime; -}; - -} // namespace repl -} // namespace mongo diff --git a/src/mongo/db/s/set_shard_version_command.cpp b/src/mongo/db/s/set_shard_version_command.cpp index 03b96373844..f95bc3cef7a 100644 --- a/src/mongo/db/s/set_shard_version_command.cpp +++ b/src/mongo/db/s/set_shard_version_command.cpp @@ -149,11 +149,15 @@ public: } // step 2 - ChunkVersionAndOpTime verAndOpTime = - uassertStatusOK(ChunkVersionAndOpTime::parseFromBSONForSetShardVersion(cmdObj)); - const auto& version = verAndOpTime.getVersion(); + if (!ChunkVersion::canParseBSON(cmdObj, "version")) { + errmsg = "need to specify version"; + return false; + } + + const ChunkVersion version = ChunkVersion::fromBSON(cmdObj, "version"); // step 3 + const ChunkVersion oldVersion = info->getVersion(ns); const ChunkVersion globalVersion = ShardingState::get(txn)->getVersion(ns); diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index 72ddfe1549f..df9b3cdef5d 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -33,13 +33,11 @@ env.Library( target='common', source=[ 'chunk_diff.cpp', - 'chunk_version.cpp', 'set_shard_version_request.cpp', ], LIBDEPS=[ 'catalog/catalog_types', '$BUILD_DIR/mongo/client/connection_string', - '$BUILD_DIR/mongo/db/repl/optime', ] ) diff --git a/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp b/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp index 957f799ba44..73d38b1e610 100644 --- a/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp +++ b/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp @@ -607,7 +607,7 @@ Status CatalogManagerLegacy::dropCollection(OperationContext* txn, const Namespa shardEntry.getName(), fassertStatusOK(28753, ConnectionString::parse(shardEntry.getHost())), ns, - ChunkVersionAndOpTime(ChunkVersion::DROPPED()), + ChunkVersion::DROPPED(), true); auto ssvResult = shardRegistry->runCommandWithNotMasterRetries( diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp index bc8ee282ef3..dcc3e2d68e3 100644 --- a/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp +++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp @@ -212,7 +212,7 @@ Status CatalogManagerReplicaSet::shardCollection(OperationContext* txn, dbPrimaryShardId, primaryShard->getConnString(), NamespaceString(ns), - ChunkVersionAndOpTime(manager->getVersion(), manager->getConfigOpTime()), + manager->getVersion(), true); auto ssvStatus = grid.shardRegistry()->runCommandWithNotMasterRetries( @@ -518,18 +518,13 @@ Status CatalogManagerReplicaSet::dropCollection(OperationContext* txn, const Nam LOG(1) << "dropCollection " << ns << " collection marked as dropped"; - // We just called updateCollection above and this would have advanced the config op time, so use - // the latest value. On the MongoD side, we need to load the latest config metadata, which - // indicates that the collection was dropped. - const ChunkVersionAndOpTime droppedVersion(ChunkVersion::DROPPED(), _getConfigOpTime()); - for (const auto& shardEntry : allShards) { SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioningNoPersist( grid.shardRegistry()->getConfigServerConnectionString(), shardEntry.getName(), fassertStatusOK(28781, ConnectionString::parse(shardEntry.getHost())), ns, - droppedVersion, + ChunkVersion::DROPPED(), true); auto ssvResult = shardRegistry->runCommandWithNotMasterRetries( diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp index 74fabae55a9..638935ddbf5 100644 --- a/src/mongo/s/chunk_manager.cpp +++ b/src/mongo/s/chunk_manager.cpp @@ -172,10 +172,6 @@ ChunkManager::ChunkManager(const CollectionType& coll) _version = ChunkVersion::fromBSON(coll.toBSON()); } -repl::OpTime ChunkManager::getConfigOpTime() const { - return repl::OpTime(Timestamp(0, 0), 0); -} - void ChunkManager::loadExistingRanges(OperationContext* txn, const ChunkManager* oldManager) { int tries = 3; diff --git a/src/mongo/s/chunk_manager.h b/src/mongo/s/chunk_manager.h index 23440fced18..0ca94237920 100644 --- a/src/mongo/s/chunk_manager.h +++ b/src/mongo/s/chunk_manager.h @@ -44,10 +44,6 @@ class CollectionType; struct QuerySolutionNode; class OperationContext; -namespace repl { -class OpTime; -} - typedef std::shared_ptr<ChunkManager> ChunkManagerPtr; // The key for the map is max for each Chunk or ChunkRange @@ -158,11 +154,6 @@ public: return _sequenceNumber; } - /** - * Returns the latest op time from when this chunk manager's data was loaded. - */ - repl::OpTime getConfigOpTime() const; - // // After constructor is invoked, we need to call loadExistingRanges. If this is a new // sharded collection, we can call createFirstChunks first. diff --git a/src/mongo/s/chunk_manager_targeter.cpp b/src/mongo/s/chunk_manager_targeter.cpp index a3de1e2235e..f4448dafe5d 100644 --- a/src/mongo/s/chunk_manager_targeter.cpp +++ b/src/mongo/s/chunk_manager_targeter.cpp @@ -320,8 +320,7 @@ Status ChunkManagerTargeter::targetInsert(OperationContext* txn, << "; no metadata found"); } - *endpoint = - new ShardEndpoint(_primary->getId(), ChunkVersionAndOpTime(ChunkVersion::UNSHARDED())); + *endpoint = new ShardEndpoint(_primary->getId(), ChunkVersion::UNSHARDED()); return Status::OK(); } } @@ -497,10 +496,7 @@ Status ChunkManagerTargeter::targetQuery(const BSONObj& query, for (const ShardId& shardId : shardIds) { endpoints->push_back(new ShardEndpoint( - shardId, - _manager - ? ChunkVersionAndOpTime(_manager->getVersion(shardId), _manager->getConfigOpTime()) - : ChunkVersionAndOpTime(ChunkVersion::UNSHARDED()))); + shardId, _manager ? _manager->getVersion(shardId) : ChunkVersion::UNSHARDED())); } return Status::OK(); @@ -520,9 +516,7 @@ Status ChunkManagerTargeter::targetShardKey(OperationContext* txn, _stats.chunkSizeDelta[chunk->getMin()] += estDataSize; } - *endpoint = new ShardEndpoint(chunk->getShardId(), - ChunkVersionAndOpTime(_manager->getVersion(chunk->getShardId()), - _manager->getConfigOpTime())); + *endpoint = new ShardEndpoint(chunk->getShardId(), _manager->getVersion(chunk->getShardId())); return Status::OK(); } @@ -543,10 +537,7 @@ Status ChunkManagerTargeter::targetCollection(vector<ShardEndpoint*>* endpoints) for (const ShardId& shardId : shardIds) { endpoints->push_back(new ShardEndpoint( - shardId, - _manager - ? ChunkVersionAndOpTime(_manager->getVersion(shardId), _manager->getConfigOpTime()) - : ChunkVersionAndOpTime(ChunkVersion::UNSHARDED()))); + shardId, _manager ? _manager->getVersion(shardId) : ChunkVersion::UNSHARDED())); } return Status::OK(); @@ -564,10 +555,7 @@ Status ChunkManagerTargeter::targetAllShards(vector<ShardEndpoint*>* endpoints) for (const ShardId& shardId : shardIds) { endpoints->push_back(new ShardEndpoint( - shardId, - _manager - ? ChunkVersionAndOpTime(_manager->getVersion(shardId), _manager->getConfigOpTime()) - : ChunkVersionAndOpTime(ChunkVersion::UNSHARDED()))); + shardId, _manager ? _manager->getVersion(shardId) : ChunkVersion::UNSHARDED())); } return Status::OK(); diff --git a/src/mongo/s/chunk_version.cpp b/src/mongo/s/chunk_version.cpp deleted file mode 100644 index 305875d4a6e..00000000000 --- a/src/mongo/s/chunk_version.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright (C) 2015 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. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/s/chunk_version.h" - -#include "mongo/bson/bsonobj.h" -#include "mongo/bson/bsonobjbuilder.h" -#include "mongo/base/status_with.h" -#include "mongo/bson/util/bson_extract.h" -#include "mongo/util/mongoutils/str.h" - -namespace mongo { -namespace { - -const char kVersion[] = "version"; -const char kShardVersion[] = "shardVersion"; - -} // namespace - -StatusWith<ChunkVersion> ChunkVersion::parseFromBSONForCommands(const BSONObj& obj) { - BSONElement versionElem; - Status status = bsonExtractField(obj, kShardVersion, &versionElem); - if (!status.isOK()) - return status; - - if (versionElem.type() != Array) { - return {ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << versionElem.type() - << " for shardVersion element. Expected an array"}; - } - - BSONObjIterator it(versionElem.Obj()); - if (!it.more()) - return {ErrorCodes::BadValue, "Unexpected empty version"}; - - ChunkVersion version; - - // Expect the timestamp - { - BSONElement tsPart = it.next(); - if (tsPart.type() != bsonTimestamp) - return {ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << tsPart.type() - << " for version timestamp part."}; - - version._combined = tsPart.timestamp().asULL(); - } - - // Expect the epoch OID - { - BSONElement epochPart = it.next(); - if (epochPart.type() != jstOID) - return {ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << epochPart.type() - << " for version epoch part."}; - - version._epoch = epochPart.OID(); - } - - return version; -} - -StatusWith<ChunkVersion> ChunkVersion::parseFromBSONForSetShardVersion(const BSONObj& obj) { - bool canParse; - const ChunkVersion chunkVersion = ChunkVersion::fromBSON(obj, kVersion, &canParse); - if (!canParse) - return {ErrorCodes::BadValue, "Unable to parse shard version"}; - - return chunkVersion; -} - - -ChunkVersionAndOpTime::ChunkVersionAndOpTime(ChunkVersion chunkVersion) - : _verAndOpT(chunkVersion) {} - -ChunkVersionAndOpTime::ChunkVersionAndOpTime(ChunkVersion chunkVersion, repl::OpTime ts) - : _verAndOpT(chunkVersion, ts) {} - -StatusWith<ChunkVersionAndOpTime> ChunkVersionAndOpTime::parseFromBSONForCommands( - const BSONObj& obj) { - const auto chunkVersionStatus = ChunkVersion::parseFromBSONForCommands(obj); - if (!chunkVersionStatus.isOK()) - return chunkVersionStatus.getStatus(); - - const ChunkVersion& chunkVersion = chunkVersionStatus.getValue(); - - const auto opTimeStatus = repl::OpTime::parseFromBSON(obj); - if (opTimeStatus.isOK()) { - return ChunkVersionAndOpTime(chunkVersion, opTimeStatus.getValue()); - } else if (opTimeStatus == ErrorCodes::NoSuchKey) { - return ChunkVersionAndOpTime(chunkVersion); - } - - return opTimeStatus.getStatus(); -} - -StatusWith<ChunkVersionAndOpTime> ChunkVersionAndOpTime::parseFromBSONForSetShardVersion( - const BSONObj& obj) { - const auto chunkVersionStatus = ChunkVersion::parseFromBSONForSetShardVersion(obj); - if (!chunkVersionStatus.isOK()) - return chunkVersionStatus.getStatus(); - - const ChunkVersion& chunkVersion = chunkVersionStatus.getValue(); - - const auto opTimeStatus = repl::OpTime::parseFromBSON(obj); - if (opTimeStatus.isOK()) { - return ChunkVersionAndOpTime(chunkVersion, opTimeStatus.getValue()); - } else if (opTimeStatus == ErrorCodes::NoSuchKey) { - return ChunkVersionAndOpTime(chunkVersion); - } - - return opTimeStatus.getStatus(); -} - -void ChunkVersionAndOpTime::appendForSetShardVersion(BSONObjBuilder* builder) const { - _verAndOpT.value.addToBSON(*builder, kVersion); - _verAndOpT.opTime.append(builder); -} - -void ChunkVersionAndOpTime::appendForCommands(BSONObjBuilder* builder) const { - builder->appendArray(kShardVersion, _verAndOpT.value.toBSON()); - _verAndOpT.opTime.append(builder); -} - -} // namespace mongo diff --git a/src/mongo/s/chunk_version.h b/src/mongo/s/chunk_version.h index 7c4b2655412..02a05f3dd57 100644 --- a/src/mongo/s/chunk_version.h +++ b/src/mongo/s/chunk_version.h @@ -1,42 +1,37 @@ /** - * Copyright (C) 2012-2015 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. - */ +* Copyright (C) 2012 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 <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. +*/ #pragma once #include "mongo/db/jsobj.h" -#include "mongo/db/repl/optime_pair.h" namespace mongo { -class BSONObj; -template <typename T> -class StatusWith; - /** * ChunkVersions consist of a major/minor version scoped to a version epoch * @@ -51,38 +46,32 @@ class StatusWith; * expected from types. */ struct ChunkVersion { -public: + union { + struct { + int _minor; + int _major; + }; + unsigned long long _combined; + }; + OID _epoch; + ChunkVersion() : _minor(0), _major(0), _epoch(OID()) {} + // + // Constructors shouldn't have default parameters here, since it's vital we track from + // here on the epochs of versions, even if not used. + // + ChunkVersion(int major, int minor, const OID& epoch) : _minor(minor), _major(major), _epoch(epoch) {} - /** - * Interprets the specified BSON content as the format for commands, which is in the form: - * { ..., shardVersion: [ <combined major/minor>, <OID epoch> ], ... } - */ - static StatusWith<ChunkVersion> parseFromBSONForCommands(const BSONObj& obj); - - /** - * Interprets the specified BSON content as the format for the setShardVersion command, which - * is in the form: - * { ..., version: [ <combined major/minor> ], versionEpoch: [ <OID epoch> ], ... } - */ - static StatusWith<ChunkVersion> parseFromBSONForSetShardVersion(const BSONObj& obj); - - /** - * Indicates a dropped collection. All components are zeroes (OID is zero time, zero - * machineId/inc). - */ static ChunkVersion DROPPED() { - return ChunkVersion(0, 0, OID()); + return ChunkVersion(0, 0, OID()); // dropped OID is zero time, zero machineId/inc } - /** - * Indicates that the collection is not sharded. Same as DROPPED. - */ static ChunkVersion UNSHARDED() { - return ChunkVersion(0, 0, OID()); + // TODO: Distinguish between these cases + return DROPPED(); } static ChunkVersion IGNORED() { @@ -380,23 +369,35 @@ public: return b.arr(); } + bool parseBSON(const BSONObj& source, std::string* errMsg) { + // ChunkVersion wants to be an array. + BSONArray arrSource = static_cast<BSONArray>(source); + + bool canParse; + ChunkVersion version = fromBSON(arrSource, &canParse); + if (!canParse) { + *errMsg = "Could not parse version structure"; + return false; + } + + _minor = version._minor; + _major = version._major; + _epoch = version._epoch; + return true; + } + void clear() { _minor = 0; _major = 0; _epoch = OID(); } -private: - union { - struct { - int _minor; - int _major; - }; - - uint64_t _combined; - }; - - OID _epoch; + void cloneTo(ChunkVersion* other) const { + other->clear(); + other->_minor = _minor; + other->_major = _major; + other->_epoch = _epoch; + } }; inline std::ostream& operator<<(std::ostream& s, const ChunkVersion& v) { @@ -404,51 +405,4 @@ inline std::ostream& operator<<(std::ostream& s, const ChunkVersion& v) { return s; } - -/** - * Represents a chunk version along with the optime from when it was retrieved. Provides logic to - * serialize and deserialize the combo to BSON. - */ -class ChunkVersionAndOpTime { -public: - ChunkVersionAndOpTime(ChunkVersion chunkVersion); - ChunkVersionAndOpTime(ChunkVersion chunkVersion, repl::OpTime ts); - - const ChunkVersion& getVersion() const { - return _verAndOpT.value; - } - - const repl::OpTime& getOpTime() const { - return _verAndOpT.opTime; - } - - /** - * Interprets the contents of the BSON documents as having been constructed in the format for - * write commands. The optime component is optional for backwards compatibility and if not - * present, the optime will be default initialized. - */ - static StatusWith<ChunkVersionAndOpTime> parseFromBSONForCommands(const BSONObj& obj); - - /** - * Interprets the contents of the BSON document as having been constructed in the format for the - * setShardVersion command. The optime component is optional for backwards compatibility and if - * not present, the optime will be default initialized. - */ - static StatusWith<ChunkVersionAndOpTime> parseFromBSONForSetShardVersion(const BSONObj& obj); - - /** - * Appends the contents to the specified builder in the format expected by the setShardVersion - * command. - */ - void appendForSetShardVersion(BSONObjBuilder* builder) const; - - /** - * Appends the contents to the specified builder in the format expected by the write commands. - */ - void appendForCommands(BSONObjBuilder* builder) const; - -private: - repl::OpTimePair<ChunkVersion> _verAndOpT; -}; - } // namespace mongo diff --git a/src/mongo/s/mock_ns_targeter.h b/src/mongo/s/mock_ns_targeter.h index 79c6d517445..44bc5be18c2 100644 --- a/src/mongo/s/mock_ns_targeter.h +++ b/src/mongo/s/mock_ns_targeter.h @@ -211,11 +211,8 @@ private: inline void assertEndpointsEqual(const ShardEndpoint& endpointA, const ShardEndpoint& endpointB) { ASSERT_EQUALS(endpointA.shardName, endpointB.shardName); - ASSERT_EQUALS(endpointA.shardVersion.getVersion().toLong(), - endpointB.shardVersion.getVersion().toLong()); - ASSERT_EQUALS(endpointA.shardVersion.getVersion().epoch(), - endpointB.shardVersion.getVersion().epoch()); - ASSERT_EQUALS(endpointA.shardVersion.getOpTime(), endpointB.shardVersion.getOpTime()); + ASSERT_EQUALS(endpointA.shardVersion.toLong(), endpointB.shardVersion.toLong()); + ASSERT_EQUALS(endpointA.shardVersion.epoch(), endpointB.shardVersion.epoch()); } } // namespace mongo diff --git a/src/mongo/s/ns_targeter.h b/src/mongo/s/ns_targeter.h index 1e6182b67b7..087725697d2 100644 --- a/src/mongo/s/ns_targeter.h +++ b/src/mongo/s/ns_targeter.h @@ -157,11 +157,26 @@ struct ShardEndpoint { ShardEndpoint(const ShardEndpoint& other) : shardName(other.shardName), shardVersion(other.shardVersion) {} - ShardEndpoint(const std::string& shardName, const ChunkVersionAndOpTime& shardVersion) + ShardEndpoint(const std::string& shardName, const ChunkVersion& shardVersion) : shardName(shardName), shardVersion(shardVersion) {} const std::string shardName; - const ChunkVersionAndOpTime shardVersion; + const ChunkVersion shardVersion; + + // + // For testing *only* - do not use as part of API + // + + BSONObj toBSON() const { + BSONObjBuilder b; + appendBSON(&b); + return b.obj(); + } + + void appendBSON(BSONObjBuilder* builder) const { + builder->append("shardName", shardName); + shardVersion.addToBSON(*builder, "shardVersion"); + } }; } // namespace mongo diff --git a/src/mongo/s/set_shard_version_request.cpp b/src/mongo/s/set_shard_version_request.cpp index 15389a66d43..eb843a963dd 100644 --- a/src/mongo/s/set_shard_version_request.cpp +++ b/src/mongo/s/set_shard_version_request.cpp @@ -46,6 +46,7 @@ const char kShardName[] = "shard"; const char kShardConnectionString[] = "shardHost"; const char kInit[] = "init"; const char kAuthoritative[] = "authoritative"; +const char kVersion[] = "version"; const char kNoConnectionVersioning[] = "noConnectionVersioning"; } // namespace @@ -63,7 +64,7 @@ SetShardVersionRequest::SetShardVersionRequest(ConnectionString configServer, std::string shardName, ConnectionString shardConnectionString, NamespaceString nss, - ChunkVersionAndOpTime version, + ChunkVersion version, bool isAuthoritative) : _init(false), _isAuthoritative(isAuthoritative), @@ -87,7 +88,7 @@ SetShardVersionRequest SetShardVersionRequest::makeForVersioning( const std::string& shardName, const ConnectionString& shardConnectionString, const NamespaceString& nss, - const ChunkVersionAndOpTime& nssVersion, + const ChunkVersion& nssVersion, bool isAuthoritative) { return SetShardVersionRequest( configServer, shardName, shardConnectionString, nss, nssVersion, isAuthoritative); @@ -98,7 +99,7 @@ SetShardVersionRequest SetShardVersionRequest::makeForVersioningNoPersist( const std::string& shardName, const ConnectionString& shard, const NamespaceString& nss, - const ChunkVersionAndOpTime& nssVersion, + const ChunkVersion& nssVersion, bool isAuthoritative) { auto ssv = makeForVersioning(configServer, shardName, shard, nss, nssVersion, isAuthoritative); ssv._noConnectionVersioning = true; @@ -184,11 +185,14 @@ StatusWith<SetShardVersionRequest> SetShardVersionRequest::parseFromBSON(const B } { - auto versionStatus = ChunkVersionAndOpTime::parseFromBSONForSetShardVersion(cmdObj); - if (!versionStatus.isOK()) - return versionStatus.getStatus(); + bool canParse; - request._version = versionStatus.getValue(); + ChunkVersion chunkVersion = ChunkVersion::fromBSON(cmdObj, kVersion, &canParse); + if (!canParse) { + return {ErrorCodes::BadValue, "Unable to parse shard version"}; + } + + request._version = std::move(chunkVersion); } return request; @@ -205,7 +209,7 @@ BSONObj SetShardVersionRequest::toBSON() const { cmdBuilder.append(kShardConnectionString, _shardCS.toString()); if (!_init) { - _version.get().appendForSetShardVersion(&cmdBuilder); + _version.get().addToBSON(cmdBuilder, kVersion); } if (_noConnectionVersioning) { @@ -222,7 +226,7 @@ const NamespaceString& SetShardVersionRequest::getNS() const { const ChunkVersion SetShardVersionRequest::getNSVersion() const { invariant(!_init); - return _version.get().getVersion(); + return _version.get(); } } // namespace mongo diff --git a/src/mongo/s/set_shard_version_request.h b/src/mongo/s/set_shard_version_request.h index 3f06b4546c8..02fcb3099dc 100644 --- a/src/mongo/s/set_shard_version_request.h +++ b/src/mongo/s/set_shard_version_request.h @@ -38,6 +38,7 @@ namespace mongo { class BSONObj; +struct ChunkVersion; template <typename T> class StatusWith; @@ -66,7 +67,7 @@ public: const std::string& shardName, const ConnectionString& shard, const NamespaceString& nss, - const ChunkVersionAndOpTime& nssVersion, + const ChunkVersion& nssVersion, bool isAuthoritative); /** @@ -76,13 +77,12 @@ public: * connection WILL NOT be marked as "versioned". DO NOT USE unless the command will be sent * through the TaskExecutor. */ - static SetShardVersionRequest makeForVersioningNoPersist( - const ConnectionString& configServer, - const std::string& shardName, - const ConnectionString& shard, - const NamespaceString& nss, - const ChunkVersionAndOpTime& nssVersion, - bool isAuthoritative); + static SetShardVersionRequest makeForVersioningNoPersist(const ConnectionString& configServer, + const std::string& shardName, + const ConnectionString& shard, + const NamespaceString& nss, + const ChunkVersion& nssVersion, + bool isAuthoritative); /** * Parses an SSV request from a set shard version command. @@ -153,7 +153,7 @@ private: std::string shardName, ConnectionString shardConnectionString, NamespaceString nss, - ChunkVersionAndOpTime version, + ChunkVersion nssVersion, bool isAuthoritative); SetShardVersionRequest(); @@ -169,7 +169,7 @@ private: // These values are only set if _init is false boost::optional<NamespaceString> _nss; - boost::optional<ChunkVersionAndOpTime> _version; + boost::optional<ChunkVersion> _version; }; } // namespace mongo diff --git a/src/mongo/s/set_shard_version_request_test.cpp b/src/mongo/s/set_shard_version_request_test.cpp index ab370835f7a..6328a9763c2 100644 --- a/src/mongo/s/set_shard_version_request_test.cpp +++ b/src/mongo/s/set_shard_version_request_test.cpp @@ -215,8 +215,7 @@ TEST(SetShardVersionRequest, ToSSVCommandInit) { } TEST(SetShardVersionRequest, ToSSVCommandFull) { - const ChunkVersionAndOpTime chunkVersion(ChunkVersion(1, 2, OID::gen()), - repl::OpTime(Timestamp(10), 20LL)); + const ChunkVersion chunkVersion(1, 2, OID::gen()); SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioning( configCS, "TestShard", shardCS, NamespaceString("db.coll"), chunkVersion, false); @@ -229,7 +228,7 @@ TEST(SetShardVersionRequest, ToSSVCommandFull) { ASSERT_EQ(ssv.getShardConnectionString().toString(), shardCS.toString()); ASSERT_EQ(ssv.getNS().ns(), "db.coll"); ASSERT_EQ(ssv.getNSVersion().toBSONWithPrefix("version"), - chunkVersion.getVersion().toBSONWithPrefix("version")); + chunkVersion.toBSONWithPrefix("version")); ASSERT_EQ(ssv.toBSON(), BSON("setShardVersion" @@ -238,13 +237,11 @@ TEST(SetShardVersionRequest, ToSSVCommandFull) { << configCS.toString() << "shard" << "TestShard" << "shardHost" << shardCS.toString() << "version" - << Timestamp(chunkVersion.getVersion().toLong()) << "versionEpoch" - << chunkVersion.getVersion().epoch() << "ts" << Timestamp(10) << "t" << 20LL)); + << Timestamp(chunkVersion.toLong()) << "versionEpoch" << chunkVersion.epoch())); } TEST(SetShardVersionRequest, ToSSVCommandFullAuthoritative) { - const ChunkVersionAndOpTime chunkVersion(ChunkVersion(1, 2, OID::gen()), - repl::OpTime(Timestamp(10), 20LL)); + const ChunkVersion chunkVersion(1, 2, OID::gen()); SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioning( configCS, "TestShard", shardCS, NamespaceString("db.coll"), chunkVersion, true); @@ -257,7 +254,7 @@ TEST(SetShardVersionRequest, ToSSVCommandFullAuthoritative) { ASSERT_EQ(ssv.getShardConnectionString().toString(), shardCS.toString()); ASSERT_EQ(ssv.getNS().ns(), "db.coll"); ASSERT_EQ(ssv.getNSVersion().toBSONWithPrefix("version"), - chunkVersion.getVersion().toBSONWithPrefix("version")); + chunkVersion.toBSONWithPrefix("version")); ASSERT_EQ(ssv.toBSON(), BSON("setShardVersion" @@ -266,13 +263,11 @@ TEST(SetShardVersionRequest, ToSSVCommandFullAuthoritative) { << configCS.toString() << "shard" << "TestShard" << "shardHost" << shardCS.toString() << "version" - << Timestamp(chunkVersion.getVersion().toLong()) << "versionEpoch" - << chunkVersion.getVersion().epoch() << "ts" << Timestamp(10) << "t" << 20LL)); + << Timestamp(chunkVersion.toLong()) << "versionEpoch" << chunkVersion.epoch())); } TEST(SetShardVersionRequest, ToSSVCommandFullNoConnectionVersioning) { - const ChunkVersionAndOpTime chunkVersion(ChunkVersion(1, 2, OID::gen()), - repl::OpTime(Timestamp(10), 20LL)); + const ChunkVersion chunkVersion(1, 2, OID::gen()); SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioningNoPersist( configCS, "TestShard", shardCS, NamespaceString("db.coll"), chunkVersion, true); @@ -285,7 +280,7 @@ TEST(SetShardVersionRequest, ToSSVCommandFullNoConnectionVersioning) { ASSERT_EQ(ssv.getShardConnectionString().toString(), shardCS.toString()); ASSERT_EQ(ssv.getNS().ns(), "db.coll"); ASSERT_EQ(ssv.getNSVersion().toBSONWithPrefix("version"), - chunkVersion.getVersion().toBSONWithPrefix("version")); + chunkVersion.toBSONWithPrefix("version")); ASSERT_EQ(ssv.toBSON(), BSON("setShardVersion" @@ -294,8 +289,7 @@ TEST(SetShardVersionRequest, ToSSVCommandFullNoConnectionVersioning) { << configCS.toString() << "shard" << "TestShard" << "shardHost" << shardCS.toString() << "version" - << Timestamp(chunkVersion.getVersion().toLong()) << "versionEpoch" - << chunkVersion.getVersion().epoch() << "ts" << Timestamp(10) << "t" << 20LL + << Timestamp(chunkVersion.toLong()) << "versionEpoch" << chunkVersion.epoch() << "noConnectionVersioning" << true)); } diff --git a/src/mongo/s/version_manager.cpp b/src/mongo/s/version_manager.cpp index 4d4f87a3159..a77243627d5 100644 --- a/src/mongo/s/version_manager.cpp +++ b/src/mongo/s/version_manager.cpp @@ -1,30 +1,32 @@ +// @file version_manager.cpp + /** - * Copyright (C) 2010-2015 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. - */ +* Copyright (C) 2010 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 <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::kSharding @@ -43,7 +45,6 @@ #include "mongo/s/config.h" #include "mongo/s/grid.h" #include "mongo/s/mongos_options.h" -#include "mongo/s/set_shard_version_request.h" #include "mongo/s/stale_exception.h" #include "mongo/util/log.h" @@ -110,36 +111,35 @@ private: */ bool setShardVersion(DBClientBase& conn, const string& ns, - const ConnectionString& configServer, + const string& configServerPrimary, ChunkVersion version, ChunkManager* manager, bool authoritative, BSONObj& result) { + BSONObjBuilder cmdBuilder; + cmdBuilder.append("setShardVersion", ns); + cmdBuilder.append("configdb", configServerPrimary); + ShardId shardId; - ConnectionString shardCS; { const auto shard = grid.shardRegistry()->getShard(conn.getServerAddress()); shardId = shard->getId(); - shardCS = shard->getConnString(); + cmdBuilder.append("shard", shardId); + cmdBuilder.append("shardHost", shard->getConnString().toString()); } - BSONObj cmd; - - if (ns.empty()) { - SetShardVersionRequest ssv = - SetShardVersionRequest::makeForInit(configServer, shardId, shardCS); - cmd = ssv.toBSON(); + if (ns.size() > 0) { + version.addToBSON(cmdBuilder); } else { - const ChunkVersionAndOpTime verAndOpT = manager - ? ChunkVersionAndOpTime(version, manager->getConfigOpTime()) - : ChunkVersionAndOpTime(version); - - SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioning( - configServer, shardId, shardCS, NamespaceString(ns), verAndOpT, authoritative); + cmdBuilder.append("init", true); + } - cmd = ssv.toBSON(); + if (authoritative) { + cmdBuilder.appendBool("authoritative", 1); } + BSONObj cmd = cmdBuilder.obj(); + LOG(1) << " setShardVersion " << shardId << " " << conn.getServerAddress() << " " << ns << " " << cmd << (manager ? string(str::stream() << " " << manager->getSequenceNumber()) : ""); @@ -214,7 +214,7 @@ bool initShardVersionEmptyNS(OperationContext* txn, DBClientBase* conn_in) { ok = setShardVersion(*conn, "", - grid.shardRegistry()->getConfigServerConnectionString(), + grid.shardRegistry()->getConfigServerConnectionString().toString(), ChunkVersion(), NULL, true, @@ -373,7 +373,7 @@ bool checkShardVersion(OperationContext* txn, BSONObj result; if (setShardVersion(*conn, ns, - grid.shardRegistry()->getConfigServerConnectionString(), + grid.shardRegistry()->getConfigServerConnectionString().toString(), version, manager.get(), authoritative, diff --git a/src/mongo/s/write_ops/batch_write_op.cpp b/src/mongo/s/write_ops/batch_write_op.cpp index ba7ddae8d95..113dd9133f8 100644 --- a/src/mongo/s/write_ops/batch_write_op.cpp +++ b/src/mongo/s/write_ops/batch_write_op.cpp @@ -87,13 +87,11 @@ static int compareEndpoints(const ShardEndpoint* endpointA, const ShardEndpoint* if (shardNameDiff != 0) return shardNameDiff; - long shardVersionDiff = endpointA->shardVersion.getVersion().toLong() - - endpointB->shardVersion.getVersion().toLong(); + long shardVersionDiff = endpointA->shardVersion.toLong() - endpointB->shardVersion.toLong(); if (shardVersionDiff != 0) return shardVersionDiff; - int shardEpochDiff = endpointA->shardVersion.getVersion().epoch().compare( - endpointB->shardVersion.getVersion().epoch()); + int shardEpochDiff = endpointA->shardVersion.epoch().compare(endpointB->shardVersion.epoch()); return shardEpochDiff; } @@ -458,8 +456,7 @@ void BatchWriteOp::buildBatchRequest(const TargetedWriteBatch& targetedBatch, unique_ptr<BatchedRequestMetadata> requestMetadata(new BatchedRequestMetadata()); requestMetadata->setShardName(targetedBatch.getEndpoint().shardName); - requestMetadata->setShardVersion( - ChunkVersionAndOpTime(targetedBatch.getEndpoint().shardVersion)); + requestMetadata->setShardVersion(targetedBatch.getEndpoint().shardVersion); requestMetadata->setSession(0); request->setMetadata(requestMetadata.release()); } diff --git a/src/mongo/s/write_ops/batched_delete_request_test.cpp b/src/mongo/s/write_ops/batched_delete_request_test.cpp index c8f71652599..87d883f1b0b 100644 --- a/src/mongo/s/write_ops/batched_delete_request_test.cpp +++ b/src/mongo/s/write_ops/batched_delete_request_test.cpp @@ -46,24 +46,32 @@ TEST(BatchedDeleteRequest, Basic) { BSON(BatchedDeleteDocument::query(BSON("a" << 1)) << BatchedDeleteDocument::limit(1)) << BSON(BatchedDeleteDocument::query(BSON("b" << 1)) << BatchedDeleteDocument::limit(1))); - BSONObj origDeleteRequestObj = BSON( - BatchedDeleteRequest::collName("test") - << BatchedDeleteRequest::deletes() << deleteArray - << BatchedDeleteRequest::writeConcern(BSON("w" << 1)) << BatchedDeleteRequest::ordered(true) - << BatchedDeleteRequest::metadata() << BSON("shardName" - << "shard000" - << "shardVersion" - << BSON_ARRAY(Timestamp(1, 2) << OID::gen()) - << "ts" << Timestamp(3, 4) << "t" << 5 - << "session" << 0LL)); + BSONObj writeConcernObj = BSON("w" << 1); + + // The BSON_ARRAY macro doesn't support Timestamps. + BSONArrayBuilder arrBuilder; + arrBuilder.append(Timestamp(1, 1)); + arrBuilder.append(OID::gen()); + BSONArray shardVersionArray = arrBuilder.arr(); + + BSONObj origDeleteRequestObj = + BSON(BatchedDeleteRequest::collName("test") + << BatchedDeleteRequest::deletes() << deleteArray + << BatchedDeleteRequest::writeConcern(writeConcernObj) + << BatchedDeleteRequest::ordered(true) << BatchedDeleteRequest::metadata() + << BSON(BatchedRequestMetadata::shardName("shard000") + << BatchedRequestMetadata::shardVersion() << shardVersionArray + << BatchedRequestMetadata::session(0))); string errMsg; BatchedDeleteRequest request; - ASSERT_TRUE(request.parseBSON("foo", origDeleteRequestObj, &errMsg)); + bool ok = request.parseBSON("foo", origDeleteRequestObj, &errMsg); + ASSERT_TRUE(ok); ASSERT_EQ("foo.test", request.getNS().ns()); - ASSERT_EQUALS(origDeleteRequestObj, request.toBSON()); + BSONObj genDeleteRequestObj = request.toBSON(); + ASSERT_EQUALS(0, genDeleteRequestObj.woCompare(origDeleteRequestObj)); } } // namespace diff --git a/src/mongo/s/write_ops/batched_insert_request_test.cpp b/src/mongo/s/write_ops/batched_insert_request_test.cpp index 09e8e950c08..e31503d431f 100644 --- a/src/mongo/s/write_ops/batched_insert_request_test.cpp +++ b/src/mongo/s/write_ops/batched_insert_request_test.cpp @@ -45,24 +45,32 @@ namespace { TEST(BatchedInsertRequest, Basic) { BSONArray insertArray = BSON_ARRAY(BSON("a" << 1) << BSON("b" << 1)); - BSONObj origInsertRequestObj = BSON( - BatchedInsertRequest::collName("test") - << BatchedInsertRequest::documents() << insertArray - << BatchedInsertRequest::writeConcern(BSON("w" << 1)) << BatchedInsertRequest::ordered(true) - << BatchedInsertRequest::metadata() << BSON("shardName" - << "shard000" - << "shardVersion" - << BSON_ARRAY(Timestamp(1, 2) << OID::gen()) - << "ts" << Timestamp(3, 4) << "t" << 5 - << "session" << 0LL)); + BSONObj writeConcernObj = BSON("w" << 1); + + // The BSON_ARRAY macro doesn't support Timestamps. + BSONArrayBuilder arrBuilder; + arrBuilder.append(Timestamp(1, 1)); + arrBuilder.append(OID::gen()); + BSONArray shardVersionArray = arrBuilder.arr(); + + BSONObj origInsertRequestObj = + BSON(BatchedInsertRequest::collName("test") + << BatchedInsertRequest::documents() << insertArray + << BatchedInsertRequest::writeConcern(writeConcernObj) + << BatchedInsertRequest::ordered(true) << BatchedInsertRequest::metadata() + << BSON(BatchedRequestMetadata::shardName("shard0000") + << BatchedRequestMetadata::shardVersion() << shardVersionArray + << BatchedRequestMetadata::session(0))); string errMsg; BatchedInsertRequest request; - ASSERT_TRUE(request.parseBSON("foo", origInsertRequestObj, &errMsg)); + bool ok = request.parseBSON("foo", origInsertRequestObj, &errMsg); + ASSERT_TRUE(ok); ASSERT_EQ("foo.test", request.getNS().ns()); - ASSERT_EQUALS(origInsertRequestObj, request.toBSON()); + BSONObj genInsertRequestObj = request.toBSON(); + ASSERT_EQUALS(0, genInsertRequestObj.woCompare(origInsertRequestObj)); } TEST(BatchedInsertRequest, GenIDAll) { diff --git a/src/mongo/s/write_ops/batched_request_metadata.cpp b/src/mongo/s/write_ops/batched_request_metadata.cpp index 78ecefbb9df..a2e21f99e4c 100644 --- a/src/mongo/s/write_ops/batched_request_metadata.cpp +++ b/src/mongo/s/write_ops/batched_request_metadata.cpp @@ -26,8 +26,6 @@ * it in the license file. */ -#include "mongo/platform/basic.h" - #include "mongo/s/write_ops/batched_request_metadata.h" #include "mongo/db/field_parser.h" @@ -57,8 +55,9 @@ BSONObj BatchedRequestMetadata::toBSON() const { if (_isShardNameSet) metadataBuilder << shardName(_shardName); - if (_shardVersion) { - _shardVersion.get().appendForCommands(&metadataBuilder); + if (_shardVersion.get()) { + // ChunkVersion wants to be an array. + metadataBuilder.append(shardVersion(), static_cast<BSONArray>(_shardVersion->toBSON())); } if (_isSessionSet) @@ -81,12 +80,12 @@ bool BatchedRequestMetadata::parseBSON(const BSONObj& source, string* errMsg) { _isShardNameSet = fieldState == FieldParser::FIELD_SET; { - auto verAndOpTStatus = ChunkVersionAndOpTime::parseFromBSONForCommands(source); - if (!verAndOpTStatus.isOK()) { + std::unique_ptr<ChunkVersion> tempChunkVersion(new ChunkVersion); + fieldState = FieldParser::extract(source, shardVersion, tempChunkVersion.get(), errMsg); + if (fieldState == FieldParser::FIELD_INVALID) return false; - } - - _shardVersion = verAndOpTStatus.getValue(); + if (fieldState == FieldParser::FIELD_SET) + _shardVersion.swap(tempChunkVersion); } fieldState = FieldParser::extract(source, session, &_session, errMsg); @@ -114,7 +113,10 @@ string BatchedRequestMetadata::toString() const { void BatchedRequestMetadata::cloneTo(BatchedRequestMetadata* other) const { other->_shardName = _shardName; other->_isShardNameSet = _isShardNameSet; - other->_shardVersion = _shardVersion; + + if (other->_shardVersion.get()) + _shardVersion->cloneTo(other->_shardVersion.get()); + other->_session = _session; other->_isSessionSet = _isSessionSet; } @@ -124,21 +126,36 @@ void BatchedRequestMetadata::setShardName(StringData shardName) { _isShardNameSet = true; } +void BatchedRequestMetadata::unsetShardName() { + _isShardNameSet = false; +} + +bool BatchedRequestMetadata::isShardNameSet() const { + return _isShardNameSet; +} + const string& BatchedRequestMetadata::getShardName() const { dassert(_isShardNameSet); return _shardName; } -void BatchedRequestMetadata::setShardVersion(const ChunkVersionAndOpTime& shardVersion) { - _shardVersion = shardVersion; +void BatchedRequestMetadata::setShardVersion(const ChunkVersion& shardVersion) { + unique_ptr<ChunkVersion> temp(new ChunkVersion); + shardVersion.cloneTo(temp.get()); + _shardVersion.reset(temp.release()); +} + +void BatchedRequestMetadata::unsetShardVersion() { + _shardVersion.reset(); } bool BatchedRequestMetadata::isShardVersionSet() const { - return _shardVersion.is_initialized(); + return _shardVersion.get() != NULL; } const ChunkVersion& BatchedRequestMetadata::getShardVersion() const { - return _shardVersion.get().getVersion(); + dassert(_shardVersion.get()); + return *_shardVersion; } void BatchedRequestMetadata::setSession(long long session) { diff --git a/src/mongo/s/write_ops/batched_request_metadata.h b/src/mongo/s/write_ops/batched_request_metadata.h index 2b885e9018d..6e31cb60713 100644 --- a/src/mongo/s/write_ops/batched_request_metadata.h +++ b/src/mongo/s/write_ops/batched_request_metadata.h @@ -28,33 +28,34 @@ #pragma once -#include <boost/optional.hpp> #include <string> +#include "mongo/base/disallow_copying.h" #include "mongo/db/jsobj.h" #include "mongo/s/bson_serializable.h" #include "mongo/s/chunk_version.h" namespace mongo { +class BatchedRequestMetadata : public BSONSerializable { + MONGO_DISALLOW_COPYING(BatchedRequestMetadata); -class BatchedRequestMetadata { public: static const BSONField<std::string> shardName; static const BSONField<ChunkVersion> shardVersion; static const BSONField<long long> session; BatchedRequestMetadata(); - ~BatchedRequestMetadata(); + virtual ~BatchedRequestMetadata(); // // bson serializable interface implementation // - bool isValid(std::string* errMsg) const; - BSONObj toBSON() const; - bool parseBSON(const BSONObj& source, std::string* errMsg); - void clear(); - std::string toString() const; + virtual bool isValid(std::string* errMsg) const; + virtual BSONObj toBSON() const; + virtual bool parseBSON(const BSONObj& source, std::string* errMsg); + virtual void clear(); + virtual std::string toString() const; void cloneTo(BatchedRequestMetadata* other) const; @@ -63,12 +64,14 @@ public: // void setShardName(StringData shardName); + void unsetShardName(); + bool isShardNameSet() const; const std::string& getShardName() const; - void setShardVersion(const ChunkVersionAndOpTime& shardVersion); + void setShardVersion(const ChunkVersion& shardVersion); + void unsetShardVersion(); bool isShardVersionSet() const; const ChunkVersion& getShardVersion() const; - const repl::OpTime& getOpTime() const; void setSession(long long session); void unsetSession(); @@ -81,11 +84,10 @@ private: bool _isShardNameSet; // (O) version for this collection on a given shard - boost::optional<ChunkVersionAndOpTime> _shardVersion; + std::unique_ptr<ChunkVersion> _shardVersion; // (O) session number the inserts belong to long long _session; bool _isSessionSet; }; - -} // namespace mongo +} diff --git a/src/mongo/s/write_ops/batched_request_metadata_test.cpp b/src/mongo/s/write_ops/batched_request_metadata_test.cpp index 978ee865045..f35bcee4ef9 100644 --- a/src/mongo/s/write_ops/batched_request_metadata_test.cpp +++ b/src/mongo/s/write_ops/batched_request_metadata_test.cpp @@ -40,16 +40,22 @@ using std::string; namespace { TEST(BatchedRequestMetadata, Basic) { - BSONObj metadataObj(BSON("shardName" - << "shard0000" - << "shardVersion" << BSON_ARRAY(Timestamp(1, 2) << OID::gen()) << "ts" - << Timestamp(3, 4) << "t" << 5 << "session" << 0LL)); + // The BSON_ARRAY macro doesn't support Timestamps. + BSONArrayBuilder arrBuilder; + arrBuilder.append(Timestamp(1, 1)); + arrBuilder.append(OID::gen()); + BSONArray shardVersionArray = arrBuilder.arr(); + + BSONObj metadataObj(BSON(BatchedRequestMetadata::shardName("shard0000") + << BatchedRequestMetadata::shardVersion() << shardVersionArray + << BatchedRequestMetadata::session(100))); string errMsg; BatchedRequestMetadata metadata; ASSERT_TRUE(metadata.parseBSON(metadataObj, &errMsg)); - ASSERT_EQUALS(metadataObj, metadata.toBSON()); + BSONObj genMetadataObj = metadata.toBSON(); + ASSERT_EQUALS(metadataObj, genMetadataObj); } } // namespace diff --git a/src/mongo/s/write_ops/batched_update_request_test.cpp b/src/mongo/s/write_ops/batched_update_request_test.cpp index af7bb5aadfb..04994733537 100644 --- a/src/mongo/s/write_ops/batched_update_request_test.cpp +++ b/src/mongo/s/write_ops/batched_update_request_test.cpp @@ -50,24 +50,32 @@ TEST(BatchedUpdateRequest, Basic) { << BatchedUpdateDocument::updateExpr(BSON("$set" << BSON("b" << 2))) << BatchedUpdateDocument::multi(false) << BatchedUpdateDocument::upsert(false))); - BSONObj origUpdateRequestObj = BSON( - BatchedUpdateRequest::collName("test") - << BatchedUpdateRequest::updates() << updateArray - << BatchedUpdateRequest::writeConcern(BSON("w" << 1)) << BatchedUpdateRequest::ordered(true) - << BatchedUpdateRequest::metadata() << BSON("shardName" - << "shard000" - << "shardVersion" - << BSON_ARRAY(Timestamp(1, 2) << OID::gen()) - << "ts" << Timestamp(3, 4) << "t" << 5 - << "session" << 0LL)); + BSONObj writeConcernObj = BSON("w" << 1); + + // The BSON_ARRAY macro doesn't support Timestamps. + BSONArrayBuilder arrBuilder; + arrBuilder.append(Timestamp(1, 1)); + arrBuilder.append(OID::gen()); + BSONArray shardVersionArray = arrBuilder.arr(); + + BSONObj origUpdateRequestObj = + BSON(BatchedUpdateRequest::collName("test") + << BatchedUpdateRequest::updates() << updateArray + << BatchedUpdateRequest::writeConcern(writeConcernObj) + << BatchedUpdateRequest::ordered(true) << BatchedUpdateRequest::metadata() + << BSON(BatchedRequestMetadata::shardName("shard0000") + << BatchedRequestMetadata::shardVersion() << shardVersionArray + << BatchedRequestMetadata::session(0))); string errMsg; BatchedUpdateRequest request; - ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg)); + bool ok = request.parseBSON("foo", origUpdateRequestObj, &errMsg); + ASSERT_TRUE(ok); ASSERT_EQ("foo.test", request.getNS().ns()); - ASSERT_EQUALS(origUpdateRequestObj, request.toBSON()); + BSONObj genUpdateRequestObj = request.toBSON(); + ASSERT_EQUALS(0, genUpdateRequestObj.woCompare(origUpdateRequestObj)); } } // namespace diff --git a/src/mongo/s/write_ops/write_op.cpp b/src/mongo/s/write_ops/write_op.cpp index 8cd20fa4865..25f9f13b3aa 100644 --- a/src/mongo/s/write_ops/write_op.cpp +++ b/src/mongo/s/write_ops/write_op.cpp @@ -127,8 +127,7 @@ Status WriteOp::targetWrites(OperationContext* txn, if (endpoints.size() == 1u) { targetedWrites->push_back(new TargetedWrite(*endpoint, ref)); } else { - ShardEndpoint broadcastEndpoint(endpoint->shardName, - ChunkVersionAndOpTime(ChunkVersion::IGNORED())); + ShardEndpoint broadcastEndpoint(endpoint->shardName, ChunkVersion::IGNORED()); targetedWrites->push_back(new TargetedWrite(broadcastEndpoint, ref)); } diff --git a/src/mongo/s/write_ops/write_op_test.cpp b/src/mongo/s/write_ops/write_op_test.cpp index 233aa824337..e488c068e47 100644 --- a/src/mongo/s/write_ops/write_op_test.cpp +++ b/src/mongo/s/write_ops/write_op_test.cpp @@ -218,11 +218,11 @@ TEST(WriteOpTests, TargetMultiAllShards) { ASSERT_EQUALS(targeted.size(), 3u); sortByEndpoint(&targeted); ASSERT_EQUALS(targeted[0]->endpoint.shardName, endpointA.shardName); - ASSERT(ChunkVersion::isIgnoredVersion(targeted[0]->endpoint.shardVersion.getVersion())); + ASSERT(ChunkVersion::isIgnoredVersion(targeted[0]->endpoint.shardVersion)); ASSERT_EQUALS(targeted[1]->endpoint.shardName, endpointB.shardName); - ASSERT(ChunkVersion::isIgnoredVersion(targeted[1]->endpoint.shardVersion.getVersion())); + ASSERT(ChunkVersion::isIgnoredVersion(targeted[1]->endpoint.shardVersion)); ASSERT_EQUALS(targeted[2]->endpoint.shardName, endpointC.shardName); - ASSERT(ChunkVersion::isIgnoredVersion(targeted[2]->endpoint.shardVersion.getVersion())); + ASSERT(ChunkVersion::isIgnoredVersion(targeted[2]->endpoint.shardVersion)); writeOp.noteWriteComplete(*targeted[0]); writeOp.noteWriteComplete(*targeted[1]); |