[libgdata] core: Make behaviour of response values more consistent



commit 0c5cb2bee46d0646cba336dc44feb28301bd5e6d
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sat Dec 18 21:56:04 2010 +0000

    core: Make behaviour of response values more consistent
    
    We now make more guarantees about the response values (response_status and
    response_error). Firstly, we guarantee that they won't be set until the
    network activity has finished. Secondly, we guarantee that they won't be
    returned by any GOutputStream methods other than g_output_stream_close().
    Thirdly, we guarantee that they are immutable once set.

 gdata/gdata-upload-stream.c |   32 ++++++++++++++++++--------------
 1 files changed, 18 insertions(+), 14 deletions(-)
---
diff --git a/gdata/gdata-upload-stream.c b/gdata/gdata-upload-stream.c
index a1c0dfe..ca67723 100644
--- a/gdata/gdata-upload-stream.c
+++ b/gdata/gdata-upload-stream.c
@@ -99,9 +99,9 @@ struct _GDataUploadStreamPrivate {
 	gsize network_bytes_written; /* the number of bytes which have been written to the network (signalled by write_cond) */
 	GCond *write_cond; /* signalled when a chunk has been written (protected by write_mutex) */
 
-	guint response_status; /* set once we finish receiving the response (0 otherwise) (protected by response_mutex) */
+	guint response_status; /* set once we finish receiving the response (SOUP_STATUS_NONE otherwise) (protected by response_mutex) */
 	GCond *finished_cond; /* signalled when sending the message (and receiving the response) is finished (protected by response_mutex) */
-	GError *response_error; /* error asynchronously set by the network thread, and picked up by the main thread when appropriate*/
+	GError *response_error; /* error asynchronously set by the network thread, and picked up by the main thread when appropriate */
 	GStaticMutex response_mutex; /* mutex for ->response_error, ->response_status and ->finished_cond */
 };
 
@@ -334,6 +334,7 @@ gdata_upload_stream_finalize (GObject *object)
 	g_cond_free (priv->write_cond);
 	g_static_mutex_free (&(priv->write_mutex));
 	gdata_buffer_free (priv->buffer);
+	g_clear_error (&(priv->response_error));
 	g_free (priv->upload_uri);
 	g_free (priv->method);
 	g_free (priv->slug);
@@ -518,11 +519,7 @@ write:
 	g_static_mutex_lock (&(priv->response_mutex));
 
 	/* Check for an error and return if necessary */
-	if (priv->response_error != NULL) {
-		g_propagate_error (error, priv->response_error);
-		priv->response_error = NULL;
-		length_written = -1;
-	} else if (cancelled == TRUE && length_written < 1) {
+	if (cancelled == TRUE && length_written < 1) {
 		g_assert (g_cancellable_set_error_if_cancelled (cancellable, error) == TRUE ||
 		          g_cancellable_set_error_if_cancelled (priv->cancellable, error) == TRUE);
 		length_written = -1;
@@ -659,7 +656,7 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr
 	g_static_mutex_lock (&(priv->response_mutex));
 
 	/* If an operation is still in progress, and no response has been received yetâ?¦ */
-	if (priv->response_status == 0) {
+	if (priv->response_status == SOUP_STATUS_NONE) {
 		/* Mark the buffer as having reached EOF, and the write operation will close in its own time */
 		gdata_buffer_push_data (priv->buffer, NULL, 0);
 
@@ -671,7 +668,7 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr
 	}
 
 	/* Error handling */
-	if (priv->response_status == 0 && cancelled == TRUE) {
+	if (priv->response_status == SOUP_STATUS_NONE && cancelled == TRUE) {
 		/* Cancelled? If response_status is non-zero, the network activity finished before the gdata_upload_stream_close() operation was
 		 * cancelled, so we don't need to return an error. */
 		g_assert (g_cancellable_set_error_if_cancelled (cancellable, &child_error) == TRUE ||
@@ -695,7 +692,7 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr
 		g_cancellable_disconnect (priv->cancellable, global_cancelled_signal);
 
 	g_assert ((success == TRUE && child_error == NULL) || (success == FALSE && child_error != NULL));
-	g_assert (priv->response_status != 0);
+	g_assert (priv->response_status != SOUP_STATUS_NONE && (SOUP_STATUS_IS_SUCCESSFUL (priv->response_status) || child_error != NULL));
 
 	if (child_error != NULL)
 		g_propagate_error (error, child_error);
@@ -750,7 +747,7 @@ write_next_chunk (GDataUploadStream *self, SoupMessage *message)
 	if (reached_eof == TRUE) {
 		/* We've reached the end of the stream, so append the footer (if appropriate) and stop */
 		g_static_mutex_lock (&(priv->response_mutex));
-		if (priv->entry != NULL && priv->response_error == NULL) {
+		if (priv->entry != NULL) {
 			const gchar *footer = "\n--" BOUNDARY_STRING "--";
 			gsize footer_length = strlen (footer);
 
@@ -823,6 +820,9 @@ upload_thread (GDataUploadStream *self)
 		g_cond_signal (priv->write_cond);
 	g_static_mutex_unlock (&(priv->write_mutex));
 
+	g_assert (priv->response_status == SOUP_STATUS_NONE);
+	g_assert (priv->response_error == NULL);
+
 	/* Deal with the response if it was unsuccessful */
 	if (SOUP_STATUS_IS_SUCCESSFUL (priv->message->status_code) == FALSE) {
 		GDataServiceClass *klass = GDATA_SERVICE_GET_CLASS (priv->service);
@@ -916,9 +916,13 @@ gdata_upload_stream_new (GDataService *service, const gchar *method, const gchar
  *
  * If there was an error during the upload operation (but it is complete), %NULL is returned, and @length is set to <code class="literal">0</code>.
  *
- * While it is safe to call this function from any thread at any time during the network operation, the only way to
- * guarantee that the response has been set before calling this function is to have closed the #GDataUploadStream. Once
- * the stream has been closed, all network communication is guaranteed to have finished.
+ * While it is safe to call this function from any thread at any time during the network operation, the only way to guarantee that the response has
+ * been set before calling this function is to have closed the #GDataUploadStream by calling gdata_output_stream_close() on it, without cancelling
+ * the close operation. Once the stream has been closed, all network communication is guaranteed to have finished. Note that if a call to
+ * g_output_stream_close() is cancelled, g_output_stream_is_closed() will immediately start to return %TRUE, even if the #GDataUploadStream is still
+ * attempting to flush the network buffers asynchronously â?? consequently, gdata_upload_stream_get_response() may still return %NULL and a @length of
+ * <code class="literal">-1</code>. The only reliable way to determine if the stream has been fully closed in this situation is to check the results
+ * of gdata_upload_stream_get_response(), rather than g_output_stream_is_closed().
  *
  * Return value: the server's response to the upload, or %NULL
  *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]