diff options
Diffstat (limited to 'src/mongo/db/storage/biggie')
-rw-r--r-- | src/mongo/db/storage/biggie/biggie_record_store.cpp | 34 | ||||
-rw-r--r-- | src/mongo/db/storage/biggie/biggie_record_store.h | 9 |
2 files changed, 38 insertions, 5 deletions
diff --git a/src/mongo/db/storage/biggie/biggie_record_store.cpp b/src/mongo/db/storage/biggie/biggie_record_store.cpp index 70e358f1c99..266097121b6 100644 --- a/src/mongo/db/storage/biggie/biggie_record_store.cpp +++ b/src/mongo/db/storage/biggie/biggie_record_store.cpp @@ -140,6 +140,7 @@ bool RecordStore::findRecord(OperationContext* opCtx, const RecordId& loc, Recor } void RecordStore::deleteRecord(OperationContext* opCtx, const RecordId& dl) { + _initHighestIdIfNeeded(opCtx); auto ru = RecoveryUnit::get(opCtx); StringStore* workingCopy(ru->getHead()); SizeAdjuster adjuster(opCtx, this); @@ -172,7 +173,7 @@ Status RecordStore::insertRecords(OperationContext* opCtx, thisRecordId = status.getValue().repr(); _visibilityManager->addUncommittedRecord(opCtx, this, RecordId(thisRecordId)); } else { - thisRecordId = _nextRecordId(); + thisRecordId = _nextRecordId(opCtx); } workingCopy->insert( StringStore::value_type{createKey(_ident, thisRecordId), @@ -333,6 +334,37 @@ boost::optional<RecordId> RecordStore::oplogStartHack(OperationContext* opCtx, return rid; } +void RecordStore::_initHighestIdIfNeeded(OperationContext* opCtx) { + // In the normal case, this will already be initialized, so use a weak load. Since this value + // will only change from 0 to a positive integer, the only risk is reading an outdated value, 0, + // and having to take the mutex. + if (_highestRecordId.loadRelaxed() > 0) { + return; + } + + // Only one thread needs to do this. + stdx::lock_guard<Latch> lk(_initHighestIdMutex); + if (_highestRecordId.load() > 0) { + return; + } + + // Need to start at 1 so we are always higher than RecordId::min() + int64_t nextId = 1; + + // Find the largest RecordId currently in use. + std::unique_ptr<SeekableRecordCursor> cursor = getCursor(opCtx, /*forward=*/false); + if (auto record = cursor->next()) { + nextId = record->id.repr() + 1; + } + + _highestRecordId.store(nextId); +}; + +int64_t RecordStore::_nextRecordId(OperationContext* opCtx) { + _initHighestIdIfNeeded(opCtx); + return _highestRecordId.fetchAndAdd(1); +} + bool RecordStore::_cappedAndNeedDelete(OperationContext* opCtx, StringStore* workingCopy) { if (!_isCapped) return false; diff --git a/src/mongo/db/storage/biggie/biggie_record_store.h b/src/mongo/db/storage/biggie/biggie_record_store.h index b65cf933db2..bb0f6abbd75 100644 --- a/src/mongo/db/storage/biggie/biggie_record_store.h +++ b/src/mongo/db/storage/biggie/biggie_record_store.h @@ -112,12 +112,12 @@ public: private: friend class VisibilityManagerChange; + void _initHighestIdIfNeeded(OperationContext* opCtx); + /** * This gets the next (guaranteed) unique record id. */ - inline int64_t _nextRecordId() { - return _highestRecordId.fetchAndAdd(1); - } + int64_t _nextRecordId(OperationContext* opCtx); /** * Two helper functions for deleting excess records in capped record stores. @@ -142,7 +142,8 @@ private: mutable Mutex _cappedDeleterMutex = MONGO_MAKE_LATCH("RecordStore::_cappedDeleterMutex"); - AtomicWord<long long> _highestRecordId{1}; + mutable Mutex _initHighestIdMutex = MONGO_MAKE_LATCH("RecordStore::_initHighestIdMutex"); + AtomicWord<long long> _highestRecordId{0}; AtomicWord<long long> _numRecords{0}; AtomicWord<long long> _dataSize{0}; |