ChunkManager::ChunkManager( DBConfig * config , string ns , ShardKeyPattern pattern , bool unique ) : _config( config ) , _ns( ns ) , _key( pattern ) , _unique( unique ){ Chunk temp(0); ScopedDbConnection conn( temp.modelServer() ); auto_ptr<DBClientCursor> cursor = conn->query( temp.getNS() , BSON( "ns" << ns ) ); while ( cursor->more() ){ BSONObj d = cursor->next(); if ( d["isMaxMarker"].trueValue() ){ continue; } Chunk * c = new Chunk( this ); c->unserialize( d ); _chunks.push_back( c ); c->_id = d["_id"].wrap().getOwned(); } conn.done(); if ( _chunks.size() == 0 ){ Chunk * c = new Chunk( this ); c->_ns = ns; c->setMin(_key.globalMin()); c->setMax(_key.globalMax()); c->_shard = config->getPrimary(); c->_markModified(); _chunks.push_back( c ); log() << "no chunks for:" << ns << " so creating first: " << c->toString() << endl; } _sequenceNumber = ++NextSequenceNumber; }
Chunk * Chunk::split( const BSONObj& m ){ uassert( 10165 , "can't split as shard that doesn't have a manager" , _manager ); log(1) << " before split on: " << m << "\n" << "\t self : " << toString() << endl; uassert( 10166 , "locking namespace on server failed" , lockNamespaceOnServer( getShard() , _ns ) ); Chunk * s = new Chunk( _manager ); s->_ns = _ns; s->_shard = _shard; s->setMin(m.getOwned()); s->setMax(_max); s->_markModified(); _markModified(); _manager->_chunks.push_back( s ); setMax(m.getOwned()); log(1) << " after split:\n" << "\t left : " << toString() << "\n" << "\t right: "<< s->toString() << endl; _manager->save(); return s; }
bool Chunk::moveAndCommit( const string& to , string& errmsg ){ uassert( 10167 , "can't move shard to its current location!" , to != getShard() ); log() << "moving chunk ns: " << _ns << " moving chunk: " << toString() << " " << _shard << " -> " << to << endl; string from = _shard; ShardChunkVersion oldVersion = _manager->getVersion( from ); BSONObj filter; { BSONObjBuilder b; getFilter( b ); filter = b.obj(); } ScopedDbConnection fromconn( from ); BSONObj startRes; bool worked = fromconn->runCommand( "admin" , BSON( "movechunk.start" << _ns << "from" << from << "to" << to << "filter" << filter ) , startRes ); if ( ! worked ){ errmsg = (string)"movechunk.start failed: " + startRes.toString(); fromconn.done(); return false; } // update config db setShard( to ); // need to increment version # for old server Chunk * randomChunkOnOldServer = _manager->findChunkOnServer( from ); if ( randomChunkOnOldServer ) randomChunkOnOldServer->_markModified(); _manager->save(); BSONObj finishRes; { ShardChunkVersion newVersion = _manager->getVersion( from ); if ( newVersion == 0 && oldVersion > 0 ){ newVersion = oldVersion; newVersion++; _manager->save(); } else if ( newVersion <= oldVersion ){ log() << "newVersion: " << newVersion << " oldVersion: " << oldVersion << endl; uassert( 10168 , "version has to be higher" , newVersion > oldVersion ); } BSONObjBuilder b; b << "movechunk.finish" << _ns; b << "to" << to; b.appendTimestamp( "newVersion" , newVersion ); b.append( startRes["finishToken"] ); worked = fromconn->runCommand( "admin" , b.done() , finishRes ); } if ( ! worked ){ errmsg = (string)"movechunk.finish failed: " + finishRes.toString(); fromconn.done(); return false; } fromconn.done(); return true; }