Track journal files which contain dirty data and which can be reclaimed.
[bluesky.git] / bluesky / log.c
index 976e32e..66b4edb 100644 (file)
@@ -103,6 +103,11 @@ static gboolean log_open(BlueSkyLog *log)
         log->fd = -1;
     }
 
+    if (log->current_log != NULL) {
+        bluesky_cachefile_unref(log->current_log);
+        log->current_log = NULL;
+    }
+
     while (log->fd < 0) {
         g_snprintf(logname, sizeof(logname), "journal-%08d", log->seq_num);
         log->fd = openat(log->dirfd, logname, O_CREAT|O_WRONLY|O_EXCL, 0600);
@@ -116,6 +121,10 @@ static gboolean log_open(BlueSkyLog *log)
         }
     }
 
+    log->current_log = bluesky_cachefile_lookup(log->fs, -1, log->seq_num);
+    g_assert(log->current_log != NULL);
+    g_mutex_unlock(log->current_log->lock);
+
     if (ftruncate(log->fd, LOG_SEGMENT_SIZE) < 0) {
         fprintf(stderr, "Unable to truncate logfile %s: %m\n", logname);
     }
@@ -204,6 +213,13 @@ static gpointer log_thread(gpointer d)
 
         offset += sizeof(header) + sizeof(footer) + item->data->len;
 
+        /* Since we have just written a new dirty object to the journal,
+         * increment the count of live dirty objects in that journal file.  The
+         * count will be decremented when objects are deleted or written to the
+         * cloud. */
+        g_atomic_int_add(&log->current_log->dirty_refs, 1);
+        item->dirty_journal = log->current_log;
+
         /* Replace the log item's string data with a memory-mapped copy of the
          * data, now that it has been written to the log file.  (Even if it
          * isn't yet on disk, it should at least be in the page cache and so
@@ -481,16 +497,16 @@ void bluesky_cachefile_gc(BlueSkyFS *fs)
          * then we'll just skip the file on this pass. */
         if (g_mutex_trylock(cachefile->lock)) {
             int64_t age = bluesky_get_current_time() - cachefile->atime;
-            g_print("%s addr=%p mapcount=%d refcount=%d atime_age=%f",
+            g_print("%s addr=%p mapcount=%d refcount=%d dirty=%d atime_age=%f",
                     cachefile->filename, cachefile->addr, cachefile->mapcount,
-                    cachefile->refcount, age / 1e6);
+                    cachefile->refcount, cachefile->dirty_refs, age / 1e6);
             if (cachefile->fetching)
                 g_print(" (fetching)");
             g_print("\n");
 
             if (g_atomic_int_get(&cachefile->refcount) == 0
                 && g_atomic_int_get(&cachefile->mapcount) == 0
-                && cachefile->type == CLOUDLOG_CLOUD /* FIXME: journals too */)
+                && g_atomic_int_get(&cachefile->dirty_refs) == 0)
             {
                 g_print("   ...deleting\n");
                 if (unlinkat(fs->log->dirfd, cachefile->filename, 0) < 0) {