MongoDB C++ Driver  legacy-1.1.2
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 
39 namespace 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> > ConnectionMap;
50 
51  // Guard that creates a connection if needed, or removes it from
52  // the cache. This is so multiple isMaster calls can be in flight in the same
53  // set simultaneously.
54  class ConnectionGuard {
55  public:
56  // Lifetime of guard must be subset of lifetime of host
57  ConnectionGuard(ConnectionCache& cache, const HostAndPort& host)
58  : _cache(cache), _host(host) {
59  // this could throw.
60  _conn = _cache.getConnectionTo(_host);
61  }
62 
63  ~ConnectionGuard() {
64  _cache.returnConnection(_host, _conn);
65  }
66 
67  boost::shared_ptr<DBClientConnection> _conn;
68  // Reference to owner.
69  ConnectionCache& _cache;
70  const HostAndPort& _host;
71  };
72 
73  // If we don't have a connection to this host cached,
74  // or we have one that is dead, we reconnect and return
75  // If we have one, we remove it from the cache and return it
76  boost::shared_ptr<DBClientConnection> getConnectionTo(const HostAndPort& host);
77 
78  void returnConnection(const HostAndPort& host, boost::shared_ptr<DBClientConnection> conn);
79 
80  inline bool connectionOk(const boost::shared_ptr<DBClientConnection>& conn) {
81  // checks are ordered from cheap to expensive
82  return conn && !conn->isFailed() && conn->isStillConnected();
83  }
84 
85  ConnectionMap _cacheStorage;
86  boost::mutex _cacheLock;
87 };
88 
90  IsMasterReply() : ok(false) {}
91  IsMasterReply(const HostAndPort& host, int64_t latencyMicros, const BSONObj& reply)
92  : ok(false), host(host), latencyMicros(latencyMicros) {
93  parse(reply);
94  }
95 
99  void parse(const BSONObj& obj);
100 
101  bool ok; // if false, ignore all other fields
102  BSONObj raw; // Always owned. Other fields are allowed to be a view into this.
103  std::string setName;
104  bool isMaster;
105  bool secondary;
106  bool hidden;
107  OID electionId; // Set if this isMaster reply is from the primary
108  HostAndPort primary; // empty if not present
109  std::set<HostAndPort> normalHosts; // both "hosts" and "passives"
110  BSONObj tags;
111 
112  // remaining fields aren't in isMaster reply, but are known to caller.
113  HostAndPort host;
114  int64_t latencyMicros; // ignored if negative
115 };
116 
118  MONGO_DISALLOW_COPYING(SetState);
119 
120 public:
121  // A single node in the replicaSet
122  struct Node {
123  explicit Node(const HostAndPort& host) : host(host), latencyMicros(unknownLatency) {
124  markFailed();
125  }
126 
127  void markFailed() {
128  isUp = false;
129  isMaster = false;
130  }
131 
132  bool matches(const ReadPreference& pref) const;
133 
147  bool matches(const BSONObj& tag) const;
148 
152  void update(const IsMasterReply& reply);
153 
154  // Intentionally chosen to compare worse than all known latencies.
155  static const int64_t unknownLatency; // = numeric_limits<int64_t>::max()
156 
157  HostAndPort host;
158  bool isUp;
159  bool isMaster; // implies isUp
160  int64_t latencyMicros; // unknownLatency if unknown
161  BSONObj tags; // owned
162  };
163  typedef std::vector<Node> Nodes;
164 
168  SetState(StringData name, const std::set<HostAndPort>& seedNodes);
169 
175  HostAndPort getMatchingHost(const ReadPreferenceSetting& criteria) const;
176 
180  Node* findNode(const HostAndPort& host);
181 
186  Node* findOrCreateNode(const HostAndPort& host);
187 
188  void updateNodeIfInNodes(const IsMasterReply& reply);
189 
190  std::string getServerAddress() const;
191 
195  void checkInvariants() const;
196 
197  static ConfigChangeHook configChangeHook;
198 
199  boost::mutex mutex; // must hold this to access any other member or method (except name).
200 
201  // If Refresher::getNextStep returns WAIT, you should wait on the condition_variable,
202  // releasing mutex. It will be notified when either getNextStep will return something other
203  // than WAIT, or a new host is available for consideration by getMatchingHost. Essentially,
204  // this will be hit whenever the _refreshUntilMatches loop has the potential to make
205  // progress.
206  // TODO consider splitting cv into two: one for when looking for a master, one for all other
207  // cases.
208  boost::condition_variable cv;
209 
210  const std::string name; // safe to read outside lock since it is const
211  int consecutiveFailedScans;
212  std::set<HostAndPort> seedNodes; // updated whenever a master reports set membership changes
213  OID maxElectionId; // largest election id observed by this ReplicaSetMonitor
214  HostAndPort lastSeenMaster; // empty if we have never seen a master. can be same as current
215  Nodes nodes; // maintained sorted and unique by host
216  ScanStatePtr currentScan; // NULL if no scan in progress
217  int64_t latencyThresholdMicros;
218  mutable PseudoRandom rand; // only used for host selection to balance load
219  mutable int roundRobin; // used when useDeterministicHostSelection is true
220  mutable ConnectionCache connectionCache;
221 };
222 
224  MONGO_DISALLOW_COPYING(ScanState);
225 
226 public:
227  ScanState() : foundUpMaster(false), foundAnyUpNodes(false) {}
228 
233  template <typename Container>
234  void enqueAllUntriedHosts(const Container& container, PseudoRandom& rand);
235 
236  // Access to fields is guarded by associated SetState's mutex.
237  bool foundUpMaster;
238  bool foundAnyUpNodes;
239  std::deque<HostAndPort> hostsToScan; // Work queue.
240  std::set<HostAndPort> possibleNodes; // Nodes reported by non-primary hosts.
241  std::set<HostAndPort> waitingFor; // Hosts we have dispatched but haven't replied yet.
242  std::set<HostAndPort> triedHosts; // Hosts that have been returned from getNextStep.
243 
244  // All responses go here until we find a master.
245  typedef std::vector<IsMasterReply> UnconfirmedReplies;
246  UnconfirmedReplies unconfirmedReplies;
247 };
248 }
Definition: dbclient_rs.h:363
Node * findNode(const HostAndPort &host)
Returns the Node with the given host, or NULL if no Node has that host.
void update(const IsMasterReply &reply)
Updates this Node based on information in reply.
A StringData object wraps a 'const string&' or a 'const char*' without copying its contents...
Definition: string_data.h:43
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
Object ID type.
Definition: oid.h:60
BSON classes.
Node * findOrCreateNode(const HostAndPort &host)
Returns the Node with the given host, or creates one if no Node has that host.
SetState(StringData name, const std::set< HostAndPort > &seedNodes)
seedNodes must not be empty
void parse(const BSONObj &obj)
Never throws.
Definition: replica_set_monitor_internal.h:117
Definition: replica_set_monitor_internal.h:223
Connect to a Replica Set, from C++.
HostAndPort getMatchingHost(const ReadPreferenceSetting &criteria) const
Returns a host matching criteria or an empty host if no known host matches.
Name of a process on the network.
Definition: hostandport.h:37
Definition: replica_set_monitor_internal.h:122
void checkInvariants() const
Before unlocking, do DEV checkInvariants();.
Uses http://en.wikipedia.org/wiki/Xorshift.
Definition: random.h:27
Definition: replica_set_monitor_internal.h:89
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary represent...
Definition: bsonobj.h:78
Definition: replica_set_monitor_internal.h:42
void enqueAllUntriedHosts(const Container &container, PseudoRandom &rand)
Adds all hosts in container that aren't in triedHosts to hostsToScan, then shuffles the queue...