Skip to content

Commit

Permalink
SERVER-29373 relax index name constraint when doing two phase collect…
Browse files Browse the repository at this point in the history
…ion drops under non-mmapv1 storage engines
  • Loading branch information
benety committed Jul 12, 2017
1 parent 32ce928 commit 9bd5e1f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 15 deletions.
15 changes: 15 additions & 0 deletions jstests/replsets/drop_collections_two_phase.js
Expand Up @@ -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.");
Expand Down
23 changes: 14 additions & 9 deletions src/mongo/db/catalog/database_impl.cpp
Expand Up @@ -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.
Expand Down
17 changes: 11 additions & 6 deletions src/mongo/db/catalog/index_catalog_impl.cpp
Expand Up @@ -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);
Expand Down

0 comments on commit 9bd5e1f

Please sign in to comment.