From d12c5aaba8f2f6208c3493b42ab15a139c049d58 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Thu, 20 Jun 2019 18:15:54 -0500 Subject: Add gvdb_table_write_contents_async() This is just an async version of gvdb_table_write_contents(). Future work: someone could write an async version of gvdb_table_new(), then sync I/O would no longer be required to construct a GvdbTable. --- gvdb-builder.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gvdb-builder.h | 11 +++++++ 2 files changed, 109 insertions(+) diff --git a/gvdb-builder.c b/gvdb-builder.c index 2383e60..55b4513 100644 --- a/gvdb-builder.c +++ b/gvdb-builder.c @@ -520,3 +520,101 @@ gvdb_table_write_contents (GHashTable *table, return status; } + +typedef struct { + GBytes *contents; /* (owned) */ + GFile *file; /* (owned) */ +} WriteContentsData; + +static WriteContentsData * +write_contents_data_new (GBytes *contents, + GFile *file) +{ + WriteContentsData *data; + + data = g_slice_new (WriteContentsData); + data->contents = g_bytes_ref (contents); + data->file = g_object_ref (file); + + return data; +} + +static void +write_contents_data_free (WriteContentsData *data) +{ + g_bytes_unref (data->contents); + g_object_unref (data->file); + g_slice_free (WriteContentsData, data); +} + +static void +replace_contents_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = user_data; + WriteContentsData *data = g_task_get_task_data (task); + GError *error = NULL; + + g_return_if_fail (g_task_get_source_tag (task) == gvdb_table_write_contents_async); + + if (!g_file_replace_contents_finish (data->file, result, NULL, &error)) + g_task_return_error (task, g_steal_pointer (&error)); + else + g_task_return_boolean (task, TRUE); + + g_object_unref (task); +} + +void +gvdb_table_write_contents_async (GHashTable *table, + const gchar *filename, + gboolean byteswap, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + struct gvdb_pointer root; + FileBuilder *fb; + WriteContentsData *data; + GString *str; + GBytes *bytes; + GFile *file; + GTask *task; + + g_return_if_fail (table != NULL); + g_return_if_fail (filename != NULL); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + fb = file_builder_new (byteswap); + file_builder_add_hash (fb, table, &root); + str = file_builder_serialise (fb, root); + bytes = g_string_free_to_bytes (str); + + file = g_file_new_for_path (filename); + data = write_contents_data_new (bytes, file); + + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_task_data (task, data, (GDestroyNotify)write_contents_data_free); + g_task_set_source_tag (task, gvdb_table_write_contents_async); + + g_file_replace_contents_async (file, str->str, str->len, + NULL, FALSE, + G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, + cancellable, replace_contents_cb, g_steal_pointer (&task)); + + g_bytes_unref (bytes); + g_object_unref (file); +} + +gboolean +gvdb_table_write_contents_finish (GHashTable *table, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (table != NULL, FALSE); + g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} diff --git a/gvdb-builder.h b/gvdb-builder.h index b4815f0..30757d0 100644 --- a/gvdb-builder.h +++ b/gvdb-builder.h @@ -51,5 +51,16 @@ gboolean gvdb_table_write_contents (GHashTa const gchar *filename, gboolean byteswap, GError **error); +G_GNUC_INTERNAL +void gvdb_table_write_contents_async (GHashTable *table, + const gchar *filename, + gboolean byteswap, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +G_GNUC_INTERNAL +gboolean gvdb_table_write_contents_finish (GHashTable *table, + GAsyncResult *result, + GError **error); #endif /* __gvdb_builder_h__ */ -- cgit v1.2.1 From 16fb81cd7e3a3586252fc5d185e5c2c95125d045 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Fri, 21 Jun 2019 09:58:15 -0500 Subject: Add some g_return checks to gvdb_table_write_contents() I'm not auditing all the public functions in this file for precondition checks, but since I'm adding an async version of this function, it makes sense to ensure there are matching checks for the sync version. --- gvdb-builder.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gvdb-builder.c b/gvdb-builder.c index 55b4513..ff28edf 100644 --- a/gvdb-builder.c +++ b/gvdb-builder.c @@ -511,6 +511,10 @@ gvdb_table_write_contents (GHashTable *table, FileBuilder *fb; GString *str; + g_return_val_if_fail (table != NULL, FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + fb = file_builder_new (byteswap); file_builder_add_hash (fb, table, &root); str = file_builder_serialise (fb, root); -- cgit v1.2.1