Exemplo n.º 1
0
    CollectionMetadata* CollectionMetadata::cloneMerge( const BSONObj& minKey,
                                                        const BSONObj& maxKey,
                                                        const ChunkVersion& newShardVersion,
                                                        string* errMsg ) const {

        if (newShardVersion <= _shardVersion) {

            *errMsg = stream() << "cannot merge range " << rangeToString( minKey, maxKey )
                               << ", new shard version " << newShardVersion.toString()
                               << " is not greater than current version "
                               << _shardVersion.toString();

            warning() << *errMsg << endl;
            return NULL;
        }

        RangeVector overlap;
        getRangeMapOverlap( _chunksMap, minKey, maxKey, &overlap );

        if ( overlap.empty() || overlap.size() == 1 ) {

            *errMsg = stream() << "cannot merge range " << rangeToString( minKey, maxKey )
                               << ( overlap.empty() ? ", no chunks found in this range" :
                                                      ", only one chunk found in this range" );

            warning() << *errMsg << endl;
            return NULL;
        }

        bool validStartEnd = true;
        bool validNoHoles = true;
        if ( overlap.begin()->first.woCompare( minKey ) != 0 ) {
            // First chunk doesn't start with minKey
            validStartEnd = false;
        }
        else if ( overlap.rbegin()->second.woCompare( maxKey ) != 0 ) {
            // Last chunk doesn't end with maxKey
            validStartEnd = false;
        }
        else {
            // Check that there are no holes
            BSONObj prevMaxKey = minKey;
            for ( RangeVector::iterator it = overlap.begin(); it != overlap.end(); ++it ) {
                if ( it->first.woCompare( prevMaxKey ) != 0 ) {
                    validNoHoles = false;
                    break;
                }
                prevMaxKey = it->second;
            }
        }

        if ( !validStartEnd || !validNoHoles ) {

            *errMsg = stream() << "cannot merge range " << rangeToString( minKey, maxKey )
                               << ", overlapping chunks " << overlapToString( overlap )
                               << ( !validStartEnd ? " do not have the same min and max key" :
                                                     " are not all adjacent" );

            warning() << *errMsg << endl;
            return NULL;
        }

        auto_ptr<CollectionMetadata> metadata( new CollectionMetadata );
        metadata->_keyPattern = this->_keyPattern;
        metadata->_keyPattern.getOwned();
        metadata->_pendingMap = this->_pendingMap;
        metadata->_chunksMap = this->_chunksMap;
        metadata->_rangesMap = this->_rangesMap;
        metadata->_shardVersion = newShardVersion;
        metadata->_collVersion =
                newShardVersion > _collVersion ? newShardVersion : this->_collVersion;

        for ( RangeVector::iterator it = overlap.begin(); it != overlap.end(); ++it ) {
            metadata->_chunksMap.erase( it->first );
        }

        metadata->_chunksMap.insert( make_pair( minKey, maxKey ) );

        dassert(metadata->isValid());
        return metadata.release();
    }
Exemplo n.º 2
0
StatusWith<std::unique_ptr<CollectionMetadata>> CollectionMetadata::cloneMerge(
    const BSONObj& minKey, const BSONObj& maxKey, const ChunkVersion& newShardVersion) const {
    invariant(newShardVersion.epoch() == _shardVersion.epoch());
    invariant(newShardVersion > _shardVersion);

    RangeVector overlap;
    getRangeMapOverlap(_chunksMap, minKey, maxKey, &overlap);

    if (overlap.empty() || overlap.size() == 1) {
        return {ErrorCodes::IllegalOperation,
                stream() << "cannot merge range " << rangeToString(minKey, maxKey)
                         << (overlap.empty() ? ", no chunks found in this range"
                                             : ", only one chunk found in this range")};
    }

    bool validStartEnd = true;
    bool validNoHoles = true;

    if (overlap.begin()->first.woCompare(minKey) != 0) {
        // First chunk doesn't start with minKey
        validStartEnd = false;
    } else if (overlap.rbegin()->second.woCompare(maxKey) != 0) {
        // Last chunk doesn't end with maxKey
        validStartEnd = false;
    } else {
        // Check that there are no holes
        BSONObj prevMaxKey = minKey;
        for (RangeVector::iterator it = overlap.begin(); it != overlap.end(); ++it) {
            if (it->first.woCompare(prevMaxKey) != 0) {
                validNoHoles = false;
                break;
            }
            prevMaxKey = it->second;
        }
    }

    if (!validStartEnd || !validNoHoles) {
        return {ErrorCodes::IllegalOperation,
                stream() << "cannot merge range " << rangeToString(minKey, maxKey)
                         << ", overlapping chunks " << overlapToString(overlap)
                         << (!validStartEnd ? " do not have the same min and max key"
                                            : " are not all adjacent")};
    }

    unique_ptr<CollectionMetadata> metadata(stdx::make_unique<CollectionMetadata>());
    metadata->_keyPattern = _keyPattern.getOwned();
    metadata->fillKeyPatternFields();
    metadata->_pendingMap = _pendingMap;
    metadata->_chunksMap = _chunksMap;
    metadata->_rangesMap = _rangesMap;
    metadata->_shardVersion = newShardVersion;
    metadata->_collVersion = newShardVersion > _collVersion ? newShardVersion : this->_collVersion;

    for (RangeVector::iterator it = overlap.begin(); it != overlap.end(); ++it) {
        metadata->_chunksMap.erase(it->first);
    }

    metadata->_chunksMap.insert(make_pair(minKey, maxKey));

    invariant(metadata->isValid());
    return std::move(metadata);
}