// 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)
{
{
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");
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;