@@ -542,27 +542,48 @@ static PyObject* _cbson_get_more_message(PyObject* self, PyObject* args) {
542542
543543static void
544544_set_document_too_large (int size , long max ) {
545- PyObject * InvalidDocument = _error ("InvalidDocument " );
546- if (InvalidDocument ) {
545+ PyObject * DocumentTooLarge = _error ("DocumentTooLarge " );
546+ if (DocumentTooLarge ) {
547547#if PY_MAJOR_VERSION >= 3
548548 PyObject * error = PyUnicode_FromFormat (DOC_TOO_LARGE_FMT , size , max );
549549#else
550550 PyObject * error = PyString_FromFormat (DOC_TOO_LARGE_FMT , size , max );
551551#endif
552552 if (error ) {
553- PyErr_SetObject (InvalidDocument , error );
553+ PyErr_SetObject (DocumentTooLarge , error );
554554 Py_DECREF (error );
555555 }
556- Py_DECREF (InvalidDocument );
556+ Py_DECREF (DocumentTooLarge );
557557 }
558558}
559559
560+ static PyObject *
561+ _send_insert (PyObject * self , PyObject * client ,
562+ PyObject * gle_args , buffer_t buffer ,
563+ char * coll_name , int coll_len , int request_id , int safe ) {
564+
565+ PyObject * result ;
566+ if (safe ) {
567+ if (!add_last_error (self , buffer , request_id ,
568+ coll_name , coll_len , gle_args )) {
569+ return NULL ;
570+ }
571+ }
572+
573+ result = Py_BuildValue ("i" BYTES_FORMAT_STRING , request_id ,
574+ buffer_get_buffer (buffer ),
575+ buffer_get_position (buffer ));
576+
577+ return PyObject_CallMethod (client , "_send_message" , "NN" ,
578+ result , PyBool_FromLong ((long )safe ));
579+ }
580+
560581static PyObject * _cbson_do_batched_insert (PyObject * self , PyObject * args ) {
561582 struct module_state * state = GETSTATE (self );
562583
563584 /* NOTE just using a random number as the request_id */
564585 int request_id = rand ();
565- int options = 0 ;
586+ int send_safe , options = 0 ;
566587 int length_location , message_length ;
567588 int collection_name_length ;
568589 char * collection_name = NULL ;
@@ -574,7 +595,6 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
574595 PyObject * result ;
575596 PyObject * max_bson_size_obj ;
576597 PyObject * max_message_size_obj ;
577- PyObject * send_message_result ;
578598 unsigned char check_keys ;
579599 unsigned char safe ;
580600 unsigned char continue_on_error ;
@@ -598,6 +618,11 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
598618 if (continue_on_error ) {
599619 options += 1 ;
600620 }
621+ /*
622+ * If we are doing unacknowledged writes *and* continue_on_error
623+ * is True it's pointless (and slower) to send GLE.
624+ */
625+ send_safe = (safe || !continue_on_error );
601626
602627 max_bson_size_obj = PyObject_GetAttrString (client , "max_bson_size" );
603628#if PY_MAJOR_VERSION >= 3
@@ -651,7 +676,6 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
651676 while ((doc = PyIter_Next (iterator )) != NULL ) {
652677 int before = buffer_get_position (buffer );
653678 int cur_size ;
654- empty = 0 ;
655679 if (!write_dict (state -> _cbson , buffer , doc , check_keys , uuid_subtype , 1 )) {
656680 Py_DECREF (doc );
657681 goto iterfail ;
@@ -660,15 +684,28 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
660684
661685 cur_size = buffer_get_position (buffer ) - before ;
662686 if (cur_size > max_bson_size ) {
687+ /* If we've encoded anything send it before raising. */
688+ if (!empty ) {
689+ buffer_update_position (buffer , before );
690+ message_length = buffer_get_position (buffer ) - length_location ;
691+ memcpy (buffer_get_buffer (buffer ) + length_location ,
692+ & message_length , 4 );
693+ result = _send_insert (self , client , last_error_args , buffer ,
694+ collection_name , collection_name_length ,
695+ request_id , send_safe );
696+ if (!result )
697+ goto iterfail ;
698+ Py_DECREF (result );
699+ }
663700 _set_document_too_large (cur_size , max_bson_size );
664701 goto iterfail ;
665702 }
703+ empty = 0 ;
666704
667705 /* We have enough data, send this batch. */
668706 if (buffer_get_position (buffer ) > max_message_size ) {
669707 int new_request_id = rand ();
670708 int message_start ;
671- PyObject * send_gle = Py_False ;
672709 buffer_t new_buffer = buffer_new ();
673710 if (!new_buffer ) {
674711 PyErr_NoMemory ();
@@ -696,29 +733,16 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
696733 message_length = buffer_get_position (buffer ) - length_location ;
697734 memcpy (buffer_get_buffer (buffer ) + length_location , & message_length , 4 );
698735
699- /* If we are doing unacknowledged writes *and* continue_on_error
700- * is True it's pointless (and slower) to send GLE. */
701- if (safe || !continue_on_error ) {
702- send_gle = Py_True ;
703- if (!add_last_error (self , buffer , request_id , collection_name ,
704- collection_name_length , last_error_args )) {
705- buffer_free (new_buffer );
706- goto iterfail ;
707- }
708- }
709- /* Objectify buffer */
710- result = Py_BuildValue ("i" BYTES_FORMAT_STRING , request_id ,
711- buffer_get_buffer (buffer ),
712- buffer_get_position (buffer ));
736+ result = _send_insert (self , client , last_error_args , buffer ,
737+ collection_name , collection_name_length ,
738+ request_id , send_safe );
739+
713740 buffer_free (buffer );
714741 buffer = new_buffer ;
715742 request_id = new_request_id ;
716743 length_location = message_start ;
717744
718- send_message_result = PyObject_CallMethod (client , "_send_message" ,
719- "NO" , result , send_gle );
720-
721- if (!send_message_result ) {
745+ if (!result ) {
722746 PyObject * etype = NULL , * evalue = NULL , * etrace = NULL ;
723747 PyObject * OperationFailure ;
724748 PyErr_Fetch (& etype , & evalue , & etrace );
@@ -757,7 +781,7 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
757781 PyErr_Restore (etype , evalue , etrace );
758782 goto iterfail ;
759783 } else {
760- Py_DECREF (send_message_result );
784+ Py_DECREF (result );
761785 }
762786 }
763787 }
@@ -779,33 +803,21 @@ static PyObject* _cbson_do_batched_insert(PyObject* self, PyObject* args) {
779803 message_length = buffer_get_position (buffer ) - length_location ;
780804 memcpy (buffer_get_buffer (buffer ) + length_location , & message_length , 4 );
781805
782- if (safe ) {
783- if (!add_last_error (self , buffer , request_id , collection_name ,
784- collection_name_length , last_error_args )) {
785- goto insertfail ;
786- }
787- }
806+ /* Send the last (or only) batch */
807+ result = _send_insert (self , client , last_error_args , buffer ,
808+ collection_name , collection_name_length ,
809+ request_id , safe );
788810
789811 PyMem_Free (collection_name );
790-
791- /* objectify buffer */
792- result = Py_BuildValue ("i" BYTES_FORMAT_STRING , request_id ,
793- buffer_get_buffer (buffer ),
794- buffer_get_position (buffer ));
795812 buffer_free (buffer );
796813
797- /* Send the last (or only) batch */
798- send_message_result = PyObject_CallMethod (client , "_send_message" , "NN" ,
799- result ,
800- PyBool_FromLong ((long )safe ));
801-
802- if (!send_message_result ) {
814+ if (!result ) {
803815 Py_XDECREF (exc_type );
804816 Py_XDECREF (exc_value );
805817 Py_XDECREF (exc_trace );
806818 return NULL ;
807819 } else {
808- Py_DECREF (send_message_result );
820+ Py_DECREF (result );
809821 }
810822
811823 if (exc_type ) {
@@ -1050,15 +1062,15 @@ _cbson_do_batched_write_command(PyObject* self, PyObject* args) {
10501062 if (op == _INSERT ) {
10511063 _set_document_too_large (cur_size , max_bson_size );
10521064 } else {
1053- PyObject * InvalidDocument = _error ("InvalidDocument " );
1054- if (InvalidDocument ) {
1065+ PyObject * DocumentTooLarge = _error ("DocumentTooLarge " );
1066+ if (DocumentTooLarge ) {
10551067 /*
10561068 * There's nothing intelligent we can say
10571069 * about size for update and remove.
10581070 */
1059- PyErr_SetString (InvalidDocument ,
1071+ PyErr_SetString (DocumentTooLarge ,
10601072 "command document too large" );
1061- Py_DECREF (InvalidDocument );
1073+ Py_DECREF (DocumentTooLarge );
10621074 }
10631075 }
10641076 goto cmditerfail ;
0 commit comments