diff options
author | Antonin Kral <a.kral@bobek.cz> | 2011-09-14 17:08:06 +0200 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2011-09-14 17:08:06 +0200 |
commit | 5d342a758c6095b4d30aba0750b54f13b8916f51 (patch) | |
tree | 762e9aa84781f5e3b96db2c02d356c29cf0217c0 /db/repl/rs_config.h | |
parent | cbe2d992e9cd1ea66af9fa91df006106775d3073 (diff) | |
download | mongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz |
Imported Upstream version 2.0.0
Diffstat (limited to 'db/repl/rs_config.h')
-rw-r--r-- | db/repl/rs_config.h | 144 |
1 files changed, 134 insertions, 10 deletions
diff --git a/db/repl/rs_config.h b/db/repl/rs_config.h index 7d43fe6..f69052a 100644 --- a/db/repl/rs_config.h +++ b/db/repl/rs_config.h @@ -20,26 +20,37 @@ #pragma once -#include "../../util/hostandport.h" +#include "../../util/net/hostandport.h" +#include "../../util/concurrency/race.h" #include "health.h" namespace mongo { - - /* singleton config object is stored here */ + class Member; const string rsConfigNs = "local.system.replset"; class ReplSetConfig { enum { EMPTYCONFIG = -2 }; + struct TagSubgroup; public: - /* if something is misconfigured, throws an exception. - if couldn't be queried or is just blank, ok() will be false. - */ + /** + * This contacts the given host and tries to get a config from them. + * + * This sends a test heartbeat to the host and, if all goes well and the + * host has a more recent config, fetches the config and loads it (see + * from(). + * + * If it's contacting itself, it skips the heartbeat (for obvious + * reasons.) If something is misconfigured, throws an exception. If the + * host couldn't be queried or is just blank, ok() will be false. + */ ReplSetConfig(const HostAndPort& h); - ReplSetConfig(BSONObj cfg); + ReplSetConfig(BSONObj cfg, bool force=false); bool ok() const { return _ok; } + struct TagRule; + struct MemberCfg { MemberCfg() : _id(-1), votes(1), priority(1.0), arbiterOnly(false), slaveDelay(0), hidden(false), buildIndexes(true) { } int _id; /* ordinal */ @@ -50,12 +61,24 @@ namespace mongo { int slaveDelay; /* seconds. int rather than unsigned for convenient to/front bson conversion. */ bool hidden; /* if set, don't advertise to drives in isMaster. for non-primaries (priority 0) */ bool buildIndexes; /* if false, do not create any non-_id indexes */ - set<string> tags; /* tagging for data center, rack, etc. */ - BSONObj initialSync; /* directions for initial sync source */ - + map<string,string> tags; /* tagging for data center, rack, etc. */ + private: + set<TagSubgroup*> _groups; // the subgroups this member belongs to + public: + const set<TagSubgroup*>& groups() const { + return _groups; + } + set<TagSubgroup*>& groupsw() { + return _groups; + } void check() const; /* check validity, assert if not. */ BSONObj asBson() const; bool potentiallyHot() const { return !arbiterOnly && priority > 0; } + void updateGroups(const OpTime& last) { + for (set<TagSubgroup*>::iterator it = _groups.begin(); it != _groups.end(); it++) { + ((TagSubgroup*)(*it))->updateLast(last); + } + } bool operator==(const MemberCfg& r) const { return _id==r._id && votes == r.votes && h == r.h && priority == r.priority && arbiterOnly == r.arbiterOnly && slaveDelay == r.slaveDelay && hidden == r.hidden && @@ -70,6 +93,7 @@ namespace mongo { HealthOptions ho; string md5; BSONObj getLastErrorDefaults; + map<string,TagRule*> rules; list<HostAndPort> otherMemberHostnames() const; // except self @@ -88,12 +112,112 @@ namespace mongo { void saveConfigLocally(BSONObj comment); // to local db string saveConfigEverywhere(); // returns textual info on what happened + /** + * Update members' groups when the config changes but members stay the same. + */ + void updateMembers(List1<Member> &dest); + BSONObj asBson() const; + bool _constructed; private: bool _ok; void from(BSONObj); void clear(); + + struct TagClause; + + /** + * This is a logical grouping of servers. It is pointed to by a set of + * servers with a certain tag. + * + * For example, suppose servers A, B, and C have the tag "dc" : "nyc". If we + * have a rule {"dc" : 2}, then we want A _or_ B _or_ C to have the + * write for one of the "dc" critiria to be fulfilled, so all three will + * point to this subgroup. When one of their oplog-tailing cursors is + * updated, this subgroup is updated. + */ + struct TagSubgroup : boost::noncopyable { + ~TagSubgroup(); // never called; not defined + TagSubgroup(string nm) : name(nm) { } + const string name; + OpTime last; + vector<TagClause*> clauses; + + // this probably won't actually point to valid members after the + // subgroup is created, as initFromConfig() makes a copy of the + // config + set<MemberCfg*> m; + + void updateLast(const OpTime& op); + + //string toString() const; + + /** + * If two tags have the same name, they should compare as equal so + * that members don't have to update two identical groups on writes. + */ + bool operator() (TagSubgroup& lhs, TagSubgroup& rhs) const { + return lhs.name < rhs.name; + } + }; + + /** + * An argument in a rule. For example, if we had the rule {dc : 2, + * machines : 3}, "dc" : 2 and "machines" : 3 would be two TagClauses. + * + * Each tag clause has a set of associated subgroups. For example, if + * we had "dc" : 2, our subgroups might be "nyc", "sf", and "hk". + */ + struct TagClause { + OpTime last; + map<string,TagSubgroup*> subgroups; + TagRule *rule; + string name; + /** + * If we have get a clause like {machines : 3} and this server is + * tagged with "machines", then it's really {machines : 2}, as we + * will always be up-to-date. So, target would be 3 and + * actualTarget would be 2, in that example. + */ + int target; + int actualTarget; + + void updateLast(const OpTime& op); + string toString() const; + }; + + /** + * Parses getLastErrorModes. + */ + void parseRules(const BSONObj& modes); + + /** + * Create a hash containing every possible clause that could be used in a + * rule and the servers related to that clause. + * + * For example, suppose we have the following servers: + * A {"dc" : "ny", "ny" : "rk1"} + * B {"dc" : "ny", "ny" : "rk1"} + * C {"dc" : "ny", "ny" : "rk2"} + * D {"dc" : "sf", "sf" : "rk1"} + * E {"dc" : "sf", "sf" : "rk2"} + * + * This would give us the possible criteria: + * "dc" -> {A, B, C},{D, E} + * "ny" -> {A, B},{C} + * "sf" -> {D},{E} + */ + void _populateTagMap(map<string,TagClause> &tagMap); + + public: + struct TagRule { + vector<TagClause*> clauses; + OpTime last; + + void updateLast(const OpTime& op); + string toString() const; + }; }; } |