summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/clientlistplugin.cpp6
-rw-r--r--src/mongo/db/commands/current_op.cpp166
-rw-r--r--src/mongo/db/currentop_command.cpp185
-rw-r--r--src/mongo/db/instance.cpp11
-rw-r--r--src/mongo/db/stats/fill_locker_info.cpp62
-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