[libgdata] core: Add a “cancellable” property to GDataUploadStream
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] core: Add a “cancellable” property to GDataUploadStream
- Date: Mon, 20 Dec 2010 13:48:38 +0000 (UTC)
commit 2338e007e768770627158f5298cc44bd6de80ed8
Author: Philip Withnall <philip tecnocode co uk>
Date: Fri Dec 17 23:13:53 2010 +0000
core: Add a â??cancellableâ?? property to GDataUploadStream
Allow the code which creates the GDataUploadStream to specify a GCancellable
which will cancel the entire upload operation (i.e. permanently cancel all
I/O on the stream and all network activity).
This breaks the following API:
â?¢ gdata_upload_stream_new()
The following API has been added:
â?¢ GDataUploadStream:cancellable
â?¢ gdata_upload_stream_get_cancellable()
Helps: bgo#637036
docs/reference/gdata-sections.txt | 1 +
gdata/gdata-upload-stream.c | 79 ++++++++++++++++----
gdata/gdata-upload-stream.h | 3 +-
gdata/gdata.symbols | 1 +
gdata/services/documents/gdata-documents-service.c | 3 +-
gdata/services/picasaweb/gdata-picasaweb-service.c | 2 +-
gdata/services/youtube/gdata-youtube-service.c | 2 +-
7 files changed, 72 insertions(+), 19 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 34d0235..43ffdc3 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -1776,6 +1776,7 @@ GDataUploadStreamClass
gdata_upload_stream_new
gdata_upload_stream_get_response
gdata_upload_stream_get_service
+gdata_upload_stream_get_cancellable
gdata_upload_stream_get_method
gdata_upload_stream_get_upload_uri
gdata_upload_stream_get_entry
diff --git a/gdata/gdata-upload-stream.c b/gdata/gdata-upload-stream.c
index f684aee..8ccc240 100644
--- a/gdata/gdata-upload-stream.c
+++ b/gdata/gdata-upload-stream.c
@@ -110,7 +110,8 @@ enum {
PROP_ENTRY,
PROP_SLUG,
PROP_CONTENT_TYPE,
- PROP_METHOD
+ PROP_METHOD,
+ PROP_CANCELLABLE
};
G_DEFINE_TYPE (GDataUploadStream, gdata_upload_stream, G_TYPE_OUTPUT_STREAM)
@@ -211,6 +212,27 @@ gdata_upload_stream_class_init (GDataUploadStreamClass *klass)
"Content type", "The content type of the file being uploaded.",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GDataUploadStream:cancellable:
+ *
+ * An optional cancellable used to cancel the entire upload operation. If a #GCancellable instance isn't provided for this property at
+ * construction time (i.e. to gdata_upload_stream_new()), one will be created internally and can be retrieved using
+ * gdata_upload_stream_get_cancellable() and used to cancel the upload operation with g_cancellable_cancel() just as if it was passed to
+ * gdata_upload_stream_new().
+ *
+ * If the upload operation is cancelled using this #GCancellable, any ongoing network activity will be stopped, and any pending or future calls
+ * to #GOutputStream API on the #GDataUploadStream will return %G_IO_ERROR_CANCELLED. Note that the #GCancellable objects which can be passed
+ * to individual #GOutputStream operations will not cancel the upload operation proper if cancelled â?? they will merely cancel that API call.
+ * The only way to cancel the upload operation completely is using #GDataUploadStream:cancellable.
+ *
+ * Since: 0.8.0
+ **/
+ g_object_class_install_property (gobject_class, PROP_CANCELLABLE,
+ g_param_spec_object ("cancellable",
+ "Cancellable", "An optional cancellable used to cancel the entire upload operation.",
+ G_TYPE_CANCELLABLE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
@@ -235,6 +257,10 @@ gdata_upload_stream_constructor (GType type, guint n_construct_params, GObjectCo
object = G_OBJECT_CLASS (gdata_upload_stream_parent_class)->constructor (type, n_construct_params, construct_params);
priv = GDATA_UPLOAD_STREAM (object)->priv;
+ /* Create a #GCancellable for the entire upload operation if one wasn't specified for #GDataUploadStream:cancellable during construction */
+ if (priv->cancellable == NULL)
+ priv->cancellable = g_cancellable_new ();
+
/* Build the message */
priv->message = soup_message_new (priv->method, priv->upload_uri);
@@ -339,6 +365,9 @@ gdata_upload_stream_get_property (GObject *object, guint property_id, GValue *va
case PROP_CONTENT_TYPE:
g_value_set_string (value, priv->content_type);
break;
+ case PROP_CANCELLABLE:
+ g_value_set_object (value, priv->cancellable);
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -371,6 +400,10 @@ gdata_upload_stream_set_property (GObject *object, guint property_id, const GVal
case PROP_CONTENT_TYPE:
priv->content_type = g_value_dup_string (value);
break;
+ case PROP_CANCELLABLE:
+ /* Construction only */
+ priv->cancellable = g_value_dup_object (value);
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -715,19 +748,9 @@ static void
create_network_thread (GDataUploadStream *self, GError **error)
{
GDataUploadStreamPrivate *priv = self->priv;
- GError *child_error = NULL;
- g_assert (priv->cancellable == NULL);
g_assert (priv->network_thread == NULL);
-
- priv->cancellable = g_cancellable_new ();
- priv->network_thread = g_thread_create ((GThreadFunc) upload_thread, self, TRUE, &child_error);
-
- if (child_error != NULL) {
- g_object_unref (priv->cancellable);
- priv->cancellable = NULL;
- g_propagate_error (error, child_error);
- }
+ priv->network_thread = g_thread_create ((GThreadFunc) upload_thread, self, TRUE, error);
}
/**
@@ -738,6 +761,7 @@ create_network_thread (GDataUploadStream *self, GError **error)
* @entry: (allow-none): the entry to upload as metadata, or %NULL
* @slug: the file's slug (filename)
* @content_type: the content type of the file being uploaded
+ * @cancellable: (allow-none): a #GCancellable for the entire upload stream, or %NULL
*
* Creates a new #GDataUploadStream, allowing a file to be uploaded from a GData service using standard #GOutputStream API.
*
@@ -754,15 +778,21 @@ create_network_thread (GDataUploadStream *self, GError **error)
* As well as the standard GIO errors, calls to the #GOutputStream API on a #GDataUploadStream can also return any relevant specific error from
* #GDataServiceError, or %GDATA_SERVICE_ERROR_PROTOCOL_ERROR in the general case.
*
+ * If a #GCancellable is provided in @cancellable, the upload operation may be cancelled at any time from another thread using g_cancellable_cancel().
+ * In this case, any ongoing network activity will be stopped, and any pending or future calls to #GOutputStream API on the #GDataUploadStream will
+ * return %G_IO_ERROR_CANCELLED. Note that the #GCancellable objects which can be passed to individual #GOutputStream operations will not cancel the
+ * upload operation proper if cancelled â?? they will merely cancel that API call. The only way to cancel the upload operation completely is using this
+ * @cancellable.
+ *
* Note that network communication won't begin until the first call to g_output_stream_write() on the #GDataUploadStream.
*
* Return value: a new #GOutputStream, or %NULL; unref with g_object_unref()
*
- * Since: 0.5.0
+ * Since: 0.8.0
**/
GOutputStream *
gdata_upload_stream_new (GDataService *service, const gchar *method, const gchar *upload_uri, GDataEntry *entry,
- const gchar *slug, const gchar *content_type)
+ const gchar *slug, const gchar *content_type, GCancellable *cancellable)
{
g_return_val_if_fail (GDATA_IS_SERVICE (service), NULL);
g_return_val_if_fail (method != NULL, NULL);
@@ -770,10 +800,11 @@ gdata_upload_stream_new (GDataService *service, const gchar *method, const gchar
g_return_val_if_fail (entry == NULL || GDATA_IS_ENTRY (entry), NULL);
g_return_val_if_fail (slug != NULL, NULL);
g_return_val_if_fail (content_type != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
/* Create the upload stream */
return G_OUTPUT_STREAM (g_object_new (GDATA_TYPE_UPLOAD_STREAM, "method", method, "upload-uri", upload_uri, "service", service,
- "entry", entry, "slug", slug, "content-type", content_type, NULL));
+ "entry", entry, "slug", slug, "content-type", content_type, "cancellable", cancellable, NULL));
}
/**
@@ -926,3 +957,21 @@ gdata_upload_stream_get_content_type (GDataUploadStream *self)
g_return_val_if_fail (GDATA_IS_UPLOAD_STREAM (self), NULL);
return self->priv->content_type;
}
+
+/**
+ * gdata_upload_stream_get_cancellable:
+ * @self: a #GDataUploadStream
+ *
+ * Gets the #GCancellable for the entire upload operation, #GDataUploadStream:cancellable.
+ *
+ * Return value: (transfer none): the #GCancellable for the entire upload operation
+ *
+ * Since: 0.8.0
+ **/
+GCancellable *
+gdata_upload_stream_get_cancellable (GDataUploadStream *self)
+{
+ g_return_val_if_fail (GDATA_IS_UPLOAD_STREAM (self), NULL);
+ g_assert (self->priv->cancellable != NULL);
+ return self->priv->cancellable;
+}
diff --git a/gdata/gdata-upload-stream.h b/gdata/gdata-upload-stream.h
index 9413ba5..133b6f4 100644
--- a/gdata/gdata-upload-stream.h
+++ b/gdata/gdata-upload-stream.h
@@ -65,7 +65,7 @@ typedef struct {
GType gdata_upload_stream_get_type (void) G_GNUC_CONST;
GOutputStream *gdata_upload_stream_new (GDataService *service, const gchar *method, const gchar *upload_uri, GDataEntry *entry,
- const gchar *slug, const gchar *content_type) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+ const gchar *slug, const gchar *content_type, GCancellable *cancellable) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
const gchar *gdata_upload_stream_get_response (GDataUploadStream *self, gssize *length);
@@ -75,6 +75,7 @@ const gchar *gdata_upload_stream_get_upload_uri (GDataUploadStream *self) G_GNUC
GDataEntry *gdata_upload_stream_get_entry (GDataUploadStream *self) G_GNUC_PURE;
const gchar *gdata_upload_stream_get_slug (GDataUploadStream *self) G_GNUC_PURE;
const gchar *gdata_upload_stream_get_content_type (GDataUploadStream *self) G_GNUC_PURE;
+GCancellable *gdata_upload_stream_get_cancellable (GDataUploadStream *self) G_GNUC_PURE;
G_END_DECLS
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 1d05b77..ec777a6 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -862,3 +862,4 @@ gdata_contacts_contact_set_photo_async
gdata_contacts_contact_set_photo_finish
gdata_youtube_video_get_coordinates
gdata_youtube_video_set_coordinates
+gdata_upload_stream_get_cancellable
diff --git a/gdata/services/documents/gdata-documents-service.c b/gdata/services/documents/gdata-documents-service.c
index 4ec5b01..0e3c260 100644
--- a/gdata/services/documents/gdata-documents-service.c
+++ b/gdata/services/documents/gdata-documents-service.c
@@ -302,7 +302,8 @@ upload_update_document (GDataDocumentsService *self, GDataDocumentsDocument *doc
content_type = "application/x-vnd.oasis.opendocument.spreadsheet";
/* We need streaming file I/O: GDataUploadStream */
- return GDATA_UPLOAD_STREAM (gdata_upload_stream_new (GDATA_SERVICE (self), method, upload_uri, GDATA_ENTRY (document), slug, content_type));
+ return GDATA_UPLOAD_STREAM (gdata_upload_stream_new (GDATA_SERVICE (self), method, upload_uri, GDATA_ENTRY (document), slug, content_type,
+ NULL));
}
/**
diff --git a/gdata/services/picasaweb/gdata-picasaweb-service.c b/gdata/services/picasaweb/gdata-picasaweb-service.c
index d656150..b19e384 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-service.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-service.c
@@ -499,7 +499,7 @@ gdata_picasaweb_service_upload_file (GDataPicasaWebService *self, GDataPicasaWeb
/* Build the upload URI and upload stream */
upload_uri = _gdata_service_build_uri (TRUE, "http://picasaweb.google.com/data/feed/api/user/%s/albumid/%s", user_id, album_id);
upload_stream = GDATA_UPLOAD_STREAM (gdata_upload_stream_new (GDATA_SERVICE (self), SOUP_METHOD_POST, upload_uri, GDATA_ENTRY (file_entry),
- slug, content_type));
+ slug, content_type, NULL));
g_free (upload_uri);
return upload_stream;
diff --git a/gdata/services/youtube/gdata-youtube-service.c b/gdata/services/youtube/gdata-youtube-service.c
index bd75b23..de5fa55 100644
--- a/gdata/services/youtube/gdata-youtube-service.c
+++ b/gdata/services/youtube/gdata-youtube-service.c
@@ -643,7 +643,7 @@ gdata_youtube_service_upload_video (GDataYouTubeService *self, GDataYouTubeVideo
/* Streaming upload support using GDataUploadStream; automatically handles the XML and multipart stuff for us */
return GDATA_UPLOAD_STREAM (gdata_upload_stream_new (GDATA_SERVICE (self), SOUP_METHOD_POST,
"http://uploads.gdata.youtube.com/feeds/api/users/default/uploads",
- GDATA_ENTRY (video), slug, content_type));
+ GDATA_ENTRY (video), slug, content_type, NULL));
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]