summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/replsets/drop_collections_two_phase_long_index_names.js13
-rw-r--r--src/mongo/db/catalog/database_impl.cpp71
2 files changed, 49 insertions, 35 deletions
diff --git a/jstests/replsets/drop_collections_two_phase_long_index_names.js b/jstests/replsets/drop_collections_two_phase_long_index_names.js
index 576d1a0b425..46745a27427 100644
--- a/jstests/replsets/drop_collections_two_phase_long_index_names.js
+++ b/jstests/replsets/drop_collections_two_phase_long_index_names.js
@@ -55,6 +55,19 @@
assert(indexes.find(idx => idx.name === shortIndexName));
assert.eq(undefined, indexes.find(idx => idx.name === longIndexName));
+ // Check that index drop appears before collection drop in the oplog.
+ const oplogColl = primary.getCollection('local.oplog.rs');
+ const cmdNs = primaryDB.getCollection('$cmd').getFullName();
+ const dropOplogEntry = oplogColl.findOne({ns: cmdNs, o: {drop: collName}});
+ const dropIndexOplogEntry =
+ oplogColl.findOne({ns: cmdNs, o: {dropIndexes: collName, index: longIndexName}});
+ const dropTimestamp = dropOplogEntry.ts;
+ const dropIndexTimestamp = dropIndexOplogEntry.ts;
+ assert.lt(dropIndexTimestamp,
+ dropTimestamp,
+ 'index was not dropped before collection. index drop: ' +
+ tojson(dropIndexOplogEntry) + ' . collection drop: ' + tojson(dropOplogEntry));
+
twoPhaseDropTest.commitDropCollection(collName);
replTest.stopSet();
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index 22399430260..7b829e6da16 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -523,39 +523,11 @@ Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx,
// Replicated collections will be renamed with a special drop-pending namespace and dropped when
// the replica set optime reaches the drop optime.
if (dropOpTime.isNull()) {
- dropOpTime = opObserver->onDropCollection(opCtx, fullns, uuid);
-
- // Drop collection immediately if OpObserver did not write entry to oplog.
- // After writing the oplog entry, all errors are fatal. See getNextOpTime() comments in
- // oplog.cpp.
- if (dropOpTime.isNull()) {
- log() << "dropCollection: " << fullns
- << " - no drop optime available for pending-drop. "
- << "Dropping collection immediately.";
- fassertStatusOK(40462, _finishDropCollection(opCtx, fullns, collection));
- return Status::OK();
- }
- } else {
- // If we are provided with a valid 'dropOpTime', it means we are dropping this collection
- // in the context of applying an oplog entry on a secondary.
- // OpObserver::onDropCollection() should be returning a null OpTime because we should not be
- // writing to the oplog.
- auto opTime = opObserver->onDropCollection(opCtx, fullns, uuid);
- if (!opTime.isNull()) {
- severe() << "dropCollection: " << fullns
- << " - unexpected oplog entry written to the oplog with optime " << opTime;
- fassertFailed(40468);
- }
- }
-
- auto dpns = fullns.makeDropPendingNamespace(dropOpTime);
-
- // MMAPv1 requires that index namespaces are subject to the same length constraints as indexes
- // in collections that are not in a drop-pending state. Therefore, we check if the drop-pending
- // namespace is too long for any index names in the collection.
- // These indexes are dropped regardless of the storage engine on the current node because we may
- // still have nodes running MMAPv1 in the replica set.
- {
+ // MMAPv1 requires that index namespaces are subject to the same length constraints as
+ // indexes in collections that are not in a drop-pending state. Therefore, we check if the
+ // drop-pending namespace is too long for any index names in the collection.
+ // These indexes are dropped regardless of the storage engine on the current node because we
+ // may still have nodes running MMAPv1 in the replica set.
// Compile a list of any indexes that would become too long following the drop-pending
// rename. In the case that this collection drop gets rolled back, this will incur a
@@ -564,10 +536,12 @@ Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx,
std::vector<IndexDescriptor*> indexesToDrop;
auto indexIter = collection->getIndexCatalog()->getIndexIterator(opCtx, true);
- // Determine which index names are too long.
+ // Determine which index names are too long. Since we don't have the collection drop optime
+ // at this time, use the maximum optime to check the index names.
+ auto longDpns = fullns.makeDropPendingNamespace(repl::OpTime::max());
while (indexIter.more()) {
auto index = indexIter.next();
- auto status = dpns.checkLengthForRename(index->indexName().size());
+ auto status = longDpns.checkLengthForRename(index->indexName().size());
if (!status.isOK()) {
indexesToDrop.push_back(index);
}
@@ -582,8 +556,35 @@ Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx,
opObserver->onDropIndex(
opCtx, fullns, collection->uuid(), index->indexName(), index->infoObj());
}
+
+ // Log oplog entry for collection drop and proceed to complete rest of two phase drop
+ // process.
+ dropOpTime = opObserver->onDropCollection(opCtx, fullns, uuid);
+
+ // Drop collection immediately if OpObserver did not write entry to oplog.
+ // After writing the oplog entry, all errors are fatal. See getNextOpTime() comments in
+ // oplog.cpp.
+ if (dropOpTime.isNull()) {
+ log() << "dropCollection: " << fullns
+ << " - no drop optime available for pending-drop. "
+ << "Dropping collection immediately.";
+ fassertStatusOK(40462, _finishDropCollection(opCtx, fullns, collection));
+ return Status::OK();
+ }
+ } else {
+ // If we are provided with a valid 'dropOpTime', it means we are dropping this collection
+ // in the context of applying an oplog entry on a secondary.
+ // OpObserver::onDropCollection() should be returning a null OpTime because we should not be
+ // writing to the oplog.
+ auto opTime = opObserver->onDropCollection(opCtx, fullns, uuid);
+ if (!opTime.isNull()) {
+ severe() << "dropCollection: " << fullns
+ << " - unexpected oplog entry written to the oplog with optime " << opTime;
+ fassertFailed(40468);
+ }
}
+ auto dpns = fullns.makeDropPendingNamespace(dropOpTime);
// Rename collection using drop-pending namespace generated from drop optime.
const bool stayTemp = true;