propagate from branch 'i2p.i2p.zzz.test2' (head 0feb2e6806927f68c7333aaa0892de185bb2629c)

to branch 'i2p.i2p' (head 0482fa843cb1e9d7ec281440056eef3a0ab07bdb)
This commit is contained in:
zzz
2014-12-05 15:14:40 +00:00
55 changed files with 666 additions and 295 deletions

View File

@@ -108,6 +108,9 @@ public class DataHelper {
* for the value. Finally after that comes the literal UTF-8 character ';'. This key=value;
* is repeated until there are no more bytes (not characters!) left as defined by the
* first two byte integer.
*
* As of 0.9.18, throws DataFormatException on duplicate key
*
* @param rawStream stream to read the mapping from
* @throws DataFormatException if the format is invalid
* @throws IOException if there is a problem reading the data
@@ -122,7 +125,14 @@ public class DataHelper {
/**
* Ditto, load into an existing properties
*
* As of 0.9.18, throws DataFormatException on duplicate key
*
* @param props the Properties to load into
* @param rawStream stream to read the mapping from
* @throws DataFormatException if the format is invalid
* @throws IOException if there is a problem reading the data
* @return the parameter props
* @since 0.8.13
*/
public static Properties readProperties(InputStream rawStream, Properties props)
@@ -148,7 +158,9 @@ public class DataHelper {
if ((read != semiBuf.length) || (!eq(semiBuf, SEMICOLON_BYTES))) {
throw new DataFormatException("Bad value");
}
props.put(key, val);
Object old = props.put(key, val);
if (old != null)
throw new DataFormatException("Duplicate key " + key);
}
return props;
}
@@ -299,6 +311,8 @@ public class DataHelper {
* Warning - confusing method name, Properties is the target.
* Strings must be UTF-8 encoded in the byte array.
*
* As of 0.9.18, throws DataFormatException on duplicate key
*
* @param source source
* @param target returned Properties
* @return new offset
@@ -333,7 +347,9 @@ public class DataHelper {
} catch (IOException ioe) {
throw new DataFormatException("Bad value", ioe);
}
target.put(key, val);
Object old= target.put(key, val);
if (old != null)
throw new DataFormatException("Duplicate key " + key);
}
return offset + size;
}
@@ -398,6 +414,9 @@ public class DataHelper {
* - '=' is the only key-termination character (not ':' or whitespace)
*
* As of 0.9.10, an empty value is allowed.
*
* As in Java Properties, duplicate keys are allowed, last one wins.
*
*/
public static void loadProps(Properties props, File file) throws IOException {
loadProps(props, file, false);

View File

@@ -61,6 +61,8 @@ public class LogManager {
private static final String PROP_DROP = "logger.dropOnOverflow";
/** @since 0.9.3 */
private static final String PROP_DUP = "logger.dropDuplicates";
/** @since 0.9.18 */
private static final String PROP_FLUSH = "logger.flushInterval";
public final static String PROP_RECORD_PREFIX = "logger.record.";
public final static String DEFAULT_FORMAT = DATE + " " + PRIORITY + " [" + THREAD + "] " + CLASS + ": " + MESSAGE;
@@ -125,6 +127,8 @@ public class LogManager {
private boolean _dropOnOverflow;
private boolean _dropDuplicates;
private final AtomicLong _droppedRecords = new AtomicLong();
// in seconds
private int _flushInterval = (int) (LogWriter.FLUSH_INTERVAL / 1000);
private boolean _alreadyNoticedMissingConfig;
@@ -160,6 +164,7 @@ public class LogManager {
if (_writer != null)
return;
_writer = new LogWriter(this);
_writer.setFlushInterval(_flushInterval * 1000);
// if you enable logging in I2PThread again, you MUST change this back to Thread
Thread t = new I2PThread(_writer, "LogWriter");
t.setDaemon(true);
@@ -269,6 +274,10 @@ public class LogManager {
try {
_records.put(record);
} catch (InterruptedException ie) {}
} else if (_flushInterval <= 0) {
synchronized (_writer) {
_writer.notifyAll();
}
}
}
@@ -384,6 +393,17 @@ public class LogManager {
_logBufferSize = Integer.parseInt(str);
} catch (NumberFormatException nfe) {}
try {
String str = config.getProperty(PROP_FLUSH);
if (str != null) {
_flushInterval = Integer.parseInt(str);
synchronized(this) {
if (_writer != null)
_writer.setFlushInterval(_flushInterval * 1000);
}
}
} catch (NumberFormatException nfe) {}
_dropOnOverflow = Boolean.parseBoolean(config.getProperty(PROP_DROP));
String str = config.getProperty(PROP_DUP);
_dropDuplicates = str == null || Boolean.parseBoolean(str);
@@ -647,6 +667,7 @@ public class LogManager {
rv.setProperty(PROP_DEFAULTLEVEL, Log.toLevelString(_defaultLimit));
rv.setProperty(PROP_DISPLAYONSCREENLEVEL, Log.toLevelString(_onScreenLimit));
rv.setProperty(PROP_CONSOLEBUFFERSIZE, Integer.toString(_consoleBufferSize));
rv.setProperty(PROP_FLUSH, Integer.toString(_flushInterval));
for (LogLimit lim : _limits) {
rv.setProperty(PROP_RECORD_PREFIX + lim.getRootName(), Log.toLevelString(lim.getLimit()));

View File

@@ -25,7 +25,9 @@ import java.util.Queue;
class LogWriter implements Runnable {
/** every 10 seconds? why? Just have the gui force a reread after a change?? */
private final static long CONFIG_READ_INTERVAL = 50 * 1000;
private final static long FLUSH_INTERVAL = 29 * 1000;
final static long FLUSH_INTERVAL = 29 * 1000;
private final static long MIN_FLUSH_INTERVAL = 2*1000;
private final static long MAX_FLUSH_INTERVAL = 5*60*1000;
private long _lastReadConfig;
private long _numBytesInCurrentFile;
// volatile as it changes on log file rotation
@@ -38,6 +40,8 @@ class LogWriter implements Runnable {
private static final int MAX_DISKFULL_MESSAGES = 8;
private int _diskFullMessageCount;
private LogRecord _last;
// ms
private volatile long _flushInterval = FLUSH_INTERVAL;
public LogWriter(LogManager manager) {
_manager = manager;
@@ -47,6 +51,14 @@ class LogWriter implements Runnable {
public void stopWriting() {
_write = false;
}
/**
* @param ms
* @since 0.9.18
*/
public void setFlushInterval(long interval) {
_flushInterval = Math.min(MAX_FLUSH_INTERVAL, Math.max(MIN_FLUSH_INTERVAL, interval));
}
public void run() {
_write = true;
@@ -109,7 +121,7 @@ class LogWriter implements Runnable {
if (shouldWait) {
try {
synchronized (this) {
this.wait(FLUSH_INTERVAL);
this.wait(_flushInterval);
}
} catch (InterruptedException ie) { // nop
}