+/* For locking reasons cloudlog unrefs may sometimes need to be performed in
+ * the future. We launch a thread for handling these delayed unreference
+ * requests. */
+static gpointer cloudlog_unref_thread(gpointer q)
+{
+ GAsyncQueue *queue = (GAsyncQueue *)q;
+
+ while (TRUE) {
+ BlueSkyCloudLog *item = (BlueSkyCloudLog *)g_async_queue_pop(queue);
+ bluesky_cloudlog_unref(item);
+ }
+
+ return NULL;
+}
+
+void bluesky_cloudlog_unref_delayed(BlueSkyCloudLog *log)
+{
+ if (log != NULL)
+ g_async_queue_push(log->fs->unref_queue, log);
+}
+
+void bluesky_cloudlog_threads_init(BlueSkyFS *fs)
+{
+ fs->unref_queue = g_async_queue_new();
+ g_thread_create(cloudlog_unref_thread, fs->unref_queue, FALSE, NULL);
+}
+
+/* Erase the information contained within the in-memory cloud log
+ * representation. This does not free up the item itself, but frees the data
+ * and references to other log items and resets the type back to unknown. If
+ * the object was written out to persistent storage, all state about it can be
+ * recovered by loading the object back in. The object must be locked before
+ * calling this function. */
+void bluesky_cloudlog_erase(BlueSkyCloudLog *log)
+{
+ g_assert(log->data_lock_count == 0);
+
+ if (log->type == LOGTYPE_UNKNOWN)
+ return;
+
+ log->type = LOGTYPE_UNKNOWN;
+ log->data_size = 0;
+ bluesky_string_unref(log->data);
+ log->data = NULL;
+ log->data_lock_count = 0;
+
+ for (int i = 0; i < log->links->len; i++) {
+ BlueSkyCloudLog *c = g_array_index(log->links,
+ BlueSkyCloudLog *, i);
+ bluesky_cloudlog_unref(c);
+ }
+ g_array_unref(log->links);
+ log->links = g_array_new(FALSE, TRUE, sizeof(BlueSkyCloudLog *));
+}
+