diff options
Diffstat (limited to 'src/mongo/db/clientcursor.cpp')
| -rw-r--r-- | src/mongo/db/clientcursor.cpp | 133 |
1 files changed, 27 insertions, 106 deletions
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp index ac60a6b14be..bb205d784f2 100644 --- a/src/mongo/db/clientcursor.cpp +++ b/src/mongo/db/clientcursor.cpp @@ -51,7 +51,6 @@ #include "mongo/db/cursor_server_params.h" #include "mongo/db/jsobj.h" #include "mongo/db/query/explain.h" -#include "mongo/db/query/query_stats/query_stats.h" #include "mongo/db/repl/repl_client_info.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/util/background.h" @@ -82,49 +81,6 @@ static ServerStatusMetricField<Counter64> dCursorStatsTotalOpened("cursor.totalO static ServerStatusMetricField<Counter64> dCursorStatsMoreThanOneBatch( "cursor.moreThanOneBatch", &cursorStatsMoreThanOneBatch); -static Counter64 cursorStatsLifespanLessThan1Second; -static Counter64 cursorStatsLifespanLessThan5Seconds; -static Counter64 cursorStatsLifespanLessThan15Seconds; -static Counter64 cursorStatsLifespanLessThan30Seconds; -static Counter64 cursorStatsLifespanLessThan1Minute; -static Counter64 cursorStatsLifespanLessThan10Minutes; -static Counter64 cursorStatsLifespanGreaterThanOrEqual10Minutes; - -static ServerStatusMetricField<Counter64> dCursorStatsLifespanLessThan1Second( - "cursor.lifespan.lessThan1Second", &cursorStatsLifespanLessThan1Second); -static ServerStatusMetricField<Counter64> dCursorStatsLifespanLessThan5Seconds( - "cursor.lifespan.lessThan5Seconds", &cursorStatsLifespanLessThan5Seconds); -static ServerStatusMetricField<Counter64> dCursorStatsLifespanLessThan15Seconds( - "cursor.lifespan.lessThan15Seconds", &cursorStatsLifespanLessThan15Seconds); -static ServerStatusMetricField<Counter64> dCursorStatsLifespanLessThan30Seconds( - "cursor.lifespan.lessThan30Seconds", &cursorStatsLifespanLessThan30Seconds); -static ServerStatusMetricField<Counter64> dCursorStatsLifespanLessThan1Minute( - "cursor.lifespan.lessThan1Minute", &cursorStatsLifespanLessThan1Minute); -static ServerStatusMetricField<Counter64> dCursorStatsLifespanLessThan10Minutes( - "cursor.lifespan.lessThan10Minutes", &cursorStatsLifespanLessThan10Minutes); -static ServerStatusMetricField<Counter64> dCursorStatsLifespanGreaterThanOrEqual10Minutes( - "cursor.lifespan.greaterThanOrEqual10Minutes", &cursorStatsLifespanGreaterThanOrEqual10Minutes); - -void incrementCursorLifespanMetric(Date_t birth, Date_t death) { - auto elapsed = death - birth; - - if (elapsed < Seconds(1)) { - cursorStatsLifespanLessThan1Second.increment(); - } else if (elapsed < Seconds(5)) { - cursorStatsLifespanLessThan5Seconds.increment(); - } else if (elapsed < Seconds(15)) { - cursorStatsLifespanLessThan15Seconds.increment(); - } else if (elapsed < Seconds(30)) { - cursorStatsLifespanLessThan30Seconds.increment(); - } else if (elapsed < Minutes(1)) { - cursorStatsLifespanLessThan1Minute.increment(); - } else if (elapsed < Minutes(10)) { - cursorStatsLifespanLessThan10Minutes.increment(); - } else { - cursorStatsLifespanGreaterThanOrEqual10Minutes.increment(); - } -} - ClientCursor::ClientCursor(ClientCursorParams params, CursorId cursorId, OperationContext* operationUsingCursor, @@ -149,10 +105,6 @@ ClientCursor::ClientCursor(ClientCursorParams params, _planSummary(_exec->getPlanExplainer().getPlanSummary()), _planCacheKey(CurOp::get(operationUsingCursor)->debug().planCacheKey), _queryHash(CurOp::get(operationUsingCursor)->debug().queryHash), - _queryStatsKeyHash(CurOp::get(operationUsingCursor)->debug().queryStatsInfo.keyHash), - _queryStatsKey(std::move(CurOp::get(operationUsingCursor)->debug().queryStatsInfo.key)), - _queryStatsWillNeverExhaust( - CurOp::get(operationUsingCursor)->debug().queryStatsInfo.willNeverExhaust), _opKey(operationUsingCursor->getOperationKey()) { invariant(_exec); invariant(_operationUsingCursor); @@ -177,33 +129,23 @@ ClientCursor::~ClientCursor() { // needs to keep data pinned. _stashedRecoveryUnit->setAbandonSnapshotMode(RecoveryUnit::AbandonSnapshotMode::kAbort); } -} - -void ClientCursor::dispose(OperationContext* opCtx, boost::optional<Date_t> now) { - if (_disposed) { - return; - } - - query_stats::writeQueryStatsOnCursorDisposeOrKill( - opCtx, - _queryStatsKeyHash, - std::move(_queryStatsKey), - _queryStatsWillNeverExhaust, - _metrics.executionTime.value_or(Microseconds{0}).count(), - _firstResponseExecutionTime.value_or(Microseconds{0}).count(), - _metrics.nreturned.value_or(0)); - - if (now) { - incrementCursorLifespanMetric(_createdDate, *now); - } cursorStatsOpen.decrement(); if (isNoTimeout()) { cursorStatsOpenNoTimeout.decrement(); } - if (_metrics.nBatches && *_metrics.nBatches > 1) { + if (_nBatchesReturned > 1) cursorStatsMoreThanOneBatch.increment(); +} + +void ClientCursor::markAsKilled(Status killStatus) { + _exec->markAsKilled(killStatus); +} + +void ClientCursor::dispose(OperationContext* opCtx) { + if (_disposed) { + return; } _exec->dispose(opCtx); @@ -214,7 +156,7 @@ GenericCursor ClientCursor::toGenericCursor() const { GenericCursor gc; gc.setCursorId(cursorid()); gc.setNs(nss()); - gc.setNDocsReturned(_metrics.nreturned.value_or(0)); + gc.setNDocsReturned(_nReturnedSoFar); gc.setTailable(isTailable()); gc.setAwaitData(isAwaitData()); gc.setNoCursorTimeout(isNoTimeout()); @@ -327,12 +269,24 @@ void ClientCursorPin::deleteUnderlying() { invariant(_cursor); invariant(_cursor->_operationUsingCursor); invariant(_cursorManager); - - std::unique_ptr<ClientCursor, ClientCursor::Deleter> ownedCursor(_cursor); - _cursor = nullptr; - _cursorManager->deregisterAndDestroyCursor(_opCtx, std::move(ownedCursor)); + // Note the following subtleties of this method's implementation: + // - We must unpin the cursor (by clearing the '_operationUsingCursor' field) before + // destruction, since it is an error to delete a pinned cursor. + // - In addition, we must deregister the cursor before clearing the '_operationUsingCursor' + // field, since it is an error to unpin a registered cursor without holding the appropriate + // cursor manager mutex. By first deregistering the cursor, we ensure that no other thread can + // access '_cursor', meaning that it is safe for us to write to '_operationUsingCursor' + // without holding the CursorManager mutex. + + _cursorManager->deregisterCursor(_cursor); + + // Make sure the cursor is disposed and unpinned before being destroyed. + _cursor->dispose(_opCtx); + _cursor->_operationUsingCursor = nullptr; + delete _cursor; cursorStatsOpenPinned.decrement(); + _cursor = nullptr; _shouldSaveRecoveryUnit = false; } @@ -404,37 +358,4 @@ void startClientCursorMonitor() { getClientCursorMonitor(getGlobalServiceContext()).go(); } -void collectQueryStatsMongod(OperationContext* opCtx, ClientCursorPin& pinnedCursor) { - pinnedCursor->incrementCursorMetrics(CurOp::get(opCtx)->debug().additiveMetrics); - - // For a change stream query, we want to collect and update query stats on the initial query and - // for every getMore. - // TODO SERVER-89058 Modify comment to include tailable cursors. - if (pinnedCursor->getQueryStatsWillNeverExhaust()) { - auto& opDebug = CurOp::get(opCtx)->debug(); - - int64_t execTime = opDebug.additiveMetrics.executionTime.value_or(Microseconds{0}).count(); - query_stats::writeQueryStats(opCtx, - opDebug.queryStatsInfo.keyHash, - pinnedCursor->takeKey(), - execTime, - execTime, - opDebug.additiveMetrics.nreturned.value_or(0), - pinnedCursor->getQueryStatsWillNeverExhaust()); - } -} - -void collectQueryStatsMongod(OperationContext* opCtx, std::unique_ptr<query_stats::Key> key) { - // If we haven't registered a cursor to prepare for getMore requests, we record - // query stats directly. - auto& opDebug = CurOp::get(opCtx)->debug(); - int64_t execTime = opDebug.additiveMetrics.executionTime.value_or(Microseconds{0}).count(); - query_stats::writeQueryStats(opCtx, - opDebug.queryStatsInfo.keyHash, - std::move(key), - execTime, - execTime, - opDebug.additiveMetrics.nreturned.value_or(0)); -} - } // namespace mongo |
