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 /s/d_split.cpp | |
parent | cbe2d992e9cd1ea66af9fa91df006106775d3073 (diff) | |
download | mongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz |
Imported Upstream version 2.0.0
Diffstat (limited to 's/d_split.cpp')
-rw-r--r-- | s/d_split.cpp | 100 |
1 files changed, 67 insertions, 33 deletions
diff --git a/s/d_split.cpp b/s/d_split.cpp index 3ed6e9b..cef6188 100644 --- a/s/d_split.cpp +++ b/s/d_split.cpp @@ -22,10 +22,10 @@ #include "../db/btree.h" #include "../db/commands.h" -#include "../db/dbmessage.h" #include "../db/jsobj.h" -#include "../db/query.h" +#include "../db/instance.h" #include "../db/queryoptimizer.h" +#include "../db/clientcursor.h" #include "../client/connpool.h" #include "../client/distlock.h" @@ -57,7 +57,7 @@ namespace mongo { "example: { medianKey:\"blog.posts\", keyPattern:{x:1}, min:{x:10}, max:{x:55} }\n" "NOTE: This command may take a while to run"; } - bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { + bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { const char *ns = jsobj.getStringField( "medianKey" ); BSONObj min = jsobj.getObjectField( "min" ); BSONObj max = jsobj.getObjectField( "max" ); @@ -74,22 +74,25 @@ namespace mongo { NamespaceDetails *d = nsdetails(ns); int idxNo = d->idxNo(*id); - // only yielding on firt half for now + // only yielding on first half for now // after this it should be in ram, so 2nd should be fast { - shared_ptr<Cursor> c( new BtreeCursor( d, idxNo, *id, min, max, false, 1 ) ); - scoped_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); + shared_ptr<Cursor> c( BtreeCursor::make( d, idxNo, *id, min, max, false, 1 ) ); + auto_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); while ( c->ok() ) { num++; c->advance(); - if ( ! cc->yieldSometimes() ) + if ( ! cc->yieldSometimes( ClientCursor::DontNeed ) ) { + cc.release(); break; + } } } num /= 2; - BtreeCursor c( d, idxNo, *id, min, max, false, 1 ); + auto_ptr<BtreeCursor> _c( BtreeCursor::make( d, idxNo, *id, min, max, false, 1 ) ); + BtreeCursor& c = *_c; for( ; num; c.advance(), --num ); ostringstream os; @@ -133,12 +136,12 @@ namespace mongo { help << "Internal command.\n"; } - bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { + bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { const char* ns = jsobj.getStringField( "checkShardingIndex" ); BSONObj keyPattern = jsobj.getObjectField( "keyPattern" ); - if ( keyPattern.nFields() == 1 && str::equals( "_id" , keyPattern.firstElement().fieldName() ) ) { + if ( keyPattern.nFields() == 1 && str::equals( "_id" , keyPattern.firstElementFieldName() ) ) { result.appendBool( "idskip" , true ); return true; } @@ -174,9 +177,14 @@ namespace mongo { return false; } - BtreeCursor * bc = new BtreeCursor( d , d->idxNo(*idx) , *idx , min , max , false , 1 ); + if( d->isMultikey( d->idxNo( *idx ) ) ) { + errmsg = "index is multikey, cannot use for sharding"; + return false; + } + + BtreeCursor * bc = BtreeCursor::make( d , d->idxNo(*idx) , *idx , min , max , false , 1 ); shared_ptr<Cursor> c( bc ); - scoped_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); + auto_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); if ( ! cc->ok() ) { // range is empty return true; @@ -217,8 +225,10 @@ namespace mongo { } cc->advance(); - if ( ! cc->yieldSometimes() ) + if ( ! cc->yieldSometimes( ClientCursor::DontNeed ) ) { + cc.release(); break; + } } return true; @@ -243,7 +253,7 @@ namespace mongo { "NOTE: This command may take a while to run"; } - bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { + bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { // // 1.a We'll parse the parameters in two steps. First, make sure the we can use the split index to get @@ -368,9 +378,9 @@ namespace mongo { long long currCount = 0; long long numChunks = 0; - BtreeCursor * bc = new BtreeCursor( d , d->idxNo(*idx) , *idx , min , max , false , 1 ); + BtreeCursor * bc = BtreeCursor::make( d , d->idxNo(*idx) , *idx , min , max , false , 1 ); shared_ptr<Cursor> c( bc ); - scoped_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); + auto_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); if ( ! cc->ok() ) { errmsg = "can't open a cursor for splitting (desired range is possibly empty)"; return false; @@ -414,13 +424,13 @@ namespace mongo { break; } - if ( ! cc->yieldSometimes() ) { + if ( ! cc->yieldSometimes( ClientCursor::DontNeed ) ) { // we were near and and got pushed to the end // i think returning the splits we've already found is fine - // don't use the btree cursor pointer to acces keys beyond this point but ok + // don't use the btree cursor pointer to access keys beyond this point but ok // to use it for format the keys we've got already - + cc.release(); break; } } @@ -433,7 +443,7 @@ namespace mongo { currCount = 0; log() << "splitVector doing another cycle because of force, keyCount now: " << keyCount << endl; - bc = new BtreeCursor( d , d->idxNo(*idx) , *idx , min , max , false , 1 ); + bc = BtreeCursor::make( d , d->idxNo(*idx) , *idx , min , max , false , 1 ); c.reset( bc ); cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) ); } @@ -519,7 +529,7 @@ namespace mongo { virtual bool adminOnly() const { return true; } virtual LockType locktype() const { return NONE; } - bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { + bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { // // 1. check whether parameters passed to splitChunk are sound @@ -531,31 +541,31 @@ namespace mongo { return false; } - BSONObj keyPattern = cmdObj["keyPattern"].Obj(); + const BSONObj keyPattern = cmdObj["keyPattern"].Obj(); if ( keyPattern.isEmpty() ) { errmsg = "need to specify the key pattern the collection is sharded over"; return false; } - BSONObj min = cmdObj["min"].Obj(); + const BSONObj min = cmdObj["min"].Obj(); if ( min.isEmpty() ) { - errmsg = "neet to specify the min key for the chunk"; + errmsg = "need to specify the min key for the chunk"; return false; } - BSONObj max = cmdObj["max"].Obj(); + const BSONObj max = cmdObj["max"].Obj(); if ( max.isEmpty() ) { - errmsg = "neet to specify the max key for the chunk"; + errmsg = "need to specify the max key for the chunk"; return false; } - string from = cmdObj["from"].str(); + const string from = cmdObj["from"].str(); if ( from.empty() ) { errmsg = "need specify server to split chunk at"; return false; } - BSONObj splitKeysElem = cmdObj["splitKeys"].Obj(); + const BSONObj splitKeysElem = cmdObj["splitKeys"].Obj(); if ( splitKeysElem.isEmpty() ) { errmsg = "need to provide the split points to chunk over"; return false; @@ -566,7 +576,7 @@ namespace mongo { splitKeys.push_back( it.next().Obj().getOwned() ); } - BSONElement shardId = cmdObj["shardId"]; + const BSONElement shardId = cmdObj["shardId"]; if ( shardId.eoo() ) { errmsg = "need to provide shardId"; return false; @@ -594,7 +604,16 @@ namespace mongo { // DistributedLock lockSetup( ConnectionString( shardingState.getConfigServer() , ConnectionString::SYNC) , ns ); - dist_lock_try dlk( &lockSetup, string("split-") + min.toString() ); + dist_lock_try dlk; + + try{ + dlk = dist_lock_try( &lockSetup, string("split-") + min.toString() ); + } + catch( LockException& e ){ + errmsg = str::stream() << "Error locking distributed lock for split." << causedBy( e ); + return false; + } + if ( ! dlk.got() ) { errmsg = "the collection's metadata lock is taken"; result.append( "who" , dlk.other() ); @@ -672,7 +691,7 @@ namespace mongo { BSONObjBuilder logDetail; origChunk.appendShortVersion( "before" , logDetail ); - log(1) << "before split on " << origChunk << endl; + LOG(1) << "before split on " << origChunk << endl; vector<ChunkInfo> newChunks; ShardChunkVersion myVersion = maxVersion; @@ -695,7 +714,7 @@ namespace mongo { op.appendBool( "b" , true ); op.append( "ns" , ShardNS::chunk ); - // add the modified (new) chunk infomation as the update object + // add the modified (new) chunk information as the update object BSONObjBuilder n( op.subobjStart( "o" ) ); n.append( "_id" , Chunk::genID( ns , startKey ) ); n.appendTimestamp( "lastmod" , myVersion ); @@ -781,13 +800,28 @@ namespace mongo { for ( int i=0; i < newChunksSize; i++ ) { BSONObjBuilder chunkDetail; chunkDetail.appendElements( beforeDetailObj ); - chunkDetail.append( "number", i ); + chunkDetail.append( "number", i+1 ); chunkDetail.append( "of" , newChunksSize ); newChunks[i].appendShortVersion( "chunk" , chunkDetail ); configServer.logChange( "multi-split" , ns , chunkDetail.obj() ); } } + if (newChunks.size() == 2){ + // If one of the chunks has only one object in it we should move it + static const BSONObj fields = BSON("_id" << 1 ); + DBDirectClient conn; + for (int i=1; i >= 0 ; i--){ // high chunk more likely to have only one obj + ChunkInfo chunk = newChunks[i]; + Query q = Query().minKey(chunk.min).maxKey(chunk.max); + scoped_ptr<DBClientCursor> c (conn.query(ns, q, /*limit*/-2, 0, &fields)); + if (c && c->itcount() == 1) { + result.append("shouldMigrate", BSON("min" << chunk.min << "max" << chunk.max)); + break; + } + } + } + return true; } } cmdSplitChunk; |