diff options
author | Spencer T Brody <spencer@mongodb.com> | 2015-04-28 17:41:48 -0400 |
---|---|---|
committer | Spencer T Brody <spencer@mongodb.com> | 2015-05-14 17:13:59 -0400 |
commit | 4e5f3dd2ee37b118f9bfa5fb49adaa5a6b994cca (patch) | |
tree | 6209b86cf8b65693947e3d7a18392c7de3f92198 | |
parent | b1140e1d7f3ed75161f9220581ce8475ce2ca2d3 (diff) | |
download | mongo-4e5f3dd2ee37b118f9bfa5fb49adaa5a6b994cca.tar.gz |
SERVER-18117 Add replset view back to http interface
-rw-r--r-- | src/mongo/SConscript | 5 | ||||
-rw-r--r-- | src/mongo/db/dbwebserver.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_html_summary.cpp | 221 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_html_summary.h | 101 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator.h | 7 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.h | 5 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_mock.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_mock.h | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/replset_web_handler.cpp | 96 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator.h | 9 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_impl.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_impl.h | 1 |
14 files changed, 486 insertions, 5 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index e0ac7b1c914..c3b18c27e06 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -1037,10 +1037,13 @@ env.Library("mongodandmongos", mongodAndMongosFiles, env.Library("mongodwebserver", [ "db/clientlistplugin.cpp", + "db/repl/replset_web_handler.cpp", "db/restapi.cpp", "db/stats/snapshots_webplugins.cpp", ], - LIBDEPS=["coredb", "mongodandmongos"]) + LIBDEPS=["coredb", + "mongodandmongos", + "$BUILD_DIR/mongo/db/repl/repl_coordinator_global"]) mongodOnlyFiles = [ "db/db.cpp", "db/mongod_options_init.cpp" ] diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp index 6c71a4f8cd5..92d7a3d9959 100644 --- a/src/mongo/db/dbwebserver.cpp +++ b/src/mongo/db/dbwebserver.cpp @@ -376,7 +376,8 @@ namespace { } ss << start(dbname) << h2(dbname); - ss << "<p><a href=\"/_commands\">List all commands</a></p>\n"; + ss << "<p><a href=\"/_commands\">List all commands</a> | \n"; + ss << "<a href=\"/_replSet\">Replica set status</a></p>\n"; { const Command::CommandMap* m = Command::webCommands(); diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index f016b18a92c..c0ec7f1a6c1 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -178,6 +178,7 @@ env.Library('replica_set_messages', 'member_config.cpp', 'repl_set_heartbeat_args.cpp', 'repl_set_heartbeat_response.cpp', + 'repl_set_html_summary.cpp', 'replica_set_config.cpp', 'replica_set_tag.cpp', 'update_position_args.cpp', diff --git a/src/mongo/db/repl/repl_set_html_summary.cpp b/src/mongo/db/repl/repl_set_html_summary.cpp new file mode 100644 index 00000000000..465bfdeb95e --- /dev/null +++ b/src/mongo/db/repl/repl_set_html_summary.cpp @@ -0,0 +1,221 @@ +/** + * 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::kReplication + +#include "mongo/platform/basic.h" + +#include "mongo/db/repl/repl_set_html_summary.h" + +#include <string> +#include <sstream> + +#include "mongo/util/mongoutils/html.h" +#include "mongo/util/mongoutils/str.h" + + +namespace mongo { +namespace repl { + + ReplSetHtmlSummary::ReplSetHtmlSummary() : _selfIndex(-1), _primaryIndex(-1), _selfUptime(0) {} + +namespace { + + /** + * Turns an unsigned int representing a duration of time in milliseconds and turns it into + * a human readable time string representation. + */ + std::string ago(unsigned int duration) { + std::stringstream s; + if( duration < 180 ) { + s << duration << " sec"; + if( duration != 1 ) s << 's'; + } + else if( duration < 3600 ) { + s.precision(2); + s << duration / 60.0 << " mins"; + } + else { + s.precision(2); + s << duration / 3600.0 << " hrs"; + } + return s.str(); + } + + unsigned int timeDifference(Date_t now, Date_t past) { + return static_cast<unsigned int> ((past ? + (now - past) / 1000 /* convert millis to secs */ : 0)); + } + + std::string stateAsHtml(const MemberState& s) { + using namespace html; + + if( s.s == MemberState::RS_STARTUP ) + return a("", + "server still starting up, or still trying to initiate the set", + "STARTUP"); + if( s.s == MemberState::RS_PRIMARY ) + return a("", "this server thinks it is primary", "PRIMARY"); + if( s.s == MemberState::RS_SECONDARY ) + return a("", "this server thinks it is a secondary (slave mode)", "SECONDARY"); + if( s.s == MemberState::RS_RECOVERING ) + return a("", + "recovering/resyncing; after recovery usually auto-transitions to secondary", + "RECOVERING"); + if( s.s == MemberState::RS_STARTUP2 ) + return a("", "loaded config, still determining who is primary", "STARTUP2"); + if( s.s == MemberState::RS_ARBITER ) + return a("", "this server is an arbiter only", "ARBITER"); + if( s.s == MemberState::RS_DOWN ) + return a("", "member is down, slow, or unreachable", "DOWN"); + if( s.s == MemberState::RS_ROLLBACK ) + return a("", "rolling back operations to get in sync", "ROLLBACK"); + if( s.s == MemberState::RS_UNKNOWN) + return a("", "we do not know what state this node is in", "UNKNOWN"); + if( s.s == MemberState::RS_REMOVED) + return a("", "this server has been removed from the replica set config", "ROLLBACK"); + return ""; + } +} + + const std::string ReplSetHtmlSummary::toHtmlString() const { + using namespace html; + + std::stringstream s; + + if (!_config.isInitialized()) { + s << p("Still starting up, or else replset is not yet initiated."); + return s.str(); + } + if (_selfIndex < 0) { + s << p("This node is not a member of its replica set configuration, it most likely was" + " removed recently"); + return s.str(); + } + + int votesUp = 0; + int totalVotes = 0; + // Build table of node information. + std::stringstream memberTable; + const char *h[] = + {"Member", + "<a title=\"member id in the replset config\">id</a>", + "Up", + "<a title=\"length of time we have been continuously connected to the other member " + "with no reconnects (for self, shows uptime)\">cctime</a>", + "<a title=\"when this server last received a heartbeat response - includes error code " + "responses\">Last heartbeat</a>", + "Votes", + "Priority", + "State", + "Messages", + "<a title=\"how up to date this server is. this value polled every few seconds so " + "actually lag is typically lower than value shown here.\">optime</a>", + 0 + }; + memberTable << table(h); + + for (int i = 0; i < _config.getNumMembers(); ++i) { + const MemberConfig& memberConfig = _config.getMemberAt(i); + const MemberHeartbeatData& memberHB = _hbData[i]; + bool isSelf = _selfIndex == i; + bool up = memberHB.getHealth() > 0; + + totalVotes += memberConfig.getNumVotes(); + if (up || isSelf) { + votesUp += memberConfig.getNumVotes(); + } + + memberTable << tr(); + if (isSelf) { + memberTable << td(memberConfig.getHostAndPort().toString() + " (me)"); + memberTable << td(memberConfig.getId()); + memberTable << td("1"); // up + memberTable << td(ago(_selfUptime)); + memberTable << td(""); // last heartbeat + memberTable << td(std::to_string(memberConfig.getNumVotes())); + memberTable << td(std::to_string(memberConfig.getPriority())); + memberTable << td(stateAsHtml(_selfState) + + (memberConfig.isHidden() ? " (hidden)" : "")); + memberTable << td(_selfHeartbeatMessage); + memberTable << td(_selfOptime.toString()); + } + else { + std::stringstream link; + link << "http://" << memberConfig.getHostAndPort().host() << ':' << + (memberConfig.getHostAndPort().port() + 1000) << "/_replSet"; + memberTable << td( a(link.str(), "", memberConfig.getHostAndPort().toString()) ); + memberTable << td(memberConfig.getId()); + memberTable << td(red(str::stream() << memberHB.getHealth(), !up)); + const unsigned int uptime = timeDifference(_now, memberHB.getUpSince()); + memberTable << td(ago(uptime)); + if (memberHB.getLastHeartbeat() == 0) { + memberTable << td("never"); + } + else { + memberTable << td(ago(timeDifference(_now, memberHB.getLastHeartbeat()))); + } + memberTable << td(std::to_string(memberConfig.getNumVotes())); + memberTable << td(std::to_string(memberConfig.getPriority())); + std::string state = memberHB.getState().toString() + + (memberConfig.isHidden() ? " (hidden)" : ""); + if (up) { + memberTable << td(state); + } + else { + memberTable << td( grey(str::stream() << "(was " << state << ')', true) ); + } + memberTable << td(grey(memberHB.getLastHeartbeatMsg(), !up)); + memberTable << td(memberHB.getLastHeartbeat() == 0 ? + "?" : memberHB.getOpTime().toString()); + } + memberTable << _tr(); + } + memberTable << _table(); + + s << table(0, false); + s << tr("Set name:", _config.getReplSetName()); + bool majorityUp = votesUp * 2 > totalVotes; + s << tr("Majority up:", majorityUp ? "yes" : "no" ); + + const MemberConfig& selfConfig = _config.getMemberAt(_selfIndex); + + if (_primaryIndex >= 0 && _primaryIndex != _selfIndex && !selfConfig.isArbiter()) { + int lag = _hbData[_primaryIndex].getOpTime().getSecs() - _selfOptime.getSecs(); + s << tr("Lag: ", str::stream() << lag << " secs"); + } + + s << _table(); + + s << memberTable.str(); + + return s.str(); + } + +} // namespace repl +} // namespace mongo diff --git a/src/mongo/db/repl/repl_set_html_summary.h b/src/mongo/db/repl/repl_set_html_summary.h new file mode 100644 index 00000000000..278f1ca35b6 --- /dev/null +++ b/src/mongo/db/repl/repl_set_html_summary.h @@ -0,0 +1,101 @@ +/** + * 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. + */ + +#pragma once + +#include <string> +#include <vector> + +#include "mongo/db/repl/member_heartbeat_data.h" +#include "mongo/db/repl/replica_set_config.h" + +namespace mongo { + +namespace repl { + + /** + * Class containing all the information needed to build the replSet page on http interface, + * and the logic to generate that page. + */ + class ReplSetHtmlSummary { + public: + ReplSetHtmlSummary(); + + const std::string toHtmlString() const; + + void setConfig(const ReplicaSetConfig& config) { + _config = config; + } + + void setHBData(const std::vector<MemberHeartbeatData>& hbData) { + _hbData = hbData; + } + + void setSelfIndex(int index) { + _selfIndex = index; + } + + void setPrimaryIndex(int index) { + _primaryIndex = index; + } + + void setSelfOptime(const OpTime& ts) { + _selfOptime = ts; + } + + void setSelfUptime(unsigned int time) { + _selfUptime = time; + } + + void setNow(Date_t now) { + _now = now; + } + + void setSelfState(const MemberState& state) { + _selfState = state; + } + + void setSelfHeartbeatMessage(StringData msg) { + _selfHeartbeatMessage = msg.toString(); + } + + private: + + ReplicaSetConfig _config; + std::vector<MemberHeartbeatData> _hbData; + Date_t _now; + int _selfIndex; + int _primaryIndex; + OpTime _selfOptime; + unsigned int _selfUptime; + MemberState _selfState; + std::string _selfHeartbeatMessage; + }; + +} // namespace repl +} // namespace mongo diff --git a/src/mongo/db/repl/replication_coordinator.h b/src/mongo/db/repl/replication_coordinator.h index 4efa58f02cb..e97a0635af5 100644 --- a/src/mongo/db/repl/replication_coordinator.h +++ b/src/mongo/db/repl/replication_coordinator.h @@ -55,6 +55,7 @@ namespace repl { class OplogReader; class ReplSetHeartbeatArgs; class ReplSetHeartbeatResponse; + class ReplSetHtmlSummary; class UpdatePositionArgs; /** @@ -551,6 +552,12 @@ namespace repl { */ virtual bool shouldChangeSyncSource(const HostAndPort& currentSource) = 0; + /** + * Writes into 'output' all the information needed to generate a summary of the current + * replication state for use by the web interface. + */ + virtual void summarizeAsHtml(ReplSetHtmlSummary* output) = 0; + protected: ReplicationCoordinator(); diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index ce6b7ea64b8..55b2be1e97e 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -47,6 +47,7 @@ #include "mongo/db/repl/is_master_response.h" #include "mongo/db/repl/repl_set_heartbeat_args.h" #include "mongo/db/repl/repl_set_heartbeat_response.h" +#include "mongo/db/repl/repl_set_html_summary.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/repl/replica_set_config_checks.h" #include "mongo/db/repl/replication_executor.h" @@ -2394,5 +2395,32 @@ namespace { return shouldChange; } + void ReplicationCoordinatorImpl::summarizeAsHtml(ReplSetHtmlSummary* output) { + CBHStatus cbh = _replExecutor.scheduleWork( + stdx::bind(&ReplicationCoordinatorImpl::_summarizeAsHtml_finish, + this, + stdx::placeholders::_1, + output)); + if (cbh.getStatus() == ErrorCodes::ShutdownInProgress) { + return; + } + fassert(28638, cbh.getStatus()); + _replExecutor.wait(cbh.getValue()); + } + + void ReplicationCoordinatorImpl::_summarizeAsHtml_finish( + const ReplicationExecutor::CallbackData& cbData, + ReplSetHtmlSummary* output) { + if (cbData.status == ErrorCodes::CallbackCanceled) { + return; + } + + output->setSelfOptime(getMyLastOptime()); + output->setSelfUptime(time(0) - serverGlobalParams.started); + output->setNow(_replExecutor.now()); + + _topCoord->summarizeAsHtml(output); + } + } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h index ce62a716d05..62fb61b5380 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.h +++ b/src/mongo/db/repl/replication_coordinator_impl.h @@ -225,6 +225,8 @@ namespace repl { virtual bool shouldChangeSyncSource(const HostAndPort& currentSource); + virtual void summarizeAsHtml(ReplSetHtmlSummary* s); + // ================== Test support API =================== /** @@ -744,6 +746,9 @@ namespace repl { ReplSetHeartbeatResponse* response, Status* outStatus); + void _summarizeAsHtml_finish(const ReplicationExecutor::CallbackData& cbData, + ReplSetHtmlSummary* output); + // // All member variables are labeled with one of the following codes indicating the // synchronization rules for accessing them. diff --git a/src/mongo/db/repl/replication_coordinator_mock.cpp b/src/mongo/db/repl/replication_coordinator_mock.cpp index 17a34d5b164..da3fb0e71d6 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.cpp +++ b/src/mongo/db/repl/replication_coordinator_mock.cpp @@ -293,5 +293,7 @@ namespace repl { invariant(false); } + void ReplicationCoordinatorMock::summarizeAsHtml(ReplSetHtmlSummary* output) {} + } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/replication_coordinator_mock.h b/src/mongo/db/repl/replication_coordinator_mock.h index 4c3f96e7169..daff00cec54 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.h +++ b/src/mongo/db/repl/replication_coordinator_mock.h @@ -180,6 +180,8 @@ namespace repl { virtual bool shouldChangeSyncSource(const HostAndPort& currentSource); + virtual void summarizeAsHtml(ReplSetHtmlSummary* output); + private: const ReplSettings _settings; diff --git a/src/mongo/db/repl/replset_web_handler.cpp b/src/mongo/db/repl/replset_web_handler.cpp new file mode 100644 index 00000000000..12fe6ab8bd0 --- /dev/null +++ b/src/mongo/db/repl/replset_web_handler.cpp @@ -0,0 +1,96 @@ +/** +* Copyright (C) 2015 10gen 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/platform/basic.h" + +#include <sstream> + +#include "mongo/db/dbwebserver.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/repl/replication_coordinator_global.h" +#include "mongo/db/repl/repl_set_html_summary.h" +#include "mongo/db/repl/rslog.h" +#include "mongo/util/mongoutils/html.h" +#include "mongo/util/mongoutils/str.h" + +namespace mongo { +namespace repl { + + using namespace html; + + class ReplSetHandler : public DbWebHandler { + public: + ReplSetHandler() : DbWebHandler( "_replSet" , 1 , false ) {} + + virtual bool handles( const std::string& url ) const { + return str::startsWith( url , "/_replSet" ); + } + + virtual void handle( OperationContext* txn, + const char *rq, + const std::string& url, + BSONObj params, + std::string& responseMsg, + int& responseCode, + std::vector<std::string>& headers, + const SockAddr &from ) { + responseMsg = _replSet(txn); + responseCode = 200; + } + + /* /_replSet show replica set status in html format */ + std::string _replSet(OperationContext* txn) { + std::stringstream s; + s << start("Replica Set Status " + prettyHostName()); + s << p( a("/", "back", "Home") + " | " + + a("/local/system.replset/?html=1", "", "View Replset Config") + " | " + + a("/replSetGetStatus?text=1", "", "replSetGetStatus") + " | " + + a("http://dochub.mongodb.org/core/replicasets", "", "Docs") + ); + + ReplicationCoordinator* replCoord = getGlobalReplicationCoordinator(); + if (replCoord->getReplicationMode() != ReplicationCoordinator::modeReplSet) { + s << p("Not using --replSet"); + s << _end(); + return s.str(); + } + + ReplSetHtmlSummary summary; + replCoord->summarizeAsHtml(&summary); + s << summary.toHtmlString(); + + s << p("Recent replset log activity:"); + fillRsLog(&s); + s << _end(); + return s.str(); + } + + } replSetHandler; + +} // namespace repl +} // namespace mongo diff --git a/src/mongo/db/repl/topology_coordinator.h b/src/mongo/db/repl/topology_coordinator.h index 1da4aa09642..97f85faf521 100644 --- a/src/mongo/db/repl/topology_coordinator.h +++ b/src/mongo/db/repl/topology_coordinator.h @@ -40,9 +40,6 @@ namespace mongo { - class OperationContext; - class OpTime; - namespace repl { class HeartbeatResponseAction; @@ -355,6 +352,12 @@ namespace repl { */ virtual void setMyHeartbeatMessage(const Date_t now, const std::string& s) = 0; + /** + * Writes into 'output' all the information needed to generate a summary of the current + * replication state for use by the web interface. + */ + virtual void summarizeAsHtml(ReplSetHtmlSummary* output) = 0; + protected: TopologyCoordinator() {} }; diff --git a/src/mongo/db/repl/topology_coordinator_impl.cpp b/src/mongo/db/repl/topology_coordinator_impl.cpp index 29bb3cab4d3..e777481203c 100644 --- a/src/mongo/db/repl/topology_coordinator_impl.cpp +++ b/src/mongo/db/repl/topology_coordinator_impl.cpp @@ -40,6 +40,7 @@ #include "mongo/db/repl/isself.h" #include "mongo/db/repl/repl_set_heartbeat_args.h" #include "mongo/db/repl/repl_set_heartbeat_response.h" +#include "mongo/db/repl/repl_set_html_summary.h" #include "mongo/db/repl/replication_executor.h" #include "mongo/db/repl/rslog.h" #include "mongo/db/server_parameters.h" @@ -2083,5 +2084,14 @@ namespace { } + void TopologyCoordinatorImpl::summarizeAsHtml(ReplSetHtmlSummary* output) { + output->setConfig(_rsConfig); + output->setHBData(_hbdata); + output->setSelfIndex(_selfIndex); + output->setPrimaryIndex(_currentPrimaryIndex); + output->setSelfState(getMemberState()); + output->setSelfHeartbeatMessage(_hbmsg); + } + } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/topology_coordinator_impl.h b/src/mongo/db/repl/topology_coordinator_impl.h index 3e9c9a48c18..55c199fbd10 100644 --- a/src/mongo/db/repl/topology_coordinator_impl.h +++ b/src/mongo/db/repl/topology_coordinator_impl.h @@ -186,6 +186,7 @@ namespace repl { virtual bool stepDown(Date_t until, bool force, OpTime lastOpApplied); virtual bool stepDownIfPending(); virtual Date_t getStepDownTime() const; + virtual void summarizeAsHtml(ReplSetHtmlSummary* output); //////////////////////////////////////////////////////////// // |