[virt-tools-list] [libosinfo 2/2] Async variant of osinfo_media_create_from_location()
Zeeshan Ali (Khattak)
zeeshanak at gnome.org
Tue Aug 23 20:47:43 UTC 2011
From: "Zeeshan Ali (Khattak)" <zeeshanak at gnome.org>
---
docs/reference/Libosinfo-sections.txt | 2 +
osinfo/libosinfo.syms | 2 +
osinfo/osinfo_media.c | 351 +++++++++++++++++++++++++-------
osinfo/osinfo_media.h | 7 +
4 files changed, 285 insertions(+), 77 deletions(-)
diff --git a/docs/reference/Libosinfo-sections.txt b/docs/reference/Libosinfo-sections.txt
index e2454da..68464e3 100644
--- a/docs/reference/Libosinfo-sections.txt
+++ b/docs/reference/Libosinfo-sections.txt
@@ -404,6 +404,8 @@ OsinfMediaoClass
OsinfMediaoPrivate
osinfo_media_new
osinfo_media_create_from_location
+osinfo_media_create_from_location_async
+osinfo_media_create_from_location_finish
osinfo_media_get_architecture
osinfo_media_get_url
osinfo_media_get_volume_id
diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms
index 6541a90..2be90ee 100644
--- a/osinfo/libosinfo.syms
+++ b/osinfo/libosinfo.syms
@@ -144,6 +144,8 @@ LIBOSINFO_0.0.1 {
osinfo_media_error_quark;
osinfo_media_new;
osinfo_media_create_from_location;
+ osinfo_media_create_from_location_async;
+ osinfo_media_create_from_location_finish;
osinfo_media_get_architecture;
osinfo_media_get_url;
osinfo_media_get_volume_id;
diff --git a/osinfo/osinfo_media.c b/osinfo/osinfo_media.c
index 431ae72..6adf623 100644
--- a/osinfo/osinfo_media.c
+++ b/osinfo/osinfo_media.c
@@ -53,6 +53,44 @@ struct _SupplementaryVolumeDescriptor {
gchar system[MAX_SYSTEM]; /* System ID */
};
+typedef struct _CreateFromLocationAsyncData CreateFromLocationAsyncData;
+struct _CreateFromLocationAsyncData {
+ GFile *file;
+
+ gint priority;
+ GCancellable *cancellable;
+
+ GSimpleAsyncResult *res;
+
+ PrimaryVolumeDescriptor pvd;
+ SupplementaryVolumeDescriptor svd;
+};
+
+static void create_from_location_async_data_free
+ (CreateFromLocationAsyncData *data)
+{
+ g_object_unref(data->file);
+ g_clear_object(&data->cancellable);
+ g_object_unref(data->res);
+
+ g_slice_free(CreateFromLocationAsyncData, data);
+}
+
+typedef struct _CreateFromLocationData CreateFromLocationData;
+struct _CreateFromLocationData {
+ GMainLoop *main_loop;
+
+ GAsyncResult *res;
+};
+
+static void create_from_location_data_free(CreateFromLocationData *data)
+{
+ g_object_unref(data->res);
+ g_main_loop_unref(data->main_loop);
+
+ g_slice_free(CreateFromLocationData, data);
+}
+
GQuark
osinfo_media_error_quark (void)
{
@@ -114,7 +152,7 @@ OsinfoMedia *osinfo_media_new(const gchar *id,
const gchar *architecture)
{
OsinfoMedia *media;
-
+
media = g_object_new(OSINFO_TYPE_MEDIA,
"id", id,
NULL);
@@ -126,6 +164,17 @@ OsinfoMedia *osinfo_media_new(const gchar *id,
return media;
}
+static void on_media_create_from_location_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CreateFromLocationData *data = (CreateFromLocationData *)user_data;
+
+ data->res = g_object_ref(res);
+
+ g_main_loop_quit(data->main_loop);
+}
+
/**
* osinfo_media_create_from_location:
* @location: the location of an installation media
@@ -143,91 +192,61 @@ OsinfoMedia *osinfo_media_create_from_location(const gchar *location,
GCancellable *cancellable,
GError **error)
{
- OsinfoMedia *ret = NULL;
- PrimaryVolumeDescriptor pvd;
- SupplementaryVolumeDescriptor svd;
- GFile *file;
- GFileInputStream *stream;
- gchar *uri;
+ CreateFromLocationData *data;
+ OsinfoMedia *ret;
- g_return_val_if_fail(location != NULL, NULL);
- g_return_val_if_fail(error == NULL || *error == NULL, NULL);
-
- file = g_file_new_for_commandline_arg(location);
- stream = g_file_read(file, cancellable, error);
- if (error != NULL && *error != NULL) {
- g_prefix_error(error, "Failed to open file");
+ data = g_slice_new0(CreateFromLocationData);
+ data->main_loop = g_main_loop_new (g_main_context_get_thread_default (),
+ TRUE);
- goto EXIT;
- }
+ osinfo_media_create_from_location_async(location,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ on_media_create_from_location_ready,
+ data);
- memset(&pvd, 0, sizeof(pvd));
- if (g_input_stream_skip(G_INPUT_STREAM(stream),
- PVD_OFFSET,
- cancellable,
- error) < sizeof(pvd)) {
- if (*error)
- g_prefix_error(error, "Failed to skip %d bytes", PVD_OFFSET);
- else
- g_set_error(error,
- OSINFO_MEDIA_ERROR,
- OSINFO_MEDIA_ERROR_NO_DESCRIPTORS,
- "No volume descriptors");
-
- goto EXIT;
- }
-
- if (g_input_stream_read(G_INPUT_STREAM(stream),
- &pvd,
- sizeof(pvd),
- cancellable,
- error) < sizeof(pvd)) {
- if (*error)
- g_prefix_error(error, "Failed to read primary volume descriptor");
- else
- g_set_error(error,
- OSINFO_MEDIA_ERROR,
- OSINFO_MEDIA_ERROR_NO_PVD,
- "Primary volume descriptor unavailable");
+ /* Loop till we get a reply (or time out) */
+ if (g_main_loop_is_running (data->main_loop))
+ g_main_loop_run (data->main_loop);
- goto EXIT;
- }
+ ret = osinfo_media_create_from_location_finish(data->res, error);
+ create_from_location_data_free(data);
- pvd.volume[MAX_VOLUME - 1] = 0;
- pvd.system[MAX_SYSTEM - 1] = 0;
- pvd.publisher[MAX_PUBLISHER - 1] = 0;
+ return ret;
+}
- if (pvd.volume[0] && (pvd.system[0] == 0 && pvd.publisher[0] == 0)) {
- g_set_error(error,
- OSINFO_MEDIA_ERROR,
- OSINFO_MEDIA_ERROR_INSUFFIENT_METADATA,
- "Insufficient metadata on installation media");
+static void on_svd_read (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ OsinfoMedia *ret = NULL;
+ GInputStream *stream = G_INPUT_STREAM(source);
+ gchar *uri;
+ GError *error = NULL;
+ CreateFromLocationAsyncData *data;
- goto EXIT;
- }
+ data = (CreateFromLocationAsyncData *)user_data;
- memset(&svd, 0, sizeof(svd));
- if (g_input_stream_read(G_INPUT_STREAM(stream),
- &svd,
- sizeof(svd),
- cancellable,
- error) < sizeof(svd)) {
- if (*error)
- g_prefix_error(error,
+ if (g_input_stream_read_finish(stream,
+ res,
+ &error) < sizeof(data->svd)) {
+ if (error)
+ g_prefix_error(&error,
"Failed to read supplementary volume descriptor");
else
- g_set_error(error,
+ g_set_error(&error,
OSINFO_MEDIA_ERROR,
OSINFO_MEDIA_ERROR_NO_SVD,
"Supplementary volume descriptor unavailable");
+
goto EXIT;
}
- svd.system[MAX_SYSTEM - 1] = 0;
+ data->svd.system[MAX_SYSTEM - 1] = 0;
- if (strncmp(BOOTABLE_TAG, svd.system, sizeof(BOOTABLE_TAG) != 0)) {
- g_set_error(error,
+ if (strncmp(BOOTABLE_TAG, data->svd.system, sizeof(BOOTABLE_TAG) != 0)) {
+ g_set_error(&error,
OSINFO_MEDIA_ERROR,
OSINFO_MEDIA_ERROR_NOT_BOOTABLE,
"Install media is not bootable");
@@ -235,7 +254,7 @@ OsinfoMedia *osinfo_media_create_from_location(const gchar *location,
goto EXIT;
}
- uri = g_file_get_uri(file);
+ uri = g_file_get_uri(data->file);
ret = g_object_new(OSINFO_TYPE_MEDIA,
"id", uri,
NULL);
@@ -243,24 +262,202 @@ OsinfoMedia *osinfo_media_create_from_location(const gchar *location,
OSINFO_MEDIA_PROP_URL,
uri);
g_free(uri);
- if (pvd.volume[0] != 0)
+ if (data->pvd.volume[0] != 0)
osinfo_entity_set_param(OSINFO_ENTITY(ret),
OSINFO_MEDIA_PROP_VOLUME_ID,
- pvd.volume);
- if (pvd.system[0] != 0)
+ data->pvd.volume);
+ if (data->pvd.system[0] != 0)
osinfo_entity_set_param(OSINFO_ENTITY(ret),
OSINFO_MEDIA_PROP_SYSTEM_ID,
- pvd.system);
- if (pvd.publisher[0] != 0)
+ data->pvd.system);
+ if (data->pvd.publisher[0] != 0)
osinfo_entity_set_param(OSINFO_ENTITY(ret),
OSINFO_MEDIA_PROP_PUBLISHER_ID,
- pvd.publisher);
+ data->pvd.publisher);
EXIT:
+ if (error != NULL)
+ g_simple_async_result_take_error(data->res, error);
+ else
+ g_simple_async_result_set_op_res_gpointer(data->res, ret, NULL);
+ g_simple_async_result_complete (data->res);
+
g_object_unref(stream);
- g_object_unref(file);
+ create_from_location_async_data_free(data);
+}
- return ret;
+static void on_pvd_read (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM(source);
+ CreateFromLocationAsyncData *data;
+ GError *error = NULL;
+
+ data = (CreateFromLocationAsyncData *)user_data;
+
+ if (g_input_stream_read_finish(stream,
+ res,
+ &error) < sizeof(data->pvd)) {
+ if (error)
+ g_prefix_error(&error, "Failed to read primary volume descriptor");
+ else
+ g_set_error(&error,
+ OSINFO_MEDIA_ERROR,
+ OSINFO_MEDIA_ERROR_NO_PVD,
+ "Primary volume descriptor unavailable");
+
+ goto ON_ERROR;
+ }
+
+ data->pvd.volume[MAX_VOLUME - 1] = 0;
+ data->pvd.system[MAX_SYSTEM - 1] = 0;
+ data->pvd.publisher[MAX_PUBLISHER - 1] = 0;
+
+ if (data->pvd.volume[0] &&
+ (data->pvd.system[0] == 0 && data->pvd.publisher[0] == 0)) {
+ g_set_error(&error,
+ OSINFO_MEDIA_ERROR,
+ OSINFO_MEDIA_ERROR_INSUFFIENT_METADATA,
+ "Insufficient metadata on installation media");
+
+ goto ON_ERROR;
+ }
+
+ g_input_stream_read_async(stream,
+ &data->svd,
+ sizeof(data->svd),
+ data->priority,
+ data->cancellable,
+ on_svd_read,
+ data);
+ return;
+
+ON_ERROR:
+ g_simple_async_result_take_error(data->res, error);
+ g_simple_async_result_complete (data->res);
+ create_from_location_async_data_free(data);
+}
+
+static void on_location_skipped(GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM(source);
+ CreateFromLocationAsyncData *data;
+ GError *error = NULL;
+
+ data = (CreateFromLocationAsyncData *)user_data;
+
+ if (g_input_stream_skip_finish(stream, res, &error) < PVD_OFFSET) {
+ if (error)
+ g_prefix_error(&error, "Failed to skip %d bytes", PVD_OFFSET);
+ else
+ g_set_error(&error,
+ OSINFO_MEDIA_ERROR,
+ OSINFO_MEDIA_ERROR_NO_DESCRIPTORS,
+ "No volume descriptors");
+ g_simple_async_result_take_error(data->res, error);
+ g_simple_async_result_complete (data->res);
+ create_from_location_async_data_free(data);
+
+ return;
+ }
+
+ g_input_stream_read_async(stream,
+ &data->pvd,
+ sizeof(data->pvd),
+ data->priority,
+ data->cancellable,
+ on_pvd_read,
+ data);
+}
+
+static void on_location_read(GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GFileInputStream *stream;
+ CreateFromLocationAsyncData *data;
+ GError *error = NULL;
+
+ data = (CreateFromLocationAsyncData *)user_data;
+
+ stream = g_file_read_finish(G_FILE(source), res, &error);
+ if (error != NULL) {
+ g_prefix_error(&error, "Failed to open file");
+ g_simple_async_result_take_error(data->res, error);
+ g_simple_async_result_complete (data->res);
+ create_from_location_async_data_free(data);
+
+ return;
+ }
+
+ g_input_stream_skip_async(G_INPUT_STREAM(stream),
+ PVD_OFFSET,
+ data->priority,
+ data->cancellable,
+ on_location_skipped,
+ data);
+}
+
+/**
+ * osinfo_media_create_from_location_async:
+ * @location: the location of an installation media
+ * @priority: the I/O priority of the request
+ * @cancellable (allow-none): a #GCancellable, or %NULL
+ * @callback: Function to call when result of this call is ready
+ * @user_data: The user data to pass to @callback, or %NULL
+ *
+ * Asynchronous variant of #osinfo_media_create_from_location.
+ */
+void osinfo_media_create_from_location_async(const gchar *location,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CreateFromLocationAsyncData *data;
+
+ g_return_if_fail(location != NULL);
+
+ data = g_slice_new0(CreateFromLocationAsyncData);
+ data->res = g_simple_async_result_new
+ (NULL,
+ callback,
+ user_data,
+ osinfo_media_create_from_location_async);
+ data->file = g_file_new_for_commandline_arg(location);
+ data->priority = priority;
+ data->cancellable = cancellable;
+ g_file_read_async(data->file,
+ priority,
+ cancellable,
+ on_location_read,
+ data);
+}
+
+/**
+ * osinfo_media_create_from_location_finish:
+ * @res: a #GAsyncResult
+ * @error: The location where to store any error, or %NULL
+ *
+ * Finishes an asynchronous media object creation process started with
+ * #osinfo_media_create_from_location_async.
+ *
+ * Returns: (transfer full): a new #OsinfoMedia , or NULL on error
+ */
+OsinfoMedia *osinfo_media_create_from_location_finish(GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
+
+ g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+
+ if (g_simple_async_result_propagate_error(simple, error))
+ return NULL;
+
+ return g_simple_async_result_get_op_res_gpointer(simple);
}
/**
diff --git a/osinfo/osinfo_media.h b/osinfo/osinfo_media.h
index 89eb1f6..9ecf0b1 100644
--- a/osinfo/osinfo_media.h
+++ b/osinfo/osinfo_media.h
@@ -101,6 +101,13 @@ OsinfoMedia *osinfo_media_new(const gchar *id, const gchar *architecture);
OsinfoMedia *osinfo_media_create_from_location(const gchar *location,
GCancellable *cancellable,
GError **error);
+void osinfo_media_create_from_location_async(const gchar *location,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OsinfoMedia *osinfo_media_create_from_location_finish(GAsyncResult *res,
+ GError **error);
const gchar *osinfo_media_get_architecture(OsinfoMedia *media);
const gchar *osinfo_media_get_url(OsinfoMedia *media);
--
1.7.6
More information about the virt-tools-list
mailing list