Status ReplicationCoordinatorExternalStateImpl::storeLocalConfigDocument( OperationContext* txn, const BSONObj& config) { try { Lock::DBWrite dbWriteLock(txn->lockState(), configCollectionName); Helpers::putSingleton(txn, configCollectionName, config); return Status::OK(); } catch (const DBException& ex) { return ex.toStatus(); } }
Status ReplicationCoordinatorExternalStateImpl::storeLocalConfigDocument(OperationContext* opCtx, const BSONObj& config) { try { writeConflictRetry(opCtx, "save replica set config", configCollectionName, [&] { Lock::DBLock dbWriteLock(opCtx, configDatabaseName, MODE_X); Helpers::putSingleton(opCtx, configCollectionName, config); }); return Status::OK(); } catch (const DBException& ex) { return ex.toStatus(); } }
Status ReplicationCoordinatorExternalStateImpl::storeLocalConfigDocument(OperationContext* txn, const BSONObj& config) { try { MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { ScopedTransaction transaction(txn, MODE_IX); Lock::DBLock dbWriteLock(txn->lockState(), configDatabaseName, MODE_X); Helpers::putSingleton(txn, configCollectionName, config); return Status::OK(); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "save replica set config", configCollectionName); } catch (const DBException& ex) { return ex.toStatus(); } }
Status ReplicationCoordinatorExternalStateImpl::storeLocalLastVoteDocument( OperationContext* txn, const LastVote& lastVote) { BSONObj lastVoteObj = lastVote.toBSON(); try { MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { ScopedTransaction transaction(txn, MODE_IX); Lock::DBLock dbWriteLock(txn->lockState(), lastVoteDatabaseName, MODE_X); Helpers::putSingleton(txn, lastVoteCollectionName, lastVoteObj); return Status::OK(); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END( txn, "save replica set lastVote", lastVoteCollectionName); MONGO_UNREACHABLE; } catch (const DBException& ex) { return ex.toStatus(); } }
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(); } }
/**************************************************************************** Desc: Try to perform a checkpoint on the database. Returns TRUE if we need to terminate. ****************************************************************************/ FLMBOOL F_Database::tryCheckpoint( IF_Thread * pThread, CP_INFO * pCPInfo) { RCODE rc = NE_XFLM_OK; FLMBOOL bTerminate = FALSE; FLMBOOL bForceCheckpoint; FLMINT iForceReason; FLMUINT uiCurrTime; XFLM_DB_STATS * pDbStats; // See if we should terminate the thread. if (pThread->getShutdownFlag()) { // Set terminate flag to TRUE and then see if // we have been set up to do one final checkpoint // to flush dirty buffers to disk. bTerminate = TRUE; } // Determine if we need to force a checkpoint. bForceCheckpoint = FALSE; iForceReason = 0; uiCurrTime = (FLMUINT)FLM_GET_TIMER(); if (bTerminate) { bForceCheckpoint = TRUE; iForceReason = XFLM_CP_SHUTTING_DOWN_REASON; } else if (!m_pRfl->seeIfRflVolumeOk() || RC_BAD( m_CheckpointRc)) { bForceCheckpoint = TRUE; iForceReason = XFLM_CP_RFL_VOLUME_PROBLEM; } else if ((FLM_ELAPSED_TIME( uiCurrTime, m_uiLastCheckpointTime) >= gv_XFlmSysData.uiMaxCPInterval) || (!gv_XFlmSysData.uiMaxCPInterval)) { bForceCheckpoint = TRUE; iForceReason = XFLM_CP_TIME_INTERVAL_REASON; } if (gv_XFlmSysData.Stats.bCollectingStats) { // Statistics are being collected for the system. Therefore, // if we are not currently collecting statistics in the // start. If we were collecting statistics, but the // start time was earlier than the start time in the system // statistics structure, reset the statistics. if (!pCPInfo->Stats.bCollectingStats) { flmStatStart( &pCPInfo->Stats); } else if (pCPInfo->Stats.uiStartTime < gv_XFlmSysData.Stats.uiStartTime) { flmStatReset( &pCPInfo->Stats, FALSE); } (void)flmStatGetDb( &pCPInfo->Stats, this, 0, &pDbStats, NULL, NULL); } else { pDbStats = NULL; } // Lock write object - If we are forcing a checkpoint // wait until we get the lock. Otherwise, if we can't get // the lock without waiting, don't do anything. if (bForceCheckpoint || (gv_XFlmSysData.pBlockCacheMgr->m_uiMaxDirtyCache && (m_uiDirtyCacheCount + m_uiLogCacheCount) * m_uiBlockSize > gv_XFlmSysData.pBlockCacheMgr->m_uiMaxDirtyCache)) { if (RC_BAD( rc = dbWriteLock( pCPInfo->hWaitSem, pDbStats))) { // THIS SHOULD NEVER HAPPEN BECAUSE dbWriteLock will // wait forever for the lock! RC_UNEXPECTED_ASSERT( rc); goto Exit; } pThread->setThreadStatusStr( "Forcing checkpoint"); // Must wait for any RFL writes to complete. (void)m_pRfl->seeIfRflWritesDone( pCPInfo->hWaitSem, TRUE); } else { if (RC_BAD( dbWriteLock( pCPInfo->hWaitSem, pDbStats, 0))) { goto Exit; } pThread->setThreadStatus( FLM_THREAD_STATUS_RUNNING); // See if we actually need to do the checkpoint. If the // current transaction ID and the last checkpoint transaction // ID are the same, no updates have occurred that would require // a checkpoint to take place. if (m_lastCommittedDbHdr.ui64RflLastCPTransID == m_lastCommittedDbHdr.ui64CurrTransID || !m_pRfl->seeIfRflWritesDone( pCPInfo->hWaitSem, FALSE)) { dbWriteUnlock(); goto Exit; } } // Do the checkpoint. (void)doCheckpoint( pCPInfo->hWaitSem, pDbStats, pCPInfo->pSFileHdl, FALSE, bForceCheckpoint, iForceReason, 0, 0); if (pDbStats) { (void)flmStatUpdate( &pCPInfo->Stats); } dbWriteUnlock(); // Set the thread's status pThread->setThreadStatus( FLM_THREAD_STATUS_SLEEPING); Exit: return( bTerminate); }