ShardChunkManager* ShardChunkManager::cloneMinus( const BSONObj& min, const BSONObj& max, const ShardChunkVersion& version ) { // check that we have the exact chunk that will be subtracted _assertChunkExists( min , max ); auto_ptr<ShardChunkManager> p( new ShardChunkManager ); p->_key = this->_key; if ( _chunksMap.size() == 1 ) { // if left with no chunks, just reset version uassert( 13590 , str::stream() << "setting version to " << version.toString() << " on removing last chunk", ! version.isSet() ); p->_version = ShardChunkVersion( 0, OID() ); p->_collVersion = _collVersion; } else { // can't move version backwards when subtracting chunks // this is what guarantees that no read or write would be taken once we subtract data from the current shard if ( version <= _version ) { uasserted( 13585 , str::stream() << "version " << version.toString() << " not greater than " << _version.toString() ); } p->_chunksMap = this->_chunksMap; p->_chunksMap.erase( min ); p->_version = version; if( version > _collVersion ) p->_collVersion = version; else p->_collVersion = this->_collVersion; p->_fillRanges(); } return p.release(); }
ShardChunkManager* ShardChunkManager::cloneSplit( const BSONObj& min , const BSONObj& max , const vector<BSONObj>& splitKeys , const ChunkVersion& version ) { // the version required in both resulting chunks could be simply an increment in the minor portion of the current version // however, we are enforcing uniqueness over the attributes <ns, lastmod> of the configdb collection 'chunks' // so in practice, a migrate somewhere may force this split to pick up a version that has the major portion higher // than the one that this shard has been using // // TODO drop the uniqueness constraint and tighten the check below so that only the minor portion of version changes if ( version <= _version ) { uasserted( 14039 , str::stream() << "version " << version.toString() << " not greater than " << _version.toString() ); } // check that we have the exact chunk that will be split and that the split point is valid _assertChunkExists( min , max ); for ( vector<BSONObj>::const_iterator it = splitKeys.begin() ; it != splitKeys.end() ; ++it ) { if ( ! contains( min , max , *it ) ) { uasserted(14040, str::stream() << "cannot split " << min << " -> " << max << " on " << *it); } } auto_ptr<ShardChunkManager> p( new ShardChunkManager ); p->_key = this->_key; p->_chunksMap = this->_chunksMap; p->_version = version; // will increment second, third, ... chunks below BSONObj startKey = min; for ( vector<BSONObj>::const_iterator it = splitKeys.begin() ; it != splitKeys.end() ; ++it ) { BSONObj split = *it; p->_chunksMap[startKey] = split.getOwned(); p->_chunksMap.insert( make_pair( split.getOwned() , max.getOwned() ) ); p->_version.incMinor(); startKey = split; } if( version > _collVersion ) p->_collVersion = version; else p->_collVersion = this->_collVersion; p->_fillRanges(); return p.release(); }