StatusWith<std::string> KVCatalog::newOrphanedIdent(OperationContext* opCtx, std::string ident) {
    // The collection will be named local.orphan.xxxxx.
    std::string identNs = ident;
    std::replace(identNs.begin(), identNs.end(), '-', '_');
    std::string ns = NamespaceString(NamespaceString::kOrphanCollectionDb,
                                     NamespaceString::kOrphanCollectionPrefix + identNs)
                         .ns();

    stdx::lock_guard<stdx::mutex> lk(_identsLock);
    Entry& old = _idents[ns];
    if (!old.ident.empty()) {
        return Status(ErrorCodes::NamespaceExists,
                      str::stream() << ns << " already exists in the catalog");
    }
    opCtx->recoveryUnit()->registerChange(new AddIdentChange(this, ns));

    // Generate a new UUID for the orphaned collection.
    CollectionOptions optionsWithUUID;
    optionsWithUUID.uuid.emplace(CollectionUUID::gen());
    BSONObj obj;
    {
        BSONObjBuilder b;
        b.append("ns", ns);
        b.append("ident", ident);
        BSONCollectionCatalogEntry::MetaData md;
        md.ns = ns;
        // Default options with newly generated UUID.
        md.options = optionsWithUUID;
        // Not Prefixed.
        md.prefix = KVPrefix::kNotPrefixed;
        b.append("md", md.toBSON());
        obj = b.obj();
    }
    StatusWith<RecordId> res = _rs->insertRecord(opCtx, obj.objdata(), obj.objsize(), Timestamp());
    if (!res.isOK())
        return res.getStatus();

    old = Entry(ident, res.getValue());
    LOG(1) << "stored meta data for orphaned collection " << ns << " @ " << res.getValue();
    return StatusWith<std::string>(std::move(ns));
}
Ejemplo n.º 2
0
Status KVCatalog::newCollection(OperationContext* opCtx,
                                StringData ns,
                                const CollectionOptions& options) {
    invariant(opCtx->lockState() == NULL ||
              opCtx->lockState()->isDbLockedForMode(nsToDatabaseSubstring(ns), MODE_X));

    std::unique_ptr<Lock::ResourceLock> rLk;
    if (!_isRsThreadSafe && opCtx->lockState()) {
        rLk.reset(new Lock::ResourceLock(opCtx->lockState(), resourceIdCatalogMetadata, MODE_X));
    }

    const string ident = _newUniqueIdent(ns, "collection");

    stdx::lock_guard<stdx::mutex> lk(_identsLock);
    Entry& old = _idents[ns.toString()];
    if (!old.ident.empty()) {
        return Status(ErrorCodes::NamespaceExists, "collection already exists");
    }

    opCtx->recoveryUnit()->registerChange(new AddIdentChange(this, ns));

    BSONObj obj;
    {
        BSONObjBuilder b;
        b.append("ns", ns);
        b.append("ident", ident);
        BSONCollectionCatalogEntry::MetaData md;
        md.ns = ns.toString();
        md.options = options;
        b.append("md", md.toBSON());
        obj = b.obj();
    }

    StatusWith<RecordId> res = _rs->insertRecord(opCtx, obj.objdata(), obj.objsize(), false);
    if (!res.isOK())
        return res.getStatus();

    old = Entry(ident, res.getValue());
    LOG(1) << "stored meta data for " << ns << " @ " << res.getValue();
    return Status::OK();
}
void ReplicationCoordinatorImpl::_handleHeartbeatResponseAction(
    const HeartbeatResponseAction& action,
    const StatusWith<ReplSetHeartbeatResponse>& responseStatus) {
    switch (action.getAction()) {
        case HeartbeatResponseAction::NoAction:
            // Update the cached member state if different than the current topology member state
            if (_memberState != _topCoord->getMemberState()) {
                stdx::unique_lock<stdx::mutex> lk(_mutex);
                const PostMemberStateUpdateAction postUpdateAction =
                    _updateMemberStateFromTopologyCoordinator_inlock();
                lk.unlock();
                _performPostMemberStateUpdateAction(postUpdateAction);
            }
            break;
        case HeartbeatResponseAction::Reconfig:
            invariant(responseStatus.isOK());
            _scheduleHeartbeatReconfig(responseStatus.getValue().getConfig());
            break;
        case HeartbeatResponseAction::StartElection:
            if (isV1ElectionProtocol()) {
                _startElectSelfV1();
            } else {
                _startElectSelf();
            }
            break;
        case HeartbeatResponseAction::StepDownSelf:
            invariant(action.getPrimaryConfigIndex() == _selfIndex);
            log() << "Stepping down from primary in response to heartbeat";
            _stepDownStart();
            break;
        case HeartbeatResponseAction::StepDownRemotePrimary: {
            invariant(action.getPrimaryConfigIndex() != _selfIndex);
            _requestRemotePrimaryStepdown(
                _rsConfig.getMemberAt(action.getPrimaryConfigIndex()).getHostAndPort());
            break;
        }
        default:
            severe() << "Illegal heartbeat response action code " << int(action.getAction());
            invariant(false);
    }
}
TEST_F(WiredTigerRecoveryUnitTestFixture, CreateAndCheckForCachePressure) {
    int time = 1;

    // Reconfigure the size of the cache to be very small so that building cache pressure is fast.
    WiredTigerKVEngine* engine = harnessHelper->getEngine();
    std::string cacheSizeReconfig = "cache_size=1MB";
    ASSERT_EQ(engine->reconfigure(cacheSizeReconfig.c_str()), 0);

    OperationContext* opCtx = clientAndCtx1.second.get();
    std::unique_ptr<RecordStore> rs(harnessHelper->createRecordStore(opCtx, "a.b"));

    // Insert one document so that we can then update it in a loop to create cache pressure.
    // Note: inserts will not create cache pressure.
    WriteUnitOfWork wu(opCtx);
    ASSERT_OK(ru1->setTimestamp(Timestamp(time++)));
    std::string str = str::stream() << "foobarbaz";
    StatusWith<RecordId> ress = rs->insertRecord(opCtx, str.c_str(), str.size() + 1, Timestamp());
    ASSERT_OK(ress.getStatus());
    auto recordId = ress.getValue();
    wu.commit();

    for (int j = 0; j < 1000; ++j) {
        // Once we hit the cache pressure threshold, i.e. have successfully created cache pressure
        // that is detectable, we are done.
        if (engine->isCacheUnderPressure(opCtx)) {
            invariant(j != 0);
            break;
        }

        try {
            WriteUnitOfWork wuow(opCtx);
            ASSERT_OK(ru1->setTimestamp(Timestamp(time++)));
            std::string s = str::stream()
                << "abcbcdcdedefefgfghghihijijkjklklmlmnmnomopopqpqrqrsrststutuv" << j;
            ASSERT_OK(rs->updateRecord(opCtx, recordId, s.c_str(), s.size() + 1));
            wuow.commit();
        } catch (const DBException& ex) {
            invariant(ex.toStatus().code() == ErrorCodes::WriteConflict);
        }
    }
}
Ejemplo n.º 5
0
    Status MultiIndexBlock::init(std::vector<BSONObj>& indexSpecs) {
        for ( size_t i = 0; i < indexSpecs.size(); i++ ) {
            BSONObj info = indexSpecs[i];

            string pluginName = IndexNames::findPluginName( info["key"].Obj() );
            if ( pluginName.size() ) {
                Status s =
                    _collection->getIndexCatalog()->_upgradeDatabaseMinorVersionIfNeeded(_txn, pluginName);
                if ( !s.isOK() )
                    return s;
            }

        }

        for ( size_t i = 0; i < indexSpecs.size(); i++ ) {
            BSONObj info = indexSpecs[i];
            StatusWith<BSONObj> statusWithInfo =
                _collection->getIndexCatalog()->prepareSpecForCreate( info );
            Status status = statusWithInfo.getStatus();
            if ( !status.isOK() )
                return status;
            info = statusWithInfo.getValue();

            IndexState state;
            state.block = new IndexCatalog::IndexBuildBlock(_txn, _collection, info);
            status = state.block->init();
            if ( !status.isOK() )
                return status;

            state.real = state.block->getEntry()->accessMethod();
            status = state.real->initializeAsEmpty(_txn);
            if ( !status.isOK() )
                return status;

            state.bulk = state.real->initiateBulk(_txn);

            _states.push_back( state );
        }

        return Status::OK();
    }
Ejemplo n.º 6
0
    StatusWith<DiskLoc> RecordStoreV1Base::updateRecord( OperationContext* txn,
                                                         const DiskLoc& oldLocation,
                                                         const char* data,
                                                         int dataSize,
                                                         bool enforceQuota,
                                                         UpdateMoveNotifier* notifier ) {
        Record* oldRecord = recordFor( oldLocation );
        if ( oldRecord->netLength() >= dataSize ) {
            // we fit
            _paddingFits( txn );
            memcpy( txn->recoveryUnit()->writingPtr( oldRecord->data(), dataSize ), data, dataSize );
            return StatusWith<DiskLoc>( oldLocation );
        }

        if ( isCapped() )
            return StatusWith<DiskLoc>( ErrorCodes::InternalError,
                                        "failing update: objects in a capped ns cannot grow",
                                        10003 );

        // we have to move

        _paddingTooSmall( txn );

        StatusWith<DiskLoc> newLocation = _insertRecord( txn, data, dataSize, enforceQuota );
        if ( !newLocation.isOK() )
            return newLocation;

        // insert worked, so we delete old record
        if ( notifier ) {
            Status moveStatus = notifier->recordStoreGoingToMove( txn,
                                                                  oldLocation,
                                                                  oldRecord->data(),
                                                                  oldRecord->netLength() );
            if ( !moveStatus.isOK() )
                return StatusWith<DiskLoc>( moveStatus );
        }

        deleteRecord( txn, oldLocation );

        return newLocation;
    }
Ejemplo n.º 7
0
    std::unique_ptr<SortedDataInterface> newSortedDataInterface(bool unique) final {
        std::string ns = "test.wt";
        OperationContextNoop txn(newRecoveryUnit().release());

        BSONObj spec = BSON("key" << BSON("a" << 1) << "name"
                                  << "testIndex"
                                  << "ns" << ns);

        IndexDescriptor desc(NULL, "", spec);

        StatusWith<std::string> result =
            TerichDbIndex::generateCreateString(kTerichDbEngineName, "", "", desc);
        ASSERT_OK(result.getStatus());

        string uri = "table:" + ns;
        invariantTerichDbOK(TerichDbIndex::Create(&txn, uri, result.getValue()));

        if (unique)
            return stdx::make_unique<TerichDbIndexUnique>(&txn, uri, &desc);
        return stdx::make_unique<TerichDbIndexStandard>(&txn, uri, &desc);
    }
Ejemplo n.º 8
0
    /**
     * Perform a single insert into a collection.  Requires the insert be preprocessed and the
     * collection already has been created.
     *
     * Might fault or error, otherwise populates the result.
     */
    static void singleInsert( OperationContext* txn,
                              const BSONObj& docToInsert,
                              Collection* collection,
                              WriteOpResult* result ) {

        const string& insertNS = collection->ns().ns();

        txn->lockState()->assertWriteLocked( insertNS );

        WriteUnitOfWork wunit(txn);
        StatusWith<DiskLoc> status = collection->insertDocument( txn, docToInsert, true );

        if ( !status.isOK() ) {
            result->setError(toWriteError(status.getStatus()));
        }
        else {
            repl::logOp( txn, "i", insertNS.c_str(), docToInsert );
            result->getStats().n = 1;
            wunit.commit();
        }
    }
Ejemplo n.º 9
0
        virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
            string coll = cmdObj[ "godinsert" ].valuestrsafe();
            log() << "test only command godinsert invoked coll:" << coll << endl;
            uassert( 13049, "godinsert must specify a collection", !coll.empty() );
            string ns = dbname + "." + coll;
            BSONObj obj = cmdObj[ "obj" ].embeddedObjectUserCheck();

            Lock::DBWrite lk(ns);
            Client::Context ctx( ns );
            Database* db = ctx.db();
            Collection* collection = db->getCollection( ns );
            if ( !collection ) {
                collection = db->createCollection( ns );
                if ( !collection ) {
                    errmsg = "could not create collection";
                    return false;
                }
            }
            StatusWith<DiskLoc> res = collection->insertDocument( obj, false );
            return appendCommandStatus( result, res.getStatus() );
        }
Ejemplo n.º 10
0
BtreeLogicTestHelper<OnDiskFormat>::BtreeLogicTestHelper(const BSONObj& order)
    : recordStore("TestRecordStore"),
      btree(&headManager,
            &recordStore,
            &cursorRegistry,
            Ordering::make(order),
            "TestIndex",
            /*isUnique*/ false) {
    static const string randomData("RandomStuff");

    // Generate a valid record location for a "fake" record, which we will repeatedly use
    // thoughout the tests.
    OperationContextNoop opCtx;
    StatusWith<RecordId> s =
        recordStore.insertRecord(&opCtx, randomData.c_str(), randomData.length(), false);

    ASSERT_TRUE(s.isOK());
    ASSERT_EQUALS(1, recordStore.numRecords(NULL));

    dummyDiskLoc = DiskLoc::fromRecordId(s.getValue());
}
Ejemplo n.º 11
0
    TEST( RecordStoreTestHarness, Simple1InsertDocWroter ) {
        scoped_ptr<HarnessHelper> harnessHelper( newHarnessHelper() );
        scoped_ptr<RecordStore> rs( harnessHelper->newNonCappedRecordStore() );
        
        DiskLoc loc1;

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );

            {
                WriteUnitOfWork uow( opCtx.get() );
                DummyDocWriter dw;
                StatusWith<DiskLoc> res = rs->insertRecord( opCtx.get(), &dw, false );
                ASSERT_OK( res.getStatus() );
                loc1 = res.getValue();
                uow.commit();
            }

            ASSERT_EQUALS( string("eliot"), rs->dataFor( opCtx.get(), loc1 ).data() );
        }
    }
void ReplicationCoordinatorImpl::_startVoteRequester(long long newTerm) {
    invariant(_voteRequester);
    invariant(!_electionWinnerDeclarer);
    LoseElectionGuardV1 lossGuard(this);

    _voteRequester.reset(new VoteRequester);
    StatusWith<ReplicationExecutor::EventHandle> nextPhaseEvh = _voteRequester->start(
        &_replExecutor,
        _rsConfig,
        _rsConfig.getMemberAt(_selfIndex).getId(),
        _topCoord->getTerm(),
        false,
        getMyLastOptime(),
        stdx::bind(&ReplicationCoordinatorImpl::_onVoteRequestComplete, this, newTerm));
    if (nextPhaseEvh.getStatus() == ErrorCodes::ShutdownInProgress) {
        return;
    }
    fassert(28643, nextPhaseEvh.getStatus());

    lossGuard.dismiss();
}
Ejemplo n.º 13
0
    // Goes over the request and preprocesses normalized versions of all the inserts in the request
    static void normalizeInserts( const BatchedCommandRequest& request,
                                  vector<StatusWith<BSONObj> >* normalizedInserts,
                                  vector<PregeneratedKeys>* pregen ) {

        normalizedInserts->reserve(request.sizeWriteOps());
        for ( size_t i = 0; i < request.sizeWriteOps(); ++i ) {
            BSONObj insertDoc = request.getInsertRequest()->getDocumentsAt( i );
            StatusWith<BSONObj> normalInsert = fixDocumentForInsert( insertDoc );
            normalizedInserts->push_back( normalInsert );
            if ( request.getOrdered() && !normalInsert.isOK() )
                break;

            if ( !normalInsert.getValue().isEmpty() )
                insertDoc = normalInsert.getValue();

            pregen->push_back( PregeneratedKeys() );
            GeneratorHolder::getInstance()->prepare( request.getTargetingNS(),
                                                     insertDoc,
                                                     &pregen->back() );
        }
    }
Ejemplo n.º 14
0
    StatusWith<DiskLoc> Collection::insertDocument( OperationContext* txn,
                                                    const BSONObj& doc,
                                                    MultiIndexBlock& indexBlock ) {
        StatusWith<DiskLoc> loc = _recordStore->insertRecord( txn,
                                                              doc.objdata(),
                                                              doc.objsize(),
                                                              0 );

        if ( !loc.isOK() )
            return loc;

        InsertDeleteOptions indexOptions;
        indexOptions.logIfError = false;
        indexOptions.dupsAllowed = true; // in repair we should be doing no checking

        Status status = indexBlock.insert( doc, loc.getValue(), indexOptions );
        if ( !status.isOK() )
            return StatusWith<DiskLoc>( status );

        return loc;
    }
Ejemplo n.º 15
0
    StatusWith<ReplicationExecutor::CallbackHandle>
    ReplicationExecutor::scheduleWorkWithGlobalExclusiveLock(
            const CallbackFn& work) {

        boost::lock_guard<boost::mutex> lk(_mutex);
        StatusWith<CallbackHandle> handle = enqueueWork_inlock(&_exclusiveLockInProgressQueue,
                                                               work);
        if (handle.isOK()) {
            const stdx::function<void (OperationContext*)> doOp = stdx::bind(
                    &ReplicationExecutor::doOperationWithGlobalExclusiveLock,
                    this,
                    stdx::placeholders::_1,
                    handle.getValue());
            _dblockWorkers.schedule(
                    makeNoExcept(stdx::bind(
                                         &NetworkInterface::runCallbackWithGlobalExclusiveLock,
                                         _networkInterface.get(),
                                         doOp)));
        }
        return handle;
    }
Ejemplo n.º 16
0
StatusWith<RecordId> RecordStoreV1Base::insertRecord(OperationContext* txn,
                                                     const DocWriter* doc,
                                                     bool enforceQuota) {
    int docSize = doc->documentSize();
    if (docSize < 4) {
        return StatusWith<RecordId>(ErrorCodes::InvalidLength, "record has to be >= 4 bytes");
    }
    const int lenWHdr = docSize + MmapV1RecordHeader::HeaderSize;
    if (lenWHdr > MaxAllowedAllocation) {
        return StatusWith<RecordId>(ErrorCodes::InvalidLength, "record has to be <= 16.5MB");
    }
    const int lenToAlloc =
        (doc->addPadding() && shouldPadInserts()) ? quantizeAllocationSpace(lenWHdr) : lenWHdr;

    StatusWith<DiskLoc> loc = allocRecord(txn, lenToAlloc, enforceQuota);
    if (!loc.isOK())
        return StatusWith<RecordId>(loc.getStatus());

    MmapV1RecordHeader* r = recordFor(loc.getValue());
    fassert(17319, r->lengthWithHeaders() >= lenWHdr);

    r = reinterpret_cast<MmapV1RecordHeader*>(txn->recoveryUnit()->writingPtr(r, lenWHdr));
    doc->writeDocument(r->data());

    _addRecordToRecListInExtent(txn, r, loc.getValue());

    _details->incrementStats(txn, r->netLength(), 1);

    return StatusWith<RecordId>(loc.getValue().toRecordId());
}
StatusWith<SettingsType> CatalogManagerReplicaSet::getGlobalSettings(OperationContext* txn,
                                                                     const string& key) {
    const auto configShard = grid.shardRegistry()->getShard(txn, "config");
    const auto readHost = configShard->getTargeter()->findHost(kConfigReadSelector);
    if (!readHost.isOK()) {
        return readHost.getStatus();
    }

    auto findStatus = _exhaustiveFindOnConfig(readHost.getValue(),
                                              NamespaceString(SettingsType::ConfigNS),
                                              BSON(SettingsType::key(key)),
                                              BSONObj(),
                                              1);
    if (!findStatus.isOK()) {
        return findStatus.getStatus();
    }

    const auto& docs = findStatus.getValue().value;
    if (docs.empty()) {
        return {ErrorCodes::NoMatchingDocument,
                str::stream() << "can't find settings document with key: " << key};
    }

    BSONObj settingsDoc = docs.front();
    StatusWith<SettingsType> settingsResult = SettingsType::fromBSON(settingsDoc);
    if (!settingsResult.isOK()) {
        return {ErrorCodes::FailedToParse,
                str::stream() << "error while parsing settings document: " << settingsDoc << " : "
                              << settingsResult.getStatus().toString()};
    }

    const SettingsType& settings = settingsResult.getValue();

    Status validationStatus = settings.validate();
    if (!validationStatus.isOK()) {
        return validationStatus;
    }

    return settingsResult;
}
Status EphemeralForTestRecordStore::insertRecordsWithDocWriter(OperationContext* opCtx,
                                                               const DocWriter* const* docs,
                                                               const Timestamp*,
                                                               size_t nDocs,
                                                               RecordId* idsOut) {
    stdx::lock_guard<stdx::recursive_mutex> lock(_data->recordsMutex);

    for (size_t i = 0; i < nDocs; i++) {
        const int len = docs[i]->documentSize();
        if (_isCapped && len > _cappedMaxSize) {
            // We use dataSize for capped rollover and we don't want to delete everything if we
            // know this won't fit.
            return Status(ErrorCodes::BadValue, "object to insert exceeds cappedMaxSize");
        }

        EphemeralForTestRecord rec(len);
        docs[i]->writeDocument(rec.data.get());

        RecordId loc;
        if (_data->isOplog) {
            StatusWith<RecordId> status = extractAndCheckLocForOplog(rec.data.get(), len);
            if (!status.isOK())
                return status.getStatus();
            loc = status.getValue();
        } else {
            loc = allocateLoc();
        }

        opCtx->recoveryUnit()->registerChange(new InsertChange(opCtx, _data, loc));
        _data->dataSize += len;
        _data->records[loc] = rec;

        cappedDeleteAsNeeded_inlock(opCtx);

        if (idsOut)
            idsOut[i] = loc;
    }

    return Status::OK();
}
Ejemplo n.º 19
0
    void ReplicationCoordinatorImpl::_heartbeatReconfigFinish(
            const ReplicationExecutor::CallbackData& cbData,
            const ReplicaSetConfig& newConfig,
            StatusWith<int> myIndex) {

        boost::lock_guard<boost::mutex> lk(_mutex);
        invariant(_rsConfigState == kConfigHBReconfiguring);
        invariant(!_rsConfig.isInitialized() ||
                  _rsConfig.getConfigVersion() < newConfig.getConfigVersion());
        if (!myIndex.isOK()) {
            switch (myIndex.getStatus().code()) {
            case ErrorCodes::NoSuchKey:
                log() << "Cannot find self in new replica set configuration; I must be removed; " <<
                    myIndex.getStatus();
                break;
            case ErrorCodes::DuplicateKey:
                error() << "Several entries in new config represent this node; "
                    "Removing self until an acceptable configuration arrives; " <<
                    myIndex.getStatus();
                break;
            default:
                error() << "Could not validate configuration received from remote node; "
                    "Removing self until an acceptable configuration arrives; " <<
                    myIndex.getStatus();
                break;
            }
            myIndex = StatusWith<int>(-1);
        }
        _setCurrentRSConfig_inlock(newConfig, myIndex.getValue());
    }
Ejemplo n.º 20
0
StatusWith<RecordId> RecordStoreV1Base::_insertRecord(OperationContext* txn,
                                                      const char* data,
                                                      int len,
                                                      bool enforceQuota) {
    const int lenWHdr = len + MmapV1RecordHeader::HeaderSize;
    const int lenToAlloc = shouldPadInserts() ? quantizeAllocationSpace(lenWHdr) : lenWHdr;
    fassert(17208, lenToAlloc >= lenWHdr);

    StatusWith<DiskLoc> loc = allocRecord(txn, lenToAlloc, enforceQuota);
    if (!loc.isOK())
        return StatusWith<RecordId>(loc.getStatus());

    MmapV1RecordHeader* r = recordFor(loc.getValue());
    fassert(17210, r->lengthWithHeaders() >= lenWHdr);

    // copy the data
    r = reinterpret_cast<MmapV1RecordHeader*>(txn->recoveryUnit()->writingPtr(r, lenWHdr));
    memcpy(r->data(), data, len);

    _addRecordToRecListInExtent(txn, r, loc.getValue());

    _details->incrementStats(txn, r->netLength(), 1);

    return StatusWith<RecordId>(loc.getValue().toRecordId());
}
Ejemplo n.º 21
0
    // Insert multiple records, and verify that calling touch() on a nonempty collection
    // returns an OK status, even when NULL is passed in for the stats output.
    TEST( RecordStoreTestHarness, TouchNonEmptyWithNullStats ) {
        scoped_ptr<HarnessHelper> harnessHelper( newHarnessHelper() );
        scoped_ptr<RecordStore> rs( harnessHelper->newNonCappedRecordStore() );

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT_EQUALS( 0, rs->numRecords( opCtx.get() ) );
        }

        int nToInsert = 10;
        for ( int i = 0; i < nToInsert; i++ ) {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            {
                stringstream ss;
                ss << "record " << i;
                string data = ss.str();

                WriteUnitOfWork uow( opCtx.get() );
                StatusWith<DiskLoc> res = rs->insertRecord( opCtx.get(),
                                                            data.c_str(),
                                                            data.size() + 1,
                                                            false );
                ASSERT_OK( res.getStatus() );
                uow.commit();
            }
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT_EQUALS( nToInsert, rs->numRecords( opCtx.get() ) );
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            // XXX does not verify the collection was loaded into cache
            // (even if supported by storage engine)
            Status status = rs->touch( opCtx.get(), NULL /* stats output */ );
            ASSERT( status.isOK() || status.code() == ErrorCodes::CommandNotSupported );
        }
    }
Ejemplo n.º 22
0
Status CollectionCloner::_parseCursorResponse(BSONObj response,
                                              std::vector<CursorResponse>* cursors,
                                              EstablishCursorsCommand cursorCommand) {
    switch (cursorCommand) {
        case Find: {
            StatusWith<CursorResponse> findResponse = CursorResponse::parseFromBSON(response);
            if (!findResponse.isOK()) {
                return findResponse.getStatus().withContext(
                    str::stream() << "Error parsing the 'find' query against collection '"
                                  << _sourceNss.ns()
                                  << "'");
            }
            cursors->push_back(std::move(findResponse.getValue()));
            break;
        }
        case ParallelCollScan: {
            auto cursorElements = _parseParallelCollectionScanResponse(response);
            if (!cursorElements.isOK()) {
                return cursorElements.getStatus();
            }
            std::vector<BSONElement> cursorsArray;
            cursorsArray = cursorElements.getValue();
            // Parse each BSONElement into a 'CursorResponse' object.
            for (BSONElement cursor : cursorsArray) {
                if (!cursor.isABSONObj()) {
                    Status errorStatus(
                        ErrorCodes::FailedToParse,
                        "The 'cursor' field in the list of cursor responses is not a "
                        "valid BSON Object");
                    return errorStatus;
                }
                const BSONObj cursorObj = cursor.Obj().getOwned();
                StatusWith<CursorResponse> parallelCollScanResponse =
                    CursorResponse::parseFromBSON(cursorObj);
                if (!parallelCollScanResponse.isOK()) {
                    return parallelCollScanResponse.getStatus();
                }
                cursors->push_back(std::move(parallelCollScanResponse.getValue()));
            }
            break;
        }
        default: {
            Status errorStatus(
                ErrorCodes::FailedToParse,
                "The command used to establish the collection cloner cursors is not valid.");
            return errorStatus;
        }
    }
    return Status::OK();
}
Ejemplo n.º 23
0
    TEST( RocksRecordStoreTest, Delete1 ) {
        unittest::TempDir td( _rocksRecordStoreTestDir );
        scoped_ptr<rocksdb::DB> db( getDB( td.path() ) );

        {
            RocksRecordStore rs( "foo.bar", db.get(),
                                 db->DefaultColumnFamily(),
                                 db->DefaultColumnFamily() );
            string s = "eliot was here";

            DiskLoc loc;
            {
                MyOperationContext opCtx( db.get() );
                {
                    WriteUnitOfWork uow( opCtx.recoveryUnit() );
                    StatusWith<DiskLoc> res = rs.insertRecord(&opCtx,
                                                              s.c_str(),
                                                              s.size() + 1,
                                                              -1 );
                    ASSERT_OK( res.getStatus() );
                    loc = res.getValue();
                }

                ASSERT_EQUALS( s, rs.dataFor( loc ).data() );
                ASSERT_EQUALS( 1, rs.numRecords() );
                ASSERT_EQUALS( static_cast<long long> ( s.length() + 1 ), rs.dataSize() );
            }

            ASSERT( rs.dataFor( loc ).data() != NULL );

            {
                MyOperationContext opCtx( db.get() );
                WriteUnitOfWork uow( opCtx.recoveryUnit() );
                rs.deleteRecord( &opCtx, loc );

                ASSERT_EQUALS( 0, rs.numRecords() );
                ASSERT_EQUALS( 0, rs.dataSize() );
            }
        }
    }
Ejemplo n.º 24
0
 StatusWith<ReplicationExecutor::CallbackHandle> ReplicationExecutor::scheduleRemoteCommand(
         const RemoteCommandRequest& request,
         const RemoteCommandCallbackFn& cb) {
     RemoteCommandRequest scheduledRequest = request;
     if (request.timeout == kNoTimeout) {
         scheduledRequest.expirationDate = kNoExpirationDate;
     }
     else {
         scheduledRequest.expirationDate =
             _networkInterface->now() + scheduledRequest.timeout.total_milliseconds();
     }
     boost::lock_guard<boost::mutex> lk(_mutex);
     StatusWith<CallbackHandle> handle = enqueueWork_inlock(
             &_networkInProgressQueue,
             stdx::bind(remoteCommandFailedEarly,
                        stdx::placeholders::_1,
                        cb,
                        scheduledRequest));
     if (handle.isOK()) {
         handle.getValue()._iter->isNetworkOperation = true;
         _networkInterface->startCommand(
                 handle.getValue(),
                 scheduledRequest,
                 stdx::bind(&ReplicationExecutor::_finishRemoteCommand,
                            this,
                            scheduledRequest,
                            stdx::placeholders::_1,
                            handle.getValue(),
                            handle.getValue()._iter->generation,
                            cb));
     }
     return handle;
 }
Status ReplicationCoordinatorExternalStateImpl::storeLocalLastVoteDocument(
    OperationContext* opCtx, const LastVote& lastVote) {
    BSONObj lastVoteObj = lastVote.toBSON();
    try {
        Status status =
            writeConflictRetry(opCtx, "save replica set lastVote", lastVoteCollectionName, [&] {
                Lock::DBLock dbWriteLock(opCtx, lastVoteDatabaseName, MODE_X);

                // If there is no last vote document, we want to store one. Otherwise, we only want
                // to replace it if the new last vote document would have a higher term. We both
                // check the term of the current last vote document and insert the new document
                // under the DBLock to synchronize the two operations.
                BSONObj result;
                bool exists = Helpers::getSingleton(opCtx, lastVoteCollectionName, result);
                if (!exists) {
                    Helpers::putSingleton(opCtx, lastVoteCollectionName, lastVoteObj);
                } else {
                    StatusWith<LastVote> oldLastVoteDoc = LastVote::readFromLastVote(result);
                    if (!oldLastVoteDoc.isOK()) {
                        return oldLastVoteDoc.getStatus();
                    }
                    if (lastVote.getTerm() > oldLastVoteDoc.getValue().getTerm()) {
                        Helpers::putSingleton(opCtx, lastVoteCollectionName, lastVoteObj);
                    }
                }

                return Status::OK();
            });

        if (!status.isOK()) {
            return status;
        }

        opCtx->recoveryUnit()->waitUntilDurable();

        return Status::OK();
    } catch (const DBException& ex) {
        return ex.toStatus();
    }
}
void ReplicationCoordinatorImpl::_startVoteRequester(long long newTerm) {
    invariant(_voteRequester);
    LoseElectionGuardV1 lossGuard(this);

    LockGuard lk(_topoMutex);

    const auto lastOpTime =
        _isDurableStorageEngine() ? getMyLastDurableOpTime() : getMyLastAppliedOpTime();

    _voteRequester.reset(new VoteRequester);
    StatusWith<ReplicationExecutor::EventHandle> nextPhaseEvh = _voteRequester->start(
        &_replExecutor, _rsConfig, _selfIndex, _topCoord->getTerm(), false, lastOpTime);
    if (nextPhaseEvh.getStatus() == ErrorCodes::ShutdownInProgress) {
        return;
    }
    fassert(28643, nextPhaseEvh.getStatus());
    _replExecutor.onEvent(
        nextPhaseEvh.getValue(),
        stdx::bind(&ReplicationCoordinatorImpl::_onVoteRequestComplete, this, newTerm));

    lossGuard.dismiss();
}
Ejemplo n.º 27
0
    bool WriteCmd::run(OperationContext* txn,
                       const string& dbName,
                       BSONObj& cmdObj,
                       int options,
                       string& errMsg,
                       BSONObjBuilder& result) {
        // Can't be run on secondaries.
        dassert(txn->writesAreReplicated());
        BatchedCommandRequest request( _writeType );
        BatchedCommandResponse response;

        if ( !request.parseBSON( cmdObj, &errMsg ) || !request.isValid( &errMsg ) ) {
            return appendCommandStatus( result, Status( ErrorCodes::FailedToParse, errMsg ) );
        }

        // Note that this is a runCommmand, and therefore, the database and the collection name
        // are in different parts of the grammar for the command. But it's more convenient to
        // work with a NamespaceString. We built it here and replace it in the parsed command.
        // Internally, everything work with the namespace string as opposed to just the
        // collection name.
        NamespaceString nss(dbName, request.getNS());
        request.setNSS(nss);

        StatusWith<WriteConcernOptions> wcStatus = extractWriteConcern(cmdObj);

        if (!wcStatus.isOK()) {
            return appendCommandStatus(result, wcStatus.getStatus());
        }
        txn->setWriteConcern(wcStatus.getValue());

        WriteBatchExecutor writeBatchExecutor(txn,
                                              &globalOpCounters,
                                              &LastError::get(txn->getClient()));

        writeBatchExecutor.executeBatch( request, &response );

        result.appendElements( response.toBSON() );
        return response.getOk();
    }
Ejemplo n.º 28
0
StatusWith<RecordId> Collection::insertDocument(OperationContext* txn,
                                                const BSONObj& docToInsert,
                                                bool enforceQuota,
                                                bool fromMigrate) {
    {
        auto status = checkValidation(txn, docToInsert);
        if (!status.isOK())
            return status;
    }

    const SnapshotId sid = txn->recoveryUnit()->getSnapshotId();

    if (_indexCatalog.findIdIndex(txn)) {
        if (docToInsert["_id"].eoo()) {
            return StatusWith<RecordId>(ErrorCodes::InternalError,
                                        str::stream()
                                            << "Collection::insertDocument got "
                                               "document without _id for ns:" << _ns.ns());
        }
    }

    if (_mustTakeCappedLockOnInsert)
        synchronizeOnCappedInFlightResource(txn->lockState());

    StatusWith<RecordId> res = _insertDocument(txn, docToInsert, enforceQuota);
    invariant(sid == txn->recoveryUnit()->getSnapshotId());
    if (res.isOK()) {
        getGlobalServiceContext()->getOpObserver()->onInsert(txn, ns(), docToInsert, fromMigrate);

        // If there is a notifier object and another thread is waiting on it, then we notify
        // waiters of this document insert. Waiters keep a shared_ptr to '_cappedNotifier', so
        // there are waiters if this Collection's shared_ptr is not unique.
        if (_cappedNotifier && !_cappedNotifier.unique()) {
            _cappedNotifier->notifyOfInsert();
        }
    }

    return res;
}
Ejemplo n.º 29
0
Status KVCatalog::newCollection(OperationContext* opCtx,
                                StringData ns,
                                const CollectionOptions& options,
                                KVPrefix prefix) {
    invariant(opCtx->lockState()->isDbLockedForMode(nsToDatabaseSubstring(ns), MODE_X));

    const string ident = _newUniqueIdent(ns, "collection");

    stdx::lock_guard<stdx::mutex> lk(_identsLock);
    Entry& old = _idents[ns.toString()];
    if (!old.ident.empty()) {
        return Status(ErrorCodes::NamespaceExists, "collection already exists");
    }

    opCtx->recoveryUnit()->registerChange(new AddIdentChange(this, ns));

    BSONObj obj;
    {
        BSONObjBuilder b;
        b.append("ns", ns);
        b.append("ident", ident);
        BSONCollectionCatalogEntry::MetaData md;
        md.ns = ns.toString();
        md.options = options;
        md.prefix = prefix;
        b.append("md", md.toBSON());
        obj = b.obj();
    }
    const bool enforceQuota = false;
    // TODO SERVER-30638: using timestamp 0 for these inserts.
    StatusWith<RecordId> res =
        _rs->insertRecord(opCtx, obj.objdata(), obj.objsize(), Timestamp(), enforceQuota);
    if (!res.isOK())
        return res.getStatus();

    old = Entry(ident, res.getValue());
    LOG(1) << "stored meta data for " << ns << " @ " << res.getValue();
    return Status::OK();
}
Ejemplo n.º 30
0
    void WiredTigerUtil::fetchTypeAndSourceURI(OperationContext* opCtx,
                                               const std::string& tableUri,
                                               std::string* type,
                                               std::string* source) {
        std::string colgroupUri = "colgroup";
        const size_t colon = tableUri.find(':');
        invariant(colon != string::npos);
        colgroupUri += tableUri.substr(colon);
        StatusWith<std::string> colgroupResult = getMetadata(opCtx, colgroupUri);
        invariant(colgroupResult.isOK());
        WiredTigerConfigParser parser(colgroupResult.getValue());

        WT_CONFIG_ITEM typeItem;
        invariant(parser.get("type", &typeItem) == 0);
        invariant(typeItem.type == WT_CONFIG_ITEM::WT_CONFIG_ITEM_ID);
        *type = std::string(typeItem.str, typeItem.len);

        WT_CONFIG_ITEM sourceItem;
        invariant(parser.get("source", &sourceItem) == 0);
        invariant(sourceItem.type == WT_CONFIG_ITEM::WT_CONFIG_ITEM_STRING);
        *source = std::string(sourceItem.str, sourceItem.len);
    }