From bd923a7258b93b4cba196a90159f9a835f19106e Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Wed, 7 May 2025 15:45:22 -0400 Subject: [PATCH 1/4] capture cluster time after initial data operations --- src/libmongoc/tests/unified/runner.c | 20 ++++++++++++++++++++ src/libmongoc/tests/unified/runner.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/libmongoc/tests/unified/runner.c b/src/libmongoc/tests/unified/runner.c index e2d302ee423..ad639379ff5 100644 --- a/src/libmongoc/tests/unified/runner.c +++ b/src/libmongoc/tests/unified/runner.c @@ -532,6 +532,7 @@ test_destroy (test_t *test) bson_destroy (test->run_on_requirements); bson_free (test->description); bson_free (test->skip_reason); + bson_destroy (test->cluster_time_after_initial_data); bson_free (test); } @@ -870,6 +871,11 @@ test_setup_initial_data (test_t *test, bson_error_t *error) return true; } + mongoc_client_session_t *sess = mongoc_client_start_session (test_runner->internal_client, NULL, error); + if (sess == NULL) { + return false; + } + BSON_FOREACH (test_file->initial_data, initial_data_iter) { bson_parser_t *parser = NULL; @@ -899,6 +905,9 @@ test_setup_initial_data (test_t *test, bson_error_t *error) mongoc_write_concern_set_w (wc, MONGOC_WRITE_CONCERN_W_MAJORITY); bulk_opts = bson_new (); mongoc_write_concern_append (wc, bulk_opts); + if (!mongoc_client_session_append (sess, bulk_opts, error)) { + goto loopexit; + } /* Drop the collection. */ /* Check if the server supports majority write concern on 'drop' and @@ -913,6 +922,12 @@ test_setup_initial_data (test_t *test, bson_error_t *error) BSON_APPEND_INT32 (drop_opts, "serverId", 1); BSON_APPEND_INT32 (create_opts, "serverId", 1); } + if (!mongoc_client_session_append (sess, create_opts, error)) { + goto loopexit; + } + if (!mongoc_client_session_append (sess, drop_opts, error)) { + goto loopexit; + } coll = mongoc_client_get_collection (test_runner->internal_client, database_name, collection_name); if (!mongoc_collection_drop_with_opts (coll, drop_opts, error)) { @@ -972,9 +987,14 @@ test_setup_initial_data (test_t *test, bson_error_t *error) bson_parser_destroy (parser); mongoc_database_destroy (db); if (!ret) { + mongoc_client_session_destroy (sess); return false; } } + + // Obtain cluster time to advance client sessions. See DRIVERS-2816. + test->cluster_time_after_initial_data = bson_copy (mongoc_client_session_get_cluster_time (sess)); + mongoc_client_session_destroy (sess); return true; } diff --git a/src/libmongoc/tests/unified/runner.h b/src/libmongoc/tests/unified/runner.h index 5a3c59ad059..349b15540fb 100644 --- a/src/libmongoc/tests/unified/runner.h +++ b/src/libmongoc/tests/unified/runner.h @@ -63,6 +63,7 @@ typedef struct { entity_map_t *entity_map; failpoint_t *failpoints; bool loop_operation_executed; + bson_t *cluster_time_after_initial_data; } test_t; /* Set server_id to 0 if the failpoint was not against a pinned mongos. */ From e5d2bf01381ecc4af195685e459381222495e768 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Wed, 7 May 2025 15:46:47 -0400 Subject: [PATCH 2/4] advance cluster time in newly created session entities --- src/libmongoc/tests/unified/entity-map.c | 13 ++++++++++--- src/libmongoc/tests/unified/entity-map.h | 2 +- src/libmongoc/tests/unified/operation.c | 2 +- src/libmongoc/tests/unified/runner.c | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libmongoc/tests/unified/entity-map.c b/src/libmongoc/tests/unified/entity-map.c index e12d25c384d..b6d0b88ddbf 100644 --- a/src/libmongoc/tests/unified/entity-map.c +++ b/src/libmongoc/tests/unified/entity-map.c @@ -1651,7 +1651,10 @@ session_opts_new (bson_t *bson, bson_error_t *error) } entity_t * -entity_session_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) +entity_session_new (entity_map_t *entity_map, + bson_t *bson, + const bson_t *cluster_time_after_initial_data, + bson_error_t *error) { bson_parser_t *parser = NULL; entity_t *entity = NULL; @@ -1691,6 +1694,7 @@ entity_session_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) if (!session) { goto done; } + mongoc_client_session_advance_cluster_time (session, cluster_time_after_initial_data); entity->value = session; /* Ending a session destroys the session object. * After a session is ended, match assertions may be made on the lsid. @@ -1785,7 +1789,10 @@ entity_bucket_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) * object immediately. */ bool -entity_map_create (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) +entity_map_create (entity_map_t *entity_map, + bson_t *bson, + const bson_t *cluster_time_after_initial_data, + bson_error_t *error) { bson_iter_t iter; const char *entity_type; @@ -1816,7 +1823,7 @@ entity_map_create (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) } else if (0 == strcmp (entity_type, "collection")) { entity = entity_collection_new (entity_map, &entity_bson, error); } else if (0 == strcmp (entity_type, "session")) { - entity = entity_session_new (entity_map, &entity_bson, error); + entity = entity_session_new (entity_map, &entity_bson, cluster_time_after_initial_data, error); } else if (0 == strcmp (entity_type, "bucket")) { entity = entity_bucket_new (entity_map, &entity_bson, error); } else { diff --git a/src/libmongoc/tests/unified/entity-map.h b/src/libmongoc/tests/unified/entity-map.h index f01bc1b6904..dd696dd2e81 100644 --- a/src/libmongoc/tests/unified/entity-map.h +++ b/src/libmongoc/tests/unified/entity-map.h @@ -96,7 +96,7 @@ entity_map_destroy (entity_map_t *em); /* Creates an entry in the entity map based on what is specified in @bson. */ bool -entity_map_create (entity_map_t *em, bson_t *bson, bson_error_t *error); +entity_map_create (entity_map_t *em, bson_t *bson, const bson_t *cluster_time_after_initial_data, bson_error_t *error); /* Steals ownership of changestream. */ bool diff --git a/src/libmongoc/tests/unified/operation.c b/src/libmongoc/tests/unified/operation.c index fda829dc18f..cfd9cc44989 100644 --- a/src/libmongoc/tests/unified/operation.c +++ b/src/libmongoc/tests/unified/operation.c @@ -3833,7 +3833,7 @@ operation_create_entities (test_t *test, operation_t *op, result_t *result, bson { bson_t entity; bson_iter_bson (&entity_iter, &entity); - bool create_ret = entity_map_create (test->entity_map, &entity, error); + bool create_ret = entity_map_create (test->entity_map, &entity, test->cluster_time_after_initial_data, error); bson_destroy (&entity); if (!create_ret) { goto done; diff --git a/src/libmongoc/tests/unified/runner.c b/src/libmongoc/tests/unified/runner.c index ad639379ff5..14b1d23deca 100644 --- a/src/libmongoc/tests/unified/runner.c +++ b/src/libmongoc/tests/unified/runner.c @@ -1021,7 +1021,7 @@ test_create_entities (test_t *test, bson_error_t *error) bson_t entity_bson; bson_iter_bson (&iter, &entity_bson); - if (!entity_map_create (test->entity_map, &entity_bson, error)) { + if (!entity_map_create (test->entity_map, &entity_bson, test->cluster_time_after_initial_data, error)) { return false; } } From 47c0e5bdba24682a5b28cd517c6df30f75133c34 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Wed, 7 May 2025 16:22:03 -0400 Subject: [PATCH 3/4] handle tests that do not specify initial data --- src/libmongoc/tests/unified/runner.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libmongoc/tests/unified/runner.c b/src/libmongoc/tests/unified/runner.c index 14b1d23deca..138b04e922e 100644 --- a/src/libmongoc/tests/unified/runner.c +++ b/src/libmongoc/tests/unified/runner.c @@ -867,15 +867,25 @@ test_setup_initial_data (test_t *test, bson_error_t *error) test_file = test->test_file; test_runner = test_file->test_runner; - if (!test_file->initial_data) { - return true; - } - mongoc_client_session_t *sess = mongoc_client_start_session (test_runner->internal_client, NULL, error); if (sess == NULL) { return false; } + if (!test_file->initial_data) { + // Send a "ping" command with the session to get a cluster time. + bson_t opts = BSON_INITIALIZER; + bool ok = mongoc_client_session_append (sess, &opts, error); + ok = ok && mongoc_client_command_with_opts ( + test_runner->internal_client, "db", tmp_bson ("{'ping': 1}"), NULL, &opts, NULL, error); + if (ok) { + test->cluster_time_after_initial_data = bson_copy (mongoc_client_session_get_cluster_time (sess)); + } + mongoc_client_session_destroy (sess); + bson_destroy (&opts); + return ok; + } + BSON_FOREACH (test_file->initial_data, initial_data_iter) { bson_parser_t *parser = NULL; From 14e80974e1449fa9a40a24cf865d8e2655c91e80 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 8 May 2025 12:42:15 -0400 Subject: [PATCH 4/4] do not try to read cluster time from standalone --- src/libmongoc/tests/unified/entity-map.c | 4 +++- src/libmongoc/tests/unified/runner.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libmongoc/tests/unified/entity-map.c b/src/libmongoc/tests/unified/entity-map.c index b6d0b88ddbf..ad4f50b110e 100644 --- a/src/libmongoc/tests/unified/entity-map.c +++ b/src/libmongoc/tests/unified/entity-map.c @@ -1694,7 +1694,9 @@ entity_session_new (entity_map_t *entity_map, if (!session) { goto done; } - mongoc_client_session_advance_cluster_time (session, cluster_time_after_initial_data); + if (cluster_time_after_initial_data) { + mongoc_client_session_advance_cluster_time (session, cluster_time_after_initial_data); + } entity->value = session; /* Ending a session destroys the session object. * After a session is ended, match assertions may be made on the lsid. diff --git a/src/libmongoc/tests/unified/runner.c b/src/libmongoc/tests/unified/runner.c index 138b04e922e..79591051982 100644 --- a/src/libmongoc/tests/unified/runner.c +++ b/src/libmongoc/tests/unified/runner.c @@ -879,7 +879,11 @@ test_setup_initial_data (test_t *test, bson_error_t *error) ok = ok && mongoc_client_command_with_opts ( test_runner->internal_client, "db", tmp_bson ("{'ping': 1}"), NULL, &opts, NULL, error); if (ok) { - test->cluster_time_after_initial_data = bson_copy (mongoc_client_session_get_cluster_time (sess)); + // Check for cluster time (not available on standalone). + const bson_t *ct = mongoc_client_session_get_cluster_time (sess); + if (ct) { + test->cluster_time_after_initial_data = bson_copy (ct); + } } mongoc_client_session_destroy (sess); bson_destroy (&opts); @@ -1003,7 +1007,11 @@ test_setup_initial_data (test_t *test, bson_error_t *error) } // Obtain cluster time to advance client sessions. See DRIVERS-2816. - test->cluster_time_after_initial_data = bson_copy (mongoc_client_session_get_cluster_time (sess)); + // Check for cluster time (not available on standalone). + const bson_t *ct = mongoc_client_session_get_cluster_time (sess); + if (ct) { + test->cluster_time_after_initial_data = bson_copy (ct); + } mongoc_client_session_destroy (sess); return true; }