Exemplo n.º 1
0
    bool run(OperationContext* txn,
             const std::string& db,
             BSONObj& cmdObj,
             int options,
             std::string& errmsg,
             BSONObjBuilder& result) final {
        const bool includeAll = cmdObj["$all"].trueValue();
        const bool ownOpsOnly = cmdObj["$ownOps"].trueValue();

        // Filter the output
        BSONObj filter;
        {
            BSONObjBuilder b;
            BSONObjIterator i(cmdObj);
            invariant(i.more());
            i.next();  // skip {currentOp: 1} which is required to be the first element
            while (i.more()) {
                BSONElement e = i.next();
                if (str::equals("$all", e.fieldName())) {
                    continue;
                } else if (str::equals("$ownOps", e.fieldName())) {
                    continue;
                }

                b.append(e);
            }
            filter = b.obj();
        }

        // We use ExtensionsCallbackReal here instead of ExtensionsCallbackNoop in order to support
        // the use case of having a $where filter with currentOp. However, since we don't have a
        // collection, we pass in a fake collection name (and this is okay, because $where parsing
        // only relies on the database part of the namespace).
        const NamespaceString fakeNS(db, "$cmd");
        const CollatorInterface* collator = nullptr;
        const Matcher matcher(filter, ExtensionsCallbackReal(txn, &fakeNS), collator);

        BSONArrayBuilder inprogBuilder(result.subarrayStart("inprog"));

        for (ServiceContext::LockedClientsCursor cursor(txn->getClient()->getServiceContext());
             Client* client = cursor.next();) {
            invariant(client);

            stdx::lock_guard<Client> lk(*client);

            if (ownOpsOnly &&
                !AuthorizationSession::get(txn->getClient())->isCoauthorizedWithClient(client)) {
                continue;
            }

            const OperationContext* opCtx = client->getOperationContext();

            if (!includeAll) {
                // Skip over inactive connections.
                if (!opCtx)
                    continue;
            }

            BSONObjBuilder infoBuilder;

            // The client information
            client->reportState(infoBuilder);

            // Operation context specific information
            infoBuilder.appendBool("active", static_cast<bool>(opCtx));
            if (opCtx) {
                infoBuilder.append("opid", opCtx->getOpID());
                if (opCtx->isKillPending()) {
                    infoBuilder.append("killPending", true);
                }

                CurOp::get(opCtx)->reportState(&infoBuilder);

                // LockState
                Locker::LockerInfo lockerInfo;
                opCtx->lockState()->getLockerInfo(&lockerInfo);
                fillLockerInfo(lockerInfo, infoBuilder);
            }

            infoBuilder.done();

            const BSONObj info = infoBuilder.obj();

            if (includeAll || matcher.matches(info)) {
                inprogBuilder.append(info);
            }
        }

        inprogBuilder.done();

        if (lockedForWriting()) {
            result.append("fsyncLock", true);
            result.append("info",
                          "use db.fsyncUnlock() to terminate the fsync write/snapshot lock");
        }

        return true;
    }
Exemplo n.º 2
0
    bool run(OperationContext* txn,
             const std::string& db,
             BSONObj& cmdObj,
             int options,
             std::string& errmsg,
             BSONObjBuilder& result) final {
        const bool includeAll = cmdObj["$all"].trueValue();
        const bool ownOpsOnly = cmdObj["$ownOps"].trueValue();

        // Filter the output
        BSONObj filter;
        {
            BSONObjBuilder b;
            BSONObjIterator i(cmdObj);
            invariant(i.more());
            i.next();  // skip {currentOp: 1} which is required to be the first element
            while (i.more()) {
                BSONElement e = i.next();
                if (str::equals("$all", e.fieldName())) {
                    continue;
                } else if (str::equals("$ownOps", e.fieldName())) {
                    continue;
                }

                b.append(e);
            }
            filter = b.obj();
        }

        std::vector<BSONObj> inprogInfos;
        BSONArrayBuilder inprogBuilder(result.subarrayStart("inprog"));

        for (ServiceContext::LockedClientsCursor cursor(txn->getClient()->getServiceContext());
             Client* client = cursor.next();) {
            invariant(client);

            stdx::lock_guard<Client> lk(*client);

            if (ownOpsOnly &&
                !AuthorizationSession::get(txn->getClient())->isCoauthorizedWithClient(client)) {
                continue;
            }

            const OperationContext* opCtx = client->getOperationContext();

            if (!includeAll) {
                // Skip over inactive connections.
                if (!opCtx)
                    continue;
            }

            BSONObjBuilder infoBuilder;

            // The client information
            client->reportState(infoBuilder);

            const auto& clientMetadata =
                ClientMetadataIsMasterState::get(client).getClientMetadata();
            if (clientMetadata) {
                auto appName = clientMetadata.get().getApplicationName();
                if (!appName.empty()) {
                    infoBuilder.append("appName", appName);
                }
            }

            // Operation context specific information
            infoBuilder.appendBool("active", static_cast<bool>(opCtx));
            if (opCtx) {
                infoBuilder.append("opid", opCtx->getOpID());
                if (opCtx->isKillPending()) {
                    infoBuilder.append("killPending", true);
                }

                CurOp::get(opCtx)->reportState(&infoBuilder);

                // LockState
                Locker::LockerInfo lockerInfo;
                opCtx->lockState()->getLockerInfo(&lockerInfo);
                fillLockerInfo(lockerInfo, infoBuilder);
            }

            // If we want to include all results or if the filter is empty, then we can append
            // straight to the inprogBuilder, but otherwise we should run the filter Matcher
            // outside this loop so we don't lock the ServiceContext while matching - in some cases
            // this can cause deadlocks.
            if (includeAll || filter.isEmpty()) {
                inprogBuilder.append(infoBuilder.obj());
            } else {
                inprogInfos.emplace_back(infoBuilder.obj());
            }
        }

        if (!inprogInfos.empty()) {
            // We use ExtensionsCallbackReal here instead of ExtensionsCallbackNoop in order to
            // support the use case of having a $where filter with currentOp. However, since we
            // don't have a collection, we pass in a fake collection name (and this is okay,
            // because $where parsing only relies on the database part of the namespace).
            const NamespaceString fakeNS(db, "$dummyNamespaceForCurrop");
            const Matcher matcher(filter, ExtensionsCallbackReal(txn, &fakeNS), nullptr);

            for (const auto& info : inprogInfos) {
                if (matcher.matches(info)) {
                    inprogBuilder.append(info);
                }
            }
        }
        inprogBuilder.done();

        if (lockedForWriting()) {
            result.append("fsyncLock", true);
            result.append("info",
                          "use db.fsyncUnlock() to terminate the fsync write/snapshot lock");
        }

        return true;
    }
Exemplo n.º 3
0
        bool run(OperationContext* txn,
                 const std::string& db,
                 BSONObj& cmdObj,
                 int options,
                 std::string& errmsg,
                 BSONObjBuilder& result) final {

            const bool includeAll = cmdObj["$all"].trueValue();

            // Filter the output
            BSONObj filter;
            {
                BSONObjBuilder b;
                BSONObjIterator i(cmdObj);
                invariant(i.more());
                i.next(); // skip {currentOp: 1} which is required to be the first element
                while (i.more()) {
                    BSONElement e = i.next();
                    if (str::equals("$all", e.fieldName())) {
                        continue;
                    }

                    b.append(e);
                }
                filter = b.obj();
            }

            const WhereCallbackReal whereCallback(txn, db);
            const Matcher matcher(filter, whereCallback);

            BSONArrayBuilder inprogBuilder(result.subarrayStart("inprog"));

            for (ServiceContext::LockedClientsCursor cursor(txn->getClient()->getServiceContext());
                 Client* client = cursor.next();) {

                invariant(client);

                stdx::lock_guard<Client> lk(*client);
                const OperationContext* opCtx = client->getOperationContext();

                if (!includeAll) {
                    // Skip over inactive connections.
                    if (!opCtx)
                        continue;
                }

                BSONObjBuilder infoBuilder;

                // The client information
                client->reportState(infoBuilder);

                // Operation context specific information
                infoBuilder.appendBool("active", static_cast<bool>(opCtx));
                if (opCtx) {
                    infoBuilder.append("opid", opCtx->getOpID());
                    if (opCtx->isKillPending()) {
                        infoBuilder.append("killPending", true);
                    }

                    CurOp::get(opCtx)->reportState(&infoBuilder);

                    // LockState
                    Locker::LockerInfo lockerInfo;
                    opCtx->lockState()->getLockerInfo(&lockerInfo);
                    fillLockerInfo(lockerInfo, infoBuilder);
                }

                infoBuilder.done();

                const BSONObj info = infoBuilder.obj();

                if (includeAll || matcher.matches(info)) {
                    inprogBuilder.append(info);
                }
            }

            inprogBuilder.done();

            if (lockedForWriting()) {
                result.append("fsyncLock", true);
                result.append("info",
                              "use db.fsyncUnlock() to terminate the fsync write/snapshot lock");
            }

            return true;
        }