Update of /cvsroot/freenet/freenet/src/freenet/support
In directory sc8-pr-cvs1:/tmp/cvs-serv25857/src/freenet/support
Modified Files:
Tag: stable
BlockingQueue.java CryptBucket.java Fields.java
FileBucket.java FileLoggerHook.java LRUQueue.java
LimitCounter.java Logger.java LoggerHook.java
MultiValueTable.java SimpleDataObjectStore.java
TempBucketFactory.java TempFileBucket.java
Added Files:
Tag: stable
PooledRandomAccessFile.java RandomAccessFilePool.java
Log Message:
5029: Merge from unstable after months of work. MASSIVE changes.
Highlights:
* Next Generation Routing, massive related changes
* Major changes to handling of messages and connections (PeerHandler and related
changes)
* Even more non-blocking I/O
* Documentation improvements
* Lots of new diagnostics and config options
* Lots of bug fixes and performance tweaking
* Probably lots of new bugs too!
--- NEW FILE: PooledRandomAccessFile.java ---
package freenet.support;
import java.io.*;
/**
* Interface for pooled RandomAccessFile-like objects.
* Purpose of pooling is to save FDs.
* Classes implementing this interface should be synchronized.
* @see RandomAccessFilePool
*/
public interface PooledRandomAccessFile {
public long length() throws IOException;
public void seek(long pos) throws IOException;
/** Synchronize. Provided to avoid requiring locking in client.
* In java.io.RandomAccessFile this would go via the FileDescriptor.
*/
public void sync() throws IOException;
public int read() throws IOException;
public int read(byte[] b, int off, int len) throws IOException;
public void write(int b) throws IOException;
public void write(byte[] b, int off, int len) throws IOException;
public long getFilePointer() throws IOException;
/** Close the underlying RandomAccessFile, if we are short on
* handles. Call this when you have temporarily finished with a
* RAF, but don't want to close() yet.
*/
public void closeRAF();
public void close() throws IOException;
}
--- NEW FILE: RandomAccessFilePool.java ---
package freenet.support;
import java.io.*;
import freenet.Core;
/**
* A pool of PooledRandomAccessFiles. These are similar to
* java.io.RandomAccessFiles, but we have a maximum number of file
* descriptors. If there are more RAFs than that allocated, we keep only
* the MRU fds open.
*
* Synchronized.
*/
public class RandomAccessFilePool {
int maxOpenFiles;
volatile int totalOpenFiles;
LRUQueue queue;
public int totalOpenFiles() {
return totalOpenFiles;
}
public int maxOpenFiles() {
return maxOpenFiles;
}
public RandomAccessFilePool(int maxFDsOpen) {
this.maxOpenFiles = maxFDsOpen;
queue = new LRUQueue();
if(maxFDsOpen < 2) throw new IllegalArgumentException("Unreasonable maximum
number of open files "+maxFDsOpen);
}
public PooledRandomAccessFile open(File f, String mode)
throws IOException {
return new MyPooledRandomAccessFile(f, mode);
}
class MyPooledRandomAccessFile implements PooledRandomAccessFile {
File filename;
String mode;
RandomAccessFile raf;
boolean closed = false;
long position = 0; // Not guaranteed to be up to date unless raf closed
public MyPooledRandomAccessFile(File f, String mode) throws IOException {
this.filename = f;
this.mode = mode;
reopen();
}
synchronized void reopen() throws IOException {
if(raf == null) {
if(closed)
throw new IOException("Already closed or failed to save position");
boolean firstIteration = true;
while(totalOpenFiles >= maxOpenFiles) {
PooledRandomAccessFile fClose = null;
synchronized(RandomAccessFilePool.this) {
if(firstIteration) {
totalOpenFiles++; // the one we are about to open
queue.push(this);
firstIteration = false;
}
// Do it here to try to avoid livelock
if(totalOpenFiles > maxOpenFiles) {
fClose = (PooledRandomAccessFile)(queue.pop());
}
}
// Close LRU
// Since this is MRU we shouldn't have lock contention
if(fClose == this)
throw new IllegalStateException("aaaaargh! Popped self!");
if(fClose != null) fClose.closeRAF();
}
raf = new RandomAccessFile(filename, mode);
if(position != 0) {
raf.seek(position);
}
}
}
public long length() throws IOException {
synchronized(this) {
if(raf != null)
return raf.length();
}
return filename.length();
}
public synchronized void seek(long pos) throws IOException {
reopen();
raf.seek(pos);
position = pos;
}
/**
* Not in RandomAccessFile API, but because of synchronization
* issues, it is better to put it here */
public synchronized void sync() throws IOException {
// No need to reopen
if(raf != null) {
raf.getFD().sync();
}
}
public synchronized int read() throws IOException {
reopen();
return raf.read();
}
public synchronized int read(byte[] buf, int off, int len)
throws IOException {
reopen();
return raf.read(buf, off, len);
}
public synchronized void write(int b) throws IOException {
reopen();
raf.write(b);
}
public synchronized void write(byte[] b, int offset, int len)
throws IOException {
reopen();
raf.write(b, offset, len);
}
public synchronized long getFilePointer() throws IOException {
if(raf == null)
return position;
else
return raf.getFilePointer();
}
public synchronized void closeRAF() {
if(raf == null) return;
synchronized(RandomAccessFilePool.this) {
if(totalOpenFiles < maxOpenFiles)
return;
}
try {
position = raf.getFilePointer();
} catch (IOException e) {
closed = true;
position = 0;
} catch (Throwable t) {
Core.logger.log(this, "Caught "+t+" saving file pointer for "+
raf, Logger.ERROR);
}
try {
raf.close();
} catch (IOException e) {
} catch (Throwable t) {
Core.logger.log(this, "Caught "+t+" closing "+raf,
Logger.ERROR);
// assume it is closed...
}
synchronized(RandomAccessFilePool.this) {
totalOpenFiles--;
}
raf = null;
}
public synchronized void close() throws IOException {
closed = true;
raf.close();
raf = null;
synchronized(RandomAccessFilePool.this) {
totalOpenFiles--;
}
}
}
}
Index: BlockingQueue.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/BlockingQueue.java,v
retrieving revision 1.1.1.1.4.1.2.6
retrieving revision 1.1.1.1.4.1.2.7
diff -u -w -r1.1.1.1.4.1.2.6 -r1.1.1.1.4.1.2.7
--- BlockingQueue.java 5 Aug 2003 19:41:29 -0000 1.1.1.1.4.1.2.6
+++ BlockingQueue.java 28 Oct 2003 20:20:45 -0000 1.1.1.1.4.1.2.7
@@ -1,8 +1,8 @@
package freenet.support;
import freenet.*;
-import freenet.support.Logger;
import java.util.*;
+import java.util.logging.LogManager;
/*
This code is part of the Java Adaptive Network Client by Ian Clarke.
@@ -19,7 +19,7 @@
* @author Scott G. Miller <[EMAIL PROTECTED]>
*/
public final class BlockingQueue {
- protected LinkedList queue;
+ protected final LinkedList queue;
/**
* Construct an empty BlockingQueue.
@@ -39,11 +39,23 @@
* @param o the object to enqueue
*/
public void enqueue(Object o) {
+ boolean logDEBUG = Core.logger.shouldLog(Logger.DEBUG,this);
enqueuedAt = System.currentTimeMillis();
+ if(logDEBUG)
+ Core.logger.log(this, "enqueueing "+o, Logger.DEBUG);
synchronized(queue) {
+ if(logDEBUG)
+ Core.logger.log(this, "enqueueing "+o+" (locked)",
+ Logger.DEBUG);
queue.add(o);
queue.notifyAll();
- }
+ if(logDEBUG)
+ Core.logger.log(this, "enqueued "+o+" (locked)"+
+ " to "+queue.getClass()+":"+queue, Logger.DEBUG);
+ }
+ if(logDEBUG)
+ Core.logger.log(this, "enqueued "+o+" (locked)",
+ Logger.DEBUG);
}
public Object dequeue() throws InterruptedException {
@@ -63,6 +75,8 @@
* and something interrupts this thread.
*/
public Object dequeue(int millis) throws InterruptedException {
+ boolean logDEBUG = Core.logger.shouldLog(Logger.DEBUG,this);
+ boolean logMINOR = Core.logger.shouldLog(Logger.MINOR,this);
synchronized(queue) {
//if (queue.isEmpty()) {
// synchronized(queue) {
@@ -78,20 +92,26 @@
dequeuedCounted++;
final int timeout = 200;
while (queue.isEmpty()) {
+ if(logDEBUG) Core.logger.log(this, "Waiting...
"+queue.getClass()+":"+
+ queue, Logger.DEBUG);
long now = System.currentTimeMillis();
queue.wait(timeout); // wicked evil JVMs! (1.4.2 especially) - we
have seen some interesting freezes here...
long andnow = System.currentTimeMillis();
if (andnow - now >= (timeout) && !queue.isEmpty()) {
long x = andnow - enqueuedAt;
- String err = "Waited more than "+timeout+"ms to dequeue,
"+queue.size()+" in queue, "+x+" millis since enqueued last item, "+dequeuedCounted+"
maximum waits so far - could indicate serious JVM bug. Please report to [EMAIL
PROTECTED] along with JVM and OS/kernel.";
+
if(queue.size() > 5 && x > (5*timeout)) {
+ String err = "Waited more than "+timeout+"ms to
dequeue, "+queue.size()+" in queue, "+x+" millis since enqueued last item,
"+dequeuedCounted+" maximum waits so far - could indicate serious JVM bug. Please
report to [EMAIL PROTECTED] along with JVM and OS/kernel.";
Core.logger.log(this, err, Logger.NORMAL);
System.err.println(err);
} else {
+ if(logMINOR) {
+ String err = "Waited more than "+timeout+"ms
to dequeue, "+queue.size()+" in queue, "+x+" millis since enqueued last item,
"+dequeuedCounted+" maximum waits so far - could indicate serious JVM bug. Please
report to [EMAIL PROTECTED] along with JVM and OS/kernel.";
Core.logger.log(this, err, Logger.MINOR);
}
}
}
+ }
return innerDequeue();
}else {
long x = System.currentTimeMillis();
@@ -104,7 +124,12 @@
}
}
}
-
+ //Returns a snapshot of the current contents of the queue
+ public Object[] toArray(){
+ synchronized(queue) {
+ return queue.toArray();
+ }
+ }
// override in subclasses
protected Object innerDequeue() {
Object tmp = queue.removeFirst();
Index: CryptBucket.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/CryptBucket.java,v
retrieving revision 1.1.1.1.6.1
retrieving revision 1.1.1.1.6.2
diff -u -w -r1.1.1.1.6.1 -r1.1.1.1.6.2
--- CryptBucket.java 1 Apr 2003 21:04:53 -0000 1.1.1.1.6.1
+++ CryptBucket.java 28 Oct 2003 20:20:45 -0000 1.1.1.1.6.2
@@ -30,7 +30,7 @@
if (bc == null)
throw new IllegalArgumentException();
key = new byte[bc.getKeySize() >> 3];
- Core.randSource.nextBytes(key);
+ Core.getRandSource().nextBytes(key);
}
/**
@@ -46,7 +46,7 @@
if (bc == null)
throw new IllegalArgumentException();
key = new byte[bc.getKeySize() >> 3];
- Core.randSource.nextBytes(key);
+ Core.getRandSource().nextBytes(key);
}
public OutputStream getOutputStream() throws IOException {
Index: Fields.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/Fields.java,v
retrieving revision 1.7.4.8.2.2
retrieving revision 1.7.4.8.2.3
diff -u -w -r1.7.4.8.2.2 -r1.7.4.8.2.3
--- Fields.java 21 May 2003 19:54:52 -0000 1.7.4.8.2.2
+++ Fields.java 28 Oct 2003 20:20:45 -0000 1.7.4.8.2.3
@@ -17,20 +17,10 @@
public abstract class Fields {
public static void main(String[] args) {
- System.out.println(Long.toHexString(stringToLong(args[0])));
+ System.out.println(Long.toHexString(hexToLong(args[0])));
System.out.println(Long.toHexString(Long.parseLong(args[0], 16)));
}
- /** @deprecated */
- public static final long stringToLong(String hex) throws NumberFormatException {
- return hexToLong(hex);
- }
-
- /** @deprecated */
- public static final String longToString(long l) {
- return longToHex(l);
- }
-
/** Converts a hex string into a long.
*
* Long.parseLong(hex, 16) assumes the input is nonnegative unless there
@@ -204,7 +194,7 @@
s = '0' + s;
if (out.length < off + s.length()/2)
- throw new IndexOutOfBoundsException();
+ throw new IndexOutOfBoundsException("Output buffer too small for input
("+out.length+"<"+off + s.length()/2+")");
byte b;
for (int i=0; i < s.length(); i++) {
@@ -295,7 +285,7 @@
StringTokenizer st = new StringTokenizer(ls, ",");
long[] r = new long[st.countTokens()];
for (int i = 0 ; i < r.length ; i++) {
- r[i] = stringToLong(st.nextToken());
+ r[i] = hexToLong(st.nextToken());
}
return r;
}
@@ -303,7 +293,7 @@
public static final String numberList(long[] ls) {
StringBuffer sb = new StringBuffer(ls.length*18);
for (int i = 0 ; i < ls.length ; i++) {
- sb.append(longToString(ls[i]));
+ sb.append(longToHex(ls[i]));
if (i != ls.length - 1)
sb.append(',');
}
Index: FileBucket.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/FileBucket.java,v
retrieving revision 1.4.2.5.2.3
retrieving revision 1.4.2.5.2.4
diff -u -w -r1.4.2.5.2.3 -r1.4.2.5.2.4
--- FileBucket.java 5 Jul 2003 01:09:55 -0000 1.4.2.5.2.3
+++ FileBucket.java 28 Oct 2003 20:20:45 -0000 1.4.2.5.2.4
@@ -38,7 +38,7 @@
*/
public FileBucket() {
- file = new File(tempDir, "t" +
Fields.longToString(Math.abs(Core.randSource.nextInt())));
+ file = new File(tempDir, "t" +
Fields.longToHex(Math.abs(Core.getRandSource().nextInt())));
// Useful for finding temp file leaks.
//System.err.println("-- FileBucket.ctr(1) -- " + file.getAbsolutePath());
//(new Exception("get stack")).printStackTrace();
@@ -85,7 +85,7 @@
if(!append) {
resetLength();
}
- if(Core.logger.shouldLog(Logger.DEBUG))
+ if(Core.logger.shouldLog(Logger.DEBUG,this))
e = new Exception("debug");
}
@@ -128,7 +128,7 @@
public FileBucketInputStream(File f) throws IOException {
super(f);
- if(Core.logger.shouldLog(Logger.DEBUG))
+ if(Core.logger.shouldLog(Logger.DEBUG,this))
e = new Exception("debug");
}
}
@@ -170,7 +170,7 @@
public void finalize() throws Throwable
{
- if(Core.logger.shouldLog(Logger.DEBUG))
+ if(Core.logger.shouldLog(Logger.DEBUG,this))
Core.logger.log(this, "FileBucket Finalizing "+file.getName(),
Logger.DEBUG);
if(newFile && file.exists()) {
Core.logger.log(this, "Deleting bucket "+file.getName(), Logger.DEBUGGING);
@@ -178,7 +178,7 @@
if (file.exists())
Core.logger.log(this, "Delete failed on bucket "+file.getName(),
Logger.ERROR);
}
- if(Core.logger.shouldLog(Logger.DEBUG))
+ if(Core.logger.shouldLog(Logger.DEBUG,this))
Core.logger.log(this, "FileBucket Finalized "+file.getName(),
Logger.DEBUG);
}
Index: FileLoggerHook.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/FileLoggerHook.java,v
retrieving revision 1.4.4.5.2.9
retrieving revision 1.4.4.5.2.10
diff -u -w -r1.4.4.5.2.9 -r1.4.4.5.2.10
--- FileLoggerHook.java 23 Aug 2003 12:04:43 -0000 1.4.4.5.2.9
+++ FileLoggerHook.java 28 Oct 2003 20:20:45 -0000 1.4.4.5.2.10
@@ -4,6 +4,8 @@
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Calendar;
import java.util.LinkedList;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -26,6 +28,8 @@
private volatile boolean closed = false;
+ protected static int INTERVAL = GregorianCalendar.MINUTE;
+
private static String uname;
static {
try {
@@ -56,6 +60,16 @@
protected OutputStream uout;
+ protected boolean logOverwrite = false;
+
+ /* Base filename for rotating logs */
+ protected String baseFilename = null;
+
+ /* Whether to redirect stdout */
+ protected boolean redirectStdOut = false;
+ /* Whether to redirect stderr */
+ protected boolean redirectStdErr = false;
+
/**
* Something wierd happens when the disk gets full, also we don't want to block
* So run the actual write on another thread
@@ -65,6 +79,7 @@
protected static int MAX_LIST_SIZE=100000;
protected static long MAX_LIST_BYTES=10*(1<<20);
+ protected static boolean useNativeGzip = false;
// FIXME: should reimplement LinkedList with minimal locking
@@ -72,10 +87,42 @@
MAX_LIST_SIZE = len;
}
+ public static void setUseNativeGzip(boolean x) {
+ useNativeGzip = x;
+ }
+
public static void setMaxListBytes(long len) {
MAX_LIST_BYTES = len;
}
+ public static void setInterval(String intervalName) {
+ if(intervalName.equalsIgnoreCase("MINUTE"))
+ INTERVAL = Calendar.MINUTE;
+ else if(intervalName.equalsIgnoreCase("HOUR"))
+ INTERVAL = Calendar.HOUR;
+ else if(intervalName.equalsIgnoreCase("DAY"))
+ INTERVAL = Calendar.DAY_OF_MONTH;
+ else if(intervalName.equalsIgnoreCase("WEEK"))
+ INTERVAL = Calendar.WEEK_OF_YEAR;
+ else if(intervalName.equalsIgnoreCase("MONTH"))
+ INTERVAL = Calendar.MONTH;
+ else if(intervalName.equalsIgnoreCase("YEAR"))
+ INTERVAL = Calendar.YEAR;
+ else throw new IllegalArgumentException("invalid interval "+intervalName);
+ }
+
+ protected String getHourLogName(Calendar c) {
+ return baseFilename + "-" + c.get(c.YEAR) + "-" + pad2(c.get(c.MONTH)) +
+ "-" + pad2(c.get(c.DAY_OF_MONTH)) + "-" + pad2(c.get(c.HOUR_OF_DAY)) +
+ (INTERVAL == c.MINUTE ? ("-" + pad2(c.get(c.MINUTE))) : "");
+ }
+
+ protected String pad2(int x) {
+ String s = Integer.toString(x);
+ if(s.length() == 1) s = "0" + s;
+ return s;
+ }
+
class WriterThread extends Thread {
WriterThread() {
super("Log File Writer Thread");
@@ -83,8 +130,80 @@
public void run() {
Object o = null;
+ long thisTime = System.currentTimeMillis();
+ long prevTime;
+ long nextHour = -1;
+ GregorianCalendar gc = null;
+ String filename = null;
+ if(baseFilename != null) {
+ gc = new GregorianCalendar();
+ filename = getHourLogName(gc);
+ uout = openNewLogFile(filename);
+ switch(INTERVAL) {
+ case Calendar.YEAR:
+ gc.set(Calendar.MONTH, 0);
+ case Calendar.MONTH:
+ gc.set(Calendar.DAY_OF_MONTH, 0);
+ case Calendar.WEEK_OF_YEAR:
+ if(INTERVAL == Calendar.WEEK_OF_YEAR)
+ gc.set(Calendar.DAY_OF_WEEK, 0);
+ case Calendar.DAY_OF_MONTH:
+ gc.set(Calendar.HOUR, 0);
+ case Calendar.HOUR:
+ gc.set(Calendar.MINUTE, 0);
+ case Calendar.MINUTE:
+ gc.set(Calendar.SECOND, 0);
+ gc.set(Calendar.MILLISECOND, 0);
+ }
+ gc.add(INTERVAL, 1);
+ nextHour = gc.getTimeInMillis();
+ System.err.println("Start time: "+gc);
+ lout = new PrintStream(uout);
+ }
+ freenet.Core.logStream = lout; // FIXME
+ if(redirectStdOut)
+ System.setOut(lout);
+ if(redirectStdErr)
+ System.setErr(lout);
while(true) {
try {
+ prevTime = thisTime;
+ thisTime = System.currentTimeMillis();
+ if(baseFilename != null) {
+ if(thisTime > nextHour) {
+ // Switch logs
+ try {
+ uout.flush();
+ } catch (IOException e) {
+ System.err.println("Flushing on change caught "+e);
+ }
+ String oldFilename = filename;
+ filename = getHourLogName(gc);
+ OutputStream os = openNewLogFile(filename);
+ OutputStream oldUout = uout;
+ uout = os;
+ lout = new PrintStream(uout);
+ if(redirectStdOut)
+ System.setOut(lout);
+ if(redirectStdErr)
+ System.setErr(lout);
+ freenet.Core.logStream = lout; // FIXME
+ try {
+ oldUout.close();
+ } catch (IOException e) {
+ System.err.println("Closing on change caught "+e);
+ }
+ System.err.println("Almost rotated");
+ if(useNativeGzip) {
+ CompressorThread ct = new
CompressorThread(oldFilename);
+ ct.start();
+ // Don't care about result
+ } // FIXME: implement a portable default compressor
+ gc.add(INTERVAL, 1);
+ nextHour = gc.getTimeInMillis();
+ System.err.println("Rotated");
+ }
+ }
if(uout != null) {
myWrite(uout, null);
} else lout.flush();
@@ -94,6 +213,7 @@
try {
list.wait(500);
} catch (InterruptedException e) {};
+ if(list.size() == 0) continue;
}
o = list.removeFirst();
listBytes -= (((byte[])o).length+16);
@@ -132,11 +252,83 @@
Thread.sleep(sleepTime);
} catch (InterruptedException e) {};
sleepTime += sleepTime;
+ if(sleepTime > 3600) sleepTime = 3600;
} else
return;
}
}
+ protected OutputStream openNewLogFile(String filename) {
+ while(true) {
+ long sleepTime = 1000;
+ try {
+ System.err.println("Creating new logfile "+filename);
+ return new FileOutputStream(filename, !logOverwrite);
+ } catch (IOException e) {
+ System.err.println("Could not create FOS "+filename+": "+e);
+ System.err.println("Sleeping "+sleepTime/1000+" seconds");
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException ex) {};
+ sleepTime += sleepTime;
+ }
+ }
+ }
+ }
+
+ protected int runningCompressors = 0;
+ protected Object runningCompressorsSync = new Object();
+
+ class CompressorThread extends Thread {
+ protected String filename;
+
+ public CompressorThread(String fn) {
+ super("Logfile compressor thread");
+ this.filename = fn;
+ }
+
+ public void run() {
+ synchronized(runningCompressorsSync) {
+ runningCompressors++;
+ if(runningCompressors > 3) { // try to absorb a spike...
+ System.err.println("Too many compressors ("+
+ runningCompressors+") running!");
+ return;
+ }
+ }
+ try {
+ System.err.println("Starting gzip "+filename);
+ Process r = Runtime.getRuntime().exec(new String[] {
+ "gzip", filename });
+ System.err.println("Started gzip "+filename);
+ InputStream is = r.getInputStream();
+ InputStream es = r.getErrorStream();
+ while(true) {
+ byte[] buf = new byte[1024];
+ try {
+ is.read(buf, 0, buf.length);
+ } catch (IOException e) {};
+ try {
+ es.read(buf, 0, buf.length);
+ } catch (IOException e) {};
+ try {
+ r.exitValue();
+ break;
+ } catch (IllegalThreadStateException e) {}
+ }
+ System.err.println("Finished gzip "+filename);
+ is.close();
+ es.close();
+ } catch (IOException e) {
+ System.err.println("Cannot compress old logfile "+
+ filename);
+ e.printStackTrace(System.err);
+ } finally {
+ synchronized(runningCompressorsSync) {
+ runningCompressors--;
+ }
+ }
+ }
}
/**
@@ -152,17 +344,23 @@
* @exception IOException if the file couldn't be opened for append.
*/
public FileLoggerHook(String filename, String fmt,
- String dfmt, int threshold, boolean assumeWorking)
+ String dfmt, int threshold, boolean assumeWorking,
+ boolean logOverwrite)
throws IOException {
- this(new FileOutputStream(filename, true), fmt, dfmt, threshold);
+ this(false, filename, fmt, dfmt, threshold, assumeWorking,
+ logOverwrite);
+ }
+ private void checkStdStreams() {
// Redirect System.err and System.out to the Logger Printstream
// if they don't exist (like when running under javaw)
- if(!assumeWorking) {
System.out.print(" \b");
- if(System.out.checkError()) System.setOut(lout);
+ if(System.out.checkError()) {
+ redirectStdOut = true;
+ }
System.err.print(" \b");
- if(System.err.checkError()) System.setErr(lout);
+ if(System.err.checkError()) {
+ redirectStdErr = true;
}
}
@@ -182,7 +380,40 @@
*/
public FileLoggerHook(PrintStream stream, String fmt, String dfmt,
int threshold) {
+ this(fmt, dfmt, threshold);
lout = stream;
+ WriterThread wt = new WriterThread();
+ //wt.setDaemon(true);
+ CloserThread ct = new CloserThread();
+ Runtime.getRuntime().addShutdownHook(ct);
+ wt.start();
+ }
+
+ public FileLoggerHook(boolean rotate, String baseFilename, String fmt,
+ String dfmt, int threshold, boolean assumeWorking,
+ boolean logOverwrite)
+ throws IOException {
+ this(fmt, dfmt, threshold);
+ this.logOverwrite = logOverwrite;
+ //System.err.println("Creating FileLoggerHook with threshold "+threshold);
+ if(!assumeWorking)
+ checkStdStreams();
+ if(rotate) {
+ lout = null;
+ this.baseFilename = baseFilename;
+ } else {
+ lout = new PrintStream(new FileOutputStream(baseFilename,
+ !logOverwrite));
+ }
+ WriterThread wt = new WriterThread();
+ //wt.setDaemon(true);
+ CloserThread ct = new CloserThread();
+ Runtime.getRuntime().addShutdownHook(ct);
+ wt.start();
+ }
+
+ private FileLoggerHook(String fmt, String dfmt,
+ int threshold) {
this.threshold = threshold;
if (dfmt != null && !dfmt.equals("")) {
try {
@@ -231,15 +462,10 @@
this.str = new String[strVec.size()];
str = (String[])strVec.toArray(str);
- WriterThread wt = new WriterThread();
- //wt.setDaemon(true);
- CloserThread ct = new CloserThread();
- Runtime.getRuntime().addShutdownHook(ct);
- wt.start();
}
public void log(Object o, Class c, String msg, Throwable e, int priority){
- if (!acceptPriority(priority)) return;
+ if (!shouldLog(priority, c)) return;
if(closed) return;
Index: LRUQueue.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/LRUQueue.java,v
retrieving revision 1.3
retrieving revision 1.3.6.1
diff -u -w -r1.3 -r1.3.6.1
--- LRUQueue.java 12 Apr 2002 21:44:10 -0000 1.3
+++ LRUQueue.java 28 Oct 2003 20:20:45 -0000 1.3.6.1
@@ -1,16 +1,19 @@
package freenet.support;
import java.util.Enumeration;
+import java.util.Hashtable;
public class LRUQueue {
/*
- * I moves this over to a linked list from a vector, because thinking
- * about the way it was was keeping me awake at night.
- *
- * It is still O(n) but at least this looses all the memcopies.
+ * I've just converted this to using the DLList and Hashtable
+ * this makes it Hashtable time instead of O(N) for push and
+ * remove, and Hashtable time instead of O(1) for pop. Since
+ * push is by far the most done operation, this should be an
+ * overall improvement.
*/
private final DoublyLinkedListImpl list = new DoublyLinkedListImpl();
+ private final Hashtable hash = new Hashtable();
/**
* push()ing an object that is already in
@@ -19,37 +22,37 @@
* a duplicate entry in the queue.
*/
public final synchronized void push(Object obj) {
- QItem insert = null;
- for (Enumeration e = list.forwardElements() ; e.hasMoreElements() ;) {
- QItem qi = (QItem) e.nextElement();
- if (obj.equals(qi.obj)) {
- insert = qi;
- list.remove(qi);
- break;
- }
- }
- if (insert == null)
+ QItem insert = (QItem)hash.get(obj);
+ if (insert == null) {
insert = new QItem(obj);
+ hash.put(obj,insert);
+ } else {
+ list.remove(insert);
+ }
list.unshift(insert);
}
// Least recently pushed Object.
public final synchronized Object pop() {
- return list.size() > 0 ? ((QItem) list.pop()).obj : null;
+ if ( list.size() > 0 ) {
+ return ((QItem)hash.remove(((QItem)list.pop()).obj)).obj;
+ } else {
+ return null;
+ }
}
public final int size() {
return list.size();
}
- public final synchronized void remove(Object obj) {
- for (Enumeration e = list.forwardElements() ; e.hasMoreElements() ;) {
- QItem qi = (QItem) e.nextElement();
- if (obj.equals(qi.obj)) {
- list.remove(qi);
- break;
- }
+ public final synchronized boolean remove(Object obj) {
+ QItem i = (QItem)(hash.remove(obj));
+ if(i != null) {
+ list.remove(i);
+ return true;
+ } else {
+ return false;
}
}
Index: LimitCounter.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/LimitCounter.java,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.6.1
diff -u -w -r1.1.1.1 -r1.1.1.1.6.1
--- LimitCounter.java 13 Jan 2002 05:24:57 -0000 1.1.1.1
+++ LimitCounter.java 28 Oct 2003 20:20:45 -0000 1.1.1.1.6.1
@@ -31,6 +31,12 @@
checkTimeout();
return count > maxCount;
}
+
+ // Currently dumps the current status to a string
+ public synchronized String toString() {
+ checkTimeout();
+ return count+"/"+maxCount+" ("+Float.toString(((float)count /
(float)maxCount*100f))+"%)";
+ }
// for the *current interval*.
public synchronized float rate() {
Index: Logger.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/Logger.java,v
retrieving revision 1.7.4.1
retrieving revision 1.7.4.1.2.1
diff -u -w -r1.7.4.1 -r1.7.4.1.2.1
--- Logger.java 9 Jan 2003 01:42:36 -0000 1.7.4.1
+++ Logger.java 28 Oct 2003 20:20:45 -0000 1.7.4.1.2.1
@@ -25,6 +25,7 @@
* this.
*/
public Logger(int threshold) {
+// System.err.println("Creating Logger with threshold "+threshold);
this.threshold = threshold;
hooks = new Vector();
}
@@ -38,7 +39,7 @@
* Logger.NORMAL, Logger.MINOR, or Logger.DEBUGGING.
**/
public void log(Object source, String message, int priority) {
- if (!acceptPriority(priority)) return;
+ if (!shouldLog(priority,source)) return;
log(source, source == null ? null : source.getClass(),
message, null, priority);
}
@@ -54,7 +55,7 @@
*/
public void log(Object o, String message, Throwable e,
int priority) {
- if (!acceptPriority(priority)) return;
+ if (!shouldLog(priority,o)) return;
log(o, o == null ? null : o.getClass(), message, e, priority);
}
@@ -66,7 +67,7 @@
* Logger.NORMAL, Logger.MINOR, or Logger.DEBUGGING.
*/
public void log(Class c, String message, int priority) {
- if (!acceptPriority(priority)) return;
+ if (!shouldLog(priority,c)) return;
log(null, c, message, null, priority);
}
@@ -80,7 +81,7 @@
*/
public void log(Class c, String message, Throwable e,
int priority) {
- if (!acceptPriority(priority)) return;
+ if (!shouldLog(priority,c)) return;
log(null, c, message, e, priority);
}
Index: LoggerHook.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/LoggerHook.java,v
retrieving revision 1.5.4.1
retrieving revision 1.5.4.1.2.1
diff -u -w -r1.5.4.1 -r1.5.4.1.2.1
--- LoggerHook.java 9 Jan 2003 01:42:36 -0000 1.5.4.1
+++ LoggerHook.java 28 Oct 2003 20:20:45 -0000 1.5.4.1.2.1
@@ -1,9 +1,24 @@
package freenet.support;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
public abstract class LoggerHook {
public int threshold;
+ public static final class DetailedThreshold {
+ final String section;
+ final int dThreshold;
+ public DetailedThreshold(String section, int thresh) {
+ this.section = section;
+ this.dThreshold = thresh;
+ }
+ }
+
+ public DetailedThreshold[] detailedThresholds =
+ new DetailedThreshold[0];
+
/** These indicate the verbosity levels for calls to log() **/
/** This message indicates an error which prevents correct functionality**/
@@ -36,15 +51,8 @@
public abstract long anyFlags(); // accept if any of these bits set
- public boolean acceptPriority(int prio)
- {
- long mf = minFlags();
- long nf = notFlags();
- long af = anyFlags();
- if ((prio & mf) != mf) return false;
- if ((prio & nf) != 0) return false;
- if ((prio & af) != 0) return true;
- return false;
+ public boolean acceptPriority(int prio) {
+ return prio >= threshold;
}
/**
@@ -55,4 +63,53 @@
this.threshold = thresh;
}
+ public void setDetailedThresholds(String details) {
+// System.err.println("Setting detailed thresholds for "+this+
+// ": "+details);
+ if(details == null || details.length() == 0) return;
+ StringTokenizer st = new StringTokenizer(details,",",false);
+ Vector stuff = new Vector();
+ while(st.hasMoreTokens()) {
+ String token = st.nextToken();
+// System.err.println("Got token: "+token);
+ if(token.length() == 0) continue;
+ int x = token.indexOf(':');
+ if(x < 0) continue;
+ if(x == token.length() - 1) continue;
+ String section = token.substring(0, x);
+ String value = token.substring(x+1, token.length());
+ int thresh = Logger.priorityOf(value);
+// System.err.println("Pair: "+section+" : "+value);
+ stuff.add(new DetailedThreshold(section, thresh));
+ }
+ DetailedThreshold[] newThresholds =
+ new DetailedThreshold[stuff.size()];
+ stuff.toArray(newThresholds);
+ detailedThresholds = newThresholds;
+ }
+
+ public boolean shouldLog(int priority, Class c) {
+ int thresh = threshold;
+// System.err.println(this+"shouldLog("+priority+","+c+"), thresh="+thresh);
+ if(c != null) {
+ String cname = c.getName();
+ if(detailedThresholds.length > 0) {
+ for(int i=0;i<detailedThresholds.length;i++) {
+ DetailedThreshold dt = detailedThresholds[i];
+ if(cname.startsWith(dt.section)) {
+ thresh = dt.dThreshold;
+// System.err.println(cname+" starts with "+dt.section+"("+
+// dt.dThreshold+")");
+ }
+ }
+ }
+ }
+// System.err.println("Leaving: "+this+"shouldLog("+priority+","+c+
+// "), thresh="+thresh);
+ return priority >= thresh;
+ }
+
+ public final boolean shouldLog(int prio, Object o) {
+ return shouldLog(prio, o.getClass());
+ }
}
Index: MultiValueTable.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/MultiValueTable.java,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.6.1
diff -u -w -r1.1.1.1 -r1.1.1.1.6.1
--- MultiValueTable.java 13 Jan 2002 05:24:57 -0000 1.1.1.1
+++ MultiValueTable.java 28 Oct 2003 20:20:45 -0000 1.1.1.1.6.1
@@ -68,6 +68,18 @@
v.elements());
}
+ public int countAll(Object key) {
+ Vector v = (Vector)table.get(key);
+ if(v != null)
+ return v.size();
+ else
+ return 0;
+ }
+
+ public Object getSync(Object key) {
+ return table.get(key);
+ }
+
public Object[] getArray(Object key) {
synchronized (table) {
Vector v = (Vector) table.get(key);
Index: SimpleDataObjectStore.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/SimpleDataObjectStore.java,v
retrieving revision 1.4.2.4.2.3
retrieving revision 1.4.2.4.2.4
diff -u -w -r1.4.2.4.2.3 -r1.4.2.4.2.4
--- SimpleDataObjectStore.java 2 Aug 2003 02:36:19 -0000 1.4.2.4.2.3
+++ SimpleDataObjectStore.java 28 Oct 2003 20:20:45 -0000 1.4.2.4.2.4
@@ -1,3 +1,4 @@
+/* -*- Mode: java; c-basic-indent: 4; tab-width: 4 -*- */
package freenet.support;
import freenet.Core;
import freenet.support.Comparator;
Index: TempBucketFactory.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/TempBucketFactory.java,v
retrieving revision 1.2.2.4.2.2
retrieving revision 1.2.2.4.2.3
diff -u -w -r1.2.2.4.2.2 -r1.2.2.4.2.3
--- TempBucketFactory.java 2 Aug 2003 02:36:19 -0000 1.2.2.4.2.2
+++ TempBucketFactory.java 28 Oct 2003 20:20:45 -0000 1.2.2.4.2.3
@@ -73,12 +73,12 @@
do {
if (tmpDir != null) {
f = new File(tmpDir, "tbf_" +
- Long.toHexString(Math.abs(Core.randSource.nextInt())));
+ Long.toHexString(Math.abs(Core.getRandSource().nextInt())));
Core.logger.log(this, "Temp file in "+tmpDir,
Core.logger.DEBUG);
} else {
f = new File("tbf_" +
- Long.toHexString(Math.abs(Core.randSource.nextInt())));
+ Long.toHexString(Math.abs(Core.getRandSource().nextInt())));
Core.logger.log(this, "Temp file in pwd",
Core.logger.DEBUG);
}
Index: TempFileBucket.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/TempFileBucket.java,v
retrieving revision 1.1.2.6.2.4
retrieving revision 1.1.2.6.2.5
diff -u -w -r1.1.2.6.2.4 -r1.1.2.6.2.5
--- TempFileBucket.java 13 May 2003 01:55:46 -0000 1.1.2.6.2.4
+++ TempFileBucket.java 28 Oct 2003 20:20:45 -0000 1.1.2.6.2.5
@@ -286,7 +286,7 @@
ol = l;
}
if(fakeLength != l) {
- if(Core.logger.shouldLog(Logger.DEBUG))
+ if(Core.logger.shouldLog(Logger.DEBUG,this))
Core.logger.log(this, "getLengthSynchronized("+len+"): increasing "+
fakeLength+" to: "+l+" (real length: "+length+")",
Logger.DEBUG);
@@ -313,7 +313,7 @@
long restartCount) throws IOException {
super(s, append, restartCount);
streams.addElement(this);
- if(Core.logger.shouldLog(Logger.DEBUG))
+ if(Core.logger.shouldLog(Logger.DEBUG,this))
Core.logger.log(this, "Created HookedFileBucketOutputStream("+s+","+
append+","+restartCount+")", Logger.DEBUG);
}
_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs