diff options
author | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2017-06-15 00:17:19 -0400 |
---|---|---|
committer | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2017-06-15 00:17:19 -0400 |
commit | 59ea14f97808e343a4a10a1b5352b7096b695e38 (patch) | |
tree | dfd0d9b7b04819f7e321ad8c63ac4971be85d5a8 /src | |
parent | 3ac29e19745e4a594bff892f3de8372159770565 (diff) | |
download | mongo-59ea14f97808e343a4a10a1b5352b7096b695e38.tar.gz |
Revert "SERVER-29417 Attach logical session ids to cursors"
This reverts commit 65828661c6579989fdbb43f2c21de16f2bf72586.
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/clientcursor.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/clientcursor.h | 13 | ||||
-rw-r--r-- | src/mongo/db/cursor_manager.cpp | 69 | ||||
-rw-r--r-- | src/mongo/db/cursor_manager.h | 17 | ||||
-rw-r--r-- | src/mongo/db/db_raii.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/db_raii.h | 43 | ||||
-rw-r--r-- | src/mongo/db/logical_session_id.h | 1 | ||||
-rw-r--r-- | src/mongo/db/query/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/query/query_test_service_context.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/query/query_test_service_context.h | 5 | ||||
-rw-r--r-- | src/mongo/dbtests/cursor_manager_test.cpp | 186 |
12 files changed, 6 insertions, 351 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index c7649153f78..5d2149b9e55 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -613,7 +613,6 @@ env.Library( ], LIBDEPS=[ "$BUILD_DIR/mongo/base", - "$BUILD_DIR/mongo/db/logical_session_id", "$BUILD_DIR/mongo/util/background_job", "query/query", "background", diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp index 889d9961607..b6a686ba717 100644 --- a/src/mongo/db/clientcursor.cpp +++ b/src/mongo/db/clientcursor.cpp @@ -77,15 +77,13 @@ long long ClientCursor::totalOpen() { return cursorStatsOpen.get(); } -ClientCursor::ClientCursor(ClientCursorParams params, +ClientCursor::ClientCursor(ClientCursorParams&& params, CursorManager* cursorManager, CursorId cursorId, - boost::optional<LogicalSessionId> lsid, Date_t now) : _cursorid(cursorId), _nss(std::move(params.nss)), _authenticatedUsers(std::move(params.authenticatedUsers)), - _lsid(std::move(lsid)), _isReadCommitted(params.isReadCommitted), _cursorManager(cursorManager), _originatingCommand(params.originatingCommandObj), diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h index 32fb018a8e1..d2f216b01e1 100644 --- a/src/mongo/db/clientcursor.h +++ b/src/mongo/db/clientcursor.h @@ -28,13 +28,10 @@ #pragma once -#include <boost/optional.hpp> - #include "mongo/client/dbclientinterface.h" #include "mongo/db/auth/user_name.h" #include "mongo/db/cursor_id.h" #include "mongo/db/jsobj.h" -#include "mongo/db/logical_session_id.h" #include "mongo/db/query/plan_executor.h" #include "mongo/db/record_id.h" #include "mongo/stdx/functional.h" @@ -111,10 +108,6 @@ public: return makeUserNameIterator(_authenticatedUsers.begin(), _authenticatedUsers.end()); } - boost::optional<LogicalSessionId> getSessionId() const { - return _lsid; - } - bool isReadCommitted() const { return _isReadCommitted; } @@ -225,10 +218,9 @@ private: * Constructs a ClientCursor. Since cursors must come into being registered and pinned, this is * private. See cursor_manager.h for more details. */ - ClientCursor(ClientCursorParams params, + ClientCursor(ClientCursorParams&& params, CursorManager* cursorManager, CursorId cursorId, - boost::optional<LogicalSessionId> lsid, Date_t now); /** @@ -265,9 +257,6 @@ private: // The set of authenticated users when this cursor was created. std::vector<UserName> _authenticatedUsers; - // A logical session id for this cursor, if it is running inside of a session. - const boost::optional<LogicalSessionId> _lsid; - const bool _isReadCommitted = false; CursorManager* _cursorManager; diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp index a2e9687f5b1..f1bdd8a9442 100644 --- a/src/mongo/db/cursor_manager.cpp +++ b/src/mongo/db/cursor_manager.cpp @@ -101,8 +101,6 @@ public: std::size_t timeoutCursors(OperationContext* opCtx, Date_t now); - void appendActiveSessions(OperationContext* opCtx, LogicalSessionIdSet* lsids); - int64_t nextSeed(); private: @@ -269,47 +267,12 @@ std::size_t GlobalCursorIdCache::timeoutCursors(OperationContext* opCtx, Date_t } } // namespace -void GlobalCursorIdCache::appendActiveSessions(OperationContext* opCtx, - LogicalSessionIdSet* lsids) { - // Get active session ids from the global cursor manager - globalCursorManager->appendActiveSessions(lsids); - - // Compute the set of collection names that we have to get sessions for - vector<NamespaceString> namespaces; - { - stdx::lock_guard<SimpleMutex> lk(_mutex); - for (auto&& entry : _idToNss) { - namespaces.push_back(entry.second); - } - } - - // For each collection, get its sessions under the collection lock (to prevent the - // collection from going away during the erase). - for (auto&& ns : namespaces) { - AutoGetCollectionOrView ctx(opCtx, NamespaceString(ns), MODE_IS); - if (!ctx.getDb()) { - continue; - } - - Collection* collection = ctx.getCollection(); - if (!collection) { - continue; - } - - collection->getCursorManager()->appendActiveSessions(lsids); - } -} - // --- CursorManager* CursorManager::getGlobalCursorManager() { return globalCursorManager.get(); } -void CursorManager::appendAllActiveSessions(OperationContext* opCtx, LogicalSessionIdSet* lsids) { - globalCursorIdCache->appendActiveSessions(opCtx, lsids); -} - std::size_t CursorManager::timeoutCursorsGlobal(OperationContext* opCtx, Date_t now) { return globalCursorIdCache->timeoutCursors(opCtx, now); } @@ -519,34 +482,6 @@ void CursorManager::getCursorIds(std::set<CursorId>* openCursors) const { } } -void CursorManager::appendActiveSessions(LogicalSessionIdSet* lsids) const { - auto allPartitions = _cursorMap->lockAllPartitions(); - for (auto&& partition : allPartitions) { - for (auto&& entry : partition) { - auto cursor = entry.second; - if (auto id = cursor->getSessionId()) { - lsids->insert(id.value()); - } - } - } -} - -stdx::unordered_set<CursorId> CursorManager::getCursorsForSession(LogicalSessionId lsid) const { - stdx::unordered_set<CursorId> cursors; - - auto allPartitions = _cursorMap->lockAllPartitions(); - for (auto&& partition : allPartitions) { - for (auto&& entry : partition) { - auto cursor = entry.second; - if (cursor->getSessionId() == lsid) { - cursors.insert(cursor->cursorid()); - } - } - } - - return cursors; -} - size_t CursorManager::numCursors() const { return _cursorMap->size(); } @@ -591,8 +526,8 @@ ClientCursorPin CursorManager::registerCursor(OperationContext* opCtx, // we don't insert two cursors with the same cursor id. stdx::lock_guard<SimpleMutex> lock(_registrationLock); CursorId cursorId = allocateCursorId_inlock(); - std::unique_ptr<ClientCursor, ClientCursor::Deleter> clientCursor(new ClientCursor( - std::move(cursorParams), this, cursorId, opCtx->getLogicalSessionId(), now)); + std::unique_ptr<ClientCursor, ClientCursor::Deleter> clientCursor( + new ClientCursor(std::move(cursorParams), this, cursorId, now)); // Transfer ownership of the cursor to '_cursorMap'. auto partition = _cursorMap->lockOnePartition(cursorId); diff --git a/src/mongo/db/cursor_manager.h b/src/mongo/db/cursor_manager.h index 0b243e21996..40408c48830 100644 --- a/src/mongo/db/cursor_manager.h +++ b/src/mongo/db/cursor_manager.h @@ -36,7 +36,6 @@ #include "mongo/db/record_id.h" #include "mongo/platform/unordered_map.h" #include "mongo/platform/unordered_set.h" -#include "mongo/stdx/unordered_set.h" #include "mongo/util/concurrency/mutex.h" #include "mongo/util/duration.h" @@ -79,12 +78,6 @@ public: static constexpr Minutes kDefaultCursorTimeoutMinutes{10}; using RegistrationToken = Partitioned<unordered_set<PlanExecutor*>>::PartitionId; - /** - * Appends the sessions that have open cursors on the global cursor manager and across - * all collection-level cursor managers to the given set of lsids. - */ - static void appendAllActiveSessions(OperationContext* opCtx, LogicalSessionIdSet* lsids); - CursorManager(NamespaceString nss); /** @@ -166,16 +159,6 @@ public: void getCursorIds(std::set<CursorId>* openCursors) const; /** - * Appends sessions that have open cursors in this cursor manager to the given set of lsids. - */ - void appendActiveSessions(LogicalSessionIdSet* lsids) const; - - /* - * Returns a list of all open cursors for the given session. - */ - stdx::unordered_set<CursorId> getCursorsForSession(LogicalSessionId lsid) const; - - /** * Returns the number of ClientCursors currently registered. Excludes any registered bare * PlanExecutors. */ diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp index bff855fcc5b..478047eb0cc 100644 --- a/src/mongo/db/db_raii.cpp +++ b/src/mongo/db/db_raii.cpp @@ -72,14 +72,6 @@ AutoGetCollection::AutoGetCollection(OperationContext* opCtx, } } -AutoGetCollectionOrView::AutoGetCollectionOrView(OperationContext* opCtx, - const NamespaceString& nss, - LockMode modeAll) - : _autoColl(opCtx, nss, modeAll, modeAll, AutoGetCollection::ViewMode::kViewsPermitted), - _view(_autoColl.getDb() && !_autoColl.getCollection() - ? _autoColl.getDb()->getViewCatalog()->lookup(opCtx, nss.ns()) - : nullptr) {} - AutoGetOrCreateDb::AutoGetOrCreateDb(OperationContext* opCtx, StringData ns, LockMode mode) : _dbLock(opCtx, ns, mode), _db(dbHolder().get(opCtx, ns)) { invariant(mode == MODE_IX || mode == MODE_X); diff --git a/src/mongo/db/db_raii.h b/src/mongo/db/db_raii.h index 641b64e7988..753909e3c6a 100644 --- a/src/mongo/db/db_raii.h +++ b/src/mongo/db/db_raii.h @@ -128,55 +128,12 @@ private: const Lock::CollectionLock _collLock; Collection* const _coll; - friend class AutoGetCollectionOrView; friend class AutoGetCollectionForRead; friend class AutoGetCollectionForReadCommand; friend class AutoGetCollectionOrViewForReadCommand; }; /** - * RAII-style class which acquires the appropriate hierarchy of locks for a collection or - * view. The pointer to a view definition is nullptr if it does not exist. - * - * Use this when you have not yet determined if the namespace is a view or a collection. - * For example, you can use this to access a namespace's CursorManager. - * - * It is guaranteed that locks will be released when this object goes out of scope, therefore - * the view returned by this class should not be retained. - */ -class AutoGetCollectionOrView { - MONGO_DISALLOW_COPYING(AutoGetCollectionOrView); - -public: - AutoGetCollectionOrView(OperationContext* opCtx, const NamespaceString& nss, LockMode modeAll); - - /** - * Returns nullptr if the database didn't exist. - */ - Database* getDb() const { - return _autoColl.getDb(); - } - - /** - * Returns nullptr if the collection didn't exist. - */ - Collection* getCollection() const { - return _autoColl.getCollection(); - } - - /** - * Returns nullptr if the view didn't exist. - */ - ViewDefinition* getView() const { - return _view.get(); - } - -private: - const AutoGetCollection _autoColl; - std::shared_ptr<ViewDefinition> _view; -}; - -/** * RAII-style class, which acquires a lock on the specified database in the requested mode and * obtains a reference to the database, creating it was non-existing. Used as a shortcut for * calls to dbHolder().openDb(), taking care of locking details. The requested mode must be diff --git a/src/mongo/db/logical_session_id.h b/src/mongo/db/logical_session_id.h index f1fb85ce89e..eca1d8a33f5 100644 --- a/src/mongo/db/logical_session_id.h +++ b/src/mongo/db/logical_session_id.h @@ -32,7 +32,6 @@ #include "mongo/base/status_with.h" #include "mongo/db/logical_session_id_gen.h" -#include "mongo/stdx/unordered_set.h" #include "mongo/util/uuid.h" namespace mongo { diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript index 854f3045506..7c42568f7c0 100644 --- a/src/mongo/db/query/SConscript +++ b/src/mongo/db/query/SConscript @@ -255,7 +255,6 @@ env.Library( ], LIBDEPS=[ "collation/collator_factory_mock", - "$BUILD_DIR/mongo/db/logical_session_id", "$BUILD_DIR/mongo/db/service_context", ], ) diff --git a/src/mongo/db/query/query_test_service_context.cpp b/src/mongo/db/query/query_test_service_context.cpp index 4ad6ac8e857..e2682fe44d4 100644 --- a/src/mongo/db/query/query_test_service_context.cpp +++ b/src/mongo/db/query/query_test_service_context.cpp @@ -44,13 +44,4 @@ ServiceContext::UniqueOperationContext QueryTestServiceContext::makeOperationCon return _uniqueClient->makeOperationContext(); } -ServiceContext::UniqueOperationContext QueryTestServiceContext::makeOperationContext( - LogicalSessionId lsid) { - return _uniqueClient->makeOperationContext(std::move(lsid)); -} - -Client* QueryTestServiceContext::getClient() const { - return _uniqueClient.get(); -} - } // namespace mongo diff --git a/src/mongo/db/query/query_test_service_context.h b/src/mongo/db/query/query_test_service_context.h index 658b73ef36a..7466116d354 100644 --- a/src/mongo/db/query/query_test_service_context.h +++ b/src/mongo/db/query/query_test_service_context.h @@ -29,7 +29,6 @@ #pragma once #include "mongo/db/client.h" -#include "mongo/db/logical_session_id.h" #include "mongo/db/service_context_noop.h" namespace mongo { @@ -45,10 +44,6 @@ public: ServiceContext::UniqueOperationContext makeOperationContext(); - ServiceContext::UniqueOperationContext makeOperationContext(LogicalSessionId lsid); - - Client* getClient() const; - private: ServiceContextNoop _serviceContext; ServiceContext::UniqueClient _uniqueClient; diff --git a/src/mongo/dbtests/cursor_manager_test.cpp b/src/mongo/dbtests/cursor_manager_test.cpp index 0cc69b1ad20..07ec00df8fc 100644 --- a/src/mongo/dbtests/cursor_manager_test.cpp +++ b/src/mongo/dbtests/cursor_manager_test.cpp @@ -28,11 +28,6 @@ #include "mongo/platform/basic.h" -#include <algorithm> - -#include <boost/optional/optional.hpp> -#include <boost/optional/optional_io.hpp> - #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" #include "mongo/db/cursor_manager.h" @@ -40,7 +35,6 @@ #include "mongo/db/exec/working_set.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/operation_context.h" -#include "mongo/db/operation_context_noop.h" #include "mongo/db/query/plan_executor.h" #include "mongo/db/query/query_test_service_context.h" #include "mongo/dbtests/dbtests.h" @@ -91,28 +85,15 @@ public: } std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> makeFakePlanExecutor() { - return makeFakePlanExecutor(_opCtx.get()); - } - - std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> makeFakePlanExecutor( - OperationContext* opCtx) { auto workingSet = stdx::make_unique<WorkingSet>(); - auto queuedDataStage = stdx::make_unique<QueuedDataStage>(opCtx, workingSet.get()); - return unittest::assertGet(PlanExecutor::make(opCtx, + auto queuedDataStage = stdx::make_unique<QueuedDataStage>(_opCtx.get(), workingSet.get()); + return unittest::assertGet(PlanExecutor::make(_opCtx.get(), std::move(workingSet), std::move(queuedDataStage), kTestNss, PlanExecutor::YieldPolicy::NO_YIELD)); } - ClientCursorParams makeParams(OperationContext* opCtx) { - return {makeFakePlanExecutor(opCtx), kTestNss, {}, false, BSONObj()}; - } - - ClientCursorPin makeCursor(OperationContext* opCtx) { - return _cursorManager.registerCursor(opCtx, makeParams(opCtx)); - } - ClockSourceMock* useClock() { return _clock; } @@ -130,16 +111,6 @@ private: CursorManager _cursorManager{kTestNss}; }; -class CursorManagerTestCustomOpCtx : public CursorManagerTest { - void setUp() override { - _queryServiceContext->getClient()->resetOperationContext(); - } - - void tearDown() override { - _queryServiceContext->getClient()->setOperationContext(_opCtx.get()); - } -}; - TEST_F(CursorManagerTest, GlobalCursorManagerShouldReportOwnershipOfCursorsItCreated) { for (int i = 0; i < 1000; i++) { auto cursorPin = CursorManager::getGlobalCursorManager()->registerCursor( @@ -426,158 +397,5 @@ TEST_F(CursorManagerTest, CursorShouldNotTimeOutUntilIdleForLongEnoughAfterBeing ASSERT_EQ(1UL, cursorManager->timeoutCursors(_opCtx.get(), clock->now())); ASSERT_EQ(0UL, cursorManager->numCursors()); } - -/** - * Test that cursors inherit the logical session id from their operation context - */ -TEST_F(CursorManagerTestCustomOpCtx, LogicalSessionIdOnOperationCtxTest) { - // Cursors created on an op ctx without a session id have no session id. - { - auto opCtx = _queryServiceContext->makeOperationContext(); - auto pinned = makeCursor(opCtx.get()); - - ASSERT_EQUALS(pinned.getCursor()->getSessionId(), boost::none); - } - - // Cursors created on an op ctx with a session id have a session id. - { - auto lsid = LogicalSessionId::gen(); - auto opCtx2 = _queryServiceContext->makeOperationContext(lsid); - auto pinned2 = makeCursor(opCtx2.get()); - - ASSERT_EQUALS(pinned2.getCursor()->getSessionId(), lsid); - } -} - -/** - * Test that a manager whose cursors do not have sessions does not return them. - */ -TEST_F(CursorManagerTestCustomOpCtx, CursorsWithoutSessions) { - // Add a cursor with no session to the cursor manager. - auto opCtx = _queryServiceContext->makeOperationContext(); - auto pinned = makeCursor(opCtx.get()); - ASSERT_EQUALS(pinned.getCursor()->getSessionId(), boost::none); - - // Retrieve all sessions active in manager - set should be empty. - LogicalSessionIdSet lsids; - useCursorManager()->appendActiveSessions(&lsids); - ASSERT(lsids.empty()); -} - -/** - * Test a manager that has one cursor running inside of a session. - */ -TEST_F(CursorManagerTestCustomOpCtx, OneCursorWithASession) { - // Add a cursor with a session to the cursor manager. - auto lsid = LogicalSessionId::gen(); - auto opCtx = _queryServiceContext->makeOperationContext(lsid); - auto pinned = makeCursor(opCtx.get()); - - // Retrieve all sessions active in manager - set should contain just lsid. - LogicalSessionIdSet lsids; - useCursorManager()->appendActiveSessions(&lsids); - ASSERT_EQ(lsids.size(), size_t(1)); - ASSERT(lsids.find(lsid) != lsids.end()); - - // Retrieve all cursors for this lsid - should be just ours. - auto cursors = useCursorManager()->getCursorsForSession(lsid); - ASSERT_EQ(cursors.size(), size_t(1)); - auto cursorId = pinned.getCursor()->cursorid(); - ASSERT(cursors.find(cursorId) != cursors.end()); - - // Remove the cursor from the manager. - pinned.release(); - ASSERT_OK(useCursorManager()->eraseCursor(opCtx.get(), cursorId, false)); - - // There should be no more cursor entries by session id. - LogicalSessionIdSet sessions; - useCursorManager()->appendActiveSessions(&sessions); - ASSERT(sessions.empty()); - ASSERT(useCursorManager()->getCursorsForSession(lsid).empty()); -} - -/** - * Test a manager with multiple cursors running inside of the same session. - */ -TEST_F(CursorManagerTestCustomOpCtx, MultipleCursorsWithSameSession) { - // Add two cursors on the same session to the cursor manager. - auto lsid = LogicalSessionId::gen(); - auto opCtx = _queryServiceContext->makeOperationContext(lsid); - auto pinned = makeCursor(opCtx.get()); - auto pinned2 = makeCursor(opCtx.get()); - - // Retrieve all sessions - set should contain just lsid. - stdx::unordered_set<LogicalSessionId, LogicalSessionId::Hash> lsids; - useCursorManager()->appendActiveSessions(&lsids); - ASSERT_EQ(lsids.size(), size_t(1)); - ASSERT(lsids.find(lsid) != lsids.end()); - - // Retrieve all cursors for session - should be both cursors. - auto cursors = useCursorManager()->getCursorsForSession(lsid); - ASSERT_EQ(cursors.size(), size_t(2)); - ASSERT(cursors.find(pinned.getCursor()->cursorid()) != cursors.end()); - ASSERT(cursors.find(pinned2.getCursor()->cursorid()) != cursors.end()); - - // Remove one cursor from the manager. - pinned.release(); - ASSERT_OK(useCursorManager()->eraseCursor(opCtx.get(), pinned.getCursor()->cursorid(), false)); - - // Should still be able to retrieve the session. - lsids.clear(); - useCursorManager()->appendActiveSessions(&lsids); - ASSERT_EQ(lsids.size(), size_t(1)); - ASSERT(lsids.find(lsid) != lsids.end()); - - // Should still be able to retrieve remaining cursor by session. - cursors = useCursorManager()->getCursorsForSession(lsid); - ASSERT_EQ(cursors.size(), size_t(1)); - ASSERT(cursors.find(pinned2.getCursor()->cursorid()) != cursors.end()); -} - -/** - * Test a manager with multiple cursors running inside of different sessions. - */ -TEST_F(CursorManagerTestCustomOpCtx, MultipleCursorsMultipleSessions) { - auto lsid1 = LogicalSessionId::gen(); - auto lsid2 = LogicalSessionId::gen(); - - CursorId cursor1; - CursorId cursor2; - - // Cursor with session 1. - { - auto opCtx1 = _queryServiceContext->makeOperationContext(lsid1); - cursor1 = makeCursor(opCtx1.get()).getCursor()->cursorid(); - } - - // Cursor with session 2. - { - auto opCtx2 = _queryServiceContext->makeOperationContext(lsid2); - cursor2 = makeCursor(opCtx2.get()).getCursor()->cursorid(); - } - - // Cursor with no session. - { - auto opCtx3 = _queryServiceContext->makeOperationContext(); - makeCursor(opCtx3.get()).getCursor(); - } - - // Retrieve all sessions - should be both lsids. - LogicalSessionIdSet lsids; - useCursorManager()->appendActiveSessions(&lsids); - ASSERT_EQ(lsids.size(), size_t(2)); - ASSERT(lsids.find(lsid1) != lsids.end()); - ASSERT(lsids.find(lsid2) != lsids.end()); - - // Retrieve cursors for each session - should be just one. - auto cursors1 = useCursorManager()->getCursorsForSession(lsid1); - ASSERT_EQ(cursors1.size(), size_t(1)); - ASSERT(cursors1.find(cursor1) != cursors1.end()); - - auto cursors2 = useCursorManager()->getCursorsForSession(lsid2); - ASSERT_EQ(cursors2.size(), size_t(1)); - ASSERT(cursors2.find(cursor2) != cursors2.end()); -} - } // namespace } // namespace mongo |