/**
* Copyright (C) 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 .
*
* 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
#include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
#include "mongo/base/status_with.h"
#include "mongo/db/repl/member_state.h"
#include "mongo/db/repl/repl_settings.h"
#include "mongo/db/repl/sync_source_selector.h"
#include "mongo/util/net/hostandport.h"
#include "mongo/util/time_support.h"
namespace mongo {
class BSONObj;
class BSONObjBuilder;
class IndexDescriptor;
class NamespaceString;
class OperationContext;
class ServiceContext;
class SnapshotName;
class Timestamp;
struct WriteConcernOptions;
namespace executor {
struct ConnectionPoolStats;
} // namespace executor
namespace rpc {
class OplogQueryMetadata;
class ReplSetMetadata;
class RequestInterface;
} // namespace rpc
namespace repl {
class BackgroundSync;
class HandshakeArgs;
class IsMasterResponse;
class OldUpdatePositionArgs;
class OplogReader;
class OpTime;
class ReadConcernArgs;
class ReplSetConfig;
class ReplicationExecutor;
class ReplSetHeartbeatArgs;
class ReplSetHeartbeatArgsV1;
class ReplSetHeartbeatResponse;
class ReplSetHtmlSummary;
class ReplSetRequestVotesArgs;
class ReplSetRequestVotesResponse;
class UpdatePositionArgs;
/**
* Global variable that contains a std::string telling why master/slave halted
*
* "dead" means something really bad happened like replication falling completely out of sync.
* when non-null, we are dead and the string is informational
*
* TODO(dannenberg) remove when master slave goes
*/
extern const char* replAllDead;
/**
* The ReplicationCoordinator is responsible for coordinating the interaction of replication
* with the rest of the system. The public methods on ReplicationCoordinator are the public
* API that the replication subsystem presents to the rest of the codebase.
*/
class ReplicationCoordinator : public SyncSourceSelector {
MONGO_DISALLOW_COPYING(ReplicationCoordinator);
public:
static ReplicationCoordinator* get(ServiceContext* service);
static ReplicationCoordinator* get(ServiceContext& service);
static ReplicationCoordinator* get(OperationContext* ctx);
static void set(ServiceContext* service,
std::unique_ptr replCoordinator);
struct StatusAndDuration {
public:
Status status;
Milliseconds duration;
StatusAndDuration(const Status& stat, Milliseconds ms) : status(stat), duration(ms) {}
};
virtual ~ReplicationCoordinator();
/**
* Does any initial bookkeeping needed to start replication, and instructs the other
* components of the replication system to start up whatever threads and do whatever
* initialization they need.
*/
virtual void startup(OperationContext* opCtx) = 0;
/**
* Does whatever cleanup is required to stop replication, including instructing the other
* components of the replication system to shut down and stop any threads they are using,
* blocking until all replication-related shutdown tasks are complete.
*/
virtual void shutdown(OperationContext* opCtx) = 0;
/**
* Returns a pointer to the ReplicationExecutor.
*/
virtual ReplicationExecutor* getExecutor() = 0;
/**
* Returns a reference to the parsed command line arguments that are related to replication.
*/
virtual const ReplSettings& getSettings() const = 0;
enum Mode { modeNone = 0, modeReplSet, modeMasterSlave };
/**
* Returns a value indicating whether this node was configured at start-up to run
* standalone, as part of a master-slave pair, or as a member of a replica set.
*/
virtual Mode getReplicationMode() const = 0;
/**
* Returns true if this node is configured to be a member of a replica set or master/slave
* setup.
*/
virtual bool isReplEnabled() const = 0;
/**
* Returns the current replica set state of this node (PRIMARY, SECONDARY, STARTUP, etc).
* It is invalid to call this unless getReplicationMode() == modeReplSet.
*/
virtual MemberState getMemberState() const = 0;
/**
* Waits for 'timeout' ms for member state to become 'state'.
* Returns OK if member state is 'state'.
* Returns ErrorCodes::ExceededTimeLimit if we timed out waiting for the state change.
* Returns ErrorCodes::BadValue if timeout is negative.
*/
virtual Status waitForMemberState(MemberState expectedState, Milliseconds timeout) = 0;
/**
* Returns true if this node is in state PRIMARY or SECONDARY.
*
* It is invalid to call this unless getReplicationMode() == modeReplSet.
*
* This method may be optimized to reduce synchronization overhead compared to
* reading the current member state with getMemberState().
*/
virtual bool isInPrimaryOrSecondaryState() const = 0;
/**
* Returns how slave delayed this node is configured to be, or 0 seconds if this node is not a
* member of the current replica set configuration.
*/
virtual Seconds getSlaveDelaySecs() const = 0;
/**
* Blocks the calling thread for up to writeConcern.wTimeout millis, or until "opTime" has
* been replicated to at least a set of nodes that satisfies the writeConcern, whichever
* comes first. A writeConcern.wTimeout of 0 indicates no timeout (block forever) and a
* writeConcern.wTimeout of -1 indicates return immediately after checking. Return codes:
* ErrorCodes::WriteConcernFailed if the writeConcern.wTimeout is reached before
* the data has been sufficiently replicated
* ErrorCodes::ExceededTimeLimit if the opCtx->getMaxTimeMicrosRemaining is reached before
* the data has been sufficiently replicated
* ErrorCodes::NotMaster if the node is not Primary/Master
* ErrorCodes::UnknownReplWriteConcern if the writeConcern.wMode contains a write concern
* mode that is not known
* ErrorCodes::ShutdownInProgress if we are mid-shutdown
* ErrorCodes::Interrupted if the operation was killed with killop()
*/
virtual StatusAndDuration awaitReplication(OperationContext* opCtx,
const OpTime& opTime,
const WriteConcernOptions& writeConcern) = 0;
/**
* Like awaitReplication(), above, but waits for the replication of the last operation
* performed on the client associated with "opCtx".
*/
virtual StatusAndDuration awaitReplicationOfLastOpForClient(
OperationContext* opCtx, const WriteConcernOptions& writeConcern) = 0;
/**
* Causes this node to relinquish being primary for at least 'stepdownTime'. If 'force' is
* false, before doing so it will wait for 'waitTime' for one other node to be within 10
* seconds of this node's optime before stepping down. Returns a Status with the code
* ErrorCodes::ExceededTimeLimit if no secondary catches up within waitTime,
* ErrorCodes::NotMaster if you are no longer primary when trying to step down,
* ErrorCodes::SecondaryAheadOfPrimary if we are primary but there is another node that
* seems to be ahead of us in replication, and Status::OK otherwise.
*/
virtual Status stepDown(OperationContext* opCtx,
bool force,
const Milliseconds& waitTime,
const Milliseconds& stepdownTime) = 0;
/**
* Returns true if the node can be considered master for the purpose of introspective
* commands such as isMaster() and rs.status().
*/
virtual bool isMasterForReportingPurposes() = 0;
/**
* Returns true if it is valid for this node to accept writes on the given database.
* Currently this is true only if this node is Primary, master in master/slave,
* a standalone, or is writing to the local database.
*
* If a node was started with the replSet argument, but has not yet received a config, it
* will not be able to receive writes to a database other than local (it will not be
* treated as standalone node).
*
* NOTE: This function can only be meaningfully called while the caller holds the global
* lock in some mode other than MODE_NONE.
*/
virtual bool canAcceptWritesForDatabase(OperationContext* opCtx, StringData dbName) = 0;
/**
* Version which does not check for the global lock. Do not use in new code.
* Without the global lock held, the return value may be inaccurate by the time
* the function returns.
*/
virtual bool canAcceptWritesForDatabase_UNSAFE(OperationContext* opCtx, StringData dbName) = 0;
/**
* Returns true if it is valid for this node to accept writes on the given namespace.
*
* The result of this function should be consistent with canAcceptWritesForDatabase()
* for the database the namespace refers to, with additional checks on the collection.
*/
virtual bool canAcceptWritesFor(OperationContext* opCtx, const NamespaceString& ns) = 0;
/**
* Version which does not check for the global lock. Do not use in new code.
* Without the global lock held, the return value may be inaccurate by the time
* the function returns.
*/
virtual bool canAcceptWritesFor_UNSAFE(OperationContext* opCtx, const NamespaceString& ns) = 0;
/**
* Checks if the current replica set configuration can satisfy the given write concern.
*
* Things that are taken into consideration include:
* 1. If the set has enough data-bearing members.
* 2. If the write concern mode exists.
* 3. If there are enough members for the write concern mode specified.
*/
virtual Status checkIfWriteConcernCanBeSatisfied(
const WriteConcernOptions& writeConcern) const = 0;
/**
* Returns Status::OK() if it is valid for this node to serve reads on the given collection
* and an errorcode indicating why the node cannot if it cannot.
*/
virtual Status checkCanServeReadsFor(OperationContext* opCtx,
const NamespaceString& ns,
bool slaveOk) = 0;
/**
* Version which does not check for the global lock. Do not use in new code.
* Without the global lock held, the return value may be inaccurate by the time
* the function returns.
*/
virtual Status checkCanServeReadsFor_UNSAFE(OperationContext* opCtx,
const NamespaceString& ns,
bool slaveOk) = 0;
/**
* Returns true if this node should ignore index constraints for idempotency reasons.
*
* The namespace "ns" is passed in because the "local" database is usually writable
* and we need to enforce the constraints for it.
*/
virtual bool shouldRelaxIndexConstraints(OperationContext* opCtx,
const NamespaceString& ns) = 0;
/**
* Updates our internal tracking of the last OpTime applied for the given slave
* identified by "rid". Only valid to call in master/slave mode
*/
virtual Status setLastOptimeForSlave(const OID& rid, const Timestamp& ts) = 0;
/**
* Updates our internal tracking of the last OpTime applied to this node.
*
* The new value of "opTime" must be no less than any prior value passed to this method, and
* it is the caller's job to properly synchronize this behavior. The exception to this rule
* is that after calls to resetLastOpTimesFromOplog(), the minimum acceptable value for
* "opTime" is reset based on the contents of the oplog, and may go backwards due to
* rollback.
*/
virtual void setMyLastAppliedOpTime(const OpTime& opTime) = 0;
/**
* Updates our internal tracking of the last OpTime durable to this node.
*
* The new value of "opTime" must be no less than any prior value passed to this method, and
* it is the caller's job to properly synchronize this behavior. The exception to this rule
* is that after calls to resetLastOpTimesFromOplog(), the minimum acceptable value for
* "opTime" is reset based on the contents of the oplog, and may go backwards due to
* rollback.
*/
virtual void setMyLastDurableOpTime(const OpTime& opTime) = 0;
/**
* Updates our internal tracking of the last OpTime applied to this node, but only
* if the supplied optime is later than the current last OpTime known to the replication
* coordinator.
*
* This function is used by logOp() on a primary, since the ops in the oplog do not
* necessarily commit in sequential order.
*/
virtual void setMyLastAppliedOpTimeForward(const OpTime& opTime) = 0;
/**
* Updates our internal tracking of the last OpTime durable to this node, but only
* if the supplied optime is later than the current last OpTime known to the replication
* coordinator.
*
* This function is used by logOp() on a primary, since the ops in the oplog do not
* necessarily commit in sequential order.
*/
virtual void setMyLastDurableOpTimeForward(const OpTime& opTime) = 0;
/**
* Same as above, but used during places we need to zero our last optime.
*/
virtual void resetMyLastOpTimes() = 0;
/**
* Updates our the message we include in heartbeat responses.
*/
virtual void setMyHeartbeatMessage(const std::string& msg) = 0;
/**
* Returns the last optime recorded by setMyLastAppliedOpTime.
*/
virtual OpTime getMyLastAppliedOpTime() const = 0;
/**
* Returns the last optime recorded by setMyLastDurableOpTime.
*/
virtual OpTime getMyLastDurableOpTime() const = 0;
/**
* Waits until the optime of the current node is at least the opTime specified in 'settings'.
*
* Returns whether the wait was successful.
*/
virtual Status waitUntilOpTimeForRead(OperationContext* opCtx,
const ReadConcernArgs& settings) = 0;
/**
* Retrieves and returns the current election id, which is a unique id that is local to
* this node and changes every time we become primary.
* TODO(spencer): Use term instead.
*/
virtual OID getElectionId() = 0;
/**
* Returns the RID for this node. The RID is used to identify this node to our sync source
* when sending updates about our replication progress.
*/
virtual OID getMyRID() const = 0;
/**
* Returns the id for this node as specified in the current replica set configuration.
*/
virtual int getMyId() const = 0;
/**
* Sets this node into a specific follower mode.
*
* Returns true if the follower mode was successfully set. Returns false if the
* node is or becomes a leader before setFollowerMode completes.
*
* Follower modes are RS_STARTUP2 (initial sync), RS_SECONDARY, RS_ROLLBACK and
* RS_RECOVERING. They are the valid states of a node whose topology coordinator has the
* follower role.
*
* This is essentially an interface that allows the applier to prevent the node from
* becoming a candidate or accepting reads, depending on circumstances in the oplog
* application process.
*/
virtual bool setFollowerMode(const MemberState& newState) = 0;
/**
* Step-up
* =======
* On stepup, repl coord enters catch-up mode. It's the same as the secondary mode from
* the perspective of producer and applier, so there's nothing to do with them.
* When a node enters drain mode, producer state = Stopped, applier state = Draining.
*
* If the applier state is Draining, it will signal repl coord when there's nothing to apply.
* The applier goes into Stopped state at the same time.
*
* The states go like the following:
* - secondary and during catchup mode
* (producer: Running, applier: Running)
* |
* | finish catch-up, enter drain mode
* V
* - drain mode
* (producer: Stopped, applier: Draining)
* |
* | applier signals drain is complete
* V
* - primary is in master mode
* (producer: Stopped, applier: Stopped)
*
*
* Step-down
* =========
* The state transitions become:
* - primary is in master mode
* (producer: Stopped, applier: Stopped)
* |
* | step down
* V
* - secondary mode, starting bgsync
* (producer: Starting, applier: Running)
* |
* | bgsync runs start()
* V
* - secondary mode, normal
* (producer: Running, applier: Running)
*
* When a node steps down during draining mode, it's OK to change from (producer: Stopped,
* applier: Draining) to (producer: Starting, applier: Running).
*
* When a node steps down during catchup mode, the states remain the same (producer: Running,
* applier: Running).
*/
enum class ApplierState { Running, Draining, Stopped };
/**
* In normal cases: Running -> Draining -> Stopped -> Running.
* Draining -> Running is also possible if a node steps down during drain mode.
*
* Only the applier can make the transition from Draining to Stopped by calling
* signalDrainComplete().
*/
virtual ApplierState getApplierState() = 0;
/**
* Signals that a previously requested pause and drain of the applier buffer
* has completed.
*
* This is an interface that allows the applier to reenable writes after
* a successful election triggers the draining of the applier buffer.
*
* The applier signals drain complete when the buffer is empty and it's in Draining
* state. We need to make sure the applier checks both conditions in the same term.
* Otherwise, it's possible that the applier confirms the empty buffer, but the node
* steps down and steps up so quickly that the applier signals drain complete in the wrong
* term.
*/
virtual void signalDrainComplete(OperationContext* opCtx, long long termWhenBufferIsEmpty) = 0;
/**
* Waits duration of 'timeout' for applier to finish draining its buffer of operations.
* Returns OK if we are not in drain mode.
* Returns ErrorCodes::ExceededTimeLimit if we timed out waiting for the applier to drain its
* buffer.
* Returns ErrorCodes::BadValue if timeout is negative.
*/
virtual Status waitForDrainFinish(Milliseconds timeout) = 0;
/**
* Signals the sync source feedback thread to wake up and send a handshake and
* replSetUpdatePosition command to our sync source.
*/
virtual void signalUpstreamUpdater() = 0;
enum class ReplSetUpdatePositionCommandStyle {
kNewStyle,
kOldStyle // Pre-3.2.4 servers.
};
/**
* Prepares a BSONObj describing an invocation of the replSetUpdatePosition command that can
* be sent to this node's sync source to update it about our progress in replication.
*/
virtual StatusWith prepareReplSetUpdatePositionCommand(
ReplSetUpdatePositionCommandStyle commandStyle) const = 0;
enum class ReplSetGetStatusResponseStyle { kBasic, kInitialSync };
/**
* Handles an incoming replSetGetStatus command. Adds BSON to 'result'. If kInitialSync is
* requested but initial sync is not running, kBasic will be used.
*/
virtual Status processReplSetGetStatus(BSONObjBuilder* result,
ReplSetGetStatusResponseStyle responseStyle) = 0;
/**
* Does an initial sync of data, after dropping existing data.
*/
virtual Status resyncData(OperationContext* opCtx, bool waitUntilCompleted) = 0;
/**
* Handles an incoming isMaster command for a replica set node. Should not be
* called on a master-slave or standalone node.
*/
virtual void fillIsMasterForReplSet(IsMasterResponse* result) = 0;
/**
* Adds to "result" a description of the slaveInfo data structure used to map RIDs to their
* last known optimes.
*/
virtual void appendSlaveInfoData(BSONObjBuilder* result) = 0;
/**
* Returns a copy of the current ReplSetConfig.
*/
virtual ReplSetConfig getConfig() const = 0;
/**
* Handles an incoming replSetGetConfig command. Adds BSON to 'result'.
*/
virtual void processReplSetGetConfig(BSONObjBuilder* result) = 0;
/**
* Processes the ReplSetMetadata returned from a command run against another
* replica set member and so long as the config version in the metadata matches the replica set
* config version this node currently has, updates the current term.
*
* This does NOT update this node's notion of the commit point.
*/
virtual void processReplSetMetadata(const rpc::ReplSetMetadata& replMetadata) = 0;
/**
* This updates the node's notion of the commit point.
*/
virtual void advanceCommitPoint(const OpTime& committedOptime) = 0;
/**
* Elections under protocol version 1 are triggered by a timer.
* When a node is informed of the primary's liveness (either through heartbeats or
* while reading a sync source's oplog), it calls this function to postpone the
* election timer by a duration of at least 'electionTimeoutMillis' (see getConfig()).
* If the current node is not electable (secondary with priority > 0), this function
* cancels the existing timer but will not schedule a new one.
*/
virtual void cancelAndRescheduleElectionTimeout() = 0;
/**
* Toggles maintenanceMode to the value expressed by 'activate'
* return Status::OK if the change worked, NotSecondary if it failed because we are
* PRIMARY, and OperationFailed if we are not currently in maintenance mode
*/
virtual Status setMaintenanceMode(bool activate) = 0;
/**
* Retrieves the current count of maintenanceMode and returns 'true' if greater than 0.
*/
virtual bool getMaintenanceMode() = 0;
/**
* Handles an incoming replSetSyncFrom command. Adds BSON to 'result'
* returns Status::OK if the sync target could be set and an ErrorCode indicating why it
* couldn't otherwise.
*/
virtual Status processReplSetSyncFrom(OperationContext* opCtx,
const HostAndPort& target,
BSONObjBuilder* resultObj) = 0;
/**
* Handles an incoming replSetFreeze command. Adds BSON to 'resultObj'
* returns Status::OK() if the node is a member of a replica set with a config and an
* error Status otherwise
*/
virtual Status processReplSetFreeze(int secs, BSONObjBuilder* resultObj) = 0;
/**
* Handles an incoming heartbeat command with arguments 'args'. Populates 'response';
* returns a Status with either OK or an error message.
*/
virtual Status processHeartbeat(const ReplSetHeartbeatArgs& args,
ReplSetHeartbeatResponse* response) = 0;
virtual Status processHeartbeatV1(const ReplSetHeartbeatArgsV1& args,
ReplSetHeartbeatResponse* response) = 0;
/**
* Arguments for the replSetReconfig command.
*/
struct ReplSetReconfigArgs {
BSONObj newConfigObj;
bool force;
};
/**
* Handles an incoming replSetReconfig command. Adds BSON to 'resultObj';
* returns a Status with either OK or an error message.
*/
virtual Status processReplSetReconfig(OperationContext* opCtx,
const ReplSetReconfigArgs& args,
BSONObjBuilder* resultObj) = 0;
/*
* Handles an incoming replSetInitiate command. If "configObj" is empty, generates a default
* configuration to use.
* Adds BSON to 'resultObj'; returns a Status with either OK or an error message.
*/
virtual Status processReplSetInitiate(OperationContext* opCtx,
const BSONObj& configObj,
BSONObjBuilder* resultObj) = 0;
/*
* Handles an incoming replSetGetRBID command.
* Adds BSON to 'resultObj'; returns a Status with either OK or an error message.
*/
virtual Status processReplSetGetRBID(BSONObjBuilder* resultObj) = 0;
/**
* Increments this process's rollback id. Called every time a rollback occurs.
*/
virtual void incrementRollbackID() = 0;
/**
* Arguments to the replSetFresh command.
*/
struct ReplSetFreshArgs {
std::string setName; // Name of the replset
HostAndPort who; // host and port of the member that sent the replSetFresh command
unsigned id; // replSet id of the member that sent the replSetFresh command
int cfgver; // replSet config version that the member who sent the command thinks it has
Timestamp opTime; // last optime seen by the member who sent the replSetFresh command
};
/*
* Handles an incoming replSetFresh command.
* Adds BSON to 'resultObj'; returns a Status with either OK or an error message.
*/
virtual Status processReplSetFresh(const ReplSetFreshArgs& args, BSONObjBuilder* resultObj) = 0;
/**
* Arguments to the replSetElect command.
*/
struct ReplSetElectArgs {
std::string set; // Name of the replset
int whoid; // replSet id of the member that sent the replSetFresh command
int cfgver; // replSet config version that the member who sent the command thinks it has
OID round; // unique ID for this election
};
/*
* Handles an incoming replSetElect command.
* Adds BSON to 'resultObj'; returns a Status with either OK or an error message.
*/
virtual Status processReplSetElect(const ReplSetElectArgs& args, BSONObjBuilder* resultObj) = 0;
/**
* Handles an incoming replSetUpdatePosition command, updating each node's oplog progress.
* Returns Status::OK() if all updates are processed correctly, NodeNotFound
* if any updating node cannot be found in the config, InvalidReplicaSetConfig if the
* "configVersion" sent in any of the updates doesn't match our config version, or
* NotMasterOrSecondary if we are in state REMOVED or otherwise don't have a valid
* replica set config.
* If a non-OK status is returned, it is unspecified whether none or some of the updates
* were applied.
* "configVersion" will be populated with our config version if and only if we return
* InvalidReplicaSetConfig.
*
* The OldUpdatePositionArgs version provides support for the pre-3.2.4 format of
* UpdatePositionArgs.
*/
virtual Status processReplSetUpdatePosition(const OldUpdatePositionArgs& updates,
long long* configVersion) = 0;
virtual Status processReplSetUpdatePosition(const UpdatePositionArgs& updates,
long long* configVersion) = 0;
/**
* Handles an incoming Handshake command. Associates the node's 'remoteID' with its
* 'handshake' object. This association is used to update internal representation of
* replication progress and to forward the node's replication progress upstream when this
* node is being chained through in master/slave replication.
*
* Returns ErrorCodes::IllegalOperation if we're not running with master/slave replication.
*/
virtual Status processHandshake(OperationContext* opCtx, const HandshakeArgs& handshake) = 0;
/**
* Returns a bool indicating whether or not this node builds indexes.
*/
virtual bool buildsIndexes() = 0;
/**
* Returns a vector of members that have applied the operation with OpTime 'op'.
* "durablyWritten" indicates whether the operation has to be durably applied.
*/
virtual std::vector getHostsWrittenTo(const OpTime& op, bool durablyWritten) = 0;
/**
* Returns a vector of the members other than ourself in the replica set, as specified in
* the replica set config. Invalid to call if we are not in replica set mode. Returns
* an empty vector if we do not have a valid config.
*/
virtual std::vector getOtherNodesInReplSet() const = 0;
/**
* Returns a BSONObj containing a representation of the current default write concern.
*/
virtual WriteConcernOptions getGetLastErrorDefault() = 0;
/**
* Checks that the --replSet flag was passed when starting up the node and that the node
* has a valid replica set config.
*
* Returns a Status indicating whether those conditions are met with errorcode
* NoReplicationEnabled if --replSet was not present during start up or with errorcode
* NotYetInitialized in the absence of a valid config. Also adds error info to "result".
*/
virtual Status checkReplEnabledForCommand(BSONObjBuilder* result) = 0;
/**
* Loads the optime from the last op in the oplog into the coordinator's lastAppliedOpTime and
* lastDurableOpTime values.
*/
virtual void resetLastOpTimesFromOplog(OperationContext* opCtx) = 0;
/**
* Returns the OpTime of the latest replica set-committed op known to this server.
* Committed means a majority of the voting nodes of the config are known to have the
* operation in their oplogs. This implies such ops will never be rolled back.
*/
virtual OpTime getLastCommittedOpTime() const = 0;
/*
* Handles an incoming replSetRequestVotes command.
* Adds BSON to 'resultObj'; returns a Status with either OK or an error message.
*/
virtual Status processReplSetRequestVotes(OperationContext* opCtx,
const ReplSetRequestVotesArgs& args,
ReplSetRequestVotesResponse* response) = 0;
/**
* Prepares a metadata object with the ReplSetMetadata and the OplogQueryMetadata depending
* on what has been requested.
*/
virtual void prepareReplMetadata(const BSONObj& metadataRequestObj,
const OpTime& lastOpTimeFromClient,
BSONObjBuilder* builder) const = 0;
/**
* Returns true if the V1 election protocol is being used and false otherwise.
*/
virtual bool isV1ElectionProtocol() const = 0;
/**
* Returns whether or not majority write concerns should implicitly journal, if j has not been
* explicitly set.
*/
virtual bool getWriteConcernMajorityShouldJournal() = 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;
/**
* Returns the current term.
*/
virtual long long getTerm() = 0;
/**
* Attempts to update the current term for the V1 election protocol. If the term changes and
* this node is primary, relinquishes primary.
* Returns a Status OK if the term was *not* updated (meaning, it is safe to proceed with
* the rest of the work, because the term is still the same).
* Returns StaleTerm if the supplied term was higher than the current term.
*/
virtual Status updateTerm(OperationContext* opCtx, long long term) = 0;
/**
* Reserves a unique SnapshotName.
*
* This name is guaranteed to compare > all names reserved before and < all names reserved
* after.
*
* This method will not take any locks or attempt to access storage using the passed-in
* OperationContext. It will only be used to track reserved SnapshotNames by each operation so
* that awaitReplicationOfLastOpForClient() can correctly wait for the reserved snapshot to be
* visible.
*
* A null OperationContext can be used in cases where the snapshot to wait for should not be
* adjusted.
*/
virtual SnapshotName reserveSnapshotName(OperationContext* opCtx) = 0;
/**
* Signals the SnapshotThread, if running, to take a forced snapshot even if the global
* timestamp hasn't changed.
*
* Does not wait for the snapshot to be taken.
*/
virtual void forceSnapshotCreation() = 0;
/**
* Creates a new snapshot in the storage engine and registers it for use in the replication
* coordinator.
*/
virtual void createSnapshot(OperationContext* opCtx,
OpTime timeOfSnapshot,
SnapshotName name) = 0;
/**
* Blocks until either the current committed snapshot is at least as high as 'untilSnapshot',
* or we are interrupted for any reason, including shutdown or maxTimeMs expiration.
* 'opCtx' is used to checkForInterrupt and enforce maxTimeMS.
*/
virtual void waitUntilSnapshotCommitted(OperationContext* opCtx,
const SnapshotName& untilSnapshot) = 0;
/**
* Resets all information related to snapshotting.
*/
virtual void dropAllSnapshots() = 0;
/**
* Gets the latest OpTime of the currentCommittedSnapshot.
*/
virtual OpTime getCurrentCommittedSnapshotOpTime() const = 0;
/**
* Appends connection information to the provided BSONObjBuilder.
*/
virtual void appendConnectionStats(executor::ConnectionPoolStats* stats) const = 0;
/**
* Gets the number of uncommitted snapshots currently held.
* Warning: This value can change at any time and may not even be accurate at the time of
* return. It should not be used when an exact amount is needed.
*/
virtual size_t getNumUncommittedSnapshots() = 0;
/**
* Returns a new WriteConcernOptions based on "wc" but with UNSET syncMode reset to JOURNAL or
* NONE based on our rsConfig.
*/
virtual WriteConcernOptions populateUnsetWriteConcernOptionsSyncMode(
WriteConcernOptions wc) = 0;
virtual ReplSettings::IndexPrefetchConfig getIndexPrefetchConfig() const = 0;
virtual void setIndexPrefetchConfig(const ReplSettings::IndexPrefetchConfig cfg) = 0;
virtual Status stepUpIfEligible() = 0;
virtual ServiceContext* getServiceContext() = 0;
protected:
ReplicationCoordinator();
};
} // namespace repl
} // namespace mongo