From 8f931d4443e07e3bfdfab97377b98bb1fdd53548 Mon Sep 17 00:00:00 2001 From: Jason Rassi Date: Fri, 20 Mar 2015 16:51:37 -0400 Subject: [PATCH] SERVER-17672 Helpers::getSingleton()/getLast() return owned object --- src/mongo/db/dbhelpers.cpp | 23 +++++++++++++---------- src/mongo/db/dbhelpers.h | 25 ++++++++++++++++--------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index 0f7b403cefd..10d0848182b 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -199,19 +199,18 @@ namespace mongo { return catalog->getIndex(desc)->findSingle( txn, idquery["_id"].wrap() ); } - /* Get the first object from a collection. Generally only useful if the collection - only ever has a single object -- which is a "singleton collection". Note that the - BSONObj returned is *not* owned and will become invalid if the database is closed. - - Returns: true if object exists. - */ bool Helpers::getSingleton(OperationContext* txn, const char *ns, BSONObj& result) { AutoGetCollectionForRead ctx(txn, ns); auto_ptr exec(InternalPlanner::collectionScan(txn, ns, ctx.getCollection())); - PlanExecutor::ExecState state = exec->getNext(&result, NULL); + txn->getCurOp()->done(); - return PlanExecutor::ADVANCED == state; + + if (PlanExecutor::ADVANCED == state) { + result = result.getOwned(); + return true; + } + return false; } bool Helpers::getLast(OperationContext* txn, const char *ns, BSONObj& result) { @@ -220,9 +219,13 @@ namespace mongo { ns, autoColl.getCollection(), InternalPlanner::BACKWARD)); - PlanExecutor::ExecState state = exec->getNext(&result, NULL); - return PlanExecutor::ADVANCED == state; + + if (PlanExecutor::ADVANCED == state) { + result = result.getOwned(); + return true; + } + return false; } void Helpers::upsert( OperationContext* txn, diff --git a/src/mongo/db/dbhelpers.h b/src/mongo/db/dbhelpers.h index a40114ef8ab..9fbaf372a96 100644 --- a/src/mongo/db/dbhelpers.h +++ b/src/mongo/db/dbhelpers.h @@ -107,21 +107,28 @@ namespace mongo { static RecordId findById(OperationContext* txn, Collection* collection, const BSONObj& query); - /** Get/put the first (or last) object from a collection. Generally only useful if the collection - only ever has a single object -- which is a "singleton collection". - - You do not need to set the database (Context) before calling. - - @return true if object exists. - */ + /** + * Get the first object generated from a forward natural-order scan on "ns". Callers do not + * have to lock "ns". + * + * Returns true if there is such an object. An owned copy of the object is placed into the + * out-argument "result". + * + * Returns false if there is no such object. + */ static bool getSingleton(OperationContext* txn, const char *ns, BSONObj& result); - static void putSingleton(OperationContext* txn, const char *ns, BSONObj obj); /** - * get last object int he collection; e.g. {$natural : -1} + * Same as getSingleton, but with a reverse natural-order scan on "ns". */ static bool getLast(OperationContext* txn, const char *ns, BSONObj& result); + /** + * Performs an upsert of "obj" into the collection "ns", with an empty update predicate. + * Callers must have "ns" locked. + */ + static void putSingleton(OperationContext* txn, const char *ns, BSONObj obj); + /** * you have to lock * you do not have to have Context set