[ostree] libostree: Change synchronous fetching API to return a stream
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] libostree: Change synchronous fetching API to return a stream
- Date: Mon, 2 Sep 2013 18:53:22 +0000 (UTC)
commit 597da6ca6bdddd0c50aa31f1faf8749ebcae144c
Author: Colin Walters <walters verbum org>
Date: Sat Aug 31 11:22:55 2013 -0400
libostree: Change synchronous fetching API to return a stream
There's not a good reason to write small things such as repo/config to
the filesystem, only to read them back in again. Change the
non-partial API to just return a stream, then read it into a memory
buffer.
https://bugzilla.gnome.org/show_bug.cgi?id=707157
src/libostree/ostree-fetcher.c | 81 ++++++++++++++++++++------------------
src/libostree/ostree-fetcher.h | 8 ++--
src/libostree/ostree-repo-pull.c | 31 ++++++++++----
3 files changed, 69 insertions(+), 51 deletions(-)
---
diff --git a/src/libostree/ostree-fetcher.c b/src/libostree/ostree-fetcher.c
index 697ea8e..519345f 100644
--- a/src/libostree/ostree-fetcher.c
+++ b/src/libostree/ostree-fetcher.c
@@ -42,9 +42,9 @@ typedef struct {
SoupRequest *request;
- gboolean is_partial;
- GFile *tmpfile;
+ gboolean is_stream;
GInputStream *request_body;
+ GFile *out_tmpfile;
GOutputStream *out_stream;
guint64 content_length;
@@ -63,7 +63,7 @@ pending_uri_free (OstreeFetcherPendingURI *pending)
soup_uri_free (pending->uri);
g_clear_object (&pending->self);
- g_clear_object (&pending->tmpfile);
+ g_clear_object (&pending->out_tmpfile);
g_clear_object (&pending->request);
g_clear_object (&pending->request_body);
g_clear_object (&pending->out_stream);
@@ -179,7 +179,7 @@ on_splice_complete (GObject *object,
GError *local_error = NULL;
pending->state = OSTREE_FETCHER_STATE_COMPLETE;
- file_info = g_file_query_info (pending->tmpfile, OSTREE_GIO_FAST_QUERYINFO,
+ file_info = g_file_query_info (pending->out_tmpfile, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
pending->cancellable, &local_error);
if (!file_info)
@@ -256,18 +256,20 @@ on_request_sent (GObject *object,
pending->content_length = soup_request_get_content_length (pending->request);
- if (pending->is_partial)
- pending->out_stream = G_OUTPUT_STREAM (g_file_append_to (pending->tmpfile, G_FILE_CREATE_NONE,
- pending->cancellable, &local_error));
+ if (!pending->is_stream)
+ {
+ pending->out_stream = G_OUTPUT_STREAM (g_file_append_to (pending->out_tmpfile, G_FILE_CREATE_NONE,
+ pending->cancellable, &local_error));
+ if (!pending->out_stream)
+ goto out;
+ g_output_stream_splice_async (pending->out_stream, pending->request_body, flags, G_PRIORITY_DEFAULT,
+ pending->cancellable, on_splice_complete, pending);
+ }
else
- pending->out_stream = G_OUTPUT_STREAM (g_file_replace (pending->tmpfile, NULL, FALSE,
- G_FILE_CREATE_REPLACE_DESTINATION,
- pending->cancellable, &local_error));
- if (!pending->out_stream)
- goto out;
+ {
+ g_simple_async_result_complete (pending->result);
+ }
- g_output_stream_splice_async (pending->out_stream, pending->request_body, flags, G_PRIORITY_DEFAULT,
- pending->cancellable, on_splice_complete, pending);
out:
if (local_error)
{
@@ -279,7 +281,7 @@ on_request_sent (GObject *object,
static OstreeFetcherPendingURI *
ostree_fetcher_request_uri_internal (OstreeFetcher *self,
SoupURI *uri,
- gboolean is_partial,
+ gboolean is_stream,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
@@ -287,15 +289,18 @@ ostree_fetcher_request_uri_internal (OstreeFetcher *self,
{
OstreeFetcherPendingURI *pending;
GError *local_error = NULL;
- gs_free char *uristring = soup_uri_to_string (uri, FALSE);
- gs_free char *hash = g_compute_checksum_for_string (G_CHECKSUM_SHA256, uristring, strlen (uristring));
pending = g_new0 (OstreeFetcherPendingURI, 1);
pending->refcount = 1;
pending->self = g_object_ref (self);
pending->uri = soup_uri_copy (uri);
- pending->is_partial = is_partial;
- pending->tmpfile = g_file_get_child (self->tmpdir, hash);
+ pending->is_stream = is_stream;
+ if (!is_stream)
+ {
+ gs_free char *uristring = soup_uri_to_string (uri, FALSE);
+ gs_free char *hash = g_compute_checksum_for_string (G_CHECKSUM_SHA256, uristring, strlen (uristring));
+ pending->out_tmpfile = g_file_get_child (self->tmpdir, hash);
+ }
pending->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
pending->request = soup_requester_request_uri (self->requester, uri, &local_error);
pending->result = g_simple_async_result_new ((GObject*) self,
@@ -326,11 +331,11 @@ ostree_fetcher_request_uri_with_partial_async (OstreeFetcher *self,
self->total_requests++;
- pending = ostree_fetcher_request_uri_internal (self, uri, TRUE, cancellable,
+ pending = ostree_fetcher_request_uri_internal (self, uri, FALSE, cancellable,
callback, user_data,
ostree_fetcher_request_uri_with_partial_async);
- if (!ot_gfile_query_info_allow_noent (pending->tmpfile, OSTREE_GIO_FAST_QUERYINFO,
+ if (!ot_gfile_query_info_allow_noent (pending->out_tmpfile, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
&file_info, cancellable, &local_error))
goto out;
@@ -373,23 +378,23 @@ ostree_fetcher_request_uri_with_partial_finish (OstreeFetcher *self,
return NULL;
pending = g_simple_async_result_get_op_res_gpointer (simple);
- return g_object_ref (pending->tmpfile);
+ return g_object_ref (pending->out_tmpfile);
}
void
-ostree_fetcher_request_uri_async (OstreeFetcher *self,
- SoupURI *uri,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+ostree_fetcher_stream_uri_async (OstreeFetcher *self,
+ SoupURI *uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
OstreeFetcherPendingURI *pending;
self->total_requests++;
- pending = ostree_fetcher_request_uri_internal (self, uri, FALSE, cancellable,
+ pending = ostree_fetcher_request_uri_internal (self, uri, TRUE, cancellable,
callback, user_data,
- ostree_fetcher_request_uri_async);
+ ostree_fetcher_stream_uri_async);
if (SOUP_IS_REQUEST_HTTP (pending->request))
{
@@ -402,22 +407,22 @@ ostree_fetcher_request_uri_async (OstreeFetcher *self,
on_request_sent, pending);
}
-GFile *
-ostree_fetcher_request_uri_finish (OstreeFetcher *self,
- GAsyncResult *result,
- GError **error)
+GInputStream *
+ostree_fetcher_stream_uri_finish (OstreeFetcher *self,
+ GAsyncResult *result,
+ GError **error)
{
GSimpleAsyncResult *simple;
OstreeFetcherPendingURI *pending;
- g_return_val_if_fail (g_simple_async_result_is_valid (result, (GObject*)self,
ostree_fetcher_request_uri_async), FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, (GObject*)self,
ostree_fetcher_stream_uri_async), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
pending = g_simple_async_result_get_op_res_gpointer (simple);
- return g_object_ref (pending->tmpfile);
+ return g_object_ref (pending->request_body);
}
static char *
@@ -457,17 +462,17 @@ ostree_fetcher_query_state_text (OstreeFetcher *self)
active = g_hash_table_lookup (self->message_to_request, key);
g_assert (active != NULL);
- if (active->tmpfile)
+ if (active->out_tmpfile)
{
gs_unref_object GFileInfo *file_info = NULL;
- file_info = g_file_query_info (active->tmpfile, OSTREE_GIO_FAST_QUERYINFO,
+ file_info = g_file_query_info (active->out_tmpfile, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, NULL);
if (file_info)
{
gs_free char *size = format_size_pair (g_file_info_get_size (file_info),
- active->content_length);
+ active->content_length);
g_string_append_printf (buf, " [%s]", size);
}
}
diff --git a/src/libostree/ostree-fetcher.h b/src/libostree/ostree-fetcher.h
index c0b85b6..220bd93 100644
--- a/src/libostree/ostree-fetcher.h
+++ b/src/libostree/ostree-fetcher.h
@@ -70,15 +70,15 @@ GFile *ostree_fetcher_request_uri_with_partial_finish (OstreeFetcher *self,
GAsyncResult *result,
GError **error);
-void ostree_fetcher_request_uri_async (OstreeFetcher *self,
+void ostree_fetcher_stream_uri_async (OstreeFetcher *self,
SoupURI *uri,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-GFile *ostree_fetcher_request_uri_finish (OstreeFetcher *self,
- GAsyncResult *result,
- GError **error);
+GInputStream *ostree_fetcher_stream_uri_finish (OstreeFetcher *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index da6a5a1..65ddca2 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -328,7 +328,7 @@ run_mainloop_monitor_fetcher (OtPullData *pull_data)
typedef struct {
OtPullData *pull_data;
- GFile *result_file;
+ GInputStream *result_stream;
} OstreeFetchUriSyncData;
static void
@@ -338,8 +338,8 @@ fetch_uri_sync_on_complete (GObject *object,
{
OstreeFetchUriSyncData *data = user_data;
- data->result_file = ostree_fetcher_request_uri_finish ((OstreeFetcher*)object,
- result, data->pull_data->async_error);
+ data->result_stream = ostree_fetcher_stream_uri_finish ((OstreeFetcher*)object,
+ result, data->pull_data->async_error);
data->pull_data->fetching_sync_uri = NULL;
g_main_loop_quit (data->pull_data->loop);
}
@@ -352,8 +352,9 @@ fetch_uri_contents_utf8_sync (OtPullData *pull_data,
GError **error)
{
gboolean ret = FALSE;
- gsize len;
+ const guint8 nulchar = 0;
gs_free char *ret_contents = NULL;
+ gs_unref_object GMemoryOutputStream *buf = NULL;
OstreeFetchUriSyncData fetch_data = { 0, };
if (g_cancellable_set_error_if_cancelled (cancellable, error))
@@ -362,16 +363,28 @@ fetch_uri_contents_utf8_sync (OtPullData *pull_data,
fetch_data.pull_data = pull_data;
pull_data->fetching_sync_uri = uri;
- ostree_fetcher_request_uri_async (pull_data->fetcher, uri, cancellable,
- fetch_uri_sync_on_complete, &fetch_data);
+ ostree_fetcher_stream_uri_async (pull_data->fetcher, uri, cancellable,
+ fetch_uri_sync_on_complete, &fetch_data);
run_mainloop_monitor_fetcher (pull_data);
- if (!fetch_data.result_file)
+ if (!fetch_data.result_stream)
goto out;
- if (!g_file_load_contents (fetch_data.result_file, cancellable, &ret_contents, &len, NULL, error))
+ buf = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
+ if (g_output_stream_splice ((GOutputStream*)buf, fetch_data.result_stream,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
+ cancellable, error) < 0)
goto out;
+ /* Add trailing NUL */
+ if (!g_output_stream_write ((GOutputStream*)buf, &nulchar, 1, cancellable, error))
+ goto out;
+
+ if (!g_output_stream_close ((GOutputStream*)buf, cancellable, error))
+ goto out;
+
+ ret_contents = g_memory_output_stream_steal_data (buf);
+
if (!g_utf8_validate (ret_contents, -1, NULL))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -382,7 +395,7 @@ fetch_uri_contents_utf8_sync (OtPullData *pull_data,
ret = TRUE;
ot_transfer_out_value (out_contents, &ret_contents);
out:
- g_clear_object (&(fetch_data.result_file));
+ g_clear_object (&(fetch_data.result_stream));
return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]