core: Add asynchronous checksum API, use it in checksum builtin

This commit is contained in:
Colin Walters 2011-11-27 17:21:04 -05:00
parent 8af4a62665
commit b0b0ffcd61
3 changed files with 122 additions and 10 deletions

View File

@ -320,6 +320,9 @@ ostree_checksum_file (GFile *f,
GFileInfo *file_info = NULL;
GChecksum *ret_checksum = NULL;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return NULL;
file_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error);
@ -345,6 +348,82 @@ ostree_checksum_file (GFile *f,
return ret;
}
typedef struct {
GFile *f;
OstreeObjectType objtype;
GChecksum *checksum;
} ChecksumFileAsyncData;
static void
checksum_file_async_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GError *error = NULL;
ChecksumFileAsyncData *data;
GChecksum *checksum = NULL;
data = g_simple_async_result_get_op_res_gpointer (res);
if (!ostree_checksum_file (data->f, data->objtype, &checksum, cancellable, &error))
g_simple_async_result_take_error (res, error);
else
data->checksum = checksum;
}
static void
checksum_file_async_data_free (gpointer datap)
{
ChecksumFileAsyncData *data = datap;
g_object_unref (data->f);
if (data->checksum)
g_checksum_free (data->checksum);
g_free (data);
}
void
ostree_checksum_file_async (GFile *f,
OstreeObjectType objtype,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
ChecksumFileAsyncData *data;
data = g_new0 (ChecksumFileAsyncData, 1);
data->f = g_object_ref (f);
data->objtype = objtype;
res = g_simple_async_result_new (G_OBJECT (f), callback, user_data, ostree_checksum_file_async);
g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)checksum_file_async_data_free);
g_simple_async_result_run_in_thread (res, checksum_file_async_thread, io_priority, cancellable);
g_object_unref (res);
}
gboolean
ostree_checksum_file_async_finish (GFile *f,
GAsyncResult *result,
GChecksum **out_checksum,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
ChecksumFileAsyncData *data;
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ostree_checksum_file_async);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
data = g_simple_async_result_get_op_res_gpointer (simple);
/* Transfer ownership */
*out_checksum = data->checksum;
data->checksum = NULL;
return TRUE;
}
gboolean
ostree_get_directory_metadata (GFile *dir,
GFileInfo *dir_info,
@ -912,6 +991,3 @@ ostree_unpack_object (GFile *file,
else
return unpack_file (file, dest, out_checksum, error);
}

View File

@ -116,6 +116,18 @@ gboolean ostree_checksum_file (GFile *f,
GCancellable *cancellable,
GError **error);
void ostree_checksum_file_async (GFile *f,
OstreeObjectType objtype,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ostree_checksum_file_async_finish (GFile *f,
GAsyncResult *result,
GChecksum **out_checksum,
GError **error);
gboolean ostree_get_directory_metadata (GFile *dir,
GFileInfo *dir_info,
GVariant **out_metadata,

View File

@ -31,13 +31,36 @@ static GOptionEntry options[] = {
{ NULL }
};
typedef struct {
GError **error;
GMainLoop *loop;
} AsyncChecksumData;
static void
on_checksum_received (GObject *obj,
GAsyncResult *result,
gpointer user_data)
{
GChecksum *checksum = NULL;
AsyncChecksumData *data = user_data;
if (!ostree_checksum_file_async_finish ((GFile*)obj, result, &checksum, data->error))
return;
g_print ("%s\n", g_checksum_get_string (checksum));
g_checksum_free (checksum);
g_main_loop_quit (data->loop);
}
gboolean
ostree_builtin_checksum (int argc, char **argv, const char *repo_path, GError **error)
{
GOptionContext *context;
gboolean ret = FALSE;
GChecksum *checksum = NULL;
GFile *f = NULL;
AsyncChecksumData data;
context = g_option_context_new ("FILENAME - Checksum a file or directory");
g_option_context_add_main_entries (context, options, NULL);
@ -54,15 +77,16 @@ ostree_builtin_checksum (int argc, char **argv, const char *repo_path, GError **
goto out;
}
if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE, &checksum, NULL, error))
goto out;
data.loop = g_main_loop_new (NULL, FALSE);
data.error = error;
ostree_checksum_file_async (f, OSTREE_OBJECT_TYPE_FILE, G_PRIORITY_DEFAULT, NULL, on_checksum_received, &data);
g_print ("%s\n", g_checksum_get_string (checksum));
g_main_loop_run (data.loop);
ret = TRUE;
out:
if (checksum)
g_checksum_free (checksum);
if (data.loop)
g_main_loop_unref (data.loop);
g_clear_object (&f);
if (context)
g_option_context_free (context);