diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/clientlistplugin.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/commands/current_op.cpp | 166 | ||||
-rw-r--r-- | src/mongo/db/currentop_command.cpp | 185 | ||||
-rw-r--r-- | src/mongo/db/instance.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/stats/fill_locker_info.cpp | 62 | ||||
-rw-r--r-- | src/mongo/db/stats/fill_locker_info.h (renamed from src/mongo/db/currentop_command.h) | 19 |
6 files changed, 242 insertions, 207 deletions
diff --git a/src/mongo/db/clientlistplugin.cpp b/src/mongo/db/clientlistplugin.cpp index 6f0a30efedc..4aa31d48bd7 100644 --- a/src/mongo/db/clientlistplugin.cpp +++ b/src/mongo/db/clientlistplugin.cpp @@ -37,11 +37,11 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/curop.h" -#include "mongo/db/currentop_command.h" -#include "mongo/db/service_context.h" +#include "mongo/db/dbwebserver.h" #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/operation_context.h" -#include "mongo/db/dbwebserver.h" +#include "mongo/db/service_context.h" +#include "mongo/db/stats/fill_locker_info.h" #include "mongo/util/mongoutils/html.h" #include "mongo/util/stringutils.h" diff --git a/src/mongo/db/commands/current_op.cpp b/src/mongo/db/commands/current_op.cpp new file mode 100644 index 00000000000..c4e9f49c799 --- /dev/null +++ b/src/mongo/db/commands/current_op.cpp @@ -0,0 +1,166 @@ +/** + * Copyright (C) 2015 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand + +#include "mongo/platform/basic.h" + +#include <string> + +#include "mongo/db/auth/action_type.h" +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/client.h" +#include "mongo/db/commands.h" +#include "mongo/db/commands/fsync.h" +#include "mongo/db/curop.h" +#include "mongo/db/dbmessage.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/matcher/matcher.h" +#include "mongo/db/namespace_string.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/stats/fill_locker_info.h" +#include "mongo/util/log.h" + +namespace mongo { + + class CurrentOpCommand : public Command { + public: + + CurrentOpCommand() : Command("currentOp") {} + + bool isWriteCommandForConfigServer() const final { return false; } + + bool slaveOk() const final { return true; } + + bool adminOnly() const final { return true; } + + Status checkAuthForCommand(ClientBasic* client, + const std::string& dbname, + const BSONObj& cmdObj) final { + + bool isAuthorized = client->getAuthorizationSession()->isAuthorizedForActionsOnResource( + ResourcePattern::forClusterResource(), + ActionType::inprog); + return isAuthorized ? Status::OK() : Status(ErrorCodes::Unauthorized, "Unauthorized"); + } + + bool run(OperationContext* txn, + const std::string& db, + BSONObj& cmdObj, + int options, + std::string& errmsg, + BSONObjBuilder& result, + bool fromRepl) 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")); + + boost::lock_guard<boost::mutex> scopedLock(Client::clientsMutex); + + ClientSet::const_iterator it = Client::clients.begin(); + for ( ; it != Client::clients.end(); it++) { + Client* client = *it; + invariant(client); + + boost::unique_lock<Client> uniqueLock(*client); + const OperationContext* opCtx = client->getOperationContext(); + + if (!includeAll) { + // Skip over inactive connections. + if (!opCtx || !opCtx->getCurOp() || !opCtx->getCurOp()->active()) { + continue; + } + } + + BSONObjBuilder infoBuilder; + + // The client information + client->reportState(infoBuilder); + + // Operation context specific information + if (opCtx) { + // CurOp + if (opCtx->getCurOp()) { + opCtx->getCurOp()->reportState(&infoBuilder); + } + + // LockState + Locker::LockerInfo lockerInfo; + client->getOperationContext()->lockState()->getLockerInfo(&lockerInfo); + fillLockerInfo(lockerInfo, infoBuilder); + } + else { + // If no operation context, mark the operation as inactive + infoBuilder.append("active", false); + } + + 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; + } + + } currentOpCommand; + +} // namespace mongo diff --git a/src/mongo/db/currentop_command.cpp b/src/mongo/db/currentop_command.cpp deleted file mode 100644 index 7ec8c8d3d80..00000000000 --- a/src/mongo/db/currentop_command.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Copyright (C) 2008-2014 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand - -#include "mongo/platform/basic.h" - -#include "mongo/db/currentop_command.h" - -#include "mongo/db/audit.h" -#include "mongo/db/auth/action_type.h" -#include "mongo/db/auth/authorization_session.h" -#include "mongo/bson/bsonobj.h" -#include "mongo/db/client.h" -#include "mongo/db/curop.h" -#include "mongo/db/commands/fsync.h" -#include "mongo/db/dbmessage.h" -#include "mongo/db/namespace_string.h" -#include "mongo/db/operation_context.h" -#include "mongo/db/matcher/matcher.h" -#include "mongo/util/log.h" - -namespace mongo { - - using std::stringstream; - - void inProgCmd(OperationContext* txn, - const NamespaceString& nss, - Message &message, - DbResponse &dbresponse) { - DbMessage d(message); - QueryMessage q(d); - - const bool isAuthorized = - txn->getClient()->getAuthorizationSession()->isAuthorizedForActionsOnResource( - ResourcePattern::forClusterResource(), - ActionType::inprog); - audit::logInProgAuthzCheck(txn->getClient(), - q.query, - isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized); - - BSONObjBuilder retVal; - - if (!isAuthorized) { - retVal.append("err", "unauthorized"); - replyToQuery(0, message, dbresponse, retVal.obj()); - return; - } - - const bool includeAll = q.query["$all"].trueValue(); - - // Filter the output - BSONObj filter; - { - BSONObjBuilder b; - BSONObjIterator i(q.query); - while (i.more()) { - BSONElement e = i.next(); - if (str::equals("$all", e.fieldName())) { - continue; - } - - b.append(e); - } - filter = b.obj(); - } - - const WhereCallbackReal whereCallback(txn, nss.db()); - const Matcher matcher(filter, whereCallback); - - BSONArrayBuilder inprogBuilder(retVal.subarrayStart("inprog")); - - boost::lock_guard<boost::mutex> scopedLock(Client::clientsMutex); - - ClientSet::const_iterator it = Client::clients.begin(); - for ( ; it != Client::clients.end(); it++) { - Client* client = *it; - invariant(client); - - boost::unique_lock<Client> uniqueLock(*client); - const OperationContext* opCtx = client->getOperationContext(); - - if (!includeAll) { - // Skip over inactive connections. - if (!opCtx || !opCtx->getCurOp() || !opCtx->getCurOp()->active()) { - continue; - } - } - - BSONObjBuilder infoBuilder; - - // The client information - client->reportState(infoBuilder); - - // Operation context specific information - if (opCtx) { - // CurOp - if (opCtx->getCurOp()) { - opCtx->getCurOp()->reportState(&infoBuilder); - } - - // LockState - Locker::LockerInfo lockerInfo; - client->getOperationContext()->lockState()->getLockerInfo(&lockerInfo); - fillLockerInfo(lockerInfo, infoBuilder); - } - else { - // If no operation context, mark the operation as inactive - infoBuilder.append("active", false); - } - - infoBuilder.done(); - - const BSONObj info = infoBuilder.obj(); - - if (includeAll || matcher.matches(info)) { - inprogBuilder.append(info); - } - } - - inprogBuilder.done(); - - if (lockedForWriting()) { - retVal.append("fsyncLock", true); - retVal.append("info", - "use db.fsyncUnlock() to terminate the fsync write/snapshot lock"); - } - - replyToQuery(0, message, dbresponse, retVal.obj()); - } - - - void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder) { - // "locks" section - BSONObjBuilder locks(infoBuilder.subobjStart("locks")); - for (size_t i = 0; i < lockerInfo.locks.size(); i++) { - const Locker::OneLock& lock = lockerInfo.locks[i]; - - if (resourceIdLocalDB == lock.resourceId) { - locks.append("local", legacyModeName(lock.mode)); - } - else { - locks.append( - resourceTypeName(lock.resourceId.getType()), legacyModeName(lock.mode)); - } - } - locks.done(); - - // "waitingForLock" section - infoBuilder.append("waitingForLock", lockerInfo.waitingResource.isValid()); - - // "lockStats" section - { - BSONObjBuilder lockStats(infoBuilder.subobjStart("lockStats")); - lockerInfo.stats.report(&lockStats); - lockStats.done(); - } - } - -} // namespace mongo diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index 94736779cfe..96748d818e9 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -50,7 +50,6 @@ #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/concurrency/lock_state.h" #include "mongo/db/concurrency/write_conflict_exception.h" -#include "mongo/db/currentop_command.h" #include "mongo/db/db.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" @@ -391,11 +390,19 @@ namespace { isCommand = true; opwrite(m); } + // TODO: remove this entire code path after 3.2. Refs SERVER-7775 else if (nsString.isSpecialCommand()) { opwrite(m); if (nsString.coll() == "$cmd.sys.inprog") { - inProgCmd(txn, nsString, m, dbresponse); + // HACK: + // legacy inprog could run on any database. The currentOp command + // can only run on 'admin'. To avoid breaking old shells and a multitude + // of third-party tools, we rewrite the namespace. As auth is checked + // later in Command::_checkAuthorizationImpl, we will still properly + // reject the request if the client is not authorized. + NamespaceString adminKludge("admin", nsString.coll()); + receivedPseudoCommand(txn, adminKludge, c, dbresponse, m, "currentOp"); return; } if (nsString.coll() == "$cmd.sys.killop") { diff --git a/src/mongo/db/stats/fill_locker_info.cpp b/src/mongo/db/stats/fill_locker_info.cpp new file mode 100644 index 00000000000..1bdcb2762f1 --- /dev/null +++ b/src/mongo/db/stats/fill_locker_info.cpp @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2015 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/concurrency/locker.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/stats/fill_locker_info.h" + +namespace mongo { + + void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder) { + // "locks" section + BSONObjBuilder locks(infoBuilder.subobjStart("locks")); + for (size_t i = 0; i < lockerInfo.locks.size(); i++) { + const Locker::OneLock& lock = lockerInfo.locks[i]; + + if (resourceIdLocalDB == lock.resourceId) { + locks.append("local", legacyModeName(lock.mode)); + } + else { + locks.append(resourceTypeName(lock.resourceId.getType()), + legacyModeName(lock.mode)); + } + } + locks.done(); + + // "waitingForLock" section + infoBuilder.append("waitingForLock", lockerInfo.waitingResource.isValid()); + + // "lockStats" section + { + BSONObjBuilder lockStats(infoBuilder.subobjStart("lockStats")); + lockerInfo.stats.report(&lockStats); + lockStats.done(); + } + } + +} // namespace mongo diff --git a/src/mongo/db/currentop_command.h b/src/mongo/db/stats/fill_locker_info.h index 8aa892522c5..b4743764e25 100644 --- a/src/mongo/db/currentop_command.h +++ b/src/mongo/db/stats/fill_locker_info.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 MongoDB Inc. + * Copyright (C) 2015 MongoDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, @@ -32,24 +32,9 @@ namespace mongo { - class BSONObjBuilder; - struct DbResponse; - class Message; - class NamespaceString; - class OperationContext; - - /** - * Executes the db.currentOp() command. Currently not an actual "command" object, but should - * be converted to one at some point. - */ - void inProgCmd(OperationContext* txn, - const NamespaceString& nss, - Message &m, - DbResponse &dbresponse); - /** * Constructs a human-readable BSON from the specified LockerInfo structure. */ void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder); -} // namespace mongo +} // namespace mongo |