summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeert Bosch <geert@mongodb.com>2019-01-08 13:56:33 -0500
committerGeert Bosch <geert@mongodb.com>2019-01-10 15:23:02 -0500
commit54758174fef8c2b790ff2ed04d16f6578133abc5 (patch)
tree0d2d032208706a22171098614ac4adc157aae621
parentfacdcf14cfec192876a373fc49163769215327d8 (diff)
downloadmongo-54758174fef8c2b790ff2ed04d16f6578133abc5.tar.gz
SERVER-38893 Fix out-of-order biggie oplog insert
-rw-r--r--src/mongo/db/storage/biggie/biggie_record_store.cpp29
-rw-r--r--src/mongo/db/storage/biggie/biggie_record_store.h4
-rw-r--r--src/mongo/db/storage/record_store_test_oplog.cpp27
3 files changed, 29 insertions, 31 deletions
diff --git a/src/mongo/db/storage/biggie/biggie_record_store.cpp b/src/mongo/db/storage/biggie/biggie_record_store.cpp
index 7de342838e6..32bb5fafeb3 100644
--- a/src/mongo/db/storage/biggie/biggie_record_store.cpp
+++ b/src/mongo/db/storage/biggie/biggie_record_store.cpp
@@ -168,7 +168,7 @@ Status RecordStore::insertRecords(OperationContext* opCtx,
int64_t thisRecordId = 0;
if (_isOplog) {
StatusWith<RecordId> status =
- extractAndCheckLocForOplog(opCtx, record.data.data(), record.data.size());
+ oploghack::extractKey(record.data.data(), record.data.size());
if (!status.isOK())
return status.getStatus();
thisRecordId = status.getValue().repr();
@@ -212,7 +212,7 @@ Status RecordStore::insertRecordsWithDocWriter(OperationContext* opCtx,
int64_t thisRecordId = 0;
if (_isOplog) {
- StatusWith<RecordId> status = extractAndCheckLocForOplog(opCtx, buf.data(), len);
+ StatusWith<RecordId> status = oploghack::extractKey(buf.data(), len);
if (!status.isOK())
return status.getStatus();
thisRecordId = status.getValue().repr();
@@ -441,31 +441,6 @@ boost::optional<RecordId> RecordStore::oplogStartHack(OperationContext* opCtx,
return rid;
}
-StatusWith<RecordId> RecordStore::extractAndCheckLocForOplog(OperationContext* opCtx,
- const char* data,
- int len) const {
- StatusWith<RecordId> status = oploghack::extractKey(data, len);
- if (!status.isOK())
- return status;
-
- StringStore* workingCopy(RecoveryUnit::get(opCtx)->getHead());
- StringStore::const_reverse_iterator it = workingCopy->upper_bound(_postfix);
-
- if (numRecords(opCtx) == 0)
- return status;
-
- RecordId rid = RecordId(extractRecordId(it->first));
- if (status.getValue() <= rid)
- return StatusWith<RecordId>(ErrorCodes::BadValue,
- str::stream() << "attempted out-of-order oplog insert of "
- << status.getValue()
- << " (oplog last insert was "
- << rid
- << " )");
-
- return status;
-}
-
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 88a9607968a..339b4a16e8f 100644
--- a/src/mongo/db/storage/biggie/biggie_record_store.h
+++ b/src/mongo/db/storage/biggie/biggie_record_store.h
@@ -133,10 +133,6 @@ private:
return _highestRecordId.fetchAndAdd(1);
}
- StatusWith<RecordId> extractAndCheckLocForOplog(OperationContext* opCtx,
- const char* data,
- int len) const;
-
/**
* Two helper functions for deleting excess records in capped record stores.
* The caller should not have an active SizeAdjuster.
diff --git a/src/mongo/db/storage/record_store_test_oplog.cpp b/src/mongo/db/storage/record_store_test_oplog.cpp
index 629a99bbb45..16349aad3e1 100644
--- a/src/mongo/db/storage/record_store_test_oplog.cpp
+++ b/src/mongo/db/storage/record_store_test_oplog.cpp
@@ -160,6 +160,33 @@ TEST(RecordStoreTestHarness, OplogHack) {
}
}
+TEST(RecordStoreTestHarness, OplogInsertOutOfOrder) {
+ std::unique_ptr<RecordStoreHarnessHelper> harnessHelper = newRecordStoreHarnessHelper();
+ if (!harnessHelper->supportsDocLocking())
+ return;
+
+ const int64_t cappedMaxSize = 10 * 1024; // Large enough to not exceed.
+ std::unique_ptr<RecordStore> rs(
+ harnessHelper->newCappedRecordStore("local.oplog.rs", cappedMaxSize, -1));
+ {
+ ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
+
+ // RecordId's are inserted out-of-order.
+ ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(1, 1)).getValue(), RecordId(1, 1));
+ ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(2, 2)).getValue(), RecordId(2, 2));
+ ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(1, 2)).getValue(), RecordId(1, 2));
+ }
+ {
+ ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
+ rs->waitForAllEarlierOplogWritesToBeVisible(opCtx.get());
+ auto cursor = rs->getCursor(opCtx.get());
+ ASSERT_EQ(cursor->next()->id, RecordId(1, 1));
+ ASSERT_EQ(cursor->next()->id, RecordId(1, 2));
+ ASSERT_EQ(cursor->next()->id, RecordId(2, 2));
+ ASSERT(!cursor->next());
+ }
+}
+
TEST(RecordStoreTestHarness, OplogHackOnNonOplog) {
std::unique_ptr<RecordStoreHarnessHelper> harnessHelper = newRecordStoreHarnessHelper();
if (!harnessHelper->supportsDocLocking())