From 21b76f1ca10c5612a6db43d517613064bef5ba87 Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 14 Jun 2011 19:15:04 +0000 Subject: [PATCH] concurrentify --- .../src/net/i2p/util/LogConsoleBuffer.java | 72 ++++++++++++------- core/java/src/net/i2p/util/LogManager.java | 2 +- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/core/java/src/net/i2p/util/LogConsoleBuffer.java b/core/java/src/net/i2p/util/LogConsoleBuffer.java index 2fe2708490..c189f540c8 100644 --- a/core/java/src/net/i2p/util/LogConsoleBuffer.java +++ b/core/java/src/net/i2p/util/LogConsoleBuffer.java @@ -2,61 +2,79 @@ package net.i2p.util; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import net.i2p.I2PAppContext; /** - * Offer a glimpse into the last few console messages generated - * + * Offer a glimpse into the last few console messages generated. + * Maintains two buffers, one normal and one critical. */ public class LogConsoleBuffer { - private I2PAppContext _context; - private final List _buffer; - private final List _critBuffer; + private final int lim; + private final LinkedBlockingQueue _buffer; + private final LinkedBlockingQueue _critBuffer; + /** + * Uses default limit from LogManager. + * As of 0.8.7, limit is not checked at runtime. + * + * @param context unused + */ public LogConsoleBuffer(I2PAppContext context) { - _context = context; - _buffer = new ArrayList(); - _critBuffer = new ArrayList(); + this(LogManager.DEFAULT_CONSOLEBUFFERSIZE); + } + + /** + * @param limit max size of each buffer + * In theory the limit is configurable, but it isn't in the UI, + * so set it at construction. + * + * @since 0.8.7 + */ + public LogConsoleBuffer(int limit) { + lim = Math.min(limit, 4); + // Add some extra room to minimize the chance of losing a message, + // since we are doing offer() below. + _buffer = new LinkedBlockingQueue(limit + 4); + _critBuffer = new LinkedBlockingQueue(limit + 4); } void add(String msg) { - int lim = _context.logManager().getConsoleBufferSize(); - synchronized (_buffer) { while (_buffer.size() >= lim) - _buffer.remove(0); - _buffer.add(msg); - } - } - void addCritical(String msg) { - int lim = _context.logManager().getConsoleBufferSize(); - synchronized (_critBuffer) { - while (_critBuffer.size() >= lim) - _critBuffer.remove(0); - _critBuffer.add(msg); - } + _buffer.poll(); + _buffer.offer(msg); } /** - * Retrieve the currently bufferd messages, earlier values were generated... + * Only adds to the critical buffer, not to both. + * + */ + void addCritical(String msg) { + while (_critBuffer.size() >= lim) + _critBuffer.poll(); + _critBuffer.offer(msg); + } + + /** + * Retrieve the currently buffered messages, earlier values were generated... * earlier. All values are strings with no formatting (as they are written * in the logs) * + * @return oldest first */ public List getMostRecentMessages() { - synchronized (_buffer) { return new ArrayList(_buffer); - } } + /** - * Retrieve the currently bufferd crutucak messages, earlier values were generated... + * Retrieve the currently buffered critical messages, earlier values were generated... * earlier. All values are strings with no formatting (as they are written * in the logs) * + * @return oldest first */ public List getMostRecentCriticalMessages() { - synchronized (_critBuffer) { return new ArrayList(_critBuffer); - } } } diff --git a/core/java/src/net/i2p/util/LogManager.java b/core/java/src/net/i2p/util/LogManager.java index b7d280491f..6e8655588c 100644 --- a/core/java/src/net/i2p/util/LogManager.java +++ b/core/java/src/net/i2p/util/LogManager.java @@ -129,7 +129,7 @@ public class LogManager { _log = getLog(LogManager.class); String location = context.getProperty(CONFIG_LOCATION_PROP, CONFIG_LOCATION_DEFAULT); setConfig(location); - _consoleBuffer = new LogConsoleBuffer(context); + _consoleBuffer = new LogConsoleBuffer(_consoleBufferSize); // If we aren't in the router context, delay creating the LogWriter until required, // so it doesn't create a log directory and log files unless there is output. // In the router context, we have to rotate to a new log file at startup or the logs.jsp