@@ -418,7 +418,7 @@ _mongoc_write_command_will_overflow (uint32_t len_so_far,
418
418
/* max BSON object size + 16k bytes.
419
419
* server guarantees there is enough room: SERVER-10643
420
420
*/
421
- int32_t max_cmd_size = max_bson_size + 16384 ;
421
+ int32_t max_cmd_size = max_bson_size + BSON_OBJECT_ALLOWANCE ;
422
422
423
423
BSON_ASSERT (max_bson_size );
424
424
@@ -469,10 +469,6 @@ _mongoc_write_opmsg (mongoc_write_command_t *command,
469
469
BSON_ASSERT (server_stream );
470
470
BSON_ASSERT (collection );
471
471
472
- /* MongoDB has a extra allowance to allow updating 16mb document,
473
- * as the update operators would otherwise overflow the 16mb object limit
474
- */
475
- #define BSON_OBJECT_ALLOWANCE (16 * 1024)
476
472
max_bson_obj_size = mongoc_server_stream_max_bson_obj_size (server_stream );
477
473
max_msg_size = mongoc_server_stream_max_msg_size (server_stream );
478
474
max_document_count =
@@ -683,6 +679,41 @@ _append_array_from_command (mongoc_write_command_t *command, bson_t *bson)
683
679
bson_reader_destroy (reader );
684
680
}
685
681
682
+ /* Assemble the base @cmd with all of the command options.
683
+ * @parts is always initialized, even on error.
684
+ * This is called twice in _mongoc_write_opquery.
685
+ * Once with no payload documents, to determine the total size. And once with
686
+ * payload documents, to send the final command. */
687
+ static bool
688
+ _assemble_cmd (bson_t * cmd ,
689
+ mongoc_write_command_t * command ,
690
+ mongoc_client_t * client ,
691
+ mongoc_server_stream_t * server_stream ,
692
+ const char * database ,
693
+ const mongoc_write_concern_t * write_concern ,
694
+ mongoc_cmd_parts_t * parts ,
695
+ bson_error_t * error )
696
+ {
697
+ bool ret ;
698
+ bson_iter_t iter ;
699
+
700
+ mongoc_cmd_parts_init (parts , client , database , MONGOC_QUERY_NONE , cmd );
701
+ parts -> is_write_command = true;
702
+ parts -> assembled .operation_id = command -> operation_id ;
703
+
704
+ ret = mongoc_cmd_parts_set_write_concern (
705
+ parts , write_concern , server_stream -> sd -> max_wire_version , error );
706
+ if (ret ) {
707
+ BSON_ASSERT (bson_iter_init (& iter , & command -> cmd_opts ));
708
+ ret = mongoc_cmd_parts_append_opts (
709
+ parts , & iter , server_stream -> sd -> max_wire_version , error );
710
+ }
711
+ if (ret ) {
712
+ ret = mongoc_cmd_parts_assemble (parts , server_stream , error );
713
+ }
714
+ return ret ;
715
+ }
716
+
686
717
static void
687
718
_mongoc_write_opquery (mongoc_write_command_t * command ,
688
719
mongoc_client_t * client ,
@@ -695,12 +726,10 @@ _mongoc_write_opquery (mongoc_write_command_t *command,
695
726
bson_error_t * error )
696
727
{
697
728
mongoc_cmd_parts_t parts ;
698
- bson_iter_t iter ;
699
729
const char * key ;
700
730
uint32_t len = 0 ;
701
731
bson_t ar ;
702
732
bson_t cmd ;
703
- bson_t reply ;
704
733
char str [16 ];
705
734
bool has_more ;
706
735
bool ret = false;
@@ -732,10 +761,30 @@ _mongoc_write_opquery (mongoc_write_command_t *command,
732
761
i = 0 ;
733
762
734
763
_mongoc_write_command_init (& cmd , command , collection );
764
+ /* If any part of assembling failed, return with failure. */
765
+ if (!_assemble_cmd (& cmd ,
766
+ command ,
767
+ client ,
768
+ server_stream ,
769
+ database ,
770
+ write_concern ,
771
+ & parts ,
772
+ error )) {
773
+ result -> failed = true;
774
+ bson_destroy (& cmd );
775
+ mongoc_cmd_parts_cleanup (& parts );
776
+ EXIT ;
777
+ }
735
778
736
- /* 1 byte to specify array type, 1 byte for field name's null terminator */
737
- overhead = cmd .len + 2 + gCommandFieldLens [command -> type ];
738
-
779
+ /* Use the assembled command to compute the overhead, since it may be a new
780
+ * BSON document with options applied. If no options were applied, then
781
+ * parts.assembled.command points to cmd. The constant 2 is due to 1 byte to
782
+ * specify array type and 1 byte for field name's null terminator. */
783
+ overhead =
784
+ parts .assembled .command -> len + 2 + gCommandFieldLens [command -> type ];
785
+ /* Toss out the assembled command, we'll assemble again after adding all of
786
+ * the payload documents. */
787
+ mongoc_cmd_parts_cleanup (& parts );
739
788
740
789
reader = bson_reader_new_from_data (command -> payload .data + data_offset ,
741
790
command -> payload .len - data_offset );
@@ -773,36 +822,20 @@ _mongoc_write_opquery (mongoc_write_command_t *command,
773
822
data_offset += len ;
774
823
}
775
824
} else {
776
- mongoc_cmd_parts_init (& parts , client , database , MONGOC_QUERY_NONE , & cmd );
777
- parts .is_write_command = true;
778
- parts .assembled .operation_id = command -> operation_id ;
779
- if (!mongoc_cmd_parts_set_write_concern (
780
- & parts ,
781
- write_concern ,
782
- server_stream -> sd -> max_wire_version ,
783
- error )) {
784
- bson_reader_destroy (reader );
785
- bson_destroy (& cmd );
786
- mongoc_cmd_parts_cleanup (& parts );
787
- EXIT ;
788
- }
825
+ bson_t reply ;
789
826
790
- BSON_ASSERT (bson_iter_init (& iter , & command -> cmd_opts ));
791
- if (!mongoc_cmd_parts_append_opts (
792
- & parts , & iter , server_stream -> sd -> max_wire_version , error )) {
793
- bson_reader_destroy (reader );
794
- bson_destroy (& cmd );
795
- mongoc_cmd_parts_cleanup (& parts );
796
- EXIT ;
797
- }
798
-
799
- ret = mongoc_cmd_parts_assemble (& parts , server_stream , error );
827
+ ret = _assemble_cmd (& cmd ,
828
+ command ,
829
+ client ,
830
+ server_stream ,
831
+ database ,
832
+ write_concern ,
833
+ & parts ,
834
+ error );
800
835
if (ret ) {
801
836
ret = mongoc_cluster_run_command_monitored (
802
837
& client -> cluster , & parts .assembled , & reply , error );
803
838
} else {
804
- /* assembling failed */
805
- result -> must_stop = true;
806
839
bson_init (& reply );
807
840
}
808
841
0 commit comments