MongoDB C++ Driver  legacy-1.0.3
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  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 
182  HostAndPort getMatchingHost(const ReadPreferenceSetting& criteria) const;
183 
187  Node* findNode(const HostAndPort& host);
188 
193  Node* findOrCreateNode(const HostAndPort& host);
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 }
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
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:122
Definition: replica_set_monitor_internal.h:229
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:127
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...