summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMisha Tyulenev <misha.tyulenev@mongodb.com>2022-03-29 17:03:22 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-03-29 22:15:23 +0000
commitd1306d8b8118cf6c420f6c34daab28ab7c7c33b2 (patch)
tree018df57665ce47f61f95ffd547609299c224cde1
parentaccb0f21fef16d0d114dabe533f3f013663d5c20 (diff)
downloadmongo-d1306d8b8118cf6c420f6c34daab28ab7c7c33b2.tar.gz
SERVER-63838 expose createIndexes and create events from chunkMigration only when showEventsSystem is true
-rw-r--r--jstests/change_streams/create_event_from_chunk_migration.js130
-rw-r--r--src/mongo/db/auth/auth_op_observer.cpp3
-rw-r--r--src/mongo/db/auth/auth_op_observer.h3
-rw-r--r--src/mongo/db/catalog/database.h6
-rw-r--r--src/mongo/db/catalog/database_impl.cpp13
-rw-r--r--src/mongo/db/catalog/database_impl.h6
-rw-r--r--src/mongo/db/catalog/rename_collection_test.cpp9
-rw-r--r--src/mongo/db/commands/mr_test.cpp6
-rw-r--r--src/mongo/db/fcv_op_observer.h3
-rw-r--r--src/mongo/db/free_mon/free_mon_op_observer.h3
-rw-r--r--src/mongo/db/op_observer.h3
-rw-r--r--src/mongo/db/op_observer_impl.cpp4
-rw-r--r--src/mongo/db/op_observer_impl.h3
-rw-r--r--src/mongo/db/op_observer_noop.h3
-rw-r--r--src/mongo/db/op_observer_registry.h6
-rw-r--r--src/mongo/db/pipeline/change_stream_filter_helpers.cpp33
-rw-r--r--src/mongo/db/pipeline/change_stream_filter_helpers.h7
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp3
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test_fixture.h3
-rw-r--r--src/mongo/db/repl/primary_only_service_op_observer.h3
-rw-r--r--src/mongo/db/repl/tenant_collection_cloner_test.cpp3
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_op_observer.h3
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp3
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_op_observer.h3
-rw-r--r--src/mongo/db/s/config_server_op_observer.h3
-rw-r--r--src/mongo/db/s/migration_destination_manager.cpp5
-rw-r--r--src/mongo/db/s/resharding/resharding_op_observer.h3
-rw-r--r--src/mongo/db/s/shard_server_op_observer.cpp3
-rw-r--r--src/mongo/db/s/shard_server_op_observer.h3
-rw-r--r--src/mongo/db/serverless/shard_split_donor_op_observer.h3
-rw-r--r--src/mongo/db/system_index.cpp3
-rw-r--r--src/mongo/db/system_index.h2
-rw-r--r--src/mongo/db/user_write_block_mode_op_observer.h3
-rw-r--r--src/mongo/idl/cluster_server_parameter_op_observer.h3
34 files changed, 249 insertions, 44 deletions
diff --git a/jstests/change_streams/create_event_from_chunk_migration.js b/jstests/change_streams/create_event_from_chunk_migration.js
new file mode 100644
index 00000000000..8c9d0f1761b
--- /dev/null
+++ b/jstests/change_streams/create_event_from_chunk_migration.js
@@ -0,0 +1,130 @@
+/**
+ * Test that change streams returns 'create' and 'createIndexes' events from chunk migration when
+ * showSystemEvents is set.
+ *
+ * @tags: [
+ * requires_fcv_60,
+ * requires_sharding,
+ * uses_change_streams,
+ * change_stream_does_not_expect_txns,
+ * assumes_unsharded_collection,
+ * assumes_read_preference_unchanged,
+ * featureFlagChangeStreamsVisibility
+ * ]
+ */
+
+(function() {
+"use strict";
+
+load("jstests/libs/collection_drop_recreate.js"); // For assertDropCollection.
+load('jstests/libs/change_stream_util.js'); // For 'ChangeStreamTest' and
+ // 'assertChangeStreamEventEq'.
+const dbName = jsTestName();
+const collName = "test";
+const collNS = dbName + "." + collName;
+const ns = {
+ db: dbName,
+ coll: collName
+};
+const numDocs = 1;
+
+const st = new ShardingTest({
+ shards: 2,
+ rs: {nodes: 1, setParameter: {writePeriodicNoops: true, periodicNoopIntervalSecs: 1}}
+});
+
+const mongosConn = st.s;
+const db = mongosConn.getDB(dbName);
+const test = new ChangeStreamTest(db);
+
+function getCollectionUuid(coll) {
+ const collInfo = db.getCollectionInfos({name: coll})[0];
+ return collInfo.info.uuid;
+}
+
+function assertMigrateEventObserved(cursor, expectedEvent) {
+ let events = test.getNextChanges(cursor, 1);
+ let event = events[0];
+ // Check the presence and the type of 'wallTime' field. We have no way to check the correctness
+ // of 'wallTime' value, so we delete it afterwards.
+ assert(event.wallTime instanceof Date);
+ delete event.wallTime;
+ expectedEvent.collectionUUID = getCollectionUuid(collName);
+ assertChangeStreamEventEq(event, expectedEvent);
+ return event._id;
+}
+
+function prepareCollection() {
+ assertDropCollection(db, collName);
+ assert.commandWorked(db.runCommand({create: collName}));
+ assert.commandWorked(
+ db.runCommand({createIndexes: collName, indexes: [{key: {x: 1}, name: "idx_x"}]}));
+
+ assert.commandWorked(st.s.adminCommand({shardCollection: collNS, key: {_id: 1}}));
+ assert.commandWorked(st.s.adminCommand({split: collNS, middle: {_id: 0}}));
+}
+
+// Test that create and createIndexes events are observable with migration.
+function validateCreateEventsFromChunkMigration() {
+ prepareCollection();
+ let pipeline = [
+ {$changeStream: {showExpandedEvents: true, showSystemEvents: true}},
+ ];
+
+ let cursor = test.startWatchingChanges({pipeline, collection: collName});
+
+ assert.commandWorked(
+ db.adminCommand({moveChunk: collNS, find: {_id: 0}, to: st.shard1.shardName}));
+
+ test.assertNextChangesEqual({
+ cursor: cursor,
+ expectedChanges: {
+ operationType: "create",
+ ns: ns,
+ }
+ });
+
+ test.assertNextChangesEqual({
+ cursor: cursor,
+ expectedChanges: {
+ operationType: "createIndexes",
+ ns: ns,
+ }
+ });
+}
+
+// Test that if showSystemEvents is false, we do not see the create and createIndexes events from
+// chunk migration.
+function validateShowSystemEventsFalse() {
+ prepareCollection();
+ let pipeline = [
+ {$changeStream: {showExpandedEvents: true, showSystemEvents: false}},
+ ];
+ let cursor = test.startWatchingChanges({pipeline, collection: collName});
+
+ assert.commandWorked(
+ db.adminCommand({moveChunk: collNS, find: {_id: 0}, to: st.shard1.shardName}));
+
+ assert.commandWorked(db[collName].insert({_id: 1, x: 1}));
+
+ // Confirm that we don't observe the create event in the stream, but only see
+ // the subsequent insert.
+ test.assertNextChangesEqual({
+ cursor: cursor,
+ expectedChanges: {
+ operationType: "insert",
+ ns: ns,
+ fullDocument: {_id: 1, x: 1},
+ documentKey: {_id: 1},
+ }
+ });
+}
+
+assert.commandWorked(db.adminCommand({enableSharding: dbName}));
+assert.commandWorked(st.s.adminCommand({movePrimary: dbName, to: st.shard0.shardName}));
+
+validateCreateEventsFromChunkMigration();
+validateShowSystemEventsFalse();
+
+st.stop();
+}());
diff --git a/src/mongo/db/auth/auth_op_observer.cpp b/src/mongo/db/auth/auth_op_observer.cpp
index 09bbd1ae2ca..167ae156b71 100644
--- a/src/mongo/db/auth/auth_op_observer.cpp
+++ b/src/mongo/db/auth/auth_op_observer.cpp
@@ -101,7 +101,8 @@ void AuthOpObserver::onCreateCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) {
const auto cmdNss = collectionName.getCommandNS();
const auto cmdObj =
diff --git a/src/mongo/db/auth/auth_op_observer.h b/src/mongo/db/auth/auth_op_observer.h
index 677e21e672c..c145ebc3371 100644
--- a/src/mongo/db/auth/auth_op_observer.h
+++ b/src/mongo/db/auth/auth_op_observer.h
@@ -112,7 +112,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final;
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/catalog/database.h b/src/mongo/db/catalog/database.h
index af85dbd71e8..2640abefbcb 100644
--- a/src/mongo/db/catalog/database.h
+++ b/src/mongo/db/catalog/database.h
@@ -65,7 +65,8 @@ public:
const NamespaceString& fullns,
CollectionOptions collectionOptions,
bool createDefaultIndexes = true,
- const BSONObj& idIndex = BSONObj()) const = 0;
+ const BSONObj& idIndex = BSONObj(),
+ bool fromMigrate = false) const = 0;
Database() = default;
@@ -135,7 +136,8 @@ public:
const NamespaceString& nss,
const CollectionOptions& options = CollectionOptions(),
bool createDefaultIndexes = true,
- const BSONObj& idIndex = BSONObj()) const = 0;
+ const BSONObj& idIndex = BSONObj(),
+ bool fromMigrate = false) const = 0;
virtual Status createView(OperationContext* opCtx,
const NamespaceString& viewName,
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index c96070ccd2b..58990585692 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -790,7 +790,8 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions& options,
bool createIdIndex,
- const BSONObj& idIndex) const {
+ const BSONObj& idIndex,
+ bool fromMigrate) const {
invariant(!options.isView());
invariant(opCtx->lockState()->isCollectionLockedForMode(nss, MODE_IX));
@@ -895,7 +896,7 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx,
hangBeforeLoggingCreateCollection.pauseWhileSet();
opCtx->getServiceContext()->getOpObserver()->onCreateCollection(
- opCtx, collection, nss, optionsWithUUID, fullIdIndexSpec, createOplogSlot);
+ opCtx, collection, nss, optionsWithUUID, fullIdIndexSpec, createOplogSlot, fromMigrate);
// It is necessary to create the system index *after* running the onCreateCollection so that
// the storage timestamp for the index creation is after the storage timestamp for the
@@ -904,7 +905,7 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx,
// after the collection is created.
if (canAcceptWrites && createIdIndex && nss.isSystem()) {
CollectionWriter collWriter(collection);
- createSystemIndexes(opCtx, collWriter);
+ createSystemIndexes(opCtx, collWriter, fromMigrate);
}
return collection;
@@ -1010,7 +1011,8 @@ Status DatabaseImpl::userCreateNS(OperationContext* opCtx,
const NamespaceString& nss,
CollectionOptions collectionOptions,
bool createDefaultIndexes,
- const BSONObj& idIndex) const {
+ const BSONObj& idIndex,
+ bool fromMigrate) const {
LOGV2_DEBUG(20324,
1,
"create collection {namespace} {collectionOptions}",
@@ -1110,7 +1112,8 @@ Status DatabaseImpl::userCreateNS(OperationContext* opCtx,
uassertStatusOK(createView(opCtx, nss, collectionOptions));
} else {
- invariant(createCollection(opCtx, nss, collectionOptions, createDefaultIndexes, idIndex),
+ invariant(createCollection(
+ opCtx, nss, collectionOptions, createDefaultIndexes, idIndex, fromMigrate),
str::stream() << "Collection creation failed after validating options: " << nss
<< ". Options: " << collectionOptions.toBSON());
}
diff --git a/src/mongo/db/catalog/database_impl.h b/src/mongo/db/catalog/database_impl.h
index b4a5f41afec..fa09177bc1b 100644
--- a/src/mongo/db/catalog/database_impl.h
+++ b/src/mongo/db/catalog/database_impl.h
@@ -79,13 +79,15 @@ public:
const NamespaceString& nss,
CollectionOptions collectionOptions,
bool createDefaultIndexes,
- const BSONObj& idIndex) const final;
+ const BSONObj& idIndex,
+ bool fromMigrate) const final;
Collection* createCollection(OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions& options = CollectionOptions(),
bool createDefaultIndexes = true,
- const BSONObj& idIndex = BSONObj()) const final;
+ const BSONObj& idIndex = BSONObj(),
+ bool fromMigrate = false) const final;
Status createView(OperationContext* opCtx,
const NamespaceString& viewName,
diff --git a/src/mongo/db/catalog/rename_collection_test.cpp b/src/mongo/db/catalog/rename_collection_test.cpp
index 9730c23d46c..5273e1c7ddf 100644
--- a/src/mongo/db/catalog/rename_collection_test.cpp
+++ b/src/mongo/db/catalog/rename_collection_test.cpp
@@ -113,7 +113,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override;
using OpObserver::onDropCollection;
repl::OpTime onDropCollection(OperationContext* opCtx,
@@ -230,9 +231,11 @@ void OpObserverMock::onCreateCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) {
_logOp(opCtx, collectionName, "create");
- OpObserverNoop::onCreateCollection(opCtx, coll, collectionName, options, idIndex, createOpTime);
+ OpObserverNoop::onCreateCollection(
+ opCtx, coll, collectionName, options, idIndex, createOpTime, fromMigrate);
}
repl::OpTime OpObserverMock::onDropCollection(OperationContext* opCtx,
diff --git a/src/mongo/db/commands/mr_test.cpp b/src/mongo/db/commands/mr_test.cpp
index ad7c8d6ab38..a4c8b4da699 100644
--- a/src/mongo/db/commands/mr_test.cpp
+++ b/src/mongo/db/commands/mr_test.cpp
@@ -275,7 +275,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override;
using OpObserver::onDropCollection;
repl::OpTime onDropCollection(OperationContext* opCtx,
@@ -330,7 +331,8 @@ void MapReduceOpObserver::onCreateCollection(OperationContext*,
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj&,
- const OplogSlot&) {
+ const OplogSlot&,
+ bool fromMigrate) {
if (!options.temp) {
return;
}
diff --git a/src/mongo/db/fcv_op_observer.h b/src/mongo/db/fcv_op_observer.h
index 0b638e96e77..7380f65358f 100644
--- a/src/mongo/db/fcv_op_observer.h
+++ b/src/mongo/db/fcv_op_observer.h
@@ -117,7 +117,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& uuid,
diff --git a/src/mongo/db/free_mon/free_mon_op_observer.h b/src/mongo/db/free_mon/free_mon_op_observer.h
index 40511b4360c..498d728d187 100644
--- a/src/mongo/db/free_mon/free_mon_op_observer.h
+++ b/src/mongo/db/free_mon/free_mon_op_observer.h
@@ -112,7 +112,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/op_observer.h b/src/mongo/db/op_observer.h
index a426783b907..163d4738b0e 100644
--- a/src/mongo/db/op_observer.h
+++ b/src/mongo/db/op_observer.h
@@ -228,7 +228,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) = 0;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) = 0;
/**
* This function logs an oplog entry when a 'collMod' command on a collection is executed.
* Since 'collMod' commands can take a variety of different formats, the 'o' field of the
diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp
index 37fc927add5..5ee47e84dc9 100644
--- a/src/mongo/db/op_observer_impl.cpp
+++ b/src/mongo/db/op_observer_impl.cpp
@@ -1014,7 +1014,8 @@ void OpObserverImpl::onCreateCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) {
// do not replicate system.profile modifications
if (collectionName.isSystemDotProfile()) {
return;
@@ -1035,6 +1036,7 @@ void OpObserverImpl::onCreateCollection(OperationContext* opCtx,
oplogEntry.setObject(
MutableOplogEntry::makeCreateCollCmdObj(collectionName, options, idIndex));
oplogEntry.setOpTime(createOpTime);
+ oplogEntry.setFromMigrateIfTrue(fromMigrate);
logOperation(opCtx, &oplogEntry);
}
}
diff --git a/src/mongo/db/op_observer_impl.h b/src/mongo/db/op_observer_impl.h
index 7843b06602f..77676e9548e 100644
--- a/src/mongo/db/op_observer_impl.h
+++ b/src/mongo/db/op_observer_impl.h
@@ -110,7 +110,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final;
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& uuid,
diff --git a/src/mongo/db/op_observer_noop.h b/src/mongo/db/op_observer_noop.h
index bee9db82207..667164d7564 100644
--- a/src/mongo/db/op_observer_noop.h
+++ b/src/mongo/db/op_observer_noop.h
@@ -99,7 +99,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& uuid,
diff --git a/src/mongo/db/op_observer_registry.h b/src/mongo/db/op_observer_registry.h
index e153d46d65e..4b30bc7c72b 100644
--- a/src/mongo/db/op_observer_registry.h
+++ b/src/mongo/db/op_observer_registry.h
@@ -184,10 +184,12 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override {
ReservedTimes times{opCtx};
for (auto& o : _observers)
- o->onCreateCollection(opCtx, coll, collectionName, options, idIndex, createOpTime);
+ o->onCreateCollection(
+ opCtx, coll, collectionName, options, idIndex, createOpTime, fromMigrate);
}
void onCollMod(OperationContext* const opCtx,
diff --git a/src/mongo/db/pipeline/change_stream_filter_helpers.cpp b/src/mongo/db/pipeline/change_stream_filter_helpers.cpp
index 07e60e09140..75c9e930808 100644
--- a/src/mongo/db/pipeline/change_stream_filter_helpers.cpp
+++ b/src/mongo/db/pipeline/change_stream_filter_helpers.cpp
@@ -48,9 +48,40 @@ std::unique_ptr<MatchExpression> buildTsFilter(
expCtx);
}
+std::unique_ptr<MatchExpression> buildFromMigrateSystemOpFilter(
+ const boost::intrusive_ptr<ExpressionContext>& expCtx, const MatchExpression* userMatch) {
+ auto cmdNsRegex = DocumentSourceChangeStream::getCmdNsRegexForChangeStream(expCtx);
+
+ // The filter {fromMigrate:true} allows quickly skip nonrelevant oplog entries
+ auto andMigrateEvents = std::make_unique<AndMatchExpression>();
+ andMigrateEvents->add(
+ MatchExpressionParser::parseAndNormalize(BSON("fromMigrate" << true), expCtx));
+ andMigrateEvents->add(
+ MatchExpressionParser::parseAndNormalize(BSON("ns" << BSONRegEx(cmdNsRegex)), expCtx));
+
+ auto orMigrateEvents = std::make_unique<OrMatchExpression>();
+ auto collRegex = DocumentSourceChangeStream::getCollRegexForChangeStream(expCtx);
+ orMigrateEvents->add(
+ MatchExpressionParser::parseAndNormalize(BSON("o.create" << BSONRegEx(collRegex)), expCtx));
+ orMigrateEvents->add(MatchExpressionParser::parseAndNormalize(
+ BSON("o.createIndexes" << BSONRegEx(collRegex)), expCtx));
+ andMigrateEvents->add(std::move(orMigrateEvents));
+ return andMigrateEvents;
+}
+
std::unique_ptr<MatchExpression> buildNotFromMigrateFilter(
const boost::intrusive_ptr<ExpressionContext>& expCtx, const MatchExpression* userMatch) {
- return MatchExpressionParser::parseAndNormalize(BSON("fromMigrate" << NE << true), expCtx);
+ // Exclude any events that are marked as 'fromMigrate' in the oplog.
+ auto fromMigrateFilter =
+ MatchExpressionParser::parseAndNormalize(BSON("fromMigrate" << NE << true), expCtx);
+
+ // If 'showSystemEvents' is set, however, we do return some specific 'fromMigrate' events.
+ if (expCtx->changeStreamSpec->getShowSystemEvents()) {
+ auto orMigrateEvents = std::make_unique<OrMatchExpression>(std::move(fromMigrateFilter));
+ orMigrateEvents->add(buildFromMigrateSystemOpFilter(expCtx, userMatch));
+ fromMigrateFilter = std::move(orMigrateEvents);
+ }
+ return fromMigrateFilter;
}
std::unique_ptr<MatchExpression> buildOperationFilter(
diff --git a/src/mongo/db/pipeline/change_stream_filter_helpers.h b/src/mongo/db/pipeline/change_stream_filter_helpers.h
index 09830f4cb2a..e718f122520 100644
--- a/src/mongo/db/pipeline/change_stream_filter_helpers.h
+++ b/src/mongo/db/pipeline/change_stream_filter_helpers.h
@@ -50,6 +50,13 @@ std::unique_ptr<MatchExpression> buildNotFromMigrateFilter(
const boost::intrusive_ptr<ExpressionContext>& expCtx, const MatchExpression* userMatch);
/**
+ * Produce a filter that includes operations marked fromMigrate:true when showSystemEvents feature
+ * is set.
+ */
+std::unique_ptr<MatchExpression> buildFromMigrateSystemOpFilter(
+ const boost::intrusive_ptr<ExpressionContext>& expCtx, const MatchExpression* userMatch);
+
+/**
* Produce an oplog filter which captures all operations relevant to change streams, including CRUD
* events and certain commands. Depending on the 'userMatch' $match expression, this filter may be
* able to reject some entries before they get transformed into change stream entries.
diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp
index 2c10476876f..949a69c2a29 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp
+++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp
@@ -93,7 +93,8 @@ void OplogApplierImplOpObserver::onCreateCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) {
if (!onCreateCollectionFn) {
return;
}
diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.h b/src/mongo/db/repl/oplog_applier_impl_test_fixture.h
index 0c8729259b2..7013192fba9 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.h
+++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.h
@@ -102,7 +102,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override;
/**
* Called when OplogApplierImpl renames a collection.
diff --git a/src/mongo/db/repl/primary_only_service_op_observer.h b/src/mongo/db/repl/primary_only_service_op_observer.h
index 63a93f69bb9..5f552149f98 100644
--- a/src/mongo/db/repl/primary_only_service_op_observer.h
+++ b/src/mongo/db/repl/primary_only_service_op_observer.h
@@ -114,7 +114,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/repl/tenant_collection_cloner_test.cpp b/src/mongo/db/repl/tenant_collection_cloner_test.cpp
index 6eaf831695f..a7ae564e6e8 100644
--- a/src/mongo/db/repl/tenant_collection_cloner_test.cpp
+++ b/src/mongo/db/repl/tenant_collection_cloner_test.cpp
@@ -71,7 +71,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {
if (collectionName == nssToCapture) {
collCreated = true;
collectionOptions = options;
diff --git a/src/mongo/db/repl/tenant_migration_donor_op_observer.h b/src/mongo/db/repl/tenant_migration_donor_op_observer.h
index 2f977b38c52..43992f5e040 100644
--- a/src/mongo/db/repl/tenant_migration_donor_op_observer.h
+++ b/src/mongo/db/repl/tenant_migration_donor_op_observer.h
@@ -112,7 +112,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp b/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp
index 9234f17bd70..46b4d34355a 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp
@@ -107,7 +107,8 @@ void TenantMigrationRecipientOpObserver::onCreateCollection(OperationContext* op
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) {
if (!shard_merge_utils::isDonatedFilesCollection(collectionName))
return;
diff --git a/src/mongo/db/repl/tenant_migration_recipient_op_observer.h b/src/mongo/db/repl/tenant_migration_recipient_op_observer.h
index 3a6d9e95922..dd42ff6581f 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_op_observer.h
+++ b/src/mongo/db/repl/tenant_migration_recipient_op_observer.h
@@ -113,7 +113,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final;
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/s/config_server_op_observer.h b/src/mongo/db/s/config_server_op_observer.h
index ddb36cfbd4c..f9414d4f49e 100644
--- a/src/mongo/db/s/config_server_op_observer.h
+++ b/src/mongo/db/s/config_server_op_observer.h
@@ -115,7 +115,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/s/migration_destination_manager.cpp b/src/mongo/db/s/migration_destination_manager.cpp
index 4c4e21fdf98..3873ba6d021 100644
--- a/src/mongo/db/s/migration_destination_manager.cpp
+++ b/src/mongo/db/s/migration_destination_manager.cpp
@@ -996,6 +996,7 @@ void MigrationDestinationManager::cloneCollectionIndexesAndOptions(
auto db = autoDb.ensureDbExists(opCtx);
auto collection = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
+ auto fromMigrate = true;
if (collection) {
checkUUIDsMatch(collection);
} else {
@@ -1022,7 +1023,8 @@ void MigrationDestinationManager::cloneCollectionIndexesAndOptions(
nss,
collectionOptions,
createDefaultIndexes,
- collectionOptionsAndIndexes.idIndexSpec));
+ collectionOptionsAndIndexes.idIndexSpec,
+ fromMigrate));
wuow.commit();
collection = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
}
@@ -1030,7 +1032,6 @@ void MigrationDestinationManager::cloneCollectionIndexesAndOptions(
auto indexSpecs = checkEmptyOrGetMissingIndexesFromDonor(collection);
if (!indexSpecs.empty()) {
WriteUnitOfWork wunit(opCtx);
- auto fromMigrate = true;
CollectionWriter collWriter(opCtx, collection->uuid());
IndexBuildsCoordinator::get(opCtx)->createIndexesOnEmptyCollection(
opCtx, collWriter, indexSpecs, fromMigrate);
diff --git a/src/mongo/db/s/resharding/resharding_op_observer.h b/src/mongo/db/s/resharding/resharding_op_observer.h
index 35630ed875a..30d319a041d 100644
--- a/src/mongo/db/s/resharding/resharding_op_observer.h
+++ b/src/mongo/db/s/resharding/resharding_op_observer.h
@@ -130,7 +130,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/s/shard_server_op_observer.cpp b/src/mongo/db/s/shard_server_op_observer.cpp
index b72b26e9394..b4214be121c 100644
--- a/src/mongo/db/s/shard_server_op_observer.cpp
+++ b/src/mongo/db/s/shard_server_op_observer.cpp
@@ -534,7 +534,8 @@ void ShardServerOpObserver::onCreateCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) {
+ const OplogSlot& createOpTime,
+ bool fromMigrate) {
// Only the shard primay nodes control the collection creation and secondaries just follow
if (!opCtx->writesAreReplicated()) {
return;
diff --git a/src/mongo/db/s/shard_server_op_observer.h b/src/mongo/db/s/shard_server_op_observer.h
index 82449c72136..5a0671254d6 100644
--- a/src/mongo/db/s/shard_server_op_observer.h
+++ b/src/mongo/db/s/shard_server_op_observer.h
@@ -112,7 +112,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) override;
+ const OplogSlot& createOpTime,
+ bool fromMigrate) override;
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/serverless/shard_split_donor_op_observer.h b/src/mongo/db/serverless/shard_split_donor_op_observer.h
index f55a526e389..55796479ffe 100644
--- a/src/mongo/db/serverless/shard_split_donor_op_observer.h
+++ b/src/mongo/db/serverless/shard_split_donor_op_observer.h
@@ -111,7 +111,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/db/system_index.cpp b/src/mongo/db/system_index.cpp
index 3cfb424ab45..2283e75c9d6 100644
--- a/src/mongo/db/system_index.cpp
+++ b/src/mongo/db/system_index.cpp
@@ -197,7 +197,7 @@ Status verifySystemIndexes(OperationContext* opCtx) {
return Status::OK();
}
-void createSystemIndexes(OperationContext* opCtx, CollectionWriter& collection) {
+void createSystemIndexes(OperationContext* opCtx, CollectionWriter& collection, bool fromMigrate) {
invariant(collection);
const NamespaceString& ns = collection->ns();
BSONObj indexSpec;
@@ -210,7 +210,6 @@ void createSystemIndexes(OperationContext* opCtx, CollectionWriter& collection)
40457, index_key_validate::validateIndexSpec(opCtx, v3SystemRolesIndexSpec.toBSON()));
}
if (!indexSpec.isEmpty()) {
- auto fromMigrate = false;
try {
IndexBuildsCoordinator::get(opCtx)->createIndexesOnEmptyCollection(
opCtx, collection, {indexSpec}, fromMigrate);
diff --git a/src/mongo/db/system_index.h b/src/mongo/db/system_index.h
index ed10e1f99af..d8bdbd29457 100644
--- a/src/mongo/db/system_index.h
+++ b/src/mongo/db/system_index.h
@@ -39,7 +39,7 @@ class Status;
* Creates the appropriate indexes on _new_ system collections for authentication,
* authorization, and sessions.
*/
-void createSystemIndexes(OperationContext* opCtx, CollectionWriter& collection);
+void createSystemIndexes(OperationContext* opCtx, CollectionWriter& collection, bool fromMigrate);
/**
* Verifies that only the appropriate indexes to support authentication, authorization, and
diff --git a/src/mongo/db/user_write_block_mode_op_observer.h b/src/mongo/db/user_write_block_mode_op_observer.h
index a3cfd78c518..38f61233176 100644
--- a/src/mongo/db/user_write_block_mode_op_observer.h
+++ b/src/mongo/db/user_write_block_mode_op_observer.h
@@ -117,7 +117,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,
diff --git a/src/mongo/idl/cluster_server_parameter_op_observer.h b/src/mongo/idl/cluster_server_parameter_op_observer.h
index b2c87f83fb2..530a5e63148 100644
--- a/src/mongo/idl/cluster_server_parameter_op_observer.h
+++ b/src/mongo/idl/cluster_server_parameter_op_observer.h
@@ -148,7 +148,8 @@ public:
const NamespaceString& collectionName,
const CollectionOptions& options,
const BSONObj& idIndex,
- const OplogSlot& createOpTime) final {}
+ const OplogSlot& createOpTime,
+ bool fromMigrate) final {}
void onCollMod(OperationContext* opCtx,
const NamespaceString& nss,