diff options
-rw-r--r-- | jstests/sharding/migrateBig.js | 45 | ||||
-rw-r--r-- | s/balance.cpp | 15 | ||||
-rw-r--r-- | s/d_migrate.cpp | 7 |
3 files changed, 65 insertions, 2 deletions
diff --git a/jstests/sharding/migrateBig.js b/jstests/sharding/migrateBig.js new file mode 100644 index 00000000000..f6ba18a7c02 --- /dev/null +++ b/jstests/sharding/migrateBig.js @@ -0,0 +1,45 @@ + +s = new ShardingTest( "migrateBig" , 2 , 0 , 1 , { chunksize : 1 } ); + +s.adminCommand( { enablesharding : "test" } ); +s.adminCommand( { shardcollection : "test.foo" , key : { x : 1 } } ); + +db = s.getDB( "test" ) +coll = db.foo + +big = "" +while ( big.length < 10000 ) + big += "eliot" + +for ( x=0; x<100; x++ ) + coll.insert( { x : x , big : big } ) + +s.adminCommand( { split : "test.foo" , middle : { x : 33 } } ) +s.adminCommand( { split : "test.foo" , middle : { x : 66 } } ) +s.adminCommand( { movechunk : "test.foo" , find : { x : 90 } , to : s.getOther( s.getServer( "test" ) ).name } ) + +db.printShardingStatus() + +print( "YO : " + s.getServer( "test" ).host ) +direct = new Mongo( s.getServer( "test" ).host ) +print( "direct : " + direct ) + +directDB = direct.getDB( "test" ) + +for ( done=0; done<2*1024*1024; done+=big.length ){ + directDB.foo.insert( { x : 50 + Math.random() , big : big } ) + directDB.getLastError(); +} + +db.printShardingStatus() + +assert.throws( function(){ s.adminCommand( { movechunk : "test.foo" , find : { x : 50 } , to : s.getOther( s.getServer( "test" ) ).name } ); } , [] , "move should fail" ) + +for ( i=0; i<20; i+= 2 ) + s.adminCommand( { split : "test.foo" , middle : { x : i } } ) + +db.printShardingStatus() + +assert.soon( function(){ var x = s.chunkDiff( "foo" , "test" ); print( "chunk diff: " + x ); return x < 2; } , "no balance happened" , 120 * 1000 , 2000 ) + +s.stop() diff --git a/s/balance.cpp b/s/balance.cpp index d0199b398b8..be6f0ce1b09 100644 --- a/s/balance.cpp +++ b/s/balance.cpp @@ -76,6 +76,21 @@ namespace mongo { // the move requires acquiring the collection metadata's lock, which can fail log() << "balacer move failed: " << res << " from: " << chunkInfo.from << " to: " << chunkInfo.to << " chunk: " << chunkToMove << endl; + + if ( res["chunkTooBig"].trueValue() ) { + // reload just to be safe + cm = cfg->getChunkManager( chunkInfo.ns ); + assert( cm ); + c = cm->findChunk( chunkToMove["min"].Obj() ); + + log() << "forcing a split because migrate failed for size reasons" << endl; + + res = BSONObj(); + c->singleSplit( true , res ); + log() << "forced split results: " << res << endl; + + // TODO: if the split fails, mark as jumbo SERVER-2571 + } } return movedCount; diff --git a/s/d_migrate.cpp b/s/d_migrate.cpp index 887d104a9f7..c30f693e2dc 100644 --- a/s/d_migrate.cpp +++ b/s/d_migrate.cpp @@ -401,7 +401,7 @@ namespace mongo { * @param errmsg filled with textual description of error if this call return false * @return false if approximate chunk size is too big to move or true otherwise */ - bool storeCurrentLocs( long long maxChunkSize , string& errmsg ) { + bool storeCurrentLocs( long long maxChunkSize , string& errmsg , BSONObjBuilder& result ) { readlock l( _ns ); Client::Context ctx( _ns ); NamespaceDetails *d = nsdetails( _ns.c_str() ); @@ -467,6 +467,9 @@ namespace mongo { << " because maximum size allowed to move is " << maxChunkSize << " ns: " << _ns << " " << _min << " -> " << _max << endl; + result.appendBool( "chunkTooBig" , true ); + result.appendNumber( "chunkSize" , (long long)(recCount * avgRecSize) ); + errmsg = "chunk too big to move"; return false; } @@ -760,7 +763,7 @@ namespace mongo { MigrateStatusHolder statusHolder( ns , min , max ); { // this gets a read lock, so we know we have a checkpoint for mods - if ( ! migrateFromStatus.storeCurrentLocs( maxChunkSize , errmsg ) ) + if ( ! migrateFromStatus.storeCurrentLocs( maxChunkSize , errmsg , result ) ) return false; ScopedDbConnection connTo( to ); |