1 2 /** 3 * Copyright (C) 2018-present MongoDB, Inc. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the Server Side Public License, version 1, 7 * as published by MongoDB, Inc. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * Server Side Public License for more details. 13 * 14 * You should have received a copy of the Server Side Public License 15 * along with this program. If not, see 16 * <http://www.mongodb.com/licensing/server-side-public-license>. 17 * 18 * As a special exception, the copyright holders give permission to link the 19 * code of portions of this program with the OpenSSL library under certain 20 * conditions as described in each individual source file and distribute 21 * linked combinations including the program with the OpenSSL library. You 22 * must comply with the Server Side Public License in all respects for 23 * all of the code used other than as permitted herein. If you modify file(s) 24 * with this exception, you may extend this exception to your version of the 25 * file(s), but you are not obligated to do so. If you do not wish to do so, 26 * delete this exception statement from your version. If you delete this 27 * exception statement from all source files in the program, then also delete 28 * it in the license file. 29 */ 30 31 #pragma once 32 33 #include <vector> 34 35 #include "mongo/base/disallow_copying.h" 36 #include "mongo/bson/timestamp.h" 37 #include "mongo/db/repl/repl_set_config.h" 38 #include "mongo/db/repl/scatter_gather_algorithm.h" 39 #include "mongo/executor/task_executor.h" 40 41 namespace mongo { 42 43 class Status; 44 45 namespace repl { 46 47 class ReplSetConfig; 48 class ScatterGatherRunner; 49 50 class FreshnessChecker { 51 MONGO_DISALLOW_COPYING(FreshnessChecker); 52 53 public: 54 enum ElectionAbortReason { 55 None = 0, 56 FresherNodeFound, // Freshness check found fresher node 57 FreshnessTie, // Freshness check resulted in one or more nodes with our lastAppliedOpTime 58 QuorumUnavailable, // Not enough up voters 59 QuorumUnreachable // Too many failed voter responses 60 }; 61 62 class Algorithm : public ScatterGatherAlgorithm { 63 public: 64 Algorithm(Timestamp lastOpTimeApplied, 65 const ReplSetConfig& rsConfig, 66 int selfIndex, 67 const std::vector<HostAndPort>& targets); 68 virtual ~Algorithm(); 69 virtual std::vector<executor::RemoteCommandRequest> getRequests() const; 70 virtual void processResponse(const executor::RemoteCommandRequest& request, 71 const executor::RemoteCommandResponse& response); 72 virtual bool hasReceivedSufficientResponses() const; 73 ElectionAbortReason shouldAbortElection() const; 74 75 private: 76 // Returns true if the number of failed votes is over _losableVotes() 77 bool hadTooManyFailedVoterResponses() const; 78 79 // Returns true if the member, by host and port, has a vote. 80 bool _isVotingMember(const HostAndPort host) const; 81 82 // Number of responses received so far. 83 int _responsesProcessed; 84 85 // Number of failed voter responses so far. 86 int _failedVoterResponses; 87 88 // Last Timestamp applied by the caller; used in the Fresh command 89 const Timestamp _lastOpTimeApplied; 90 91 // Config to use for this check 92 const ReplSetConfig _rsConfig; 93 94 // Our index position in _rsConfig 95 const int _selfIndex; 96 97 // The UP members we are checking 98 const std::vector<HostAndPort> _targets; 99 100 // Number of voting targets 101 int _votingTargets; 102 103 // Number of voting nodes which can error 104 int _losableVoters; 105 106 // 1 if I have a vote, otherwise 0 107 int _myVote; 108 109 // Reason to abort, start with None 110 ElectionAbortReason _abortReason; 111 }; 112 113 FreshnessChecker(); 114 virtual ~FreshnessChecker(); 115 116 /** 117 * Begins the process of sending replSetFresh commands to all non-DOWN nodes 118 * in currentConfig, with the intention of determining whether the current node 119 * is freshest. 120 * evh can be used to schedule a callback when the process is complete. 121 * If this function returns Status::OK(), evh is then guaranteed to be signaled. 122 **/ 123 StatusWith<executor::TaskExecutor::EventHandle> start(executor::TaskExecutor* executor, 124 const Timestamp& lastOpTimeApplied, 125 const ReplSetConfig& currentConfig, 126 int selfIndex, 127 const std::vector<HostAndPort>& targets); 128 129 /** 130 * Informs the freshness checker to cancel further processing. 131 */ 132 void cancel(); 133 134 /** 135 * Returns true if cancel() was called on this instance. 136 */ isCanceled()137 bool isCanceled() const { 138 return _isCanceled; 139 } 140 141 /** 142 * 'None' if the election should continue, otherwise the reason to abort 143 */ 144 ElectionAbortReason shouldAbortElection() const; 145 146 /** 147 * Returns the config version supplied in the config when start() was called. 148 * Useful for determining if the the config version has changed. 149 */ 150 long long getOriginalConfigVersion() const; 151 152 private: 153 std::shared_ptr<Algorithm> _algorithm; 154 std::unique_ptr<ScatterGatherRunner> _runner; 155 long long _originalConfigVersion; 156 bool _isCanceled; 157 }; 158 159 } // namespace repl 160 } // namespace mongo 161