diff options
author | Jason Rassi <rassi@10gen.com> | 2014-12-23 16:08:36 -0500 |
---|---|---|
committer | Jason Rassi <rassi@10gen.com> | 2014-12-23 22:57:31 -0500 |
commit | 4d14564d2f63e397cd392f1a7df27f9a2305dc23 (patch) | |
tree | a69f3ac6d56a8a2f9469a16e88b3e48f00e9fab0 /src/mongo | |
parent | 1df9c58634def7beeee86fc4f4353a70940fcbbf (diff) | |
download | mongo-4d14564d2f63e397cd392f1a7df27f9a2305dc23.tar.gz |
SERVER-16520 Add a global CursorManager
The global cursor manager owns ClientCursor objects that aren't
associated with a particular collection.
The auth check for getMore against cursors owned by the global cursor
manager is left as a TODO (tracked by SERVER-16657).
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/catalog/cursor_manager.cpp | 54 | ||||
-rw-r--r-- | src/mongo/db/catalog/cursor_manager.h | 3 | ||||
-rw-r--r-- | src/mongo/db/instance.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/query/find.cpp | 29 |
4 files changed, 76 insertions, 20 deletions
diff --git a/src/mongo/db/catalog/cursor_manager.cpp b/src/mongo/db/catalog/cursor_manager.cpp index ad03a883ee4..8dd65ccc338 100644 --- a/src/mongo/db/catalog/cursor_manager.cpp +++ b/src/mongo/db/catalog/cursor_manager.cpp @@ -31,6 +31,7 @@ #include "mongo/db/catalog/cursor_manager.h" #include "mongo/base/data_cursor.h" +#include "mongo/base/init.h" #include "mongo/db/audit.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/catalog/collection.h" @@ -108,7 +109,6 @@ namespace mongo { std::size_t timeoutCursors(OperationContext* txn, int millisSinceLastCall); int64_t nextSeed(); - private: SimpleMutex _mutex; @@ -117,7 +117,23 @@ namespace mongo { unsigned _nextId; SecureRandom* _secureRandom; - } _globalCursorIdCache; + }; + + // Note that "globalCursorIdCache" must be declared before "globalCursorManager", as the latter + // calls into the former during destruction. + boost::scoped_ptr<GlobalCursorIdCache> globalCursorIdCache; + boost::scoped_ptr<CursorManager> globalCursorManager; + + MONGO_INITIALIZER(GlobalCursorIdCache)(InitializerContext* context) { + globalCursorIdCache.reset(new GlobalCursorIdCache()); + return Status::OK(); + } + + MONGO_INITIALIZER_WITH_PREREQUISITES(GlobalCursorManager, ("GlobalCursorIdCache")) + (InitializerContext* context) { + globalCursorManager.reset(new CursorManager("")); + return Status::OK(); + } GlobalCursorIdCache::GlobalCursorIdCache() : _mutex( "GlobalCursorIdCache" ), @@ -189,6 +205,10 @@ namespace mongo { } } + if (ns == globalCursorManager->ns()) { + return globalCursorManager->eraseCursor(txn, id, checkAuth); + } + AutoGetCollectionForRead ctx(txn, nss); if (!ctx.getDb()) { return false; @@ -203,7 +223,6 @@ namespace mongo { ErrorCodes::CursorNotFound ); return false; } - return collection->cursorManager()->eraseCursor(txn, id, checkAuth); } @@ -218,7 +237,13 @@ namespace mongo { size_t totalTimedOut = 0; for ( unsigned i = 0; i < todo.size(); i++ ) { - AutoGetCollectionForRead ctx(txn, todo[i]); + const std::string& ns = todo[i]; + if ( ns == globalCursorManager->ns() ) { + totalTimedOut += globalCursorManager->timeoutCursors( millisSinceLastCall ); + continue; + } + + AutoGetCollectionForRead ctx(txn, ns); if (!ctx.getDb()) { continue; } @@ -229,7 +254,6 @@ namespace mongo { } totalTimedOut += collection->cursorManager()->timeoutCursors( millisSinceLastCall ); - } return totalTimedOut; @@ -237,9 +261,13 @@ namespace mongo { // --- + CursorManager* CursorManager::getGlobalCursorManager() { + return globalCursorManager.get(); + } + std::size_t CursorManager::timeoutCursorsGlobal(OperationContext* txn, int millisSinceLastCall) {; - return _globalCursorIdCache.timeoutCursors(txn, millisSinceLastCall); + return globalCursorIdCache->timeoutCursors(txn, millisSinceLastCall); } int CursorManager::eraseCursorGlobalIfAuthorized(OperationContext* txn, int n, @@ -255,10 +283,10 @@ namespace mongo { return numDeleted; } bool CursorManager::eraseCursorGlobalIfAuthorized(OperationContext* txn, CursorId id) { - return _globalCursorIdCache.eraseCursor(txn, id, true); + return globalCursorIdCache->eraseCursor(txn, id, true); } bool CursorManager::eraseCursorGlobal(OperationContext* txn, CursorId id) { - return _globalCursorIdCache.eraseCursor(txn, id, false ); + return globalCursorIdCache->eraseCursor(txn, id, false ); } @@ -268,13 +296,13 @@ namespace mongo { CursorManager::CursorManager( const StringData& ns ) : _nss( ns ), _mutex( "CursorManager" ) { - _collectionCacheRuntimeId = _globalCursorIdCache.created( _nss.ns() ); - _random.reset( new PseudoRandom( _globalCursorIdCache.nextSeed() ) ); + _collectionCacheRuntimeId = globalCursorIdCache->created( _nss.ns() ); + _random.reset( new PseudoRandom( globalCursorIdCache->nextSeed() ) ); } CursorManager::~CursorManager() { invalidateAll( true ); - _globalCursorIdCache.destroyed( _collectionCacheRuntimeId, _nss.ns() ); + globalCursorIdCache->destroyed( _collectionCacheRuntimeId, _nss.ns() ); } void CursorManager::invalidateAll( bool collectionGoingAway ) { @@ -430,6 +458,10 @@ namespace mongo { cursor->unsetPinned(); } + bool CursorManager::ownsCursorId( CursorId cursorId ) { + return _collectionCacheRuntimeId == idFromCursorId( cursorId ); + } + void CursorManager::getCursorIds( std::set<CursorId>* openCursors ) { SimpleMutex::scoped_lock lk( _mutex ); diff --git a/src/mongo/db/catalog/cursor_manager.h b/src/mongo/db/catalog/cursor_manager.h index 1e92aefad7a..af94d917f79 100644 --- a/src/mongo/db/catalog/cursor_manager.h +++ b/src/mongo/db/catalog/cursor_manager.h @@ -99,6 +99,7 @@ namespace mongo { bool eraseCursor(OperationContext* txn, CursorId id, bool checkAuth ); + bool ownsCursorId( CursorId cursorId ); void getCursorIds( std::set<CursorId>* openCursors ); std::size_t numCursors(); @@ -113,6 +114,8 @@ namespace mongo { // ---------------------- + static CursorManager* getGlobalCursorManager(); + static int eraseCursorGlobalIfAuthorized(OperationContext* txn, int n, const char* ids); static bool eraseCursorGlobalIfAuthorized(OperationContext* txn, CursorId id); diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index 92c3f8e30e0..048b0f81bd2 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -746,8 +746,14 @@ namespace { const NamespaceString nsString( ns ); uassert( 16258, str::stream() << "Invalid ns [" << ns << "]", nsString.isValid() ); - Status status = txn->getClient()->getAuthorizationSession()->checkAuthForGetMore( - nsString, cursorid); + Status status = Status::OK(); + if (CursorManager::getGlobalCursorManager()->ownsCursorId(cursorid)) { + // TODO Implement auth check for global cursors. SERVER-16657. + } + else { + status = txn->getClient()->getAuthorizationSession()->checkAuthForGetMore( + nsString, cursorid); + } audit::logGetMoreAuthzCheck(txn->getClient(), nsString, cursorid, status.code()); uassertStatusOK(status); diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp index 74a0de79e36..b44f4040644 100644 --- a/src/mongo/db/query/find.cpp +++ b/src/mongo/db/query/find.cpp @@ -192,9 +192,19 @@ namespace mongo { // This is a read lock. const NamespaceString nss(ns); - scoped_ptr<AutoGetCollectionForRead> ctx(new AutoGetCollectionForRead(txn, nss)); - Collection* collection = ctx->getCollection(); - uassert( 17356, "collection dropped between getMore calls", collection ); + boost::scoped_ptr<AutoGetCollectionForRead> ctx; + + CursorManager* cursorManager; + CursorManager* globalCursorManager = CursorManager::getGlobalCursorManager(); + if (globalCursorManager->ownsCursorId(cursorid)) { + cursorManager = globalCursorManager; + } + else { + ctx.reset(new AutoGetCollectionForRead(txn, nss)); + Collection* collection = ctx->getCollection(); + uassert( 17356, "collection dropped between getMore calls", collection ); + cursorManager = collection->cursorManager(); + } QLOG() << "Running getMore, cursorid: " << cursorid << endl; @@ -211,7 +221,7 @@ namespace mongo { // A pin performs a CC lookup and if there is a CC, increments the CC's pin value so it // doesn't time out. Also informs ClientCursor that there is somebody actively holding the // CC, so don't delete it. - ClientCursorPin ccPin(collection->cursorManager(), cursorid); + ClientCursorPin ccPin(cursorManager, cursorid); ClientCursor* cc = ccPin.c(); // If we're not being called from DBDirectClient we want to associate the RecoveryUnit @@ -240,9 +250,14 @@ namespace mongo { resultFlags = ResultFlag_CursorNotFound; } else { - // Quote: check for spoofing of the ns such that it does not match the one originally - // there for the cursor - uassert(17011, "auth error", str::equals(ns, cc->ns().c_str())); + // Check for spoofing of the ns such that it does not match the one originally + // there for the cursor. + if (globalCursorManager->ownsCursorId(cursorid)) { + // TODO Implement auth check for global cursors. SERVER-16657. + } + else { + uassert(17011, "auth error", str::equals(ns, cc->ns().c_str())); + } *isCursorAuthorized = true; // Restore the RecoveryUnit if we need to. |