diff options
author | Aaron <aaron@10gen.com> | 2010-08-02 22:28:04 -0700 |
---|---|---|
committer | Aaron <aaron@10gen.com> | 2010-08-02 22:28:04 -0700 |
commit | 5240b2c0ff2b0f0f3999e456ac0b493d77153735 (patch) | |
tree | 86fbb673fc079bcc9f5014dbb6e977edeb0cd366 | |
parent | 86c72c061a597dc03f0605abeff829b262d1b908 (diff) | |
parent | dde3464141b636123cff33ea45479ac9e6c9fe7d (diff) | |
download | mongo-5240b2c0ff2b0f0f3999e456ac0b493d77153735.tar.gz |
Merge branch 'master' of github.com:mongodb/mongo
-rw-r--r-- | jstests/replsets/replset1.js | 9 | ||||
-rw-r--r-- | s/config.cpp | 97 | ||||
-rw-r--r-- | s/config.h | 12 | ||||
-rw-r--r-- | s/grid.cpp | 6 | ||||
-rw-r--r-- | s/server.cpp | 2 | ||||
-rw-r--r-- | shell/servers.js | 6 | ||||
-rw-r--r-- | shell/utils.js | 34 |
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(); } |