diff options
author | Dwight <dmerriman@gmail.com> | 2008-09-11 09:15:34 -0400 |
---|---|---|
committer | Dwight <dmerriman@gmail.com> | 2008-09-11 09:15:34 -0400 |
commit | 5f163f72b8a9bf3924092af1bb695c7606ae7eb8 (patch) | |
tree | 41b15f6626ac6718a54494775a84418609a4d6d7 /db | |
parent | f2bee299e426865e92b03c49dc16ff997bd88fd0 (diff) | |
download | mongo-5f163f72b8a9bf3924092af1bb695c7606ae7eb8.tar.gz |
dbgrid.vcproj missing; more work on dbgridr0.1.2_rc1
Diffstat (limited to 'db')
-rw-r--r-- | db/jsobj.cpp | 7 | ||||
-rw-r--r-- | db/jsobj.h | 2 | ||||
-rw-r--r-- | db/repl.cpp | 109 | ||||
-rw-r--r-- | db/repl.h | 2 | ||||
-rw-r--r-- | db/replset.h | 17 |
5 files changed, 135 insertions, 2 deletions
diff --git a/db/jsobj.cpp b/db/jsobj.cpp index 8687321f3e4..dc981941167 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -19,6 +19,8 @@ #include "stdafx.h" #include "jsobj.h" #include "../util/goodies.h" +#include <limits> + Element nullElement; @@ -367,6 +369,11 @@ JSObj JSObj::extractFields(JSObj& pattern) { return b.doneAndDecouple(); } +int JSObj::getIntField(const char *name) { + Element e = getField(name); + return e.type() == Number ? (int) e.number() : INT_MIN; +} + bool JSObj::getBoolField(const char *name) { Element e = getField(name); return e.type() == Bool ? e.boolean() : false; diff --git a/db/jsobj.h b/db/jsobj.h index 810442def45..4b630b0de27 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -241,6 +241,8 @@ public: JSObj getObjectField(const char *name); + int getIntField(const char *name); // INT_MIN if not present + bool getBoolField(const char *name); /* makes a new JSObj with the fields specified in pattern. diff --git a/db/repl.cpp b/db/repl.cpp index e41473b0e5c..2c301f4735d 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -33,6 +33,7 @@ #include "query.h" #include "json.h" #include "db.h" +#include "commands.h" extern int port; extern boost::mutex dbMutex; @@ -47,6 +48,103 @@ void ensureHaveIdIndex(const char *ns); ReplPair *replPair = 0; +class CmdIsMaster : public Command { +public: + CmdIsMaster() : Command("ismaster") { } + + virtual bool run(const char *ns, JSObj& cmdObj, string& errmsg, JSObjBuilder& result) { + int x = -2; + if( replPair ) { + x = replPair->state; + } + else { + result.append("msg", "not paired"); + } + result.append("ismaster", x); + return true; + } +} cmdismaster; + +/* negotiate who is master + + -1=not set (probably means we just booted) + 0=was slave + 1=was master + + remote,local -> new remote,local + !1,1 -> 0,1 + 1,!1 -> 1,0 + -1,-1 -> dominant->1, nondom->0 + 0,0 -> dominant->1, nondom->0 + 1,1 -> dominant->1, nondom->0 + + { negotiatemaster:1, i_was:<state>, your_name:<hostname> } + returns: + { ok:1, you_are:..., i_am:... } +*/ +class CmdNegotiateMaster : public Command { +public: + CmdNegotiateMaster() : Command("negotiatemaster") { } + + virtual bool adminOnly() { return true; } + + virtual bool run(const char *ns, JSObj& cmdObj, string& errmsg, JSObjBuilder& result) { + if( replPair == 0 ) { + problem() << "got negotiatemaster cmd but we are not in paired mode." << endl; + errmsg = "not paired"; + return false; + } + + int was = cmdObj.getIntField("i_was"); + string myname = cmdObj.getStringField("your_name"); + if( myname.empty() || was < -1 ) { + errmsg = "your_name/i_was not specified"; + return false; + } + + int me, you; + if( was == replPair->state ) { + if( replPair->dominant(myname) ) { + me=1;you=0; + } + else { + me=0;you=1; + } + } + else if( was == 1 ) { + me=0;you=1; + } + else { + me=1;you=0; + } + + replPair->state = me; + result.append("you_are", you); + result.append("i_am", me); + + return true; + } +} cmdnegotiatemaster; + +void ReplPair::negotiate(DBClientConnection *conn) { + JSObjBuilder b; + b.append("negotiatemaster",1); + b.append("i_was", state); + b.append("your_name", remoteHost); + JSObj cmd = b.done(); + JSObj res = conn->findOne("admin.$cmd", cmd); + if( res.getIntField("ok") != 1 ) { + problem() << "negotiate fails: " << res.toString() << '\n'; + return; + } + int x = res.getIntField("you_are"); + if( x != 0 && x != 1 ) { + problem() << "negotiate: bad you_are value " << res.toString() << endl; + return; + } + setMaster(x); +} + OpTime last(0, 0); OpTime OpTime::now() { @@ -177,8 +275,10 @@ void ReplSource::loadAll(vector<ReplSource*>& v) { auto_ptr<Cursor> c = findTableScan("local.sources", emptyObj); while( c->ok() ) { ReplSource tmp(c->current()); - if( replPair && tmp.hostName == replPair->remote && tmp.sourceName == "main" ) + if( replPair && tmp.hostName == replPair->remote && tmp.sourceName == "main" ) { gotPairWith = true; + tmp.paired = true; + } addSourceToList(v, tmp, old); c->advance(); } @@ -450,6 +550,10 @@ bool ReplSource::sync() { conn = auto_ptr<DBClientConnection>(new DBClientConnection()); string errmsg; if( !conn->connect(hostName.c_str(), errmsg) ) { + if( replPair && paired ) { + assert( startsWith(hostName.c_str(), replPair->remoteHost.c_str()) ); + replPair->setMaster(1); + } resetConnection(); log() << "pull: cantconn " << errmsg << endl; sleepsecs(1); @@ -457,6 +561,9 @@ bool ReplSource::sync() { } } + if( paired ) + replPair->negotiate(conn.get()); + /* // get current mtime at the server. JSObj o = conn->findOne("admin.$cmd", opTimeQuery); diff --git a/db/repl.h b/db/repl.h index 52f2719073f..43c52c3232d 100644 --- a/db/repl.h +++ b/db/repl.h @@ -98,7 +98,7 @@ class ReplSource { ReplSource(); public: bool paired; // --pair in use - string hostName; // ip addr or hostname + string hostName; // ip addr or hostname plus optionally, ":<port>" string sourceName; // a logical source name. string only; // only a certain db. note that in the sources collection, this may not be changed once you start replicating. diff --git a/db/replset.h b/db/replset.h index 58b32046b55..9d3eb8dbe03 100644 --- a/db/replset.h +++ b/db/replset.h @@ -30,15 +30,32 @@ class ReplPair { public: + int state; int remotePort; string remoteHost; string remote; // host:port if port specified. + int date; // -1 not yet set; 0=slave; 1=master ReplPair(const char *remoteEnd); + bool dominant(const string& myname) { + if( myname == remoteHost ) + return port > remotePort; + return myname > remoteHost; + } + + void setMaster(int n) { + if( n == state ) + return; + log() << "pair: setting master=" << n << " was " << state << '\n'; + state = n; + } + + void negotiate(DBClientConnection *conn); }; ReplPair::ReplPair(const char *remoteEnd) { + state = -1; remote = remoteEnd; remotePort = DBPort; remoteHost = remoteEnd; |