static StatusWith<std::tuple<stdx::unique_lock<Client>, OperationContext*>> _findOp( ClientBasic* client, unsigned int opId) { AuthorizationSession* authzSession = AuthorizationSession::get(client); for (ServiceContext::LockedClientsCursor cursor(client->getServiceContext()); Client* opClient = cursor.next();) { stdx::unique_lock<Client> lk(*opClient); OperationContext* opCtx = opClient->getOperationContext(); if (opCtx && opCtx->getOpID() == opId) { if (authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forClusterResource(), ActionType::killop) || authzSession->isCoauthorizedWithClient(opClient)) { return {std::make_tuple(std::move(lk), opCtx)}; } break; } } return Status(ErrorCodes::NoSuchKey, str::stream() << "Could not access opID: " << opId); }
std::vector<BSONObj> MongoProcessCommon::getCurrentOps( const boost::intrusive_ptr<ExpressionContext>& expCtx, CurrentOpConnectionsMode connMode, CurrentOpSessionsMode sessionMode, CurrentOpUserMode userMode, CurrentOpTruncateMode truncateMode, CurrentOpCursorMode cursorMode) const { OperationContext* opCtx = expCtx->opCtx; AuthorizationSession* ctxAuth = AuthorizationSession::get(opCtx->getClient()); std::vector<BSONObj> ops; for (ServiceContext::LockedClientsCursor cursor(opCtx->getClient()->getServiceContext()); Client* client = cursor.next();) { invariant(client); stdx::lock_guard<Client> lk(*client); // If auth is disabled, ignore the allUsers parameter. if (ctxAuth->getAuthorizationManager().isAuthEnabled() && userMode == CurrentOpUserMode::kExcludeOthers && !ctxAuth->isCoauthorizedWithClient(client)) { continue; } // Ignore inactive connections unless 'idleConnections' is true. if (!client->getOperationContext() && connMode == CurrentOpConnectionsMode::kExcludeIdle) { continue; } // Delegate to the mongoD- or mongoS-specific implementation of _reportCurrentOpForClient. ops.emplace_back(_reportCurrentOpForClient(opCtx, client, truncateMode)); } // If 'cursorMode' is set to include idle cursors, retrieve them and add them to ops. if (cursorMode == CurrentOpCursorMode::kIncludeCursors) { for (auto&& cursor : getIdleCursors(expCtx, userMode)) { BSONObjBuilder cursorObj; auto ns = cursor.getNs(); auto lsid = cursor.getLsid(); cursorObj.append("type", "idleCursor"); cursorObj.append("host", getHostNameCached()); cursorObj.append("ns", ns->toString()); // If in legacy read mode, lsid is not present. if (lsid) { cursorObj.append("lsid", lsid->toBSON()); } cursor.setNs(boost::none); cursor.setLsid(boost::none); // On mongos, planSummary is not present. auto planSummaryData = cursor.getPlanSummary(); if (planSummaryData) { auto planSummaryText = planSummaryData->toString(); // Plan summary has to appear in the top level object, not the cursor object. // We remove it, create the op, then put it back. cursor.setPlanSummary(boost::none); cursorObj.append("planSummary", planSummaryText); cursorObj.append("cursor", cursor.toBSON()); cursor.setPlanSummary(StringData(planSummaryText)); } else { cursorObj.append("cursor", cursor.toBSON()); } ops.emplace_back(cursorObj.obj()); cursor.setNs(ns); cursor.setLsid(lsid); } } // If we need to report on idle Sessions, defer to the mongoD or mongoS implementations. if (sessionMode == CurrentOpSessionsMode::kIncludeIdle) { _reportCurrentOpsForIdleSessions(opCtx, userMode, &ops); } return ops; }