示例#1
0
文件: prefetch.cpp 项目: i80and/mongo
// prefetch for an oplog operation
void prefetchPagesForReplicatedOp(OperationContext* opCtx,
                                  Database* db,
                                  const OplogEntry& oplogEntry) {
    invariant(db);
    const ReplSettings::IndexPrefetchConfig prefetchConfig =
        ReplicationCoordinator::get(opCtx)->getIndexPrefetchConfig();

    // Prefetch ignores non-CRUD operations.
    if (!oplogEntry.isCrudOpType()) {
        return;
    }

    // This will have to change for engines other than MMAP V1, because they might not have
    // means for directly prefetching pages from the collection. For this purpose, acquire S
    // lock on the database, instead of optimizing with IS.
    const auto& nss = oplogEntry.getNamespace();
    Lock::CollectionLock collLock(opCtx->lockState(), nss.ns(), MODE_S);

    Collection* collection = db->getCollection(opCtx, nss);
    if (!collection) {
        return;
    }

    auto opType = oplogEntry.getOpType();
    LOG(4) << "index prefetch for op " << OpType_serializer(opType);

    // should we prefetch index pages on updates? if the update is in-place and doesn't change
    // indexed values, it is actually slower - a lot slower if there are a dozen indexes or
    // lots of multikeys.  possible variations (not all mutually exclusive):
    //  1) current behavior: full prefetch
    //  2) don't do it for updates
    //  3) don't do multikey indexes for updates
    //  4) don't prefetchIndexPages on some heuristic; e.g., if it's an $inc.
    //  5) if not prefetching index pages (#2), we should do it if we are upsertings and it
    //     will be an insert. to do that we could do the prefetchRecordPage first and if DNE
    //     then we do #1.
    //
    // note that on deletes 'obj' does not have all the keys we would want to prefetch on.
    // a way to achieve that would be to prefetch the record first, and then afterwards do
    // this part.
    //
    auto obj = oplogEntry.getOperationToApply();
    invariant(!obj.isEmpty());
    prefetchIndexPages(opCtx, collection, prefetchConfig, obj);

    // do not prefetch the data for inserts; it doesn't exist yet
    //
    // we should consider doing the record prefetch for the delete op case as we hit the record
    // when we delete.  note if done we only want to touch the first page.
    //
    // update: do record prefetch.
    if ((opType == OpTypeEnum::kUpdate) &&
        // do not prefetch the data for capped collections because
        // they typically do not have an _id index for findById() to use.
        !collection->isCapped()) {
        prefetchRecordPages(opCtx, db, nss.ns().c_str(), obj);
    }
}
std::pair<BSONObj, RecordId> RollbackTest::makeCRUDOp(OpTypeEnum opType,
                                                      Timestamp ts,
                                                      UUID uuid,
                                                      StringData nss,
                                                      BSONObj o,
                                                      boost::optional<BSONObj> o2,
                                                      int recordId) {
    invariant(opType != OpTypeEnum::kCommand);

    BSONObjBuilder bob;
    bob.append("ts", ts);
    bob.append("op", OpType_serializer(opType));
    uuid.appendToBuilder(&bob, "ui");
    bob.append("ns", nss);
    bob.append("o", o);
    if (o2) {
        bob.append("o2", *o2);
    }

    return std::make_pair(bob.obj(), RecordId(recordId));
}