summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Rassi <rassi@10gen.com>2014-12-23 16:08:36 -0500
committerJason Rassi <rassi@10gen.com>2014-12-23 22:57:31 -0500
commit4d14564d2f63e397cd392f1a7df27f9a2305dc23 (patch)
treea69f3ac6d56a8a2f9469a16e88b3e48f00e9fab0
parent1df9c58634def7beeee86fc4f4353a70940fcbbf (diff)
downloadmongo-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).
-rw-r--r--src/mongo/db/catalog/cursor_manager.cpp54
-rw-r--r--src/mongo/db/catalog/cursor_manager.h3
-rw-r--r--src/mongo/db/instance.cpp10
-rw-r--r--src/mongo/db/query/find.cpp29
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.