MongoDB C++ Driver legacy-1.0.5
Loading...
Searching...
No Matches
replica_set_monitor_internal.h
1/* Copyright 2014 MongoDB Inc.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
22#pragma once
23
24#include <boost/thread/condition_variable.hpp>
25#include <deque>
26#include <set>
27#include <string>
28#include <vector>
29
30#include "mongo/base/disallow_copying.h"
31#include "mongo/client/dbclient_rs.h" // for TagSet and ReadPreferenceSettings
32#include "mongo/client/replica_set_monitor.h"
33#include "mongo/db/jsobj.h"
34#include "mongo/platform/cstdint.h"
35#include "mongo/platform/random.h"
36#include "mongo/platform/unordered_map.h"
37#include "mongo/util/net/hostandport.h"
38
39namespace mongo {
40 // Internal connection cache for isMaster. Used to amortize the cost of establishing connections
41 // to a remote host. Not really a pool because we only keep one connection per host.
43 public:
44 // Uses a cached connection (may need to reconnect) to execute a remote isMaster call
45 // on the given host. Returns microseconds taken for remote call to complete. Throws.
46 uint64_t timedIsMaster(const HostAndPort& host, BSONObj* out);
47
48 private:
49 typedef unordered_map<HostAndPort, boost::shared_ptr<DBClientConnection> >
50 ConnectionMap;
51
52 // Guard that creates a connection if needed, or removes it from
53 // the cache. This is so multiple isMaster calls can be in flight in the same
54 // set simultaneously.
55 class ConnectionGuard {
56 public:
57 // Lifetime of guard must be subset of lifetime of host
58 ConnectionGuard(ConnectionCache& cache,
59 const HostAndPort& host)
60 : _cache(cache)
61 , _host(host)
62 {
63 // this could throw.
64 _conn = _cache.getConnectionTo(_host);
65 }
66
67 ~ConnectionGuard() {
68 _cache.returnConnection(_host, _conn);
69 }
70
71 boost::shared_ptr<DBClientConnection> _conn;
72 // Reference to owner.
73 ConnectionCache& _cache;
74 const HostAndPort& _host;
75 };
76
77 // If we don't have a connection to this host cached,
78 // or we have one that is dead, we reconnect and return
79 // If we have one, we remove it from the cache and return it
80 boost::shared_ptr<DBClientConnection> getConnectionTo(const HostAndPort& host);
81
82 void returnConnection(const HostAndPort& host, boost::shared_ptr<DBClientConnection> conn);
83
84 inline bool connectionOk(const boost::shared_ptr<DBClientConnection>& conn) {
85 // checks are ordered from cheap to expensive
86 return conn && !conn->isFailed() && conn->isStillConnected();
87 }
88
89 ConnectionMap _cacheStorage;
90 boost::mutex _cacheLock;
91 };
92
94 IsMasterReply() : ok(false) {}
95 IsMasterReply(const HostAndPort& host, int64_t latencyMicros, const BSONObj& reply)
96 : ok(false)
97 , host(host)
98 , latencyMicros(latencyMicros) {
99 parse(reply);
100 }
101
105 void parse(const BSONObj& obj);
106
107 bool ok; // if false, ignore all other fields
108 BSONObj raw; // Always owned. Other fields are allowed to be a view into this.
109 std::string setName;
110 bool isMaster;
111 bool secondary;
112 bool hidden;
113 OID electionId; // Set if this isMaster reply is from the primary
114 HostAndPort primary; // empty if not present
115 std::set<HostAndPort> normalHosts; // both "hosts" and "passives"
116 BSONObj tags;
117
118 // remaining fields aren't in isMaster reply, but are known to caller.
119 HostAndPort host;
120 int64_t latencyMicros; // ignored if negative
121 };
122
124 MONGO_DISALLOW_COPYING(SetState);
125 public:
126
127 // A single node in the replicaSet
128 struct Node {
129 explicit Node(const HostAndPort& host)
130 : host(host)
131 , latencyMicros(unknownLatency) {
132 markFailed();
133 }
134
135 void markFailed() {
136 isUp = false;
137 isMaster = false;
138 }
139
140 bool matches(const ReadPreference& pref) const;
141
155 bool matches(const BSONObj& tag) const;
156
160 void update(const IsMasterReply& reply);
161
162 // Intentionally chosen to compare worse than all known latencies.
163 static const int64_t unknownLatency; // = numeric_limits<int64_t>::max()
164
165 HostAndPort host;
166 bool isUp;
167 bool isMaster; // implies isUp
168 int64_t latencyMicros; // unknownLatency if unknown
169 BSONObj tags; // owned
170 };
171 typedef std::vector<Node> Nodes;
172
176 SetState(StringData name, const std::set<HostAndPort>& seedNodes);
177
184
188 Node* findNode(const HostAndPort& host);
189
195
196 void updateNodeIfInNodes(const IsMasterReply& reply);
197
198 std::string getServerAddress() const;
199
203 void checkInvariants() const;
204
205 static ConfigChangeHook configChangeHook;
206
207 boost::mutex mutex; // must hold this to access any other member or method (except name).
208
209 // If Refresher::getNextStep returns WAIT, you should wait on the condition_variable,
210 // releasing mutex. It will be notified when either getNextStep will return something other
211 // than WAIT, or a new host is available for consideration by getMatchingHost. Essentially,
212 // this will be hit whenever the _refreshUntilMatches loop has the potential to make
213 // progress.
214 // TODO consider splitting cv into two: one for when looking for a master, one for all other
215 // cases.
216 boost::condition_variable cv;
217
218 const std::string name; // safe to read outside lock since it is const
219 int consecutiveFailedScans;
220 std::set<HostAndPort> seedNodes; // updated whenever a master reports set membership changes
221 OID maxElectionId; // largest election id observed by this ReplicaSetMonitor
222 HostAndPort lastSeenMaster; // empty if we have never seen a master. can be same as current
223 Nodes nodes; // maintained sorted and unique by host
224 ScanStatePtr currentScan; // NULL if no scan in progress
225 int64_t latencyThresholdMicros;
226 mutable PseudoRandom rand; // only used for host selection to balance load
227 mutable int roundRobin; // used when useDeterministicHostSelection is true
228 mutable ConnectionCache connectionCache;
229 };
230
232 MONGO_DISALLOW_COPYING(ScanState);
233 public:
234 ScanState() : foundUpMaster(false), foundAnyUpNodes(false) {}
235
240 template <typename Container>
241 void enqueAllUntriedHosts(const Container& container, PseudoRandom& rand);
242
243 // Access to fields is guarded by associated SetState's mutex.
244 bool foundUpMaster;
245 bool foundAnyUpNodes;
246 std::deque<HostAndPort> hostsToScan; // Work queue.
247 std::set<HostAndPort> possibleNodes; // Nodes reported by non-primary hosts.
248 std::set<HostAndPort> waitingFor; // Hosts we have dispatched but haven't replied yet.
249 std::set<HostAndPort> triedHosts; // Hosts that have been returned from getNextStep.
250
251 // All responses go here until we find a master.
252 typedef std::vector<IsMasterReply> UnconfirmedReplies;
253 UnconfirmedReplies unconfirmedReplies;
254 };
255}
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary representa...
Definition bsonobj.h:78
Definition replica_set_monitor_internal.h:42
Object ID type.
Definition oid.h:60
Connect to a Replica Set, from C++.
BSON classes.
the main MongoDB namespace
Definition bulk_operation_builder.h:24
Name of a process on the network.
Definition hostandport.h:36
Definition dbclient_rs.h:316
Definition replica_set_monitor_internal.h:93
void parse(const BSONObj &obj)
Never throws.
Definition replica_set_monitor_internal.h:231
void enqueAllUntriedHosts(const Container &container, PseudoRandom &rand)
Adds all hosts in container that aren't in triedHosts to hostsToScan, then shuffles the queue.
Definition replica_set_monitor_internal.h:128
bool matches(const BSONObj &tag) const
Checks if the given tag matches the tag attached to this node.
void update(const IsMasterReply &reply)
Updates this Node based on information in reply.
Definition replica_set_monitor_internal.h:123
void checkInvariants() const
Before unlocking, do DEV checkInvariants();.
SetState(StringData name, const std::set< HostAndPort > &seedNodes)
seedNodes must not be empty
Node * findOrCreateNode(const HostAndPort &host)
Returns the Node with the given host, or creates one if no Node has that host.
Node * findNode(const HostAndPort &host)
Returns the Node with the given host, or NULL if no Node has that host.
HostAndPort getMatchingHost(const ReadPreferenceSetting &criteria) const
Returns a host matching criteria or an empty host if no known host matches.