@@ -155,6 +155,9 @@ typedef struct {
155
155
// `operation_ids` is a BSON document of this form:
156
156
// { "0": <int64>, "1": <int64> ... }
157
157
bson_t operation_ids ;
158
+ // `write_concerns` is a BSON document of this form:
159
+ // { "0": <document|null>, "1": <document|null> ... }
160
+ bson_t write_concerns ;
158
161
int numGetMore ;
159
162
int numKillCursors ;
160
163
} bulkWrite_ctx ;
@@ -180,6 +183,13 @@ bulkWrite_cb (const mongoc_apm_command_started_t *event)
180
183
char * key = bson_strdup_printf ("%" PRIu32 , bson_count_keys (& ctx -> ops_counts ));
181
184
BSON_APPEND_INT64 (& ctx -> ops_counts , key , ops_count );
182
185
BSON_APPEND_INT64 (& ctx -> operation_ids , key , mongoc_apm_command_started_get_operation_id (event ));
186
+ // Record write concern (if present).
187
+ bson_iter_t wc_iter ;
188
+ if (bson_iter_init_find (& wc_iter , cmd , "writeConcern" )) {
189
+ BSON_APPEND_ITER (& ctx -> write_concerns , key , & wc_iter );
190
+ } else {
191
+ BSON_APPEND_NULL (& ctx -> write_concerns , key );
192
+ }
183
193
bson_free (key );
184
194
}
185
195
@@ -199,6 +209,7 @@ capture_bulkWrite_info (mongoc_client_t *client)
199
209
bulkWrite_ctx * cb_ctx = bson_malloc0 (sizeof (* cb_ctx ));
200
210
bson_init (& cb_ctx -> ops_counts );
201
211
bson_init (& cb_ctx -> operation_ids );
212
+ bson_init (& cb_ctx -> write_concerns );
202
213
mongoc_apm_callbacks_t * cbs = mongoc_apm_callbacks_new ();
203
214
mongoc_apm_set_command_started_cb (cbs , bulkWrite_cb );
204
215
mongoc_client_set_apm_callbacks (client , cbs , cb_ctx );
@@ -211,6 +222,7 @@ bulkWrite_ctx_reset (bulkWrite_ctx *cb_ctx)
211
222
{
212
223
bson_reinit (& cb_ctx -> ops_counts );
213
224
bson_reinit (& cb_ctx -> operation_ids );
225
+ bson_reinit (& cb_ctx -> write_concerns );
214
226
cb_ctx -> numGetMore = 0 ;
215
227
cb_ctx -> numKillCursors = 0 ;
216
228
}
@@ -223,6 +235,7 @@ bulkWrite_ctx_destroy (bulkWrite_ctx *cb_ctx)
223
235
}
224
236
bson_destroy (& cb_ctx -> ops_counts );
225
237
bson_destroy (& cb_ctx -> operation_ids );
238
+ bson_destroy (& cb_ctx -> write_concerns );
226
239
bson_free (cb_ctx );
227
240
}
228
241
@@ -888,6 +901,7 @@ prose_test_10 (void *ctx)
888
901
wc = mongoc_write_concern_new ();
889
902
mongoc_write_concern_set_w (wc , MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED );
890
903
mongoc_bulkwriteopts_t * opts = mongoc_bulkwriteopts_new ();
904
+ mongoc_bulkwriteopts_set_ordered (opts , false);
891
905
mongoc_bulkwriteopts_set_writeconcern (opts , wc );
892
906
893
907
// Test a large insert.
@@ -1286,6 +1300,117 @@ prose_test_13 (void *ctx)
1286
1300
mongoc_client_destroy (client );
1287
1301
}
1288
1302
1303
+ static void
1304
+ prose_test_15 (void * ctx )
1305
+ {
1306
+ /*
1307
+ 15. `MongoClient.bulkWrite` with unacknowledged write concern uses `w:0` for all batches
1308
+ */
1309
+ mongoc_client_t * client ;
1310
+ BSON_UNUSED (ctx );
1311
+ bool ok ;
1312
+ bson_error_t error ;
1313
+
1314
+ client = test_framework_new_default_client ();
1315
+
1316
+ // Drop collection.
1317
+ {
1318
+ mongoc_collection_t * coll = mongoc_client_get_collection (client , "db" , "coll" );
1319
+ mongoc_collection_drop (coll , NULL ); // Ignore error.
1320
+ mongoc_collection_destroy (coll );
1321
+ }
1322
+
1323
+ // Create collection to workaround SERVER-95537.
1324
+ {
1325
+ mongoc_database_t * db = mongoc_client_get_database (client , "db" );
1326
+ mongoc_collection_t * coll = mongoc_database_create_collection (db , "coll" , NULL , & error );
1327
+ ASSERT_OR_PRINT (coll , error );
1328
+ mongoc_collection_destroy (coll );
1329
+ mongoc_database_destroy (db );
1330
+ }
1331
+
1332
+ // Set callbacks to count the number of bulkWrite commands sent.
1333
+ bulkWrite_ctx * cb_ctx = capture_bulkWrite_info (client );
1334
+
1335
+ // Get `maxWriteBatchSize` and `maxBsonObjectSize` from the server.
1336
+ server_limits_t sl = get_server_limits (client );
1337
+ int32_t maxMessageSizeBytes = sl .maxMessageSizeBytes ;
1338
+ int32_t maxBsonObjectSize = sl .maxBsonObjectSize ;
1339
+
1340
+
1341
+ // Make a large document.
1342
+ bson_t doc = BSON_INITIALIZER ;
1343
+ {
1344
+ char * large_str = repeat_char ('b' , (size_t ) maxBsonObjectSize - 500 );
1345
+ BSON_APPEND_UTF8 (& doc , "a" , large_str );
1346
+ bson_free (large_str );
1347
+ }
1348
+
1349
+ // Execute bulkWrite.
1350
+ {
1351
+ mongoc_bulkwrite_t * bw = mongoc_client_bulkwrite_new (client );
1352
+ for (int32_t i = 0 ; i < maxMessageSizeBytes / maxBsonObjectSize + 1 ; i ++ ) {
1353
+ ok = mongoc_bulkwrite_append_insertone (bw , "db.coll" , & doc , NULL , & error );
1354
+ ASSERT_OR_PRINT (ok , error );
1355
+ }
1356
+
1357
+ // Configure options with unacknowledge write concern and unordered writes.
1358
+ mongoc_bulkwriteopts_t * bwo ;
1359
+ {
1360
+ mongoc_write_concern_t * wc = mongoc_write_concern_new ();
1361
+ mongoc_write_concern_set_w (wc , MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED );
1362
+ bwo = mongoc_bulkwriteopts_new ();
1363
+ mongoc_bulkwriteopts_set_writeconcern (bwo , wc );
1364
+ mongoc_bulkwriteopts_set_ordered (bwo , false);
1365
+ mongoc_write_concern_destroy (wc );
1366
+ }
1367
+
1368
+ mongoc_bulkwritereturn_t ret = mongoc_bulkwrite_execute (bw , bwo );
1369
+ ASSERT (!ret .res ); // No result due to unacknowledged.
1370
+ ASSERT_NO_BULKWRITEEXCEPTION (ret );
1371
+ mongoc_bulkwriteexception_destroy (ret .exc );
1372
+ mongoc_bulkwriteresult_destroy (ret .res );
1373
+ mongoc_bulkwriteopts_destroy (bwo );
1374
+ mongoc_bulkwrite_destroy (bw );
1375
+ }
1376
+
1377
+ // Check command started events.
1378
+ {
1379
+ bson_t expect = BSON_INITIALIZER ;
1380
+ // Assert first `bulkWrite` sends `maxWriteBatchSize` ops.
1381
+ BSON_APPEND_INT64 (& expect , "0" , maxMessageSizeBytes / maxBsonObjectSize );
1382
+ // Assert second `bulkWrite` sends 1 op.
1383
+ BSON_APPEND_INT64 (& expect , "1" , 1 );
1384
+ ASSERT_EQUAL_BSON (& expect , & cb_ctx -> ops_counts );
1385
+ bson_destroy (& expect );
1386
+
1387
+ // Assert both have the same `operation_id`.
1388
+ int64_t operation_id_0 = bson_lookup_int64 (& cb_ctx -> operation_ids , "0" );
1389
+ int64_t operation_id_1 = bson_lookup_int64 (& cb_ctx -> operation_ids , "1" );
1390
+ ASSERT_CMPINT64 (operation_id_0 , = = , operation_id_1 );
1391
+
1392
+ // Assert both use unacknowledged write concern.
1393
+ bson_init (& expect );
1394
+ BCON_APPEND (& expect , "0" , "{" , "w" , BCON_INT32 (0 ), "}" );
1395
+ BCON_APPEND (& expect , "1" , "{" , "w" , BCON_INT32 (0 ), "}" );
1396
+ ASSERT_EQUAL_BSON (& expect , & cb_ctx -> write_concerns );
1397
+ bson_destroy (& expect );
1398
+ }
1399
+
1400
+ // Count documents in collection.
1401
+ {
1402
+ mongoc_collection_t * coll = mongoc_client_get_collection (client , "db" , "coll" );
1403
+ int64_t expected = maxMessageSizeBytes / maxBsonObjectSize + 1 ;
1404
+ int64_t got = mongoc_collection_count_documents (coll , tmp_bson ("{}" ), NULL , NULL , NULL , & error );
1405
+ ASSERT_CMPINT64 (got , = = , expected );
1406
+ mongoc_collection_destroy (coll );
1407
+ }
1408
+
1409
+ bson_destroy (& doc );
1410
+ bulkWrite_ctx_destroy (cb_ctx );
1411
+ mongoc_client_destroy (client );
1412
+ }
1413
+
1289
1414
1290
1415
void
1291
1416
test_crud_install (TestSuite * suite )
@@ -1392,4 +1517,12 @@ test_crud_install (TestSuite *suite)
1392
1517
NULL /* ctx */ ,
1393
1518
test_framework_skip_if_max_wire_version_less_than_25 , // require server 8.0
1394
1519
test_framework_skip_if_no_client_side_encryption );
1520
+
1521
+ TestSuite_AddFull (suite ,
1522
+ "/crud/prose_test_15" ,
1523
+ prose_test_15 ,
1524
+ NULL /* dtor */ ,
1525
+ NULL /* ctx */ ,
1526
+ test_framework_skip_if_max_wire_version_less_than_25 // require server 8.0
1527
+ );
1395
1528
}
0 commit comments