From 14d3b48316f6e2ed075d01c3a9e7dcb28c0f2b63 Mon Sep 17 00:00:00 2001 From: Benety Goh Date: Thu, 16 Apr 2015 17:32:06 -0400 Subject: SERVER-17817 SERVER-17894 Make Top a decoration on ServiceContext --- src/mongo/SConscript | 4 +- src/mongo/db/catalog/database.cpp | 4 +- src/mongo/db/commands/top_command.cpp | 91 +++++++++++++++++++++++++++++++++++ src/mongo/db/curop.cpp | 4 +- src/mongo/db/stats/SConscript | 23 +++++++++ src/mongo/db/stats/snapshots.cpp | 3 +- src/mongo/db/stats/top.cpp | 52 +++++--------------- src/mongo/db/stats/top.h | 7 +-- src/mongo/db/stats/top_test.cpp | 42 ++++++++++++++++ 9 files changed, 183 insertions(+), 47 deletions(-) create mode 100644 src/mongo/db/commands/top_command.cpp create mode 100644 src/mongo/db/stats/SConscript create mode 100644 src/mongo/db/stats/top_test.cpp (limited to 'src') diff --git a/src/mongo/SConscript b/src/mongo/SConscript index b1b78db43c3..ba060fad16a 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -38,6 +38,7 @@ env.SConscript(['base/SConscript', 'db/query/SConscript', 'db/repl/SConscript', 'db/sorter/SConscript', + 'db/stats/SConscript', 'db/storage/SConscript', 'db/storage/devnull/SConscript', 'db/storage/in_memory/SConscript', @@ -759,6 +760,7 @@ serverOnlyFiles = [ "db/background.cpp", "db/commands/rename_collection.cpp", "db/commands/repair_cursor.cpp", "db/commands/test_commands.cpp", + 'db/commands/top_command.cpp', "db/commands/touch.cpp", "db/commands/validate.cpp", "db/commands/write_commands/batch_executor.cpp", @@ -819,7 +821,6 @@ serverOnlyFiles = [ "db/background.cpp", "db/stats/lock_server_status_section.cpp", "db/stats/range_deleter_server_status.cpp", "db/stats/snapshots.cpp", - "db/stats/top.cpp", "db/storage/storage_init.cpp", "db/storage_options.cpp", "db/ttl.cpp", @@ -1067,6 +1068,7 @@ serveronlyLibdeps = ["coreshard", "db/repl/replication_executor", "db/repl/rslog", 'db/startup_warnings_mongod', + 'db/stats/top', 'db/storage/devnull/storage_devnull', 'db/storage/in_memory/storage_in_memory', 'db/storage/mmap_v1/storage_mmapv1', diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp index 52902be6161..49727f6f709 100644 --- a/src/mongo/db/catalog/database.cpp +++ b/src/mongo/db/catalog/database.cpp @@ -392,7 +392,7 @@ namespace mongo { verify( collection->_details->getTotalIndexCount( txn ) == 0 ); LOG(1) << "\t dropIndexes done" << endl; - Top::global.collectionDropped( fullns ); + Top::get(txn->getClient()->getServiceContext()).collectionDropped(fullns); s = _dbEntry->dropCollection( txn, fullns ); @@ -466,7 +466,7 @@ namespace mongo { _clearCollectionCache( txn, fromNS ); _clearCollectionCache( txn, toNS ); - Top::global.collectionDropped( fromNS.toString() ); + Top::get(txn->getClient()->getServiceContext()).collectionDropped(fromNS.toString()); } txn->recoveryUnit()->registerChange( new AddCollectionChange(this, toNS) ); diff --git a/src/mongo/db/commands/top_command.cpp b/src/mongo/db/commands/top_command.cpp new file mode 100644 index 00000000000..3328c286fd0 --- /dev/null +++ b/src/mongo/db/commands/top_command.cpp @@ -0,0 +1,91 @@ +/* + * 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 . + * + * 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/platform/basic.h" + +#include "mongo/base/init.h" +#include "mongo/db/auth/action_set.h" +#include "mongo/db/auth/action_type.h" +#include "mongo/db/auth/privilege.h" +#include "mongo/db/client.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/stats/top.h" +#include "mongo/db/commands.h" + +namespace { + + using namespace mongo; + + class TopCommand : public Command { + public: + TopCommand() : Command("top", true) {} + + virtual bool slaveOk() const { return true; } + virtual bool adminOnly() const { return true; } + virtual bool isWriteCommandForConfigServer() const { return false; } + virtual void help(std::stringstream& help) const { + help << "usage by collection, in micros "; + } + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector* out) { + ActionSet actions; + actions.addAction(ActionType::top); + out->push_back(Privilege(ResourcePattern::forClusterResource(), actions)); + } + virtual bool run(OperationContext* txn, + const std::string& db, + BSONObj& cmdObj, + int options, + std::string& errmsg, + BSONObjBuilder& result) { + { + BSONObjBuilder b( result.subobjStart( "totals" ) ); + b.append( "note", "all times in microseconds" ); + Top::get(txn->getClient()->getServiceContext()).append(b); + b.done(); + } + return true; + } + + }; + + // + // Command instance. + // Registers command with the command system and make command + // available to the client. + // + + MONGO_INITIALIZER(RegisterTopCommand)(InitializerContext* context) { + + new TopCommand(); + + return Status::OK(); + } +} // namespace diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index 46b4e336cbf..06c86a71941 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -39,6 +39,7 @@ #include "mongo/db/commands.h" #include "mongo/db/commands/server_status_metric.h" #include "mongo/db/json.h" +#include "mongo/db/service_context.h" #include "mongo/db/stats/top.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" @@ -244,7 +245,8 @@ namespace mongo { void CurOp::recordGlobalTime(bool isWriteLocked, long long micros) const { string nsStr = _ns.toString(); - Top::global.record(nsStr, _op, isWriteLocked ? 1 : -1, micros, _isCommand); + int lockType = isWriteLocked ? 1 : -1; + Top::get(getGlobalServiceContext()).record(nsStr, _op, lockType, micros, _isCommand); } void CurOp::reportState(BSONObjBuilder* builder) { diff --git a/src/mongo/db/stats/SConscript b/src/mongo/db/stats/SConscript new file mode 100644 index 00000000000..2aa132e7d48 --- /dev/null +++ b/src/mongo/db/stats/SConscript @@ -0,0 +1,23 @@ +# -*- mode: python -*- + +Import("env") + +env.Library( + target='top', + source=[ + 'top.cpp', + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/service_context', + ], +) + +env.CppUnitTest( + target='top_test', + source=[ + 'top_test.cpp', + ], + LIBDEPS=[ + 'top', + ], +) diff --git a/src/mongo/db/stats/snapshots.cpp b/src/mongo/db/stats/snapshots.cpp index 2e2d2f9398f..555c93917f0 100644 --- a/src/mongo/db/stats/snapshots.cpp +++ b/src/mongo/db/stats/snapshots.cpp @@ -36,6 +36,7 @@ #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" +#include "mongo/db/service_context.h" #include "mongo/util/exit.h" #include "mongo/util/log.h" @@ -49,7 +50,7 @@ namespace mongo { void SnapshotData::takeSnapshot() { _created = curTimeMicros64(); - Top::global.cloneMap(_usage); + Top::get(getGlobalServiceContext()).cloneMap(_usage); } SnapshotDelta::SnapshotDelta( const SnapshotData& older , const SnapshotData& newer ) diff --git a/src/mongo/db/stats/top.cpp b/src/mongo/db/stats/top.cpp index 01bc0ab3da8..dd40f8f702a 100644 --- a/src/mongo/db/stats/top.cpp +++ b/src/mongo/db/stats/top.cpp @@ -33,13 +33,10 @@ #include "mongo/db/stats/top.h" -#include "mongo/db/auth/action_set.h" -#include "mongo/db/auth/action_type.h" -#include "mongo/db/auth/authorization_manager.h" -#include "mongo/db/auth/privilege.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/service_context.h" #include "mongo/util/log.h" #include "mongo/util/net/message.h" -#include "mongo/db/commands.h" namespace mongo { @@ -48,6 +45,12 @@ namespace mongo { using std::stringstream; using std::vector; +namespace { + + const auto getTop = ServiceContext::declareDecoration(); + +} // namespace + Top::UsageData::UsageData( const UsageData& older, const UsageData& newer ) { // this won't be 100% accurate on rollovers and drop(), but at least it won't be negative time = (newer.time >= older.time) ? (newer.time - older.time) : newer.time; @@ -67,6 +70,11 @@ namespace mongo { } + // static + Top& Top::get(ServiceContext* service) { + return getTop(service); + } + void Top::record( StringData ns, int op, int lockType, long long micros, bool command ) { if ( ns[0] == '?' ) return; @@ -179,38 +187,4 @@ namespace mongo { bb.done(); } - class TopCmd : public Command { - public: - TopCmd() : Command( "top", true ) {} - - virtual bool slaveOk() const { return true; } - virtual bool adminOnly() const { return true; } - virtual bool isWriteCommandForConfigServer() const { return false; } - virtual void help( stringstream& help ) const { help << "usage by collection, in micros "; } - virtual void addRequiredPrivileges(const std::string& dbname, - const BSONObj& cmdObj, - std::vector* out) { - ActionSet actions; - actions.addAction(ActionType::top); - out->push_back(Privilege(ResourcePattern::forClusterResource(), actions)); - } - virtual bool run(OperationContext* txn, - const string&, - BSONObj& cmdObj, - int, - string& errmsg, - BSONObjBuilder& result) { - { - BSONObjBuilder b( result.subobjStart( "totals" ) ); - b.append( "note", "all times in microseconds" ); - Top::global.append( b ); - b.done(); - } - return true; - } - - } topCmd; - - Top Top::global; - } diff --git a/src/mongo/db/stats/top.h b/src/mongo/db/stats/top.h index e52c6a735c4..8d5c4919f03 100644 --- a/src/mongo/db/stats/top.h +++ b/src/mongo/db/stats/top.h @@ -36,12 +36,16 @@ namespace mongo { + class ServiceContext; + /** * tracks usage by collection */ class Top { public: + static Top& get(ServiceContext* service); + Top() : _lock("Top") { } struct UsageData { @@ -84,9 +88,6 @@ namespace mongo { void cloneMap(UsageMap& out) const; void collectionDropped( StringData ns ); - public: // static stuff - static Top global; - private: void _appendToUsageMap( BSONObjBuilder& b, const UsageMap& map ) const; void _appendStatsEntry( BSONObjBuilder& b, const char * statsName, const UsageData& map ) const; diff --git a/src/mongo/db/stats/top_test.cpp b/src/mongo/db/stats/top_test.cpp new file mode 100644 index 00000000000..8aa5bc6363d --- /dev/null +++ b/src/mongo/db/stats/top_test.cpp @@ -0,0 +1,42 @@ +/** + * 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 . + * + * 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/platform/basic.h" + +#include "mongo/db/stats/top.h" +#include "mongo/unittest/unittest.h" + +namespace { + + using namespace mongo; + + TEST(TopTest, CollectionDropped) { + Top().collectionDropped("coll"); + } + +} // namespace -- cgit v1.2.1