summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2015-11-24 18:31:14 -0500
committerMathias Stearn <mathias@10gen.com>2015-11-30 19:50:09 -0500
commitf45b7c8e34743ba89407d90ee3392acb0d2be255 (patch)
treeee1250257c3931cd63caf35af641e6d106063ab6
parent0e4d706953cd4db25fc9ffa4abf106541157f971 (diff)
downloadmongo-f45b7c8e34743ba89407d90ee3392acb0d2be255.tar.gz
SERVER-21646 limit concurrency of writes to replicated capped collections
This prevents the primary from running significantly faster than secondaries.
-rw-r--r--src/mongo/db/catalog/collection.cpp15
-rw-r--r--src/mongo/db/catalog/collection.h11
2 files changed, 21 insertions, 5 deletions
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp
index 8a71e6d5095..e7cad0bf046 100644
--- a/src/mongo/db/catalog/collection.cpp
+++ b/src/mongo/db/catalog/collection.cpp
@@ -174,6 +174,7 @@ Collection::Collection(OperationContext* txn,
_details(details),
_recordStore(recordStore),
_dbce(dbce),
+ _needCappedLock(supportsDocLocking() && _recordStore->isCapped() && _ns.db() != "local"),
_infoCache(this),
_indexCatalog(this),
_validatorDoc(_details->getCollectionOptions(txn).validator.getOwned()),
@@ -425,6 +426,13 @@ Status Collection::_insertDocuments(OperationContext* txn,
"Can't batch inserts into indexed capped collections"};
}
+ if (_needCappedLock) {
+ // X-lock the metadata resource for this capped collection until the end of the WUOW. This
+ // prevents the primary from executing with more concurrency than secondaries.
+ // See SERVER-21646.
+ Lock::ResourceLock{txn->lockState(), ResourceId(RESOURCE_METADATA, _ns.ns()), MODE_X};
+ }
+
std::vector<Record> records;
for (auto it = begin; it != end; it++) {
Record record = {RecordId(), RecordData(it->objdata(), it->objsize())};
@@ -529,6 +537,13 @@ StatusWith<RecordId> Collection::updateDocument(OperationContext* txn,
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_IX));
invariant(oldDoc.snapshotId() == txn->recoveryUnit()->getSnapshotId());
+ if (_needCappedLock) {
+ // X-lock the metadata resource for this capped collection until the end of the WUOW. This
+ // prevents the primary from executing with more concurrency than secondaries.
+ // See SERVER-21646.
+ Lock::ResourceLock{txn->lockState(), ResourceId(RESOURCE_METADATA, _ns.ns()), MODE_X};
+ }
+
SnapshotId sid = txn->recoveryUnit()->getSnapshotId();
BSONElement oldId = oldDoc.value()["_id"];
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index a176a48dc66..1ba17ee3ba4 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -448,10 +448,11 @@ private:
int _magic;
- NamespaceString _ns;
- CollectionCatalogEntry* _details;
- RecordStore* _recordStore;
- DatabaseCatalogEntry* _dbce;
+ const NamespaceString _ns;
+ CollectionCatalogEntry* const _details;
+ RecordStore* const _recordStore;
+ DatabaseCatalogEntry* const _dbce;
+ const bool _needCappedLock;
CollectionInfoCache _infoCache;
IndexCatalog _indexCatalog;
@@ -474,7 +475,7 @@ private:
// on this object until notified of the arrival of new data.
//
// This is non-null if and only if the collection is a capped collection.
- std::shared_ptr<CappedInsertNotifier> _cappedNotifier;
+ const std::shared_ptr<CappedInsertNotifier> _cappedNotifier;
const bool _mustTakeCappedLockOnInsert;