void BackgroundSync::_signalNoNewDataForApplier(OperationContext* txn) { // Signal to consumers that we have entered the stopped state // if the signal isn't already in the queue. const boost::optional<BSONObj> lastObjectPushed = _oplogBuffer->lastObjectPushed(txn); if (!lastObjectPushed || !lastObjectPushed->isEmpty()) { const BSONObj sentinelDoc; _oplogBuffer->pushEvenIfFull(txn, sentinelDoc); bufferCountGauge.increment(); bufferSizeGauge.increment(sentinelDoc.objsize()); } }
void BackgroundSync::_producerThread() { const MemberState state = _replCoord->getMemberState(); // we want to pause when the state changes to primary if (_replCoord->isWaitingForApplierToDrain() || state.primary()) { if (!isPaused()) { stop(); } if (_replCoord->isWaitingForApplierToDrain()) { // Signal to consumers that we have entered the paused state if the signal isn't already // in the queue. const boost::optional<BSONObj> lastObjectPushed = _buffer.lastObjectPushed(); if (!lastObjectPushed || !lastObjectPushed->isEmpty()) { const BSONObj sentinelDoc; _buffer.pushEvenIfFull(sentinelDoc); bufferCountGauge.increment(); bufferSizeGauge.increment(sentinelDoc.objsize()); } } sleepsecs(1); return; } // TODO(spencer): Use a condition variable to await loading a config. if (state.startup()) { // Wait for a config to be loaded sleepsecs(1); return; } // We need to wait until initial sync has started. if (_replCoord->getMyLastOptime().isNull()) { sleepsecs(1); return; } // we want to unpause when we're no longer primary // start() also loads _lastOpTimeFetched, which we know is set from the "if" OperationContextImpl txn; if (isPaused()) { start(&txn); } _produce(&txn); }