summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/biggie
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/biggie')
-rw-r--r--src/mongo/db/storage/biggie/biggie_record_store.cpp34
-rw-r--r--src/mongo/db/storage/biggie/biggie_record_store.h9
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};