MongoDB C++ Driver  legacy-1.0.5
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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> >
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 
183  HostAndPort getMatchingHost(const ReadPreferenceSetting& criteria) const;
184 
188  Node* findNode(const HostAndPort& host);
189 
194  Node* findOrCreateNode(const HostAndPort& host);
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 }
Definition: dbclient_rs.h:316
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.
the main MongoDB namespace
Definition: bulk_operation_builder.h:24
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:123
Definition: replica_set_monitor_internal.h:231
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:36
Definition: replica_set_monitor_internal.h:128
void checkInvariants() const
Before unlocking, do DEV checkInvariants();.
Definition: replica_set_monitor_internal.h:93
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...