MongoDB C++ Driver legacy-1.0.0
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 HostAndPort primary; // empty if not present
114 std::set<HostAndPort> normalHosts; // both "hosts" and "passives"
115 BSONObj tags;
116
117 // remaining fields aren't in isMaster reply, but are known to caller.
118 HostAndPort host;
119 int64_t latencyMicros; // ignored if negative
120 };
121
123 MONGO_DISALLOW_COPYING(SetState);
124 public:
125
126 // A single node in the replicaSet
127 struct Node {
128 explicit Node(const HostAndPort& host)
129 : host(host)
130 , latencyMicros(unknownLatency) {
131 markFailed();
132 }
133
134 void markFailed() {
135 isUp = false;
136 isMaster = false;
137 }
138
139 bool matches(const ReadPreference& pref) const;
140
154 bool matches(const BSONObj& tag) const;
155
159 void update(const IsMasterReply& reply);
160
161 // Intentionally chosen to compare worse than all known latencies.
162 static const int64_t unknownLatency; // = numeric_limits<int64_t>::max()
163
164 HostAndPort host;
165 bool isUp;
166 bool isMaster; // implies isUp
167 int64_t latencyMicros; // unknownLatency if unknown
168 BSONObj tags; // owned
169 };
170 typedef std::vector<Node> Nodes;
171
175 SetState(StringData name, const std::set<HostAndPort>& seedNodes);
176
183
187 Node* findNode(const HostAndPort& host);
188
194
195 void updateNodeIfInNodes(const IsMasterReply& reply);
196
197 std::string getServerAddress() const;
198
202 void checkInvariants() const;
203
204 static ConfigChangeHook configChangeHook;
205
206 boost::mutex mutex; // must hold this to access any other member or method (except name).
207
208 // If Refresher::getNextStep returns WAIT, you should wait on the condition_variable,
209 // releasing mutex. It will be notified when either getNextStep will return something other
210 // than WAIT, or a new host is available for consideration by getMatchingHost. Essentially,
211 // this will be hit whenever the _refreshUntilMatches loop has the potential to make
212 // progress.
213 // TODO consider splitting cv into two: one for when looking for a master, one for all other
214 // cases.
215 boost::condition_variable cv;
216
217 const std::string name; // safe to read outside lock since it is const
218 int consecutiveFailedScans;
219 std::set<HostAndPort> seedNodes; // updated whenever a master reports set membership changes
220 HostAndPort lastSeenMaster; // empty if we have never seen a master. can be same as current
221 Nodes nodes; // maintained sorted and unique by host
222 ScanStatePtr currentScan; // NULL if no scan in progress
223 int64_t latencyThresholdMicros;
224 mutable PseudoRandom rand; // only used for host selection to balance load
225 mutable int roundRobin; // used when useDeterministicHostSelection is true
226 mutable ConnectionCache connectionCache;
227 };
228
230 MONGO_DISALLOW_COPYING(ScanState);
231 public:
232 ScanState() : foundUpMaster(false), foundAnyUpNodes(false) {}
233
238 template <typename Container>
239 void enqueAllUntriedHosts(const Container& container, PseudoRandom& rand);
240
241 // Access to fields is guarded by associated SetState's mutex.
242 bool foundUpMaster;
243 bool foundAnyUpNodes;
244 std::deque<HostAndPort> hostsToScan; // Work queue.
245 std::set<HostAndPort> possibleNodes; // Nodes reported by non-primary hosts.
246 std::set<HostAndPort> waitingFor; // Hosts we have dispatched but haven't replied yet.
247 std::set<HostAndPort> triedHosts; // Hosts that have been returned from getNextStep.
248
249 // All responses go here until we find a master.
250 typedef std::vector<IsMasterReply> UnconfirmedReplies;
251 UnconfirmedReplies unconfirmedReplies;
252 };
253}
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
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:229
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:127
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:122
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.