summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <aaron@10gen.com>2010-08-02 22:28:04 -0700
committerAaron <aaron@10gen.com>2010-08-02 22:28:04 -0700
commit5240b2c0ff2b0f0f3999e456ac0b493d77153735 (patch)
tree86fbb673fc079bcc9f5014dbb6e977edeb0cd366
parent86c72c061a597dc03f0605abeff829b262d1b908 (diff)
parentdde3464141b636123cff33ea45479ac9e6c9fe7d (diff)
downloadmongo-5240b2c0ff2b0f0f3999e456ac0b493d77153735.tar.gz
Merge branch 'master' of github.com:mongodb/mongo
-rw-r--r--jstests/replsets/replset1.js9
-rw-r--r--s/config.cpp97
-rw-r--r--s/config.h12
-rw-r--r--s/grid.cpp6
-rw-r--r--s/server.cpp2
-rw-r--r--shell/servers.js6
-rw-r--r--shell/utils.js34
7 files changed, 133 insertions, 33 deletions
diff --git a/jstests/replsets/replset1.js b/jstests/replsets/replset1.js
index 61f3d99d549..6a18dffaaa2 100644
--- a/jstests/replsets/replset1.js
+++ b/jstests/replsets/replset1.js
@@ -70,9 +70,6 @@ doTest = function( signal ) {
}
- // Here's how to restart a node:
- replTest.restart( master_id );
-
// Now let's write some documents to the new master
for(var i=0; i<1000; i++) {
new_master.getDB("bar").bar.save({a: i});
@@ -82,6 +79,7 @@ doTest = function( signal ) {
// Here's how to restart the old master node:
slave = replTest.restart( master_id );
+
// Now, let's make sure that the old master comes up as a slave
assert.soon(function() {
var res = slave.getDB("admin").runCommand({ismaster: 1});
@@ -98,6 +96,7 @@ doTest = function( signal ) {
// And that both slave nodes have all the updates
new_master = replTest.getMaster();
+ assert.eq( 1000 , new_master.getDB( "bar" ).runCommand( { count:"bar"} ).n , "assumption 2")
replTest.awaitReplication();
slaves = replTest.liveNodes.slaves;
@@ -106,11 +105,11 @@ doTest = function( signal ) {
slave.setSlaveOk();
var count = slave.getDB("bar").runCommand({count: "bar"});
printjson( count );
- assert( count.n == 1000 , slave + " expected 1000 but count was " + count.n);
+ assert.eq( 1000 , count.n , "slave count wrong: " + slave );
});
// Shut down the set and finish the test.
replTest.stopSet( signal );
}
-// doTest( 15 );
+doTest( 15 );
diff --git a/s/config.cpp b/s/config.cpp
index 50682c67cb2..83ff5d9c545 100644
--- a/s/config.cpp
+++ b/s/config.cpp
@@ -431,11 +431,95 @@ namespace mongo {
if ( ! ok )
return false;
}
+
+ _config = configHosts;
string fullString;
joinStringDelim( configHosts, &fullString, ',' );
_primary.setAddress( fullString , true );
log(1) << " config string : " << fullString << endl;
+
+ return true;
+ }
+
+ bool ConfigServer::checkConfigServersConsistent( string& errmsg , int tries ) const {
+ if ( _config.size() == 1 )
+ return true;
+
+ if ( tries <= 0 )
+ return false;
+
+ unsigned firstGood = 0;
+ int up = 0;
+ vector<BSONObj> res;
+ for ( unsigned i=0; i<_config.size(); i++ ){
+ BSONObj x;
+ try {
+ ScopedDbConnection conn( _config[i] );
+ if ( ! conn->simpleCommand( "config" , &x , "dbhash" ) )
+ x = BSONObj();
+ else {
+ x = x.getOwned();
+ if ( up == 0 )
+ firstGood = i;
+ up++;
+ }
+ conn.done();
+ }
+ catch ( std::exception& e ){
+ log(LL_WARNING) << " couldn't check on config server:" << _config[i] << " ok for now" << endl;
+ }
+ res.push_back(x);
+ }
+
+ if ( up == 0 ){
+ errmsg = "no config servers reachable";
+ return false;
+ }
+
+ if ( up == 1 ){
+ log( LL_WARNING ) << "only 1 config server reachable, continuing" << endl;
+ return true;
+ }
+
+ BSONObj base = res[firstGood];
+ for ( unsigned i=firstGood+1; i<res.size(); i++ ){
+ if ( res[i].isEmpty() )
+ continue;
+
+ string c1 = base.getFieldDotted( "collections.chunks" );
+ string c2 = res[i].getFieldDotted( "collections.chunks" );
+
+ string d1 = base.getFieldDotted( "collections.databases" );
+ string d2 = res[i].getFieldDotted( "collections.databases" );
+
+ if ( c1 == c2 && d1 == d2 )
+ continue;
+
+ stringstream ss;
+ ss << "config servers " << _config[firstGood] << " and " << _config[i] << " differ";
+ log( LL_WARNING ) << ss.str();
+ if ( tries <= 1 ){
+ ss << "\n" << c1 << "\t" << c2 << "\n" << d1 << "\t" << d2;
+ errmsg = ss.str();
+ return false;
+ }
+
+ return checkConfigServersConsistent( errmsg , tries - 1 );
+ }
+
+ return true;
+ }
+
+ bool ConfigServer::ok( bool checkConsistency ){
+ if ( ! _primary.ok() )
+ return false;
+
+ string errmsg;
+ if ( ! checkConfigServersConsistent( errmsg ) ){
+ log( LL_ERROR ) << "config servers not in sync! " << errmsg << endl;
+ return false;
+ }
return true;
}
@@ -513,10 +597,15 @@ namespace mongo {
// indexes
- conn->ensureIndex( ShardNS::chunk , BSON( "ns" << 1 << "min" << 1 ) , true );
- conn->ensureIndex( ShardNS::chunk , BSON( "ns" << 1 << "shard" << 1 << "min" << 1 ) , true );
- conn->ensureIndex( ShardNS::chunk , BSON( "ns" << 1 << "lastmod" << 1 ) , true );
- conn->ensureIndex( ShardNS::shard , BSON( "host" << 1 ) , true );
+ try {
+ conn->ensureIndex( ShardNS::chunk , BSON( "ns" << 1 << "min" << 1 ) , true );
+ conn->ensureIndex( ShardNS::chunk , BSON( "ns" << 1 << "shard" << 1 << "min" << 1 ) , true );
+ conn->ensureIndex( ShardNS::chunk , BSON( "ns" << 1 << "lastmod" << 1 ) , true );
+ conn->ensureIndex( ShardNS::shard , BSON( "host" << 1 ) , true );
+ }
+ catch ( std::exception& e ){
+ log( LL_WARNING ) << "couldn't create indexes on config db: " << e.what() << endl;
+ }
conn.done();
}
diff --git a/s/config.h b/s/config.h
index c1767743acd..5bff03f2711 100644
--- a/s/config.h
+++ b/s/config.h
@@ -199,9 +199,7 @@ namespace mongo {
ConfigServer();
~ConfigServer();
- bool ok(){
- return _primary.ok();
- }
+ bool ok( bool checkConsistency = false );
virtual string modelServer(){
uassert( 10190 , "ConfigServer not setup" , _primary.ok() );
@@ -241,8 +239,16 @@ namespace mongo {
static int VERSION;
+
+ /**
+ * check to see if all config servers have the same state
+ * will try tries time to make sure not catching in a bad state
+ */
+ bool checkConfigServersConsistent( string& errmsg , int tries = 4 ) const;
+
private:
string getHost( string name , bool withPort );
+ vector<string> _config;
};
} // namespace mongo
diff --git a/s/grid.cpp b/s/grid.cpp
index ea05f1bcc99..6843059c8c9 100644
--- a/s/grid.cpp
+++ b/s/grid.cpp
@@ -132,6 +132,12 @@ namespace mongo {
try {
ScopedDbConnection newShardConn( host );
newShardConn->getLastError();
+
+ if ( newShardConn->type() == ConnectionString::SYNC ){
+ newShardConn.done();
+ *errMsg = "can't use sync cluster as a shard. for replica set, have to use <name>/<server1>,<server2>,...";
+ return false;
+ }
// get the shard's local db's listing
BSONObj res;
diff --git a/s/server.cpp b/s/server.cpp
index 09cdb0fbbfc..75c6c782bd8 100644
--- a/s/server.cpp
+++ b/s/server.cpp
@@ -260,7 +260,7 @@ int main(int argc, char* argv[], char *envp[] ) {
return 7;
}
- if ( ! configServer.ok() ){
+ if ( ! configServer.ok( true ) ){
cout << "configServer startup check failed" << endl;
return 8;
}
diff --git a/shell/servers.js b/shell/servers.js
index 51f3d8af3c6..c36fba4bba9 100644
--- a/shell/servers.js
+++ b/shell/servers.js
@@ -1199,7 +1199,7 @@ ReplSetTest.prototype.reInitiate = function() {
ReplSetTest.prototype.awaitReplication = function() {
this.getMaster();
- latest = this.liveNodes.master.getDB("local")['oplog.rs'].find({}).sort({'$natural': -1}).limit(1).next()['ts']['t']
+ latest = this.liveNodes.master.getDB("local")['oplog.rs'].find({}).sort({'$natural': -1}).limit(1).next()['ts']
print(latest);
this.attempt({context: this, timeout: 30000, desc: "awaiting replication"},
@@ -1220,10 +1220,10 @@ ReplSetTest.prototype.awaitReplication = function() {
if(log.find({}).sort({'$natural': -1}).limit(1).hasNext()) {
var entry = log.find({}).sort({'$natural': -1}).limit(1).next();
printjson( entry );
- var ts = entry['ts']['t'];
+ var ts = entry['ts'];
print("TS for " + slave + " is " + ts + " and latest is " + latest);
print("Oplog size for " + slave + " is " + log.count());
- synced = (synced && (latest == ts));
+ synced = (synced && friendlyEqual(latest,ts))
}
else {
synced = false;
diff --git a/shell/utils.js b/shell/utils.js
index 65fb52ed073..de26403afa6 100644
--- a/shell/utils.js
+++ b/shell/utils.js
@@ -1046,23 +1046,23 @@ Geo.distance = function( a , b ){
Math.pow( bx - ax , 2 ) );
}
-rs = function () { return "try rs.help()"; }
-
-rs.help = function () {
- print("\trs.status() { replSetGetStatus : 1 } checks repl set status");
- print("\trs.initiate() { replSetInitiate : null } initiates set with default settings");
- print("\trs.initiate(cfg) { replSetInitiate : cfg } initiates set with configuration cfg");
- print("\trs.add(hostportstr) add a new member to the set with default attributes");
- print("\trs.add(membercfgobj) add a new member to the set with extra attributes");
- print("\trs.addArb(hostportstr) add a new member which is arbiterOnly:true");
- print("\trs.stepDown() step down as primary (momentarily)");
- print("\trs.conf() return configuration from local.system.replset");
- print("\trs.slaveOk() shorthand for db.getMongo().setSlaveOk()");
- print();
- print("\tdb.isMaster() check who is primary");
- print();
- print("\tsee also http://<mongod_host>:28017/_replSet for additional diagnostic info");
-}
+rs = function () { return "try rs.help()"; }
+
+rs.help = function () {
+ print("\trs.status() { replSetGetStatus : 1 } checks repl set status");
+ print("\trs.initiate() { replSetInitiate : null } initiates set with default settings");
+ print("\trs.initiate(cfg) { replSetInitiate : cfg } initiates set with configuration cfg");
+ print("\trs.add(hostportstr) add a new member to the set with default attributes");
+ print("\trs.add(membercfgobj) add a new member to the set with extra attributes");
+ print("\trs.addArb(hostportstr) add a new member which is arbiterOnly:true");
+ print("\trs.stepDown() step down as primary (momentarily)");
+ print("\trs.conf() return configuration from local.system.replset");
+ print("\trs.slaveOk() shorthand for db.getMongo().setSlaveOk()");
+ print();
+ print("\tdb.isMaster() check who is primary");
+ print();
+ print("\tsee also http://<mongod_host>:28017/_replSet for additional diagnostic info");
+}
rs.slaveOk = function () { return db.getMongo().setSlaveOk(); }
rs.status = function () { return db._adminCommand("replSetGetStatus"); }
rs.isMaster = function () { return db.isMaster(); }