From fef19c1329680b7826cc9cd6d8c02eeadaa8acad Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 2 Jul 2020 17:20:34 +0100 Subject: [PATCH] Flush the log stream whenever there are records to flush. --- .../briar/logging/FlushingStreamHandler.java | 43 +++++++++++++++++++ .../logging/PersistentLogManagerImpl.java | 16 +++---- 2 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 briar-core/src/main/java/org/briarproject/briar/logging/FlushingStreamHandler.java diff --git a/briar-core/src/main/java/org/briarproject/briar/logging/FlushingStreamHandler.java b/briar-core/src/main/java/org/briarproject/briar/logging/FlushingStreamHandler.java new file mode 100644 index 000000000..2ffa08c4f --- /dev/null +++ b/briar-core/src/main/java/org/briarproject/briar/logging/FlushingStreamHandler.java @@ -0,0 +1,43 @@ +package org.briarproject.briar.logging; + +import java.io.OutputStream; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; +import java.util.logging.StreamHandler; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +class FlushingStreamHandler extends StreamHandler { + + private static final int FLUSH_DELAY_MS = 5_000; + + private final ScheduledExecutorService scheduler; + private final Executor ioExecutor; + private final AtomicBoolean flushScheduled = new AtomicBoolean(false); + + FlushingStreamHandler(ScheduledExecutorService scheduler, + Executor ioExecutor, OutputStream out, Formatter formatter) { + super(out, formatter); + this.scheduler = scheduler; + this.ioExecutor = ioExecutor; + } + + @Override + public void publish(LogRecord record) { + super.publish(record); + if (!flushScheduled.getAndSet(true)) { + scheduler.schedule(this::scheduledFlush, + FLUSH_DELAY_MS, MILLISECONDS); + } + } + + private void scheduledFlush() { + ioExecutor.execute(() -> { + flushScheduled.set(false); + flush(); + }); + } +} diff --git a/briar-core/src/main/java/org/briarproject/briar/logging/PersistentLogManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/logging/PersistentLogManagerImpl.java index 1d31255aa..8ab0fb838 100644 --- a/briar-core/src/main/java/org/briarproject/briar/logging/PersistentLogManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/logging/PersistentLogManagerImpl.java @@ -39,9 +39,8 @@ import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; import static java.util.Collections.emptyList; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.LogUtils.logException; @ThreadSafe @@ -50,11 +49,10 @@ class PersistentLogManagerImpl implements PersistentLogManager, OpenDatabaseHook { private static final Logger LOG = - Logger.getLogger(PersistentLogManagerImpl.class.getName()); + getLogger(PersistentLogManagerImpl.class.getName()); private static final String LOG_FILE = "briar.log"; private static final String OLD_LOG_FILE = "briar.log.old"; - private static final long FLUSH_INTERVAL_MS = MINUTES.toMillis(5); private final ScheduledExecutorService scheduler; private final Executor ioExecutor; @@ -116,15 +114,11 @@ class PersistentLogManagerImpl implements PersistentLogManager, OutputStream out = new FileOutputStream(logFile); StreamWriter writer = streamWriterFactory.createLogStreamWriter(out, logKey); - StreamHandler handler = - new StreamHandler(writer.getOutputStream(), formatter); - // Flush the log periodically in case we're killed without getting - // the chance to run shutdown hooks - scheduler.scheduleWithFixedDelay(() -> - ioExecutor.execute(handler::flush), - FLUSH_INTERVAL_MS, FLUSH_INTERVAL_MS, MILLISECONDS); + StreamHandler handler = new FlushingStreamHandler(scheduler, + ioExecutor, writer.getOutputStream(), formatter); // Flush the log and terminate the stream at shutdown shutdownManager.addShutdownHook(() -> { + LOG.info("Shutting down"); handler.flush(); try { writer.sendEndOfStream();