Allow batched log writes when writing dirty inodes.
[bluesky.git] / bluesky / log.c
index a4a8150..c3d0c2b 100644 (file)
@@ -35,7 +35,7 @@
 
 // Rough size limit for a log segment.  This is not a firm limit and there are
 // no absolute guarantees on the size of a log segment.
-#define LOG_SEGMENT_SIZE (1 << 20)
+#define LOG_SEGMENT_SIZE (1 << 23)
 
 static void writebuf(int fd, const char *buf, size_t len)
 {
@@ -66,6 +66,12 @@ static gpointer log_thread(gpointer d)
 {
     BlueSkyLog *log = (BlueSkyLog *)d;
 
+    /* If there are multiple log items to write, we may write more than one
+     * before calling fsync().  The committed list is used to track all the
+     * items that should be marked as committed once that final fsync() is
+     * done. */
+    GSList *committed = NULL;
+
     int dirfd = open(log->log_directory, O_DIRECTORY);
     if (dirfd < 0) {
         fprintf(stderr, "Unable to open logging directory: %m\n");
@@ -93,12 +99,29 @@ static gpointer log_thread(gpointer d)
         g_mutex_lock(item->lock);
         writebuf(log->fd, item->key, strlen(item->key));
         writebuf(log->fd, item->data->data, item->data->len);
-        fdatasync(log->fd);
-        item->committed = TRUE;
-        g_cond_signal(item->cond);
-        g_mutex_unlock(item->lock);
+        committed  = g_slist_prepend(committed, item);
 
+        /* Force an fsync either if we will be closing this log segment and
+         * opening a new file, or if there are no other log items currently
+         * waiting to be written. */
         off_t logsize = lseek(log->fd, 0, SEEK_CUR);
+        if (logsize >= LOG_SEGMENT_SIZE
+            || g_async_queue_length(log->queue) <= 0)
+        {
+            int batchsize = 0;
+            fdatasync(log->fd);
+            while (committed != NULL) {
+                item = (BlueSkyLogItem *)committed->data;
+                item->committed = TRUE;
+                g_cond_signal(item->cond);
+                g_mutex_unlock(item->lock);
+                committed = g_slist_delete_link(committed, committed);
+                batchsize++;
+            }
+            /* if (batchsize > 1)
+                g_print("Log batch size: %d\n", batchsize); */
+        }
+
         if (logsize < 0 || logsize >= LOG_SEGMENT_SIZE) {
             close(log->fd);
             log->fd = -1;