summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2018-02-03 10:31:45 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2018-02-06 07:33:21 -0500
commit1f376bcf8824df1a6122c297d5205daa1e6ff8a7 (patch)
tree2d8a6c5d21a042e47ed702e5426851a54e314331
parent0851ee0434ba5352561a204f368a062d660c8882 (diff)
downloadmongo-1f376bcf8824df1a6122c297d5205daa1e6ff8a7.tar.gz
SERVER-32367 Make AutoGetCollection throw if UUID cannot be resolved
-rw-r--r--src/mongo/db/catalog/catalog_raii.cpp57
-rw-r--r--src/mongo/db/catalog/catalog_raii.h13
-rw-r--r--src/mongo/db/catalog/database_test.cpp2
-rw-r--r--src/mongo/db/commands.h5
-rw-r--r--src/mongo/db/commands/count_cmd.cpp36
-rw-r--r--src/mongo/db/commands/distinct.cpp72
-rw-r--r--src/mongo/db/commands/find_cmd.cpp5
-rw-r--r--src/mongo/db/commands/parallel_collection_scan.cpp71
-rw-r--r--src/mongo/db/namespace_string.cpp6
-rw-r--r--src/mongo/db/namespace_string.h2
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp62
-rw-r--r--src/mongo/db/pipeline/pipeline_d.h2
12 files changed, 169 insertions, 164 deletions
diff --git a/src/mongo/db/catalog/catalog_raii.cpp b/src/mongo/db/catalog/catalog_raii.cpp
index 60c81373b79..fb1535f22df 100644
--- a/src/mongo/db/catalog/catalog_raii.cpp
+++ b/src/mongo/db/catalog/catalog_raii.cpp
@@ -37,12 +37,6 @@
namespace mongo {
namespace {
-StringData getDBNameToLock(const NamespaceStringOrUUID& nsOrUUID) {
- if (nsOrUUID.nss())
- return nsOrUUID.nss()->db();
- return nsOrUUID.dbAndUUID()->dbName;
-}
-
MONGO_FP_DECLARE(setAutoGetCollectionWait);
} // namespace
@@ -58,36 +52,33 @@ AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
LockMode modeDB,
LockMode modeColl,
ViewMode viewMode)
- : AutoGetCollection(opCtx,
- nsOrUUID,
- Lock::DBLock(opCtx, getDBNameToLock(nsOrUUID), modeDB),
- modeColl,
- viewMode) {}
+ : AutoGetCollection(
+ opCtx, nsOrUUID, Lock::DBLock(opCtx, nsOrUUID.db(), modeDB), modeColl, viewMode) {}
AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
const NamespaceStringOrUUID& nsOrUUID,
Lock::DBLock dbLock,
LockMode modeColl,
ViewMode viewMode)
- : _autoDb(opCtx, getDBNameToLock(nsOrUUID), std::move(dbLock)) {
- if (nsOrUUID.nss()) {
- _nsAndLock.emplace(NamespaceAndCollectionLock{
- Lock::CollectionLock(opCtx->lockState(), nsOrUUID.nss()->ns(), modeColl),
- *nsOrUUID.nss()});
- } else {
- UUIDCatalog& catalog = UUIDCatalog::get(opCtx);
- auto resolvedNss = catalog.lookupNSSByUUID(nsOrUUID.dbAndUUID()->uuid);
-
- // If the collection UUID cannot be resolved, we can't obtain a collection or check for
- // views
- if (!resolvedNss.isValid())
- return;
-
- _nsAndLock.emplace(NamespaceAndCollectionLock{
- Lock::CollectionLock(opCtx->lockState(), resolvedNss.ns(), modeColl),
- std::move(resolvedNss)});
- }
-
+ : _autoDb(opCtx, nsOrUUID.db(), std::move(dbLock)),
+ _nsAndLock([&]() -> NamespaceAndCollectionLock {
+ if (nsOrUUID.nss()) {
+ return {Lock::CollectionLock(opCtx->lockState(), nsOrUUID.nss()->ns(), modeColl),
+ *nsOrUUID.nss()};
+ } else {
+ UUIDCatalog& catalog = UUIDCatalog::get(opCtx);
+ auto resolvedNss = catalog.lookupNSSByUUID(nsOrUUID.dbAndUUID()->uuid);
+
+ // If the collection UUID cannot be resolved, we can't obtain a collection or check
+ // for vews
+ uassert(ErrorCodes::NamespaceNotFound,
+ str::stream() << "Unable to resolve " << nsOrUUID.toString(),
+ resolvedNss.isValid());
+
+ return {Lock::CollectionLock(opCtx->lockState(), resolvedNss.ns(), modeColl),
+ std::move(resolvedNss)};
+ }
+ }()) {
// Wait for a configured amount of time after acquiring locks if the failpoint is enabled
MONGO_FAIL_POINT_BLOCK(setAutoGetCollectionWait, customWait) {
const BSONObj& data = customWait.getData();
@@ -100,7 +91,7 @@ AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
if (!db)
return;
- _coll = db->getCollection(opCtx, _nsAndLock->nss);
+ _coll = db->getCollection(opCtx, _nsAndLock.nss);
// If the collection exists, there is no need to check for views and we must keep the collection
// lock
@@ -108,9 +99,9 @@ AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
return;
}
- _view = db->getViewCatalog()->lookup(opCtx, _nsAndLock->nss.ns());
+ _view = db->getViewCatalog()->lookup(opCtx, _nsAndLock.nss.ns());
uassert(ErrorCodes::CommandNotSupportedOnView,
- str::stream() << "Namespace " << _nsAndLock->nss.ns() << " is a view, not a collection",
+ str::stream() << "Namespace " << _nsAndLock.nss.ns() << " is a view, not a collection",
!_view || viewMode == kViewsPermitted);
}
diff --git a/src/mongo/db/catalog/catalog_raii.h b/src/mongo/db/catalog/catalog_raii.h
index 819d59f62ff..8c7bbb632f1 100644
--- a/src/mongo/db/catalog/catalog_raii.h
+++ b/src/mongo/db/catalog/catalog_raii.h
@@ -73,7 +73,7 @@ private:
* RAII-style class, which acquires a locks on the specified database and collection in the
* requested modes and obtains references to both.
*
- * NOTE: If the collection cannot be resolved to a name, the collection lock will not be held.
+ * NOTE: Throws NamespaceNotFound if the collection UUID cannot be resolved to a name.
*
* Any acquired locks may be released when this object goes out of scope, therefore the database
* and the collection references returned by this class should not be retained.
@@ -124,6 +124,13 @@ public:
return _view.get();
}
+ /**
+ * Returns the resolved namespace of the collection or view.
+ */
+ const NamespaceString& getNss() const {
+ return _nsAndLock.nss;
+ }
+
private:
struct NamespaceAndCollectionLock {
Lock::CollectionLock lock;
@@ -131,9 +138,7 @@ private:
};
AutoGetDb _autoDb;
-
- // This value will be initialized if the UUID can be resolved to a collection name
- boost::optional<NamespaceAndCollectionLock> _nsAndLock;
+ const NamespaceAndCollectionLock _nsAndLock;
Collection* _coll = nullptr;
std::shared_ptr<ViewDefinition> _view;
diff --git a/src/mongo/db/catalog/database_test.cpp b/src/mongo/db/catalog/database_test.cpp
index 4610735077b..c82c7fc5897 100644
--- a/src/mongo/db/catalog/database_test.cpp
+++ b/src/mongo/db/catalog/database_test.cpp
@@ -228,7 +228,7 @@ TEST_F(DatabaseTest,
// Replicated collection is renamed with a special drop-pending names in the <db>.system.drop.*
// namespace.
auto dpns = _nss.makeDropPendingNamespace(dropOpTime);
- ASSERT_TRUE(mongo::AutoGetCollectionForRead(_opCtx.get(), dpns).getCollection());
+ ASSERT_TRUE(AutoGetCollectionForRead(_opCtx.get(), dpns).getCollection());
// Reaper should have the drop optime of the collection.
auto reaperEarliestDropOpTime =
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 762b87a87ca..b301df2d131 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -79,8 +79,10 @@ struct CommandHelpers {
static void appendCommandStatus(BSONObjBuilder& result,
bool ok,
const std::string& errmsg = {});
+
// @return s.isOK()
static bool appendCommandStatus(BSONObjBuilder& result, const Status& status);
+
/**
* Helper for setting a writeConcernError field in the command result object if
* a writeConcern error occurs.
@@ -95,15 +97,18 @@ struct CommandHelpers {
static void appendCommandWCStatus(BSONObjBuilder& result,
const Status& awaitReplicationStatus,
const WriteConcernResult& wcResult = WriteConcernResult());
+
/**
* Appends passthrough fields from a cmdObj to a given request.
*/
static BSONObj appendPassthroughFields(const BSONObj& cmdObjWithPassthroughFields,
const BSONObj& request);
+
/**
* Returns a copy of 'cmdObj' with a majority writeConcern appended.
*/
static BSONObj appendMajorityWriteConcern(const BSONObj& cmdObj);
+
/**
* Returns true if the provided argument is one that is handled by the command processing layer
* and should generally be ignored by individual command implementations. In particular,
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index 129af8c89de..336bcad29e0 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -59,7 +59,11 @@ class CmdCount : public BasicCommand {
public:
CmdCount() : BasicCommand("count") {}
- virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ std::string help() const override {
+ return "count objects in collection";
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
@@ -71,28 +75,24 @@ public:
return Command::AllowedOnSecondary::kOptIn;
}
- virtual bool maintenanceOk() const {
+ bool maintenanceOk() const override {
return false;
}
- virtual bool adminOnly() const {
+ bool adminOnly() const override {
return false;
}
bool supportsReadConcern(const std::string& dbName,
const BSONObj& cmdObj,
- repl::ReadConcernLevel level) const final {
+ repl::ReadConcernLevel level) const override {
return true;
}
- ReadWriteType getReadWriteType() const {
+ ReadWriteType getReadWriteType() const override {
return ReadWriteType::kRead;
}
- std::string help() const override {
- return "count objects in collection";
- }
-
Status checkAuthForOperation(OperationContext* opCtx,
const std::string& dbname,
const BSONObj& cmdObj) override {
@@ -110,11 +110,11 @@ public:
return Status::OK();
}
- virtual Status explain(OperationContext* opCtx,
- const std::string& dbname,
- const BSONObj& cmdObj,
- ExplainOptions::Verbosity verbosity,
- BSONObjBuilder* out) const {
+ Status explain(OperationContext* opCtx,
+ const std::string& dbname,
+ const BSONObj& cmdObj,
+ ExplainOptions::Verbosity verbosity,
+ BSONObjBuilder* out) const override {
const bool isExplain = true;
Lock::DBLock dbLock(opCtx, dbname, MODE_IS);
auto nss = CommandHelpers::parseNsOrUUID(opCtx, dbname, cmdObj);
@@ -169,10 +169,10 @@ public:
return Status::OK();
}
- virtual bool run(OperationContext* opCtx,
- const string& dbname,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) {
+ bool run(OperationContext* opCtx,
+ const string& dbname,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
const bool isExplain = false;
Lock::DBLock dbLock(opCtx, dbname, MODE_IS);
auto nss = CommandHelpers::parseNsOrUUID(opCtx, dbname, cmdObj);
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index 50b05986912..99e42d567ae 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -64,32 +64,33 @@
#include "mongo/util/log.h"
namespace mongo {
+namespace {
-using std::unique_ptr;
-using std::string;
-using std::stringstream;
-
-namespace dps = ::mongo::dotted_path_support;
+namespace dps = dotted_path_support;
class DistinctCommand : public BasicCommand {
public:
DistinctCommand() : BasicCommand("distinct") {}
+ std::string help() const override {
+ return "{ distinct : 'collection name' , key : 'a.b' , query : {} }";
+ }
+
AllowedOnSecondary secondaryAllowed() const override {
return AllowedOnSecondary::kOptIn;
}
- virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
bool supportsReadConcern(const std::string& dbName,
const BSONObj& cmdObj,
- repl::ReadConcernLevel level) const final {
+ repl::ReadConcernLevel level) const override {
return true;
}
- ReadWriteType getReadWriteType() const {
+ ReadWriteType getReadWriteType() const override {
return ReadWriteType::kRead;
}
@@ -97,30 +98,24 @@ public:
return FindCommon::kInitReplyBufferSize;
}
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {
+ void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) override {
ActionSet actions;
actions.addAction(ActionType::find);
out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
}
- std::string help() const override {
- return "{ distinct : 'collection name' , key : 'a.b' , query : {} }";
- }
-
- virtual Status explain(OperationContext* opCtx,
- const std::string& dbname,
- const BSONObj& cmdObj,
- ExplainOptions::Verbosity verbosity,
- BSONObjBuilder* out) const {
+ Status explain(OperationContext* opCtx,
+ const std::string& dbname,
+ const BSONObj& cmdObj,
+ ExplainOptions::Verbosity verbosity,
+ BSONObjBuilder* out) const override {
const NamespaceString nss(CommandHelpers::parseNsCollectionRequired(dbname, cmdObj));
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
- auto parsedDistinct = ParsedDistinct::parse(opCtx, nss, cmdObj, extensionsCallback, true);
- if (!parsedDistinct.isOK()) {
- return parsedDistinct.getStatus();
- }
+ auto parsedDistinct =
+ uassertStatusOK(ParsedDistinct::parse(opCtx, nss, cmdObj, extensionsCallback, true));
AutoGetCollectionOrViewForReadCommand ctx(opCtx, nss);
Collection* collection = ctx.getCollection();
@@ -128,7 +123,7 @@ public:
if (ctx.getView()) {
ctx.releaseLocksForView();
- auto viewAggregation = parsedDistinct.getValue().asAggregationCommand();
+ auto viewAggregation = parsedDistinct.asAggregationCommand();
if (!viewAggregation.isOK()) {
return viewAggregation.getStatus();
}
@@ -143,27 +138,22 @@ public:
opCtx, nss, viewAggRequest.getValue(), viewAggregation.getValue(), *out);
}
- auto executor = getExecutorDistinct(
- opCtx, collection, nss.ns(), &parsedDistinct.getValue(), PlanExecutor::YIELD_AUTO);
- if (!executor.isOK()) {
- return executor.getStatus();
- }
+ auto executor = uassertStatusOK(getExecutorDistinct(
+ opCtx, collection, nss.ns(), &parsedDistinct, PlanExecutor::YIELD_AUTO));
- Explain::explainStages(executor.getValue().get(), collection, verbosity, out);
+ Explain::explainStages(executor.get(), collection, verbosity, out);
return Status::OK();
}
bool run(OperationContext* opCtx,
- const string& dbname,
+ const std::string& dbname,
const BSONObj& cmdObj,
- BSONObjBuilder& result) {
+ BSONObjBuilder& result) override {
const NamespaceString nss(CommandHelpers::parseNsCollectionRequired(dbname, cmdObj));
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
- auto parsedDistinct = ParsedDistinct::parse(opCtx, nss, cmdObj, extensionsCallback, false);
- if (!parsedDistinct.isOK()) {
- return CommandHelpers::appendCommandStatus(result, parsedDistinct.getStatus());
- }
+ auto parsedDistinct =
+ uassertStatusOK(ParsedDistinct::parse(opCtx, nss, cmdObj, extensionsCallback, false));
AutoGetCollectionOrViewForReadCommand ctx(opCtx, nss);
Collection* collection = ctx.getCollection();
@@ -171,7 +161,7 @@ public:
if (ctx.getView()) {
ctx.releaseLocksForView();
- auto viewAggregation = parsedDistinct.getValue().asAggregationCommand();
+ auto viewAggregation = parsedDistinct.asAggregationCommand();
if (!viewAggregation.isOK()) {
return CommandHelpers::appendCommandStatus(result, viewAggregation.getStatus());
}
@@ -183,7 +173,7 @@ public:
}
auto executor = getExecutorDistinct(
- opCtx, collection, nss.ns(), &parsedDistinct.getValue(), PlanExecutor::YIELD_AUTO);
+ opCtx, collection, nss.ns(), &parsedDistinct, PlanExecutor::YIELD_AUTO);
if (!executor.isOK()) {
return CommandHelpers::appendCommandStatus(result, executor.getStatus());
}
@@ -194,7 +184,7 @@ public:
Explain::getPlanSummary(executor.getValue().get()));
}
- string key = cmdObj[ParsedDistinct::kKeyField].valuestrsafe();
+ const auto key = cmdObj[ParsedDistinct::kKeyField].valuestrsafe();
int bufSize = BSONObjMaxUserSize - 4096;
BufBuilder bb(bufSize);
@@ -267,6 +257,8 @@ public:
return true;
}
+
} distinctCmd;
+} // namespace
} // namespace mongo
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 7139f52175f..494542a3279 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -143,8 +143,7 @@ public:
}
// Finish the parsing step by using the QueryRequest to create a CanonicalQuery.
-
- ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
+ const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx,
@@ -262,7 +261,7 @@ public:
beginQueryOp(opCtx, nss, cmdObj, ntoreturn, ntoskip);
// Finish the parsing step by using the QueryRequest to create a CanonicalQuery.
- ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
+ const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx,
diff --git a/src/mongo/db/commands/parallel_collection_scan.cpp b/src/mongo/db/commands/parallel_collection_scan.cpp
index c9f36a820e4..8a79411fc44 100644
--- a/src/mongo/db/commands/parallel_collection_scan.cpp
+++ b/src/mongo/db/commands/parallel_collection_scan.cpp
@@ -51,28 +51,23 @@ namespace {
class ParallelCollectionScanCmd : public BasicCommand {
public:
- struct ExtentInfo {
- ExtentInfo(RecordId dl, size_t s) : diskLoc(dl), size(s) {}
- RecordId diskLoc;
- size_t size;
- };
-
ParallelCollectionScanCmd() : BasicCommand("parallelCollectionScan") {}
- virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
+
AllowedOnSecondary secondaryAllowed() const override {
return AllowedOnSecondary::kAlways;
}
bool supportsReadConcern(const std::string& dbName,
const BSONObj& cmdObj,
- repl::ReadConcernLevel level) const final {
+ repl::ReadConcernLevel level) const override {
return true;
}
- ReadWriteType getReadWriteType() const {
+ ReadWriteType getReadWriteType() const override {
return ReadWriteType::kCommand;
}
@@ -93,10 +88,10 @@ public:
return Status::OK();
}
- virtual bool run(OperationContext* opCtx,
- const string& dbname,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) {
+ bool run(OperationContext* opCtx,
+ const string& dbname,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
Lock::DBLock dbSLock(opCtx, dbname, MODE_IS);
const NamespaceString ns(CommandHelpers::parseNsOrUUID(opCtx, dbname, cmdObj));
@@ -156,36 +151,34 @@ public:
mis->addIterator(std::move(iterators[i]));
}
- {
- BSONArrayBuilder bucketsBuilder;
- for (auto&& exec : execs) {
- // Need to save state while yielding locks between now and getMore().
- exec->saveState();
- exec->detachFromOperationContext();
-
- // Create and register a new ClientCursor.
- auto pinnedCursor = collection->getCursorManager()->registerCursor(
- opCtx,
- {std::move(exec),
- ns,
- AuthorizationSession::get(opCtx->getClient())->getAuthenticatedUserNames(),
- opCtx->recoveryUnit()->isReadingFromMajorityCommittedSnapshot(),
- cmdObj});
- pinnedCursor.getCursor()->setLeftoverMaxTimeMicros(
- opCtx->getRemainingMaxTimeMicros());
-
- BSONObjBuilder threadResult;
- appendCursorResponseObject(
- pinnedCursor.getCursor()->cursorid(), ns.ns(), BSONArray(), &threadResult);
- threadResult.appendBool("ok", 1);
-
- bucketsBuilder.append(threadResult.obj());
- }
- result.appendArray("cursors", bucketsBuilder.obj());
+ BSONArrayBuilder bucketsBuilder;
+ for (auto&& exec : execs) {
+ // Need to save state while yielding locks between now and getMore().
+ exec->saveState();
+ exec->detachFromOperationContext();
+
+ // Create and register a new ClientCursor.
+ auto pinnedCursor = collection->getCursorManager()->registerCursor(
+ opCtx,
+ {std::move(exec),
+ ns,
+ AuthorizationSession::get(opCtx->getClient())->getAuthenticatedUserNames(),
+ opCtx->recoveryUnit()->isReadingFromMajorityCommittedSnapshot(),
+ cmdObj});
+ pinnedCursor.getCursor()->setLeftoverMaxTimeMicros(opCtx->getRemainingMaxTimeMicros());
+
+ BSONObjBuilder threadResult;
+ appendCursorResponseObject(
+ pinnedCursor.getCursor()->cursorid(), ns.ns(), BSONArray(), &threadResult);
+ threadResult.appendBool("ok", 1);
+
+ bucketsBuilder.append(threadResult.obj());
}
+ result.appendArray("cursors", bucketsBuilder.obj());
return true;
}
+
} parallelCollectionScanCmd;
} // namespace
diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp
index 19b35fec4cd..ba17dc66cc4 100644
--- a/src/mongo/db/namespace_string.cpp
+++ b/src/mongo/db/namespace_string.cpp
@@ -245,6 +245,12 @@ bool NamespaceString::isReplicated() const {
return true;
}
+StringData NamespaceStringOrUUID::db() const {
+ if (_nss)
+ return _nss->db();
+ return _dbAndUUID->dbName;
+}
+
std::string NamespaceStringOrUUID::toString() const {
if (_nss)
return _nss->toString();
diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h
index 13b13dda0f8..eb19a5dfb04 100644
--- a/src/mongo/db/namespace_string.h
+++ b/src/mongo/db/namespace_string.h
@@ -457,6 +457,8 @@ public:
NamespaceStringOrUUID(NamespaceString nss) : _nss(std::move(nss)) {}
NamespaceStringOrUUID(StringData dbName, UUID uuid) : _dbAndUUID({dbName.toString(), uuid}) {}
+ StringData db() const;
+
const boost::optional<NamespaceString>& nss() const {
return _nss;
}
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index fb6d6355efd..2441a0cc787 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -705,11 +705,14 @@ Status PipelineD::MongoDInterface::attachCursorSourceToPipeline(
boost::optional<AutoGetCollectionForReadCommand> autoColl;
if (expCtx->uuid) {
- autoColl.emplace(expCtx->opCtx, expCtx->ns.db(), *expCtx->uuid);
- if (autoColl->getCollection() == nullptr) {
- // The UUID doesn't exist anymore.
- return {ErrorCodes::NamespaceNotFound,
- "No namespace with UUID " + expCtx->uuid->toString()};
+ try {
+ autoColl.emplace(expCtx->opCtx, expCtx->ns.db(), *expCtx->uuid);
+ uassert(ErrorCodes::NamespaceNotFound,
+ "No namespace with UUID " + expCtx->uuid->toString(),
+ autoColl->getCollection());
+ } catch (const ExceptionFor<ErrorCodes::NamespaceNotFound>& ex) {
+ // The UUID doesn't exist anymore
+ return ex.toStatus();
}
} else {
autoColl.emplace(expCtx->opCtx, expCtx->ns);
@@ -864,14 +867,17 @@ boost::optional<Document> PipelineD::MongoDInterface::lookupSingleDocument(
invariant(!readConcern); // We don't currently support a read concern on mongod - it's only
// expected to be necessary on mongos.
- // Be sure to do the lookup using the collection default collation.
- auto foreignExpCtx = expCtx->copyWith(
- nss, collectionUUID, _getCollectionDefaultCollator(expCtx->opCtx, nss, collectionUUID));
- auto swPipeline = makePipeline({BSON("$match" << documentKey)}, foreignExpCtx);
- if (swPipeline == ErrorCodes::NamespaceNotFound) {
+ std::unique_ptr<Pipeline, PipelineDeleter> pipeline;
+ try {
+ // Be sure to do the lookup using the collection default collation
+ auto foreignExpCtx = expCtx->copyWith(
+ nss,
+ collectionUUID,
+ _getCollectionDefaultCollator(expCtx->opCtx, nss.db(), collectionUUID));
+ pipeline = uassertStatusOK(makePipeline({BSON("$match" << documentKey)}, foreignExpCtx));
+ } catch (const ExceptionFor<ErrorCodes::NamespaceNotFound>&) {
return boost::none;
}
- auto pipeline = uassertStatusOK(std::move(swPipeline));
auto lookedUpDocument = pipeline->getNext();
if (auto next = pipeline->getNext()) {
@@ -888,21 +894,27 @@ boost::optional<Document> PipelineD::MongoDInterface::lookupSingleDocument(
}
std::unique_ptr<CollatorInterface> PipelineD::MongoDInterface::_getCollectionDefaultCollator(
- OperationContext* opCtx, const NamespaceString& nss, UUID collectionUUID) {
- if (_collatorCache.find(collectionUUID) == _collatorCache.end()) {
- AutoGetCollection autoColl(opCtx, NamespaceStringOrUUID(nss.db(), collectionUUID), MODE_IS);
- if (!autoColl.getCollection()) {
- // This collection doesn't exist - since we looked up by UUID, it will never exist in
- // the future, so we cache a null pointer as the default collation.
- _collatorCache[collectionUUID] = nullptr;
- } else {
- auto defaultCollator = autoColl.getCollection()->getDefaultCollator();
- // Clone the collator so that we can safely use the pointer if the collection
- // disappears right after we release the lock.
- _collatorCache[collectionUUID] = defaultCollator ? defaultCollator->clone() : nullptr;
- }
+ OperationContext* opCtx, StringData dbName, UUID collectionUUID) {
+ auto it = _collatorCache.find(collectionUUID);
+ if (it == _collatorCache.end()) {
+ auto collator = [&]() -> std::unique_ptr<CollatorInterface> {
+ AutoGetCollection autoColl(opCtx, {dbName, collectionUUID}, MODE_IS);
+ if (!autoColl.getCollection()) {
+ // This collection doesn't exist, so assume a nullptr default collation
+ return nullptr;
+ } else {
+ auto defaultCollator = autoColl.getCollection()->getDefaultCollator();
+ // Clone the collator so that we can safely use the pointer if the collection
+ // disappears right after we release the lock.
+ return defaultCollator ? defaultCollator->clone() : nullptr;
+ }
+ }();
+
+ it = _collatorCache.emplace(collectionUUID, std::move(collator)).first;
}
- return _collatorCache[collectionUUID] ? _collatorCache[collectionUUID]->clone() : nullptr;
+
+ auto& collator = it->second;
+ return collator ? collator->clone() : nullptr;
}
} // namespace mongo
diff --git a/src/mongo/db/pipeline/pipeline_d.h b/src/mongo/db/pipeline/pipeline_d.h
index afbb6b8f73f..60ad684cc7b 100644
--- a/src/mongo/db/pipeline/pipeline_d.h
+++ b/src/mongo/db/pipeline/pipeline_d.h
@@ -123,7 +123,7 @@ public:
* collation.
*/
std::unique_ptr<CollatorInterface> _getCollectionDefaultCollator(OperationContext* opCtx,
- const NamespaceString& nss,
+ StringData dbName,
UUID collectionUUID);
DBDirectClient _client;