diff --git a/src/helma/util/Logger.java b/src/helma/util/Logger.java index 6a5e3ac6..9700d5fb 100644 --- a/src/helma/util/Logger.java +++ b/src/helma/util/Logger.java @@ -11,11 +11,14 @@ import java.text.*; * Utility class for asynchronous logging. */ -public class Logger implements Runnable { +public final class Logger { - private Thread logger; + // we use one static thread for all Loggers + static Runner runner; + // the list of active loggers + static ArrayList loggers; - private Vector entries; + private LinkedList entries; private String filename; private String dirname; private File dir; @@ -27,23 +30,31 @@ public class Logger implements Runnable { private long dateLastRendered; private String dateCache; private PrintStream out = null; + boolean closed = false; + /** + * Create a logger for a PrintStream, such as System.out. + */ public Logger (PrintStream out) { - dformat = DateFormat.getInstance (); + dformat = new SimpleDateFormat ("[yyyy/MM/dd HH:mm] "); this.out = out; - entries = new Vector (); - logger = new Thread (this); - // logger.setPriority (Thread.MIN_PRIORITY+2); - logger.start (); + entries = new LinkedList (); + + // register this instance with static logger list + start (this); } + /** + * Create a file logger. The actual file names do have numbers appended and are + * rotated every x bytes. + */ public Logger (String dirname, String filename) throws IOException { if (filename == null || dirname == null) throw new IOException ("Logger can't use null as file or directory name"); this.filename = filename; this.dirname = dirname; nformat = new DecimalFormat ("00000"); - dformat = DateFormat.getInstance (); + dformat = new SimpleDateFormat ("[yyyy/MM/dd HH:mm] "); dir = new File (dirname); if (!dir.exists()) dir.mkdirs (); @@ -51,17 +62,20 @@ public class Logger implements Runnable { while (currentFile.exists()) currentFile = new File (dir, filename+nformat.format(++fileindex)+".log"); currentWriter = new PrintWriter (new FileWriter (currentFile), false); - entries = new Vector (); - logger = new Thread (this); - // logger.setPriority (Thread.MIN_PRIORITY+2); - logger.start (); + entries = new LinkedList (); + + // register this instance with static logger list + start (this); } + /** + * Append a message with to the log. + */ public void log (String msg) { // it's enough to render the date every 15 seconds if (System.currentTimeMillis () - 15000 > dateLastRendered) renderDate (); - entries.addElement (dateCache + " " + msg); + entries.add (dateCache + msg); } private synchronized void renderDate () { @@ -69,34 +83,42 @@ public class Logger implements Runnable { dateCache = dformat.format (new Date()); } + /** + * This is called by the runner thread to perform actual IO. + */ public void run () { - while (Thread.currentThread () == logger) { - try { - if (currentFile != null && currentFile.length() > 10000000) { - // rotate log files each 10 megs - swapFile (); - } - - int l = entries.size(); - for (int i=0; i 10000000) { + // rotate log files each 10 megs + swapFile (); } + + int l = entries.size(); + if (out != null) { + for (int i=0; i=0; i--) { + Logger log = (Logger) loggers.get (i); + log.run (); + if (log.closed) { + loggers.remove (log); + log.closeFiles (); + } + } + try { + sleep (700); + } catch (InterruptedException ix) {} + } + } + + } + + + /** + * test main method + */ + public static void main (String[] args) throws IOException { + Logger log = new Logger (".", "testlog"); + long start = System.currentTimeMillis (); + for (int i=0; i<50000; i++) + log.log ("test log entry aasdfasdfasdfasdf"); + log.log ("done: "+(System.currentTimeMillis () - start)); + System.err.println (System.currentTimeMillis () - start); + System.exit (0); + } + }