summaryrefslogtreecommitdiff
path: root/s/d_split.cpp
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
committerAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
commit5d342a758c6095b4d30aba0750b54f13b8916f51 (patch)
tree762e9aa84781f5e3b96db2c02d356c29cf0217c0 /s/d_split.cpp
parentcbe2d992e9cd1ea66af9fa91df006106775d3073 (diff)
downloadmongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz
Imported Upstream version 2.0.0
Diffstat (limited to 's/d_split.cpp')
-rw-r--r--s/d_split.cpp100
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;