+
+/* Run the flush daemon for a single iteration, though if it is already
+ * executing returns immediately. */
+static gpointer flushd_task(BlueSkyFS *fs)
+{
+ if (!g_mutex_trylock(fs->flushd_lock))
+ return NULL;
+ flushd_dirty(fs);
+ bluesky_cloudlog_write_log(fs);
+ flushd_clean(fs);
+ g_mutex_unlock(fs->flushd_lock);
+
+ return NULL;
+}
+
+void bluesky_flushd_invoke(BlueSkyFS *fs)
+{
+ g_thread_create((GThreadFunc)flushd_task, fs, FALSE, NULL);
+}
+
+void bluesky_flushd_invoke_conditional(BlueSkyFS *fs)
+{
+ if (g_atomic_int_get(&fs->cache_dirty) < bluesky_watermark_high_dirty
+ && g_atomic_int_get(&fs->cache_total) < bluesky_watermark_high_total)
+ return;
+
+ if (bluesky_verbose) {
+ g_log("bluesky/flushd", G_LOG_LEVEL_DEBUG,
+ "Too much data; invoking flushd: dirty=%d total=%d",
+ g_atomic_int_get(&fs->cache_dirty),
+ g_atomic_int_get(&fs->cache_total));
+ }
+
+ bluesky_flushd_invoke(fs);
+}
+
+/* Start a perpetually-running thread that flushes the cache occasionally. */
+static gpointer flushd_thread(BlueSkyFS *fs)
+{
+ while (TRUE) {
+ bluesky_flushd_invoke(fs);
+ struct timespec delay;
+ delay.tv_sec = 2;
+ delay.tv_nsec = 0;
+ nanosleep(&delay, NULL);
+ }
+
+ return NULL;
+}
+
+void bluesky_flushd_thread_launch(BlueSkyFS *fs)
+{
+ g_thread_create((GThreadFunc)flushd_thread, fs, FALSE, NULL);
+}