コード例 #1
0
bool MigrationSourceManager::transferMods(OperationContext* txn,
                                          const MigrationSessionId& sessionId,
                                          string& errmsg,
                                          BSONObjBuilder& b) {
    long long size = 0;

    {
        AutoGetCollectionForRead ctx(txn, _getNS());

        stdx::lock_guard<stdx::mutex> sl(_mutex);

        if (!_sessionId) {
            errmsg = "no active migration!";
            return false;
        }

        // TODO after 3.4 release, !sessionId.isEmpty() can be removed: versions >= 3.2 will
        // all have sessionId implemented. (two more instances below).
        // A mongod version < v3.2 will not have sessionId, in which case it is empty and ignored.
        if (!sessionId.isEmpty() && !_sessionId->matches(sessionId)) {
            errmsg = str::stream() << "requested migration session id " << sessionId.toString()
                                   << " does not match active session id "
                                   << _sessionId->toString();
            return false;
        }

        // TODO: fix SERVER-16540 race
        _xfer(txn, _nss.ns(), ctx.getDb(), &_deleted, b, "deleted", size, false);
        _xfer(txn, _nss.ns(), ctx.getDb(), &_reload, b, "reload", size, true);
    }

    b.append("size", size);

    return true;
}
コード例 #2
0
void StartChunkCloneRequest::appendAsCommand(
    BSONObjBuilder* builder,
    const NamespaceString& nss,
    const MigrationSessionId& sessionId,
    const ConnectionString& configServerConnectionString,
    const ConnectionString& fromShardConnectionString,
    const ShardId& fromShardId,
    const ShardId& toShardId,
    const BSONObj& chunkMinKey,
    const BSONObj& chunkMaxKey,
    const BSONObj& shardKeyPattern,
    const MigrationSecondaryThrottleOptions& secondaryThrottle) {
    invariant(builder->asTempObj().isEmpty());
    invariant(nss.isValid());
    invariant(fromShardConnectionString.isValid());

    builder->append(kRecvChunkStart, nss.ns());
    sessionId.append(builder);
    builder->append(kConfigServerConnectionString, configServerConnectionString.toString());
    builder->append(kFromShardConnectionString, fromShardConnectionString.toString());
    builder->append(kFromShardId, fromShardId.toString());
    builder->append(kToShardId, toShardId.toString());
    builder->append(kChunkMinKey, chunkMinKey);
    builder->append(kChunkMaxKey, chunkMaxKey);
    builder->append(kShardKeyPattern, shardKeyPattern);
    secondaryThrottle.append(builder);
}
コード例 #3
0
/**
 * Create the migration transfer mods request BSON object to send to the source shard.
 *
 * 'sessionId' unique identifier for this migration.
 */
BSONObj createTransferModsRequest(const NamespaceString& nss, const MigrationSessionId& sessionId) {
    BSONObjBuilder builder;
    builder.append("_transferMods", nss.ns());
    sessionId.append(&builder);
    return builder.obj();
}
コード例 #4
0
/**
 * Create the migration clone request BSON object to send to the source shard.
 *
 * 'sessionId' unique identifier for this migration.
 */
BSONObj createMigrateCloneRequest(const NamespaceString& nss, const MigrationSessionId& sessionId) {
    BSONObjBuilder builder;
    builder.append("_migrateClone", nss.ns());
    sessionId.append(&builder);
    return builder.obj();
}
コード例 #5
0
bool MigrationSourceManager::clone(OperationContext* txn,
                                   const MigrationSessionId& sessionId,
                                   string& errmsg,
                                   BSONObjBuilder& result) {
    ElapsedTracker tracker(internalQueryExecYieldIterations, internalQueryExecYieldPeriodMS);

    int allocSize = 0;

    {
        AutoGetCollection autoColl(txn, _getNS(), MODE_IS);

        stdx::lock_guard<stdx::mutex> sl(_mutex);

        if (!_sessionId) {
            errmsg = "not active";
            return false;
        }

        // A mongod version < v3.2 will not have sessionId, in which case it is empty and ignored.
        if (!sessionId.isEmpty() && !_sessionId->matches(sessionId)) {
            errmsg = str::stream() << "requested migration session id " << sessionId.toString()
                                   << " does not match active session id "
                                   << _sessionId->toString();
            return false;
        }

        Collection* collection = autoColl.getCollection();
        if (!collection) {
            errmsg = str::stream() << "collection " << _nss.toString() << " does not exist";
            return false;
        }

        allocSize = std::min(
            BSONObjMaxUserSize,
            static_cast<int>((12 + collection->averageObjectSize(txn)) * cloneLocsRemaining()));
    }

    bool isBufferFilled = false;
    BSONArrayBuilder clonedDocsArrayBuilder(allocSize);
    while (!isBufferFilled) {
        AutoGetCollection autoColl(txn, _getNS(), MODE_IS);

        stdx::lock_guard<stdx::mutex> sl(_mutex);

        if (!_sessionId) {
            errmsg = "not active";
            return false;
        }

        // A mongod version < v3.2 will not have sessionId, in which case it is empty and ignored.
        if (!sessionId.isEmpty() && !_sessionId->matches(sessionId)) {
            errmsg = str::stream() << "migration session id changed from " << sessionId.toString()
                                   << " to " << _sessionId->toString()
                                   << " while initial clone was active";
            return false;
        }

        // TODO: fix SERVER-16540 race
        Collection* collection = autoColl.getCollection();
        if (!collection) {
            errmsg = str::stream() << "collection " << _nss.toString() << " does not exist";
            return false;
        }

        stdx::lock_guard<stdx::mutex> lk(_cloneLocsMutex);

        std::set<RecordId>::iterator cloneLocsIter = _cloneLocs.begin();
        for (; cloneLocsIter != _cloneLocs.end(); ++cloneLocsIter) {
            if (tracker.intervalHasElapsed())  // should I yield?
                break;

            RecordId recordId = *cloneLocsIter;
            Snapshotted<BSONObj> doc;
            if (!collection->findDoc(txn, recordId, &doc)) {
                // doc was deleted
                continue;
            }

            // Use the builder size instead of accumulating 'doc's size so that we take
            // into consideration the overhead of BSONArray indices, and *always*
            // append one doc.
            if (clonedDocsArrayBuilder.arrSize() != 0 &&
                (clonedDocsArrayBuilder.len() + doc.value().objsize() + 1024) >
                    BSONObjMaxUserSize) {
                isBufferFilled = true;  // break out of outer while loop
                break;
            }

            clonedDocsArrayBuilder.append(doc.value());
        }

        _cloneLocs.erase(_cloneLocs.begin(), cloneLocsIter);

        // Note: must be holding _cloneLocsMutex, don't move this inside while condition!
        if (_cloneLocs.empty()) {
            break;
        }
    }

    result.appendArray("objects", clonedDocsArrayBuilder.arr());
    return true;
}