summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorScott Hernandez <scotthernandez@gmail.com>2015-09-11 16:06:05 -0400
committerScott Hernandez <scotthernandez@gmail.com>2015-09-17 11:12:15 -0400
commita0682efb634cd8058b312148062a14dec59cc249 (patch)
tree3254ac3941fcabe940c29d00b9d0f3f3583fd080 /src
parent1d5e8da4ece2bdd803dadb4fb271cea3a372b0e8 (diff)
downloadmongo-a0682efb634cd8058b312148062a14dec59cc249.tar.gz
SERVER-20370: AwaitData doesn't work properly with WiredTiger OplogHack visibility logic
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/collection.cpp31
-rw-r--r--src/mongo/db/catalog/collection.h7
-rw-r--r--src/mongo/db/repl/sync_tail.cpp2
-rw-r--r--src/mongo/db/storage/capped_callback.h14
-rw-r--r--src/mongo/db/storage/devnull/devnull_kv_engine.cpp2
-rw-r--r--src/mongo/db/storage/in_memory/in_memory_record_store.cpp8
-rw-r--r--src/mongo/db/storage/in_memory/in_memory_record_store.h8
-rw-r--r--src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp8
-rw-r--r--src/mongo/db/storage/mmap_v1/record_store_v1_capped.h8
-rw-r--r--src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp31
-rw-r--r--src/mongo/db/storage/record_store.h4
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp23
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h12
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp1
14 files changed, 87 insertions, 72 deletions
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp
index 91c364ae622..ab97771d7c4 100644
--- a/src/mongo/db/catalog/collection.cpp
+++ b/src/mongo/db/catalog/collection.cpp
@@ -66,6 +66,7 @@ namespace {
const auto bannedExpressionsInValidators = std::set<StringData>{
"$geoNear", "$near", "$nearSphere", "$text", "$where",
};
+
Status checkValidatorForBannedExpressions(const BSONObj& validator) {
for (auto field : validator) {
const auto name = field.fieldNameStringData();
@@ -127,6 +128,7 @@ void CappedInsertNotifier::notifyOfInsert(int count) {
void CappedInsertNotifier::notifyAll() {
stdx::lock_guard<stdx::mutex> lk(_cappedNewDataMutex);
+ ++_cappedInsertCount;
_cappedNewDataNotifier.notify_all();
}
@@ -187,7 +189,7 @@ Collection::Collection(OperationContext* txn,
_magic = 1357924;
_indexCatalog.init(txn);
if (isCapped())
- _recordStore->setCappedDeleteCallback(this);
+ _recordStore->setCappedCallback(this);
_infoCache.init(txn);
}
@@ -323,11 +325,7 @@ Status Collection::insertDocument(OperationContext* txn, const DocWriter* doc, b
// we cannot call into the OpObserver here because the document being written is not present
// fortunately, this is currently only used for adding entries to the oplog.
- // If there is a notifier object and another thread is waiting on it, then we notify waiters
- // of this document insert. Waiters keep a shared_ptr to '_cappedNotifier', so there are
- // waiters if this Collection's shared_ptr is not unique.
- if (_cappedNotifier && !_cappedNotifier.unique())
- _cappedNotifier->notifyOfInsert(1);
+ txn->recoveryUnit()->onCommit([this]() { notifyCappedWaitersIfNeeded(); });
return loc.getStatus();
}
@@ -369,11 +367,7 @@ Status Collection::insertDocuments(OperationContext* txn,
inserted++;
}
- // If there is a notifier object and another thread is waiting on it, then we notify
- // waiters of this document insert. Waiters keep a shared_ptr to '_cappedNotifier', so
- // there are waiters if this Collection's shared_ptr is not unique.
- if (_cappedNotifier && !_cappedNotifier.unique())
- _cappedNotifier->notifyOfInsert(inserted);
+ txn->recoveryUnit()->onCommit([this]() { notifyCappedWaitersIfNeeded(); });
return Status::OK();
}
@@ -414,12 +408,7 @@ Status Collection::insertDocument(OperationContext* txn,
getGlobalServiceContext()->getOpObserver()->onInsert(txn, ns(), doc);
- // If there is a notifier object and another thread is waiting on it, then we notify waiters
- // of this document insert. Waiters keep a shared_ptr to '_cappedNotifier', so there are
- // waiters if this Collection's shared_ptr is not unique.
- if (_cappedNotifier && !_cappedNotifier.unique()) {
- _cappedNotifier->notifyOfInsert(1);
- }
+ txn->recoveryUnit()->onCommit([this]() { notifyCappedWaitersIfNeeded(); });
return loc.getStatus();
}
@@ -451,6 +440,14 @@ Status Collection::_insertDocuments(OperationContext* txn,
return _indexCatalog.indexRecords(txn, bsonRecords);
}
+void Collection::notifyCappedWaitersIfNeeded() {
+ // If there is a notifier object and another thread is waiting on it, then we notify
+ // waiters of this document insert. Waiters keep a shared_ptr to '_cappedNotifier', so
+ // there are waiters if this Collection's shared_ptr is not unique (use_count > 1).
+ if (_cappedNotifier && !_cappedNotifier.unique())
+ _cappedNotifier->notifyAll();
+}
+
Status Collection::aboutToDeleteCapped(OperationContext* txn,
const RecordId& loc,
RecordData data) {
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index 6a5e3819fbb..595031030ac 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -168,7 +168,7 @@ private:
* this is NOT safe through a yield right now
* not sure if it will be, or what yet
*/
-class Collection : CappedDocumentDeleteCallback, UpdateNotifier {
+class Collection final : CappedCallback, UpdateNotifier {
public:
Collection(OperationContext* txn,
StringData fullNS,
@@ -422,6 +422,11 @@ private:
Status aboutToDeleteCapped(OperationContext* txn, const RecordId& loc, RecordData data);
/**
+ * Notify (capped collection) waiters of data changes, like an insert.
+ */
+ void notifyCappedWaitersIfNeeded();
+
+ /**
* same semantics as insertDocument, but doesn't do:
* - some user error checks
* - adjust padding
diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp
index 5d8029c5124..4b53542b1eb 100644
--- a/src/mongo/db/repl/sync_tail.cpp
+++ b/src/mongo/db/repl/sync_tail.cpp
@@ -580,6 +580,8 @@ void SyncTail::oplogApplication() {
// For pausing replication in tests
while (MONGO_FAIL_POINT(rsSyncApplyStop)) {
sleepmillis(0);
+ if (inShutdown())
+ return;
}
if (ops.empty()) {
diff --git a/src/mongo/db/storage/capped_callback.h b/src/mongo/db/storage/capped_callback.h
index 4aa040b27a2..21d5c0bad5c 100644
--- a/src/mongo/db/storage/capped_callback.h
+++ b/src/mongo/db/storage/capped_callback.h
@@ -38,13 +38,12 @@ class OperationContext;
class RecordData;
/**
- * When a capped collection has to delete a document, it needs a way to tell the caller
- * what its deleting so it can unindex or do any other cleanup.
- * This is that way.
+ * When a capped collection is modified (delete/insert/etc) then certain notifications need to
+ * be made, which this (pure virtual) interface exposes.
*/
-class CappedDocumentDeleteCallback {
+class CappedCallback {
public:
- virtual ~CappedDocumentDeleteCallback() {}
+ virtual ~CappedCallback() {}
/**
* This will be called right before loc is deleted when wrapping.
@@ -54,5 +53,10 @@ public:
virtual Status aboutToDeleteCapped(OperationContext* txn,
const RecordId& loc,
RecordData data) = 0;
+
+ /**
+ * Used to notify any waiters when new documents may be visible in the capped collection.
+ */
+ virtual void notifyCappedWaitersIfNeeded() = 0;
};
}
diff --git a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
index 60dbfe3c149..272cb344910 100644
--- a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
+++ b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
@@ -66,7 +66,7 @@ public:
return "devnull";
}
- virtual void setCappedDeleteCallback(CappedDocumentDeleteCallback*) {}
+ virtual void setCappedCallback(CappedCallback*) {}
virtual long long dataSize(OperationContext* txn) const {
return 0;
diff --git a/src/mongo/db/storage/in_memory/in_memory_record_store.cpp b/src/mongo/db/storage/in_memory/in_memory_record_store.cpp
index f6dbff637d3..20efccbc733 100644
--- a/src/mongo/db/storage/in_memory/in_memory_record_store.cpp
+++ b/src/mongo/db/storage/in_memory/in_memory_record_store.cpp
@@ -257,12 +257,12 @@ InMemoryRecordStore::InMemoryRecordStore(StringData ns,
bool isCapped,
int64_t cappedMaxSize,
int64_t cappedMaxDocs,
- CappedDocumentDeleteCallback* cappedDeleteCallback)
+ CappedCallback* cappedCallback)
: RecordStore(ns),
_isCapped(isCapped),
_cappedMaxSize(cappedMaxSize),
_cappedMaxDocs(cappedMaxDocs),
- _cappedDeleteCallback(cappedDeleteCallback),
+ _cappedCallback(cappedCallback),
_data(*dataInOut ? static_cast<Data*>(dataInOut->get())
: new Data(NamespaceString::oplog(ns))) {
if (!*dataInOut) {
@@ -344,8 +344,8 @@ void InMemoryRecordStore::cappedDeleteAsNeeded(OperationContext* txn) {
RecordId id = oldest->first;
RecordData data = oldest->second.toRecordData();
- if (_cappedDeleteCallback)
- uassertStatusOK(_cappedDeleteCallback->aboutToDeleteCapped(txn, id, data));
+ if (_cappedCallback)
+ uassertStatusOK(_cappedCallback->aboutToDeleteCapped(txn, id, data));
deleteRecord(txn, id);
}
diff --git a/src/mongo/db/storage/in_memory/in_memory_record_store.h b/src/mongo/db/storage/in_memory/in_memory_record_store.h
index 4169322d97b..eba795b862f 100644
--- a/src/mongo/db/storage/in_memory/in_memory_record_store.h
+++ b/src/mongo/db/storage/in_memory/in_memory_record_store.h
@@ -50,7 +50,7 @@ public:
bool isCapped = false,
int64_t cappedMaxSize = -1,
int64_t cappedMaxDocs = -1,
- CappedDocumentDeleteCallback* cappedDeleteCallback = NULL);
+ CappedCallback* cappedCallback = nullptr);
virtual const char* name() const;
@@ -154,8 +154,8 @@ public:
bool isCapped() const {
return _isCapped;
}
- void setCappedDeleteCallback(CappedDocumentDeleteCallback* cb) {
- _cappedDeleteCallback = cb;
+ void setCappedCallback(CappedCallback* cb) {
+ _cappedCallback = cb;
}
bool cappedMaxDocs() const {
invariant(_isCapped);
@@ -184,7 +184,7 @@ private:
const bool _isCapped;
const int64_t _cappedMaxSize;
const int64_t _cappedMaxDocs;
- CappedDocumentDeleteCallback* _cappedDeleteCallback;
+ CappedCallback* _cappedCallback;
// This is the "persistent" data.
struct Data {
diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
index 890b237677f..a21b7bab880 100644
--- a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
+++ b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
@@ -68,12 +68,12 @@ using std::hex;
using std::vector;
CappedRecordStoreV1::CappedRecordStoreV1(OperationContext* txn,
- CappedDocumentDeleteCallback* collection,
+ CappedCallback* collection,
StringData ns,
RecordStoreV1MetaData* details,
ExtentManager* em,
bool isSystemIndexes)
- : RecordStoreV1Base(ns, details, em, isSystemIndexes), _deleteCallback(collection) {
+ : RecordStoreV1Base(ns, details, em, isSystemIndexes), _cappedCallback(collection) {
DiskLoc extentLoc = details->firstExtent(txn);
while (!extentLoc.isNull()) {
_extentAdvice.push_back(_extentManager->cacheHint(extentLoc, ExtentManager::Sequential));
@@ -168,7 +168,7 @@ StatusWith<DiskLoc> CappedRecordStoreV1::allocRecord(OperationContext* txn,
}
const RecordId fr = theCapExtent()->firstRecord.toRecordId();
- Status status = _deleteCallback->aboutToDeleteCapped(txn, fr, dataFor(txn, fr));
+ Status status = _cappedCallback->aboutToDeleteCapped(txn, fr, dataFor(txn, fr));
if (!status.isOK())
return StatusWith<DiskLoc>(status);
deleteRecord(txn, fr);
@@ -477,7 +477,7 @@ void CappedRecordStoreV1::cappedTruncateAfter(OperationContext* txn,
WriteUnitOfWork wunit(txn);
// Delete the newest record, and coalesce the new deleted
// record with existing deleted records.
- Status status = _deleteCallback->aboutToDeleteCapped(txn, currId, dataFor(txn, currId));
+ Status status = _cappedCallback->aboutToDeleteCapped(txn, currId, dataFor(txn, currId));
uassertStatusOK(status);
deleteRecord(txn, currId);
_compact(txn);
diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.h b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.h
index 58f7f8c9ed5..454f2595905 100644
--- a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.h
+++ b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.h
@@ -41,7 +41,7 @@ namespace mongo {
class CappedRecordStoreV1 final : public RecordStoreV1Base {
public:
CappedRecordStoreV1(OperationContext* txn,
- CappedDocumentDeleteCallback* collection,
+ CappedCallback* collection,
StringData ns,
RecordStoreV1MetaData* details,
ExtentManager* em,
@@ -82,8 +82,8 @@ protected:
return false;
}
- void setCappedDeleteCallback(CappedDocumentDeleteCallback* cb) final {
- _deleteCallback = cb;
+ void setCappedCallback(CappedCallback* cb) final {
+ _cappedCallback = cb;
}
StatusWith<DiskLoc> allocRecord(OperationContext* txn,
@@ -121,7 +121,7 @@ private:
// -- end copy from cap.cpp --
- CappedDocumentDeleteCallback* _deleteCallback;
+ CappedCallback* _cappedCallback;
OwnedPointerVector<ExtentManager::CacheHint> _extentAdvice;
diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp b/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp
index 1089d243467..5f20ba62385 100644
--- a/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp
+++ b/src/mongo/db/storage/mmap_v1/record_store_v1_capped_test.cpp
@@ -49,12 +49,15 @@ using std::vector;
// Should be in BSS so unused portions should be free.
char zeros[20 * 1024 * 1024] = {};
-class DummyCappedDocumentDeleteCallback : public CappedDocumentDeleteCallback {
+class DummyCappedCallback : public CappedCallback {
public:
Status aboutToDeleteCapped(OperationContext* txn, const RecordId& loc, RecordData data) {
deleted.push_back(DiskLoc::fromRecordId(loc));
return Status::OK();
}
+
+ void notifyCappedWaitersIfNeeded() {}
+
vector<DiskLoc> deleted;
};
@@ -62,7 +65,7 @@ void simpleInsertTest(const char* buf, int size) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
string myns = "test.simple1";
CappedRecordStoreV1 rs(&txn, &cb, myns, md, &em, false);
@@ -105,7 +108,7 @@ TEST(CappedRecordStoreV1, EmptySingleExtent) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -131,7 +134,7 @@ TEST(CappedRecordStoreV1, FirstLoopWithSingleExtentExactSize) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -169,7 +172,7 @@ TEST(CappedRecordStoreV1, NonFirstLoopWithSingleExtentExactSize) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -210,7 +213,7 @@ TEST(CappedRecordStoreV1, WillLoopWithout24SpareBytes) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -247,7 +250,7 @@ TEST(CappedRecordStoreV1, WontLoopWith24SpareBytes) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -285,7 +288,7 @@ TEST(CappedRecordStoreV1, MoveToSecondExtentUnLooped) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -318,7 +321,7 @@ TEST(CappedRecordStoreV1, MoveToSecondExtentLooped) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -358,7 +361,7 @@ TEST(CappedRecordStoreV1, OversizedRecordHuge) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -379,7 +382,7 @@ TEST(CappedRecordStoreV1, OversizedRecordMedium) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -409,7 +412,7 @@ TEST(CappedRecordStoreV1Scrambler, Minimal) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -450,7 +453,7 @@ TEST(CappedRecordStoreV1Scrambler, FourDeletedRecordsInSingleExtent) {
OperationContextNoop txn;
DummyExtentManager em;
DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData(true, 0);
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs(&txn, &cb, "test.foo", md, &em, false);
{
@@ -606,7 +609,7 @@ public:
DummyExtentManager em;
private:
- DummyCappedDocumentDeleteCallback cb;
+ DummyCappedCallback cb;
CappedRecordStoreV1 rs;
};
diff --git a/src/mongo/db/storage/record_store.h b/src/mongo/db/storage/record_store.h
index 4321c1a187c..bbd460926d6 100644
--- a/src/mongo/db/storage/record_store.h
+++ b/src/mongo/db/storage/record_store.h
@@ -41,7 +41,7 @@
namespace mongo {
-class CappedDocumentDeleteCallback;
+class CappedCallback;
class Collection;
struct CompactOptions;
struct CompactStats;
@@ -305,7 +305,7 @@ public:
virtual bool isCapped() const = 0;
- virtual void setCappedDeleteCallback(CappedDocumentDeleteCallback*) {
+ virtual void setCappedCallback(CappedCallback*) {
invariant(false);
}
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
index 81989dee8e2..b94f8f69b98 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -712,7 +712,7 @@ WiredTigerRecordStore::WiredTigerRecordStore(OperationContext* ctx,
bool isCapped,
int64_t cappedMaxSize,
int64_t cappedMaxDocs,
- CappedDocumentDeleteCallback* cappedDeleteCallback,
+ CappedCallback* cappedCallback,
WiredTigerSizeStorer* sizeStorer)
: RecordStore(ns),
_uri(uri.toString()),
@@ -724,7 +724,7 @@ WiredTigerRecordStore::WiredTigerRecordStore(OperationContext* ctx,
_cappedMaxDocs(cappedMaxDocs),
_cappedSleep(0),
_cappedSleepMS(0),
- _cappedDeleteCallback(cappedDeleteCallback),
+ _cappedCallback(cappedCallback),
_cappedDeleteCheckCount(0),
_useOplogHack(shouldUseOplogHack(ctx, _uri)),
_sizeStorer(sizeStorer),
@@ -1019,8 +1019,8 @@ int64_t WiredTigerRecordStore::cappedDeleteAsNeeded_inlock(OperationContext* txn
++docsRemoved;
sizeSaved += old_value.size;
- if (_cappedDeleteCallback) {
- uassertStatusOK(_cappedDeleteCallback->aboutToDeleteCapped(
+ if (_cappedCallback) {
+ uassertStatusOK(_cappedCallback->aboutToDeleteCapped(
txn,
newestOld,
RecordData(static_cast<const char*>(old_value.data), old_value.size)));
@@ -1197,7 +1197,7 @@ StatusWith<RecordId> WiredTigerRecordStore::insertRecord(OperationContext* txn,
return StatusWith<RecordId>(loc);
}
-void WiredTigerRecordStore::dealtWithCappedLoc(const RecordId& loc) {
+void WiredTigerRecordStore::_dealtWithCappedLoc(const RecordId& loc) {
stdx::lock_guard<stdx::mutex> lk(_uncommittedDiskLocsMutex);
SortedDiskLocs::iterator it =
std::find(_uncommittedDiskLocs.begin(), _uncommittedDiskLocs.end(), loc);
@@ -1482,11 +1482,15 @@ public:
CappedInsertChange(WiredTigerRecordStore* rs, const RecordId& loc) : _rs(rs), _loc(loc) {}
virtual void commit() {
- _rs->dealtWithCappedLoc(_loc);
+ // Do not notify here because all committed inserts notify, always.
+ _rs->_dealtWithCappedLoc(_loc);
}
virtual void rollback() {
- _rs->dealtWithCappedLoc(_loc);
+ // Notify on rollback since it might make later commits visible.
+ _rs->_dealtWithCappedLoc(_loc);
+ if (_rs->_cappedCallback)
+ _rs->_cappedCallback->notifyCappedWaitersIfNeeded();
}
private:
@@ -1628,9 +1632,8 @@ void WiredTigerRecordStore::temp_cappedTruncateAfter(OperationContext* txn,
// Compute the number and associated sizes of the records to delete.
do {
- if (_cappedDeleteCallback) {
- uassertStatusOK(
- _cappedDeleteCallback->aboutToDeleteCapped(txn, record->id, record->data));
+ if (_cappedCallback) {
+ uassertStatusOK(_cappedCallback->aboutToDeleteCapped(txn, record->id, record->data));
}
recordsRemoved++;
bytesRemoved += record->data.size();
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
index f15419742d5..a130edb769d 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
@@ -88,8 +88,8 @@ public:
bool isCapped = false,
int64_t cappedMaxSize = -1,
int64_t cappedMaxDocs = -1,
- CappedDocumentDeleteCallback* cappedDeleteCallback = NULL,
- WiredTigerSizeStorer* sizeStorer = NULL);
+ CappedCallback* cappedCallback = nullptr,
+ WiredTigerSizeStorer* sizeStorer = nullptr);
virtual ~WiredTigerRecordStore();
@@ -187,8 +187,8 @@ public:
return _useOplogHack;
}
- void setCappedDeleteCallback(CappedDocumentDeleteCallback* cb) {
- _cappedDeleteCallback = cb;
+ void setCappedCallback(CappedCallback* cb) {
+ _cappedCallback = cb;
}
int64_t cappedMaxDocs() const;
int64_t cappedMaxSize() const;
@@ -204,7 +204,6 @@ public:
_sizeStorer = ss;
}
- void dealtWithCappedLoc(const RecordId& loc);
bool isCappedHidden(const RecordId& loc) const;
RecordId lowestCappedHiddenRecord() const;
@@ -243,6 +242,7 @@ private:
static int64_t _makeKey(const RecordId& loc);
static RecordId _fromKey(int64_t k);
+ void _dealtWithCappedLoc(const RecordId& loc);
void _addUncommitedDiskLoc_inlock(OperationContext* txn, const RecordId& loc);
RecordId _nextId();
@@ -266,7 +266,7 @@ private:
const int64_t _cappedMaxDocs;
AtomicInt64 _cappedSleep;
AtomicInt64 _cappedSleepMS;
- CappedDocumentDeleteCallback* _cappedDeleteCallback;
+ CappedCallback* _cappedCallback;
// See comment in ::cappedDeleteAsNeeded
int _cappedDeleteCheckCount;
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
index bcd82513a5c..f6f685a7017 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
@@ -878,6 +878,7 @@ TEST(WiredTigerRecordStoreTest, CappedCursorYieldFirst) {
cursorCtx->recoveryUnit()->abandonSnapshot();
ASSERT_TRUE(cursor->restore());
auto record = cursor->next();
+ ASSERT(record);
ASSERT_EQ(loc1, record->id);
ASSERT(!cursor->next());
}