32
32
*/
33
33
34
34
35
+ #define MAX_INSERT_BATCH 1000
35
36
#define SUPPORTS_WRITE_COMMANDS (n ) \
36
37
(((n)->min_wire_version <= 2) && ((n)->max_wire_version >= 2))
37
38
#define WRITE_CONCERN_DOC (wc ) \
@@ -200,8 +201,11 @@ _mongoc_write_command_insert_legacy (mongoc_write_command_t *command,
200
201
bson_iter_t iter ;
201
202
uint32_t len ;
202
203
bson_t * gle = NULL ;
204
+ size_t size = 0 ;
205
+ bool has_more = false;
203
206
char ns [MONGOC_NAMESPACE_MAX + 1 ];
204
- int i = 0 ;
207
+ bool r ;
208
+ int i ;
205
209
206
210
ENTRY ;
207
211
@@ -212,7 +216,13 @@ _mongoc_write_command_insert_legacy (mongoc_write_command_t *command,
212
216
BSON_ASSERT (collection );
213
217
BSON_ASSERT (command -> type == MONGOC_WRITE_COMMAND_INSERT );
214
218
215
- if (!command -> u .insert .n_documents ) {
219
+ r = bson_iter_init (& iter , command -> u .insert .documents );
220
+ if (!r ) {
221
+ BSON_ASSERT (false);
222
+ EXIT ;
223
+ }
224
+
225
+ if (!command -> u .insert .n_documents || !bson_iter_next (& iter )) {
216
226
bson_set_error (error ,
217
227
MONGOC_ERROR_COLLECTION ,
218
228
MONGOC_ERROR_COLLECTION_INSERT_FAILED ,
@@ -225,16 +235,50 @@ _mongoc_write_command_insert_legacy (mongoc_write_command_t *command,
225
235
226
236
iov = bson_malloc ((sizeof * iov ) * command -> u .insert .n_documents );
227
237
228
- bson_iter_init (& iter , command -> u .insert .documents );
229
-
230
- while (bson_iter_next (& iter )) {
238
+ again :
239
+ has_more = false;
240
+ i = 0 ;
241
+ size = (sizeof (mongoc_rpc_header_t ) +
242
+ 4 +
243
+ strlen (database ) +
244
+ 1 +
245
+ strlen (collection ) +
246
+ 1 );
247
+
248
+ do {
231
249
BSON_ASSERT (BSON_ITER_HOLDS_DOCUMENT (& iter ));
232
250
BSON_ASSERT (i < command -> u .insert .n_documents );
251
+
233
252
bson_iter_document (& iter , & len , & data );
253
+
254
+ /*
255
+ * Check that the server can receive this document.
256
+ */
257
+ if ((len > client -> cluster .max_bson_size ) ||
258
+ (len > client -> cluster .max_msg_size )) {
259
+ bson_set_error (error ,
260
+ MONGOC_ERROR_BSON ,
261
+ MONGOC_ERROR_BSON_INVALID ,
262
+ "Document %u is too large for the cluster. "
263
+ "Document is %u bytes, max is %u." ,
264
+ i , (unsigned )len , client -> cluster .max_bson_size );
265
+ }
266
+
267
+ /*
268
+ * Check that we will not overflow our max message size.
269
+ */
270
+ if ((i == MAX_INSERT_BATCH ) ||
271
+ (size > (client -> cluster .max_msg_size - len ))) {
272
+ has_more = true;
273
+ break ;
274
+ }
275
+
234
276
iov [i ].iov_base = (void * )data ;
235
277
iov [i ].iov_len = len ;
278
+
279
+ size += len ;
236
280
i ++ ;
237
- }
281
+ } while ( bson_iter_next ( & iter ));
238
282
239
283
rpc .insert .msg_len = 0 ;
240
284
rpc .insert .request_id = 0 ;
@@ -244,7 +288,7 @@ _mongoc_write_command_insert_legacy (mongoc_write_command_t *command,
244
288
(command -> u .insert .ordered ? 0 : MONGOC_INSERT_CONTINUE_ON_ERROR );
245
289
rpc .insert .collection = ns ;
246
290
rpc .insert .documents = iov ;
247
- rpc .insert .n_documents = command -> u . insert . n_documents ;
291
+ rpc .insert .n_documents = i ;
248
292
249
293
hint = _mongoc_client_sendv (client , & rpc , 1 , hint , write_concern ,
250
294
NULL , error );
@@ -255,16 +299,33 @@ _mongoc_write_command_insert_legacy (mongoc_write_command_t *command,
255
299
}
256
300
257
301
if (_mongoc_write_concern_has_gle (write_concern )) {
302
+ bson_iter_t iter ;
303
+
258
304
if (!_mongoc_client_recv_gle (client , hint , & gle , error )) {
259
305
result -> failed = true;
260
306
GOTO (cleanup );
261
307
}
308
+
309
+ /*
310
+ * Overwrite the "n" field since it will be zero. Otherwise, our
311
+ * merge_legacy code will not know how many we tried in this batch.
312
+ */
313
+ if (bson_iter_init_find (& iter , gle , "n" ) &&
314
+ BSON_ITER_HOLDS_INT32 (& iter ) &&
315
+ !bson_iter_int32 (& iter )) {
316
+ bson_iter_overwrite_int32 (& iter , i );
317
+ }
262
318
}
263
319
264
320
cleanup :
265
321
if (gle ) {
266
322
_mongoc_write_result_merge_legacy (result , command , gle );
267
323
bson_destroy (gle );
324
+ gle = NULL ;
325
+ }
326
+
327
+ if (has_more ) {
328
+ GOTO (again );
268
329
}
269
330
270
331
bson_free (iov );
@@ -542,6 +603,10 @@ _mongoc_write_command_execute (mongoc_write_command_t *command, /* I
542
603
BSON_ASSERT (collection );
543
604
BSON_ASSERT (result );
544
605
606
+ if (!write_concern ) {
607
+ write_concern = client -> write_concern ;
608
+ }
609
+
545
610
if (!hint ) {
546
611
hint = _mongoc_client_preselect (client , MONGOC_OPCODE_INSERT ,
547
612
write_concern , NULL , & result -> error );
@@ -686,9 +751,6 @@ _mongoc_write_result_merge_legacy (mongoc_write_result_t *result, /* IN */
686
751
case MONGOC_WRITE_COMMAND_INSERT :
687
752
if (n ) {
688
753
result -> nInserted += n ;
689
- } else if (bson_iter_init_find (& iter , reply , "ok" ) &&
690
- bson_iter_as_bool (& iter )) {
691
- result -> nInserted += command -> u .insert .n_documents ;
692
754
}
693
755
break ;
694
756
case MONGOC_WRITE_COMMAND_DELETE :
0 commit comments