summaryrefslogtreecommitdiff
path: root/src/mongo/db/clientcursor.cpp
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2017-04-14 16:33:41 -0400
committerCharlie Swanson <charlie.swanson@mongodb.com>2017-05-03 17:45:07 -0400
commit7759c61a35f835aa109131b8f1575f0e1879cba0 (patch)
treea7c4758f153a2f75ed908425dfeb294326112233 /src/mongo/db/clientcursor.cpp
parent2c00a571f4549ccdfb427b1f096157290662a0f7 (diff)
downloadmongo-7759c61a35f835aa109131b8f1575f0e1879cba0.tar.gz
SERVER-28327 Revamp cursor timeout logic.
Instead of tracking the number of idle milliseconds, each ClientCursor tracks its last time of use. This also resolves related issues SERVER-28328 and SERVER-19892.
Diffstat (limited to 'src/mongo/db/clientcursor.cpp')
-rw-r--r--src/mongo/db/clientcursor.cpp52
1 files changed, 23 insertions, 29 deletions
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp
index 3b1c5c97307..b181d8d4d6c 100644
--- a/src/mongo/db/clientcursor.cpp
+++ b/src/mongo/db/clientcursor.cpp
@@ -71,7 +71,6 @@ static ServerStatusMetricField<Counter64> dCursorStatsOpenNoTimeout("cursor.open
static ServerStatusMetricField<Counter64> dCursorStatusTimedout("cursor.timedOut",
&cursorStatsTimedOut);
-MONGO_EXPORT_SERVER_PARAMETER(cursorTimeoutMillis, int, 10 * 60 * 1000 /* 10 minutes */);
MONGO_EXPORT_SERVER_PARAMETER(clientCursorMonitorFrequencySecs, int, 4);
long long ClientCursor::totalOpen() {
@@ -80,7 +79,8 @@ long long ClientCursor::totalOpen() {
ClientCursor::ClientCursor(ClientCursorParams&& params,
CursorManager* cursorManager,
- CursorId cursorId)
+ CursorId cursorId,
+ Date_t now)
: _cursorid(cursorId),
_nss(std::move(params.nss)),
_authenticatedUsers(std::move(params.authenticatedUsers)),
@@ -88,11 +88,8 @@ ClientCursor::ClientCursor(ClientCursorParams&& params,
_cursorManager(cursorManager),
_originatingCommand(params.originatingCommandObj),
_queryOptions(params.queryOptions),
- _exec(std::move(params.exec)) {
- init();
-}
-
-void ClientCursor::init() {
+ _exec(std::move(params.exec)),
+ _lastUseDate(now) {
invariant(_cursorManager);
invariant(_exec);
@@ -129,22 +126,6 @@ void ClientCursor::dispose(OperationContext* opCtx) {
_disposed = true;
}
-//
-// Timing and timeouts
-//
-
-bool ClientCursor::shouldTimeout(int millis) {
- _idleAgeMillis += millis;
- if (isNoTimeout() || _isPinned) {
- return false;
- }
- return _idleAgeMillis > cursorTimeoutMillis.load();
-}
-
-void ClientCursor::resetIdleTime() {
- _idleAgeMillis = 0;
-}
-
void ClientCursor::updateSlaveLocation(OperationContext* opCtx) {
if (_slaveReadTill.isNull())
return;
@@ -221,6 +202,13 @@ void ClientCursorPin::release() {
if (!_cursor)
return;
+ // Note it's not safe to dereference _cursor->_cursorManager unless we know we haven't been
+ // killed. If we're not locked we assume we haven't been killed because we're working with the
+ // global cursor manager which never kills cursors.
+ const bool isLocked =
+ _opCtx->lockState()->isCollectionLockedForMode(_cursor->_nss.ns(), MODE_IS);
+ dassert(isLocked || _cursor->_cursorManager->isGlobalManager());
+
invariant(_cursor->_isPinned);
if (_cursor->getExecutor()->isMarkedAsKilled()) {
@@ -229,7 +217,7 @@ void ClientCursorPin::release() {
deleteUnderlying();
} else {
// Unpin the cursor under the collection cursor manager lock.
- _cursor->_cursorManager->unpin(_cursor);
+ _cursor->_cursorManager->unpin(_opCtx, _cursor);
cursorStatsOpenPinned.decrement();
}
@@ -247,6 +235,13 @@ void ClientCursorPin::deleteUnderlying() {
// we can't simply unpin with the cursor manager lock here, since we need to guarantee
// exclusive ownership of the cursor when we are deleting it).
+ // Note it's not safe to dereference _cursor->_cursorManager unless we know we haven't been
+ // killed. If we're not locked we assume we haven't been killed because we're working with the
+ // global cursor manager which never kills cursors.
+ const bool isLocked =
+ _opCtx->lockState()->isCollectionLockedForMode(_cursor->_nss.ns(), MODE_IS);
+ dassert(isLocked || _cursor->_cursorManager->isGlobalManager());
+
if (!_cursor->getExecutor()->isMarkedAsKilled()) {
_cursor->_cursorManager->deregisterCursor(_cursor);
}
@@ -269,7 +264,7 @@ ClientCursor* ClientCursorPin::getCursor() const {
//
/**
- * Thread for timing out old cursors
+ * Thread for timing out inactive cursors.
*/
class ClientCursorMonitor : public BackgroundJob {
public:
@@ -279,13 +274,12 @@ public:
void run() {
Client::initThread("clientcursormon");
- Timer t;
while (!globalInShutdownDeprecated()) {
{
- const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
- OperationContext& opCtx = *opCtxPtr;
+ const ServiceContext::UniqueOperationContext opCtx = cc().makeOperationContext();
+ auto now = opCtx->getServiceContext()->getPreciseClockSource()->now();
cursorStatsTimedOut.increment(
- CursorManager::timeoutCursorsGlobal(&opCtx, t.millisReset()));
+ CursorManager::timeoutCursorsGlobal(opCtx.get(), now));
}
MONGO_IDLE_THREAD_BLOCK;
sleepsecs(clientCursorMonitorFrequencySecs.load());