From 9bd5e1f1de06b7d6f97030036a2d03424399b5d0 Mon Sep 17 00:00:00 2001 From: Benety Goh Date: Tue, 11 Jul 2017 13:09:35 -0400 Subject: [PATCH] SERVER-29373 relax index name constraint when doing two phase collection drops under non-mmapv1 storage engines --- .../replsets/drop_collections_two_phase.js | 15 ++++++++++++ src/mongo/db/catalog/database_impl.cpp | 23 +++++++++++-------- src/mongo/db/catalog/index_catalog_impl.cpp | 17 +++++++++----- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/jstests/replsets/drop_collections_two_phase.js b/jstests/replsets/drop_collections_two_phase.js index fb35984704d9c..18d63f12a2407 100644 --- a/jstests/replsets/drop_collections_two_phase.js +++ b/jstests/replsets/drop_collections_two_phase.js @@ -60,6 +60,21 @@ primaryDB.createCollection(collToDrop); replTest.awaitReplication(); + // Two phase collection should handle long index names gracefully. + // MMAP imposes a hard limit on index namespaces so we have to drop indexes that are too long + // to store on disk after renaming the collection. See SERVER-29747. + // Other storage engines should allow the implicit index renames to proceed because these + // renamed indexes are internal and will not be visible to users (no risk of being exported to + // another storage engine). + // TODO: remove storage engine check when SERVER-29474 is completed. + var storageEngine = jsTest.options().storageEngine; + if (storageEngine !== 'mmapv1') { + var coll = primaryDB.getCollection(collToDrop); + var maxNsLength = 127; + var indexName = ''.pad(maxNsLength - (coll.getFullName() + '.$').length, true, 'a'); + assert.commandWorked(coll.ensureIndex({a: 1}, {name: indexName})); + } + // Pause application on secondary so that commit point doesn't advance, meaning that a dropped // collection on the primary will remain in 'drop-pending' state. jsTestLog("Pausing oplog application on the secondary node."); diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index e96bd7325d6d0..1141dab3c722b 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -511,16 +511,21 @@ Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx, } } - // Check if drop-pending namespace is too long for the index names in the collection. auto dpns = fullns.makeDropPendingNamespace(dropOpTime); - auto status = - dpns.checkLengthForRename(collection->getIndexCatalog()->getLongestIndexNameLength(opCtx)); - if (!status.isOK()) { - log() << "dropCollection: " << fullns - << " - cannot proceed with collection rename for pending-drop: " << status - << ". Dropping collection immediately."; - fassertStatusOK(40463, _finishDropCollection(opCtx, fullns, collection)); - return Status::OK(); + + // 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 the index names in the collection. + if (opCtx->getServiceContext()->getGlobalStorageEngine()->isMmapV1()) { + auto status = dpns.checkLengthForRename( + collection->getIndexCatalog()->getLongestIndexNameLength(opCtx)); + if (!status.isOK()) { + log() << "dropCollection: " << fullns + << " - cannot proceed with collection rename for pending-drop: " << status + << ". Dropping collection immediately."; + fassertStatusOK(40463, _finishDropCollection(opCtx, fullns, collection)); + return Status::OK(); + } } // Rename collection using drop-pending namespace generated from drop optime. diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp index e9cfd3a4f0cac..40f2ecb1c0d7b 100644 --- a/src/mongo/db/catalog/index_catalog_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_impl.cpp @@ -590,12 +590,17 @@ Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx, const BSONObj& spec) if (name.empty()) return Status(ErrorCodes::CannotCreateIndex, "index name cannot be empty"); - const std::string indexNamespace = IndexDescriptor::makeIndexNamespace(nss.ns(), name); - if (indexNamespace.length() > NamespaceString::MaxNsLen) - return Status(ErrorCodes::CannotCreateIndex, - str::stream() << "namespace name generated from index name \"" - << indexNamespace - << "\" is too long (127 byte max)"); + // Drop pending collections are internal to the server and will not be exported to another + // storage engine. The indexes contained in these collections are not subject to the same + // namespace length constraints as the ones in created by users. + if (!nss.isDropPendingNamespace()) { + auto indexNamespace = IndexDescriptor::makeIndexNamespace(nss.ns(), name); + if (indexNamespace.length() > NamespaceString::MaxNsLen) + return Status(ErrorCodes::CannotCreateIndex, + str::stream() << "namespace name generated from index name \"" + << indexNamespace + << "\" is too long (127 byte max)"); + } const BSONObj key = spec.getObjectField("key"); const Status keyStatus = index_key_validate::validateKeyPattern(key, indexVersion);