diff --git a/gio/gvdb/gvdb-builder.c b/gio/gvdb/gvdb-builder.c index 2383e6002..b8ecbe3d7 100644 --- a/gio/gvdb/gvdb-builder.c +++ b/gio/gvdb/gvdb-builder.c @@ -339,9 +339,11 @@ file_builder_allocate_for_hash (FileBuilder *fb, #undef chunk memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le)); + memset (*hash_buckets, 0, n_buckets * sizeof (guint32_le)); + memset (*hash_items, 0, n_items * sizeof (struct gvdb_hash_item)); /* NOTE - the code to actually fill in the bloom filter here is missing. - * Patches welcome! + * Patches welcome! * * http://en.wikipedia.org/wiki/Bloom_filter * http://0pointer.de/blog/projects/bloom.html @@ -450,6 +452,13 @@ file_builder_new (gboolean byteswap) return builder; } +static void +file_builder_free (FileBuilder *fb) +{ + g_queue_free (fb->chunks); + g_slice_free (FileBuilder, fb); +} + static GString * file_builder_serialise (FileBuilder *fb, struct gvdb_pointer root) @@ -494,9 +503,6 @@ file_builder_serialise (FileBuilder *fb, g_slice_free (FileChunk, chunk); } - g_queue_free (fb->chunks); - g_slice_free (FileBuilder, fb); - return result; } @@ -511,12 +517,118 @@ 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); + file_builder_free (fb); status = g_file_set_contents (filename, str->str, str->len, error); g_string_free (str, TRUE); 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_builder_free (fb); + + 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, + g_bytes_get_data (bytes, NULL), + g_bytes_get_size (bytes), + NULL, FALSE, + G_FILE_CREATE_PRIVATE, + 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/gio/gvdb/gvdb-builder.h b/gio/gvdb/gvdb-builder.h index b4815f0d0..30757d039 100644 --- a/gio/gvdb/gvdb-builder.h +++ b/gio/gvdb/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__ */ diff --git a/gio/gvdb/gvdb-reader.c b/gio/gvdb/gvdb-reader.c index 83ad2ac19..6bc4c6f36 100644 --- a/gio/gvdb/gvdb-reader.c +++ b/gio/gvdb/gvdb-reader.c @@ -351,10 +351,10 @@ gvdb_table_get_names (GvdbTable *table, gsize *length) { gchar **names; - gint n_names; - gint filled; - gint total; - gint i; + guint n_names; + guint filled; + guint total; + guint i; /* We generally proceed by iterating over the list of items in the * hash table (in order of appearance) recording them into an array.