summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/catalog')
-rw-r--r--src/mongo/db/catalog/apply_ops.cpp57
-rw-r--r--src/mongo/db/catalog/capped_utils.cpp5
-rw-r--r--src/mongo/db/catalog/collection_catalog_entry.h2
-rw-r--r--src/mongo/db/catalog/database.cpp19
-rw-r--r--src/mongo/db/catalog/index_create.cpp39
5 files changed, 71 insertions, 51 deletions
diff --git a/src/mongo/db/catalog/apply_ops.cpp b/src/mongo/db/catalog/apply_ops.cpp
index a7306940d68..552376301cb 100644
--- a/src/mongo/db/catalog/apply_ops.cpp
+++ b/src/mongo/db/catalog/apply_ops.cpp
@@ -180,39 +180,32 @@ Status _applyOps(OperationContext* opCtx,
NamespaceString requestNss{ns};
if (nss.isSystemDotIndexes()) {
- BSONObj indexSpec;
- NamespaceString indexNss;
- std::tie(indexSpec, indexNss) =
- repl::prepForApplyOpsIndexInsert(fieldO, opObj, requestNss);
- if (!indexSpec["collation"]) {
- // If the index spec does not include a collation, explicitly
- // specify the simple collation, so the index does not inherit the
- // collection default collation.
- auto indexVersion = indexSpec["v"];
- // The index version is populated by prepForApplyOpsIndexInsert().
- invariant(indexVersion);
- if (indexVersion.isNumber() &&
- (indexVersion.numberInt() >=
- static_cast<int>(IndexDescriptor::IndexVersion::kV2))) {
- BSONObjBuilder bob;
- bob.append("collation", CollationSpec::kSimpleSpec);
- bob.appendElements(indexSpec);
- indexSpec = bob.obj();
- }
- }
- BSONObjBuilder command;
- command.append("createIndexes", indexNss.coll());
- {
- BSONArrayBuilder indexes(command.subarrayStart("indexes"));
- indexes.append(indexSpec);
- indexes.doneFast();
+ invariant(opCtx->lockState()->isW());
+
+ // Disable background index builds when inserting into system.indexes.
+ // This causes the TempRelease to fail within applyOperation_inlock(),
+ // leading to the background index being built in the foreground.
+ // We do not want a background index build because we need to validate
+ // the index spec and also to avoid issues resulting from any metadata
+ // changes before the background thread starts.
+ Lock::GlobalWrite nestedGlobalWriteLock(opCtx->lockState());
+
+ OldClientContext ctx(opCtx, nss.ns());
+ status =
+ repl::applyOperation_inlock(opCtx, ctx.db(), opObj, alwaysUpsert);
+
+ // applyOperation_inlock() builds the index but does not notify the
+ // OpObserver. Previously, applyOps relied on the createIndexes command
+ // to perform this function. The value used for the 'forMigrate'
+ // argument is consistent with create_indexes.cpp.
+ if (status.isOK()) {
+ WriteUnitOfWork wuow(opCtx);
+ auto opObserver = getGlobalServiceContext()->getOpObserver();
+ invariant(opObserver);
+ auto indexSpec = fieldO.embeddedObject();
+ opObserver->onCreateIndex(opCtx, nss.ns(), indexSpec, false);
+ wuow.commit();
}
- const BSONObj commandObj = command.done();
-
- DBDirectClient client(opCtx);
- BSONObj infoObj;
- client.runCommand(nsToDatabase(ns), commandObj, infoObj);
- status = getStatusFromCommandResult(infoObj);
} else {
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
if (!autoColl.getCollection() && !nss.isSystemDotIndexes()) {
diff --git a/src/mongo/db/catalog/capped_utils.cpp b/src/mongo/db/catalog/capped_utils.cpp
index 71f74628f01..63b46d3c3a8 100644
--- a/src/mongo/db/catalog/capped_utils.cpp
+++ b/src/mongo/db/catalog/capped_utils.cpp
@@ -66,13 +66,13 @@ Status emptyCapped(OperationContext* txn, const NamespaceString& collectionName)
}
Database* db = autoDb.getDb();
- massert(13429, "no such database", db);
+ uassert(ErrorCodes::NamespaceNotFound, "no such database", db);
Collection* collection = db->getCollection(collectionName);
uassert(ErrorCodes::CommandNotSupportedOnView,
str::stream() << "emptycapped not supported on view: " << collectionName.ns(),
collection || !db->getViewCatalog()->lookup(txn, collectionName.ns()));
- massert(28584, "no such collection", collection);
+ uassert(ErrorCodes::NamespaceNotFound, "no such collection", collection);
if (collectionName.isSystem() && !collectionName.isSystemDotProfile()) {
return Status(ErrorCodes::IllegalOperation,
@@ -268,6 +268,7 @@ Status convertToCapped(OperationContext* txn, const NamespaceString& collectionN
Status status = db->dropCollection(txn, longTmpName);
if (!status.isOK())
return status;
+ wunit.commit();
}
diff --git a/src/mongo/db/catalog/collection_catalog_entry.h b/src/mongo/db/catalog/collection_catalog_entry.h
index dd6a1f506f1..38e5b12d234 100644
--- a/src/mongo/db/catalog/collection_catalog_entry.h
+++ b/src/mongo/db/catalog/collection_catalog_entry.h
@@ -64,6 +64,8 @@ public:
virtual BSONObj getIndexSpec(OperationContext* txn, StringData idxName) const = 0;
+ virtual void getReadyIndexes(OperationContext* txn, std::vector<std::string>* names) const = 0;
+
/**
* Returns true if the index identified by 'indexName' is multikey, and returns false otherwise.
*
diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp
index 23fdfb84e95..4b27ff0e48f 100644
--- a/src/mongo/db/catalog/database.cpp
+++ b/src/mongo/db/catalog/database.cpp
@@ -564,15 +564,26 @@ Collection* Database::createCollection(OperationContext* txn,
: ic->getDefaultIdIndexSpec(featureCompatibilityVersion)));
}
}
-
- if (nss.isSystem()) {
- authindex::createSystemIndexes(txn, collection);
- }
}
getGlobalServiceContext()->getOpObserver()->onCreateCollection(
txn, nss, options, fullIdIndexSpec);
+ // It is necessary to create the system index *after* running the onCreateCollection so that
+ // the oplog timestamp for the index creation is after the oplog timestamp for the
+ // collection creation. This way both primary and any secondaries will see the index created
+ // after the collection is created.
+ if (createIdIndex && nss.isSystem()) {
+ // We only want to create the indexes here on the primary. On secondaries, they will
+ // be created by the normal oplog application process.
+ auto coordinator = repl::ReplicationCoordinator::get(txn);
+ const bool canAcceptWrites =
+ (coordinator->getReplicationMode() != repl::ReplicationCoordinator::modeReplSet) ||
+ coordinator->canAcceptWritesForDatabase(nss.db()) || nss.isSystemDotProfile();
+ if (canAcceptWrites) {
+ authindex::createSystemIndexes(txn, collection);
+ }
+ }
return collection;
}
diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp
index 17a3d981d5d..6a323605521 100644
--- a/src/mongo/db/catalog/index_create.cpp
+++ b/src/mongo/db/catalog/index_create.cpp
@@ -65,6 +65,8 @@ using std::endl;
MONGO_FP_DECLARE(crashAfterStartingIndexBuild);
MONGO_FP_DECLARE(hangAfterStartingIndexBuild);
MONGO_FP_DECLARE(hangAfterStartingIndexBuildUnlocked);
+MONGO_FP_DECLARE(hangBeforeIndexBuildOf);
+MONGO_FP_DECLARE(hangAfterIndexBuildOf);
std::atomic<std::int32_t> maxIndexBuildMemoryUsageMegabytes(500); // NOLINT
@@ -282,6 +284,16 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj
return indexInfoObjs;
}
+void failPointHangDuringBuild(FailPoint* fp, StringData where, const BSONObj& doc) {
+ MONGO_FAIL_POINT_BLOCK(*fp, data) {
+ int i = doc.getIntField("i");
+ if (data.getData()["i"].numberInt() == i) {
+ log() << "Hanging " << where << " index build of i=" << i;
+ MONGO_FAIL_POINT_PAUSE_WHILE_SET((*fp));
+ }
+ }
+}
+
Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsOut) {
const char* curopMessage = _buildInBackground ? "Index Build (background)" : "Index Build";
const auto numRecords = _collection->numRecords(_txn);
@@ -307,11 +319,20 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO
PlanExecutor::ExecState state;
int retries = 0; // non-zero when retrying our last document.
while (retries ||
- (PlanExecutor::ADVANCED == (state = exec->getNextSnapshotted(&objToIndex, &loc)))) {
+ (PlanExecutor::ADVANCED == (state = exec->getNextSnapshotted(&objToIndex, &loc))) ||
+ MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) {
try {
if (_allowInterruption)
_txn->checkForInterrupt();
+ if (!(retries || (PlanExecutor::ADVANCED == state))) {
+ // The only reason we are still in the loop is hangAfterStartingIndexBuild.
+ log() << "Hanging index build due to 'hangAfterStartingIndexBuild' failpoint";
+ invariant(_allowInterruption);
+ sleepmillis(1000);
+ continue;
+ }
+
// Make sure we are working with the latest version of the document.
if (objToIndex.snapshotId() != _txn->recoveryUnit()->getSnapshotId() &&
!_collection->findDoc(_txn, loc, &objToIndex)) {
@@ -323,6 +344,8 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO
// Done before insert so we can retry document if it WCEs.
progress->setTotalWhileRunning(_collection->numRecords(_txn));
+ failPointHangDuringBuild(&hangBeforeIndexBuildOf, "before", objToIndex.value());
+
WriteUnitOfWork wunit(_txn);
Status ret = insert(objToIndex.value(), loc);
if (_buildInBackground)
@@ -340,6 +363,8 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO
if (_buildInBackground)
exec->restoreState(); // Handles any WCEs internally.
+ failPointHangDuringBuild(&hangAfterIndexBuildOf, "after", objToIndex.value());
+
// Go to the next document
progress->hit();
n++;
@@ -362,18 +387,6 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO
WorkingSetCommon::toStatusString(objToIndex.value()),
state == PlanExecutor::IS_EOF);
- if (MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) {
- // Need the index build to hang before the progress meter is marked as finished so we can
- // reliably check that the index build has actually started in js tests.
- while (MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) {
- log() << "Hanging index build due to 'hangAfterStartingIndexBuild' failpoint";
- sleepmillis(1000);
- }
-
- // Check for interrupt to allow for killop prior to index build completion.
- _txn->checkForInterrupt();
- }
-
if (MONGO_FAIL_POINT(hangAfterStartingIndexBuildUnlocked)) {
// Unlock before hanging so replication recognizes we've completed.
Locker::LockSnapshot lockInfo;