summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2015-04-28 17:41:48 -0400
committerSpencer T Brody <spencer@mongodb.com>2015-04-29 15:17:25 -0400
commit762e0cdc48281414c05ee3ef53277bdf138a4334 (patch)
treef9cc40354131e0fabe51687c3af7f64e312250ef /src/mongo/db
parentcf56e9bc62cab6cfcb06af83fb7a330ba6bb84e8 (diff)
downloadmongo-762e0cdc48281414c05ee3ef53277bdf138a4334.tar.gz
SERVER-18117 Add replset view back to http interface
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/dbwebserver.cpp3
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/repl/repl_set_html_summary.cpp221
-rw-r--r--src/mongo/db/repl/repl_set_html_summary.h101
-rw-r--r--src/mongo/db/repl/replication_coordinator.h7
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp27
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.h5
-rw-r--r--src/mongo/db/repl/replication_coordinator_mock.cpp2
-rw-r--r--src/mongo/db/repl/replication_coordinator_mock.h2
-rw-r--r--src/mongo/db/repl/replset_web_handler.cpp96
-rw-r--r--src/mongo/db/repl/topology_coordinator.h8
-rw-r--r--src/mongo/db/repl/topology_coordinator_impl.cpp10
-rw-r--r--src/mongo/db/repl/topology_coordinator_impl.h1
13 files changed, 482 insertions, 2 deletions
diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp
index 9a919b8967b..435cddffe6f 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 ae6bb14e865..1ad73e7c20b 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -238,6 +238,7 @@ env.Library('replica_set_messages',
'repl_set_heartbeat_args_v1.cpp',
'repl_set_heartbeat_response.cpp',
'repl_set_heartbeat_response_v1.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..463a2bcdc53
--- /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 Timestamp& 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;
+ Timestamp _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 2b176e29a10..50945a1f4be 100644
--- a/src/mongo/db/repl/replication_coordinator.h
+++ b/src/mongo/db/repl/replication_coordinator.h
@@ -60,6 +60,7 @@ namespace repl {
class ReplSetHeartbeatArgsV1;
class ReplSetHeartbeatResponse;
class ReplSetHeartbeatResponseV1;
+ class ReplSetHtmlSummary;
class ReplSetRequestVotesArgs;
class ReplSetRequestVotesResponse;
class ReplicaSetConfig;
@@ -590,6 +591,12 @@ namespace repl {
*/
virtual bool isV1ElectionProtocol() = 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 fd617a9cbe8..bc137be8ddc 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -48,6 +48,7 @@
#include "mongo/db/repl/repl_client_info.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_set_request_votes_args.h"
#include "mongo/db/repl/repl_settings.h"
#include "mongo/db/repl/replica_set_config_checks.h"
@@ -2442,5 +2443,31 @@ namespace {
return {ErrorCodes::CommandNotFound, "not implemented"};
}
+ 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 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 36d8398ac62..5304f7134df 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_impl.h
@@ -251,6 +251,8 @@ namespace repl {
virtual bool isV1ElectionProtocol();
+ virtual void summarizeAsHtml(ReplSetHtmlSummary* s);
+
// ================== Test support API ===================
/**
@@ -778,6 +780,9 @@ namespace repl {
*/
void _updateLastCommittedOpTime_inlock();
+ 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 63a917470fa..2fae22cd016 100644
--- a/src/mongo/db/repl/replication_coordinator_mock.cpp
+++ b/src/mongo/db/repl/replication_coordinator_mock.cpp
@@ -322,5 +322,7 @@ namespace repl {
return true;
}
+ 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 e8615b7c985..70fb82a946e 100644
--- a/src/mongo/db/repl/replication_coordinator_mock.h
+++ b/src/mongo/db/repl/replication_coordinator_mock.h
@@ -196,6 +196,8 @@ namespace repl {
virtual bool isV1ElectionProtocol();
+ 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 fb6bde87e71..3c97e64be29 100644
--- a/src/mongo/db/repl/topology_coordinator.h
+++ b/src/mongo/db/repl/topology_coordinator.h
@@ -40,7 +40,6 @@
namespace mongo {
- class OperationContext;
class Timestamp;
namespace repl {
@@ -361,6 +360,13 @@ namespace repl {
virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder,
const Timestamp& lastCommittedOpTime) const = 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 046710fa64b..d6dd5128375 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"
@@ -2093,5 +2094,14 @@ namespace {
objBuilder->append("primaryId", _rsConfig.getMemberAt(_currentPrimaryIndex).getId());
}
+ 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 e0cd74f7012..f421be325fd 100644
--- a/src/mongo/db/repl/topology_coordinator_impl.h
+++ b/src/mongo/db/repl/topology_coordinator_impl.h
@@ -189,6 +189,7 @@ namespace repl {
virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder,
const Timestamp& lastCommitttedOpTime) const;
+ virtual void summarizeAsHtml(ReplSetHtmlSummary* output);
////////////////////////////////////////////////////////////
//