From 1655e260f640dadc696684afb6766b86199a665b Mon Sep 17 00:00:00 2001 From: matt dannenberg Date: Tue, 21 Apr 2015 10:33:40 -0400 Subject: SERVER-18153 add repl subobject to find/getmore responses --- src/mongo/SConscript | 1 + src/mongo/db/commands.cpp | 22 -------- src/mongo/db/commands.h | 24 -------- src/mongo/db/commands/cursor_responses.cpp | 62 +++++++++++++++++++++ src/mongo/db/commands/cursor_responses.h | 65 ++++++++++++++++++++++ src/mongo/db/commands/find_cmd.cpp | 5 +- src/mongo/db/commands/getmore_cmd.cpp | 4 +- src/mongo/db/commands/list_collections.cpp | 6 +- src/mongo/db/commands/list_indexes.cpp | 6 +- src/mongo/db/commands/parallel_collection_scan.cpp | 1 + src/mongo/db/commands/pipeline_command.cpp | 3 +- src/mongo/db/commands/repair_cursor.cpp | 1 + ...ork_interface_impl_downconvert_find_getmore.cpp | 5 +- src/mongo/db/repl/replication_coordinator.h | 10 ++++ src/mongo/db/repl/replication_coordinator_impl.cpp | 13 +++++ src/mongo/db/repl/replication_coordinator_impl.h | 4 ++ src/mongo/db/repl/replication_coordinator_mock.cpp | 7 +++ src/mongo/db/repl/replication_coordinator_mock.h | 4 ++ src/mongo/db/repl/topology_coordinator.h | 6 ++ src/mongo/db/repl/topology_coordinator_impl.cpp | 10 ++++ src/mongo/db/repl/topology_coordinator_impl.h | 7 +++ 21 files changed, 207 insertions(+), 59 deletions(-) create mode 100644 src/mongo/db/commands/cursor_responses.cpp create mode 100644 src/mongo/db/commands/cursor_responses.h diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 9abc6ccd67c..2212ce0e0e9 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -756,6 +756,7 @@ serverOnlyFiles = [ "db/background.cpp", "db/commands/count.cpp", "db/commands/create_indexes.cpp", "db/commands/current_op.cpp", + "db/commands/cursor_responses.cpp", "db/commands/dbhash.cpp", "db/commands/distinct.cpp", "db/commands/drop_indexes.cpp", diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index 92e94bbd6a7..eb262282931 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -311,28 +311,6 @@ namespace mongo { return Status::OK(); } - void Command::appendCursorResponseObject(long long cursorId, - StringData cursorNamespace, - BSONArray firstBatch, - BSONObjBuilder* builder) { - BSONObjBuilder cursorObj(builder->subobjStart("cursor")); - cursorObj.append("id", cursorId); - cursorObj.append("ns", cursorNamespace); - cursorObj.append("firstBatch", firstBatch); - cursorObj.done(); - } - - void Command::appendGetMoreResponseObject(long long cursorId, - StringData cursorNamespace, - BSONArray nextBatch, - BSONObjBuilder* builder) { - BSONObjBuilder cursorObj(builder->subobjStart("cursor")); - cursorObj.append("id", cursorId); - cursorObj.append("ns", cursorNamespace); - cursorObj.append("nextBatch", nextBatch); - cursorObj.done(); - } - Status Command::checkAuthForCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 16db4cf84bd..500b6a3149b 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -293,30 +293,6 @@ namespace mutablebson { long long defaultBatchSize, long long* batchSize); - /** - * Builds a cursor response object from the provided cursor identifiers and "firstBatch", - * and appends the response object to the provided builder under the field name "cursor". - * - * The response object has the following format: - * { id: , ns: , firstBatch: }. - */ - static void appendCursorResponseObject(long long cursorId, - StringData cursorNamespace, - BSONArray firstBatch, - BSONObjBuilder* builder); - - /** - * Builds a getMore response object from the provided cursor identifiers and "nextBatch", - * and appends the response object to the provided builder under the field name "cursor". - * - * The response object has the following format: - * { id: , ns: , nextBatch: }. - */ - static void appendGetMoreResponseObject(long long cursorId, - StringData cursorNamespace, - BSONArray nextBatch, - BSONObjBuilder* builder); - /** * Helper for setting a writeConcernError field in the command result object if * a writeConcern error occurs. diff --git a/src/mongo/db/commands/cursor_responses.cpp b/src/mongo/db/commands/cursor_responses.cpp new file mode 100644 index 00000000000..3520f5e8164 --- /dev/null +++ b/src/mongo/db/commands/cursor_responses.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 . + * + * 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/commands/cursor_responses.h" + +#include "mongo/db/jsobj.h" +#include "mongo/db/repl/replication_coordinator_global.h" + +namespace mongo { + + void appendCursorResponseObject(long long cursorId, + StringData cursorNamespace, + BSONArray firstBatch, + BSONObjBuilder* builder) { + BSONObjBuilder cursorObj(builder->subobjStart("cursor")); + cursorObj.append("id", cursorId); + cursorObj.append("ns", cursorNamespace); + cursorObj.append("firstBatch", firstBatch); + cursorObj.done(); + // TODO(dannenberg): only append the replication info if it was requested + repl::getGlobalReplicationCoordinator()->prepareCursorResponseInfo(builder); + } + + void appendGetMoreResponseObject(long long cursorId, + StringData cursorNamespace, + BSONArray nextBatch, + BSONObjBuilder* builder) { + BSONObjBuilder cursorObj(builder->subobjStart("cursor")); + cursorObj.append("id", cursorId); + cursorObj.append("ns", cursorNamespace); + cursorObj.append("nextBatch", nextBatch); + cursorObj.done(); + // TODO(dannenberg): only append the replication info if it was requested + repl::getGlobalReplicationCoordinator()->prepareCursorResponseInfo(builder); + } + +} // namespace mongo diff --git a/src/mongo/db/commands/cursor_responses.h b/src/mongo/db/commands/cursor_responses.h new file mode 100644 index 00000000000..2c9fed3b610 --- /dev/null +++ b/src/mongo/db/commands/cursor_responses.h @@ -0,0 +1,65 @@ +/** + * 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. + */ + +#pragma once + +namespace mongo { + + class BSONObjBuilder; + class StringData; + struct BSONArray; + + /** + * Builds a cursor response object from the provided cursor identifiers and "firstBatch", + * and appends the response object to the provided builder under the field name "cursor". + * If the node is a member of a replSet, also appends the current term, primary, and + * lastOp information. + * + * The response object has the following format: + * { id: , ns: , firstBatch: }. + */ + void appendCursorResponseObject(long long cursorId, + StringData cursorNamespace, + BSONArray firstBatch, + BSONObjBuilder* builder); + + /** + * Builds a getMore response object from the provided cursor identifiers and "nextBatch", + * and appends the response object to the provided builder under the field name "cursor". + * If the node is a member of a replSet, also appends the current term, primary, and + * lastOp information. + * + * The response object has the following format: + * { id: , ns: , nextBatch: }. + */ + void appendGetMoreResponseObject(long long cursorId, + StringData cursorNamespace, + BSONArray nextBatch, + BSONObjBuilder* builder); + +} // namespace mongo diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp index e856c9639a8..9b78a2a0543 100644 --- a/src/mongo/db/commands/find_cmd.cpp +++ b/src/mongo/db/commands/find_cmd.cpp @@ -39,6 +39,7 @@ #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/service_context.h" @@ -263,7 +264,7 @@ namespace mongo { const CursorId cursorId = 0; endQueryOp(execHolder.get(), dbProfilingLevel, numResults, cursorId, txn->getCurOp()); - Command::appendCursorResponseObject(cursorId, nss.ns(), BSONArray(), &result); + appendCursorResponseObject(cursorId, nss.ns(), BSONArray(), &result); return true; } @@ -346,7 +347,7 @@ namespace mongo { endQueryOp(exec, dbProfilingLevel, numResults, cursorId, txn->getCurOp()); // 7) Generate the response object to send to the client. - Command::appendCursorResponseObject(cursorId, nss.ns(), firstBatch.arr(), &result); + appendCursorResponseObject(cursorId, nss.ns(), firstBatch.arr(), &result); if (cursorId) { cursorFreer.Dismiss(); } diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp index 4e96ae4544c..22087b4dcdb 100644 --- a/src/mongo/db/commands/getmore_cmd.cpp +++ b/src/mongo/db/commands/getmore_cmd.cpp @@ -39,6 +39,7 @@ #include "mongo/db/catalog/cursor_manager.h" #include "mongo/db/clientcursor.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/service_context.h" @@ -260,8 +261,7 @@ namespace mongo { txn->getCurOp()->debug().cursorExhausted = true; } - Command::appendGetMoreResponseObject(respondWithId, request.nss.ns(), nextBatch.arr(), - &result); + appendGetMoreResponseObject(respondWithId, request.nss.ns(), nextBatch.arr(), &result); if (respondWithId) { cursorFreer.Dismiss(); } diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp index 1e98b719214..b2a551610ac 100644 --- a/src/mongo/db/commands/list_collections.cpp +++ b/src/mongo/db/commands/list_collections.cpp @@ -41,11 +41,12 @@ #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/exec/working_set.h" -#include "mongo/db/service_context.h" #include "mongo/db/query/find_constants.h" +#include "mongo/db/service_context.h" #include "mongo/db/storage/storage_engine.h" namespace mongo { @@ -204,8 +205,7 @@ namespace mongo { cursorId = cursor->cursorid(); } - Command::appendCursorResponseObject( cursorId, cursorNamespace, firstBatch.arr(), - &result ); + appendCursorResponseObject( cursorId, cursorNamespace, firstBatch.arr(), &result ); return true; } diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp index c53303b04c7..afd64b0a2a6 100644 --- a/src/mongo/db/commands/list_indexes.cpp +++ b/src/mongo/db/commands/list_indexes.cpp @@ -37,13 +37,14 @@ #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/exec/working_set.h" -#include "mongo/db/service_context.h" #include "mongo/db/query/find_constants.h" +#include "mongo/db/service_context.h" #include "mongo/db/storage/storage_engine.h" namespace mongo { @@ -195,8 +196,7 @@ namespace mongo { cursorId = cursor->cursorid(); } - Command::appendCursorResponseObject( cursorId, cursorNamespace, firstBatch.arr(), - &result ); + appendCursorResponseObject( cursorId, cursorNamespace, firstBatch.arr(), &result ); return true; } diff --git a/src/mongo/db/commands/parallel_collection_scan.cpp b/src/mongo/db/commands/parallel_collection_scan.cpp index 49ebeb9de5a..68b0ecf987a 100644 --- a/src/mongo/db/commands/parallel_collection_scan.cpp +++ b/src/mongo/db/commands/parallel_collection_scan.cpp @@ -33,6 +33,7 @@ #include "mongo/db/catalog/database.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/multi_iterator.h" #include "mongo/util/touch_pages.h" diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp index f94eec9d11d..0763771af70 100644 --- a/src/mongo/db/commands/pipeline_command.cpp +++ b/src/mongo/db/commands/pipeline_command.cpp @@ -38,6 +38,7 @@ #include "mongo/db/catalog/database.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/pipeline_proxy.h" @@ -148,7 +149,7 @@ namespace mongo { } const long long cursorId = cursor ? cursor->cursorid() : 0LL; - Command::appendCursorResponseObject(cursorId, ns, resultsArray.arr(), &result); + appendCursorResponseObject(cursorId, ns, resultsArray.arr(), &result); return static_cast(cursor); } diff --git a/src/mongo/db/commands/repair_cursor.cpp b/src/mongo/db/commands/repair_cursor.cpp index 1c7c653081b..81d16f9349b 100644 --- a/src/mongo/db/commands/repair_cursor.cpp +++ b/src/mongo/db/commands/repair_cursor.cpp @@ -34,6 +34,7 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/multi_iterator.h" diff --git a/src/mongo/db/repl/network_interface_impl_downconvert_find_getmore.cpp b/src/mongo/db/repl/network_interface_impl_downconvert_find_getmore.cpp index 086c88965da..280ee8b6a9c 100644 --- a/src/mongo/db/repl/network_interface_impl_downconvert_find_getmore.cpp +++ b/src/mongo/db/repl/network_interface_impl_downconvert_find_getmore.cpp @@ -34,6 +34,7 @@ #include "mongo/client/dbclientinterface.h" #include "mongo/db/commands.h" +#include "mongo/db/commands/cursor_responses.h" #include "mongo/db/namespace_string.h" #include "mongo/db/query/getmore_request.h" @@ -115,7 +116,7 @@ namespace { batch.append(cursor->next()); } BSONObjBuilder result; - Command::appendCursorResponseObject(cursor->getCursorId(), ns, batch.arr(), &result); + appendCursorResponseObject(cursor->getCursorId(), ns, batch.arr(), &result); Command::appendCommandStatus(result, Status::OK()); *output = result.obj(); return Status::OK(); @@ -148,7 +149,7 @@ namespace { batch.append(cursor->next()); } BSONObjBuilder result; - Command::appendGetMoreResponseObject(cursor->getCursorId(), ns, batch.arr(), &result); + appendGetMoreResponseObject(cursor->getCursorId(), ns, batch.arr(), &result); Command::appendCommandStatus(result, Status::OK()); *output = result.obj(); return Status::OK(); diff --git a/src/mongo/db/repl/replication_coordinator.h b/src/mongo/db/repl/replication_coordinator.h index 7fd2ccd71c2..b214444311d 100644 --- a/src/mongo/db/repl/replication_coordinator.h +++ b/src/mongo/db/repl/replication_coordinator.h @@ -576,6 +576,16 @@ namespace repl { const ReplSetDeclareElectionWinnerArgs& args, ReplSetDeclareElectionWinnerResponse* response) = 0; + /** + * Prepares a BSONObj describing the current term, primary, and lastOp information. + */ + virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder) = 0; + + /** + * Returns true if the V1 election protocol is being used and false otherwise. + */ + virtual bool isV1ElectionProtocol() = 0; + protected: ReplicationCoordinator(); diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index a0ad7e9e4b5..0be84185926 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -2418,5 +2418,18 @@ namespace { ReplSetDeclareElectionWinnerResponse* response) { return {ErrorCodes::CommandNotFound, "not implemented"}; } + + void ReplicationCoordinatorImpl::prepareCursorResponseInfo(BSONObjBuilder* objBuilder) { + if (getReplicationMode() == modeReplSet && isV1ElectionProtocol()) { + BSONObjBuilder replObj(objBuilder->subobjStart("repl")); + _topCoord->prepareCursorResponseInfo(objBuilder, getLastCommittedOpTime()); + replObj.done(); + } + } + + bool ReplicationCoordinatorImpl::isV1ElectionProtocol() { + return getConfig().getProtocolVersion() == 1; + } + } // 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 a6bdb7a7d2c..811e0f2b494 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.h +++ b/src/mongo/db/repl/replication_coordinator_impl.h @@ -244,6 +244,10 @@ namespace repl { const ReplSetDeclareElectionWinnerArgs& args, ReplSetDeclareElectionWinnerResponse* response); + virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder); + + virtual bool isV1ElectionProtocol(); + // ================== Test support API =================== /** diff --git a/src/mongo/db/repl/replication_coordinator_mock.cpp b/src/mongo/db/repl/replication_coordinator_mock.cpp index a7440c21d23..72b6a77407d 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.cpp +++ b/src/mongo/db/repl/replication_coordinator_mock.cpp @@ -310,5 +310,12 @@ namespace repl { ReplSetDeclareElectionWinnerResponse* response) { return Status::OK(); } + + void ReplicationCoordinatorMock::prepareCursorResponseInfo(BSONObjBuilder* objBuilder) {} + + bool ReplicationCoordinatorMock::isV1ElectionProtocol() { + return true; + } + } // 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 b974db72c19..ef72a591230 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.h +++ b/src/mongo/db/repl/replication_coordinator_mock.h @@ -189,6 +189,10 @@ namespace repl { const ReplSetDeclareElectionWinnerArgs& args, ReplSetDeclareElectionWinnerResponse* response); + virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder); + + virtual bool isV1ElectionProtocol(); + private: const ReplSettings _settings; diff --git a/src/mongo/db/repl/topology_coordinator.h b/src/mongo/db/repl/topology_coordinator.h index fe8edd37333..fb6bde87e71 100644 --- a/src/mongo/db/repl/topology_coordinator.h +++ b/src/mongo/db/repl/topology_coordinator.h @@ -355,6 +355,12 @@ namespace repl { */ virtual void setMyHeartbeatMessage(const Date_t now, const std::string& s) = 0; + /** + * Prepares a BSONObj describing the current term, primary, and lastOp information. + */ + virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder, + const Timestamp& lastCommittedOpTime) const = 0; + protected: TopologyCoordinator() {} }; diff --git a/src/mongo/db/repl/topology_coordinator_impl.cpp b/src/mongo/db/repl/topology_coordinator_impl.cpp index 1d019eec216..046710fa64b 100644 --- a/src/mongo/db/repl/topology_coordinator_impl.cpp +++ b/src/mongo/db/repl/topology_coordinator_impl.cpp @@ -122,6 +122,7 @@ namespace { TopologyCoordinatorImpl::TopologyCoordinatorImpl(Seconds maxSyncSourceLagSecs) : _role(Role::follower), + _term(0), _currentPrimaryIndex(-1), _forceSyncSourceIndex(-1), _maxSyncSourceLagSecs(maxSyncSourceLagSecs), @@ -2082,6 +2083,15 @@ namespace { return false; } + void TopologyCoordinatorImpl::prepareCursorResponseInfo( + BSONObjBuilder* objBuilder, + const Timestamp& lastCommittedOpTime) const { + objBuilder->append("term", _term); + objBuilder->append("lastOpCommittedTimestamp", lastCommittedOpTime.getSecs()); + objBuilder->append("lastOpCommittedTerm", lastCommittedOpTime.getInc()); + objBuilder->append("configVersion", _rsConfig.getConfigVersion()); + objBuilder->append("primaryId", _rsConfig.getMemberAt(_currentPrimaryIndex).getId()); + } } // 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 e8d0d42a46a..e0cd74f7012 100644 --- a/src/mongo/db/repl/topology_coordinator_impl.h +++ b/src/mongo/db/repl/topology_coordinator_impl.h @@ -186,6 +186,9 @@ namespace repl { virtual bool stepDown(Date_t until, bool force, Timestamp lastOpApplied); virtual bool stepDownIfPending(); virtual Date_t getStepDownTime() const; + virtual void prepareCursorResponseInfo(BSONObjBuilder* objBuilder, + const Timestamp& lastCommitttedOpTime) const; + //////////////////////////////////////////////////////////// // @@ -327,6 +330,10 @@ namespace repl { // The time at which the current PRIMARY was elected. Timestamp _electionTime; + // This node's election term. The term is used as part of the consensus algorithm to elect + // and maintain one primary (leader) node in the cluster. + long long _term; + // the index of the member we currently believe is primary, if one exists, otherwise -1 int _currentPrimaryIndex; -- cgit v1.2.1