org.erights.e.develop.trace
Class TraceLog

java.lang.Object
  |
  +--org.erights.e.develop.trace.TraceLog
All Implemented Interfaces:
TraceConstants, TraceMessageAcceptor

class TraceLog
extends Object
implements TraceMessageAcceptor, TraceConstants

This class manages dumping of messages to the semi-permanent on-disk log.


Field Summary
static String[] acceptorNames
           
static int ADD
           
static int DEBUG
           
static String DEFAULT_NAME
           
static int ERROR
          The different trace thresholds.
static int EVENT
           
static int FOR_SUBSYSTEM
           
static int FROM_DEFAULT
          When referring to thresholds, are we talking about those from the default thresholds, or ones specific to a subsystem? XXX These could be interned strings, but interning didn't work right in 1.0.4.
static int IRRELEVANT
           
private static int lineSeparatorLength
          This variable is used to count accurately the size of the log.
static int LOG
          This identifies the TraceMessageAcceptor used for the on-disk log.
static String LOG_EXTENSION
           
static int MAX_THRESHOLD
           
private  int myBackupAction
          Determine whether to rename full log files and open new ones, or to empty a full log file.
private  TraceLogDescriptor myCurrent
          The log to which messages are currently flowing.
private  long myCurrentSize
          Number of characters in the current log file.
private  Object myLock
           
private  long myMaxSize
          The definition, in number of characters, of what a full log file is.
private  TraceLogDescriptor myPending
          The user can change the characteristics of this log descriptor, then redirect the log to it.
private  boolean mySetupComplete
          True if all the initial properties have been processed.
private  TraceMessageStringifier myStringifier
          This converts a TraceMessage into the kind of string we like.
private  boolean myWrite
          Determine whether a log file should be written at all.
static int NUM_ACCEPTORS
          The number of different types of TraceMessageAcceptors.
static int OVERWRITE
           
private  Vector queuedMessages
          Messages are queued here before the Log is initialized and while switching to a new logfile.
static String[] reasonNames
           
static long SMALLEST_LOG_SIZE_THRESHOLD
           
static int STARTING_LOG_BACKUP_ACTION
           
static File STARTING_LOG_DIR
           
static long STARTING_LOG_SIZE_THRESHOLD
           
static String STARTING_LOG_TAG
           
static int STARTING_LOG_THRESHOLD
           
static boolean STARTING_LOG_WRITE
           
static int STARTING_TRACE_BUFFER_SIZE
           
static int STARTING_TRACE_THRESHOLD
           
static int TIMING
          As a late addition, there's a "timing" boolean that can be set orthogonally from the thresholds.
static int TRACE
          This identifies the TraceMessageAcceptor used for the in-core trace and its associated window.
static String UNLIMITED_NAME
           
static int USAGE
           
static int VERBOSE
           
static String version
           
static int WARNING
           
static int WORLD
           
 
Constructor Summary
(package private) TraceLog()
          Construct the trace log.
 
Method Summary
 void accept(TraceMessage message)
          Accept a message for the log.
private  void acceptBypassingQueue(TraceMessage message)
          that we will Take a message and log it.
private  void beginLogging()
          Call to initialize a log when logging is just beginning (or resuming after having been turned off).
(package private)  void changeBackupFileHandling(String newBehavior)
          Change how a full logfile handles its backup files.
(package private)  void changeDir(String value)
          Change the default directory in which logfiles live.
(package private)  void changeName(String value)
          Explicitly set the name of the next logfile to open.
(package private)  void changeSize(String value)
          Change the new maximum allowable size for a logfile.
(package private)  void changeTag(String value)
          Change the 'tag' (base of filename) that logfiles have.
(package private)  void changeWrite(String value)
          The meaning of changeWrite is complicated.
private  void drainQueue()
          Deal with messages on the queue.
private  void handleFullLog()
          Call when the logfile fills up.
private  void hotSwap()
          Call to switch to a log when another - with a different name - is currently being used.
private  boolean isAcceptingMessages()
          The log accepts messages if the "TraceLog_write" property was set.
private  boolean isQueuing()
           
(package private)  void reopen(String ignored)
          The gist of this routine is that it shuts down the current log and reopens a new one (possibly with the same name, possibly with a different name).
 void setupIsComplete()
          Call this only after all properties have been processed.
private  void shutdownAndSwap()
          Call to initialize a log when the same file is already open.
private  void startQueuing()
          Redirect trace messages to a queue.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

myLock

private final Object myLock

myBackupAction

private int myBackupAction
Determine whether to rename full log files and open new ones, or to empty a full log file.


myWrite

private boolean myWrite
Determine whether a log file should be written at all.


myMaxSize

private long myMaxSize
The definition, in number of characters, of what a full log file is.


myCurrentSize

private long myCurrentSize
Number of characters in the current log file.


myCurrent

private TraceLogDescriptor myCurrent
The log to which messages are currently flowing. Initially null, but all messages will normally be queued until it's pointed at a log file or stdout. Messages will be redirected to stdout if a given logfile can't be opened.


myPending

private TraceLogDescriptor myPending
The user can change the characteristics of this log descriptor, then redirect the log to it.

Characteristics are changed via properties like "TraceLog_tag". Redirection is done via "TraceLog_reopen".


mySetupComplete

private boolean mySetupComplete
True if all the initial properties have been processed.


myStringifier

private final TraceMessageStringifier myStringifier
This converts a TraceMessage into the kind of string we like.


lineSeparatorLength

private static final int lineSeparatorLength
This variable is used to count accurately the size of the log. Note that I don't try to catch a SecurityException if one occurs. We'll have other, bigger, problems if that happens.


queuedMessages

private Vector queuedMessages
Messages are queued here before the Log is initialized and while switching to a new logfile.


version

public static final String version

LOG

public static final int LOG
This identifies the TraceMessageAcceptor used for the on-disk log.


TRACE

public static final int TRACE
This identifies the TraceMessageAcceptor used for the in-core trace and its associated window.


NUM_ACCEPTORS

public static final int NUM_ACCEPTORS
The number of different types of TraceMessageAcceptors.


acceptorNames

public static final String[] acceptorNames

ERROR

public static final int ERROR
The different trace thresholds. See the Trace class for documentation. There is space between the levels for expansion. If you add or delete a level, you must change Trace.java to add new methods and variables.


WARNING

public static final int WARNING

WORLD

public static final int WORLD

USAGE

public static final int USAGE

EVENT

public static final int EVENT

DEBUG

public static final int DEBUG

VERBOSE

public static final int VERBOSE

MAX_THRESHOLD

public static final int MAX_THRESHOLD

TIMING

public static final int TIMING
As a late addition, there's a "timing" boolean that can be set orthogonally from the thresholds. The above values are overloaded: thresholds, but also identifiers for the original message (was it sent with errorm(), etc.). The TIMING "level" is added for the latter purpose, but it has nothing to do with thresholds. To avoid confusion, it's set negative, thus below the minimum threshold.


FROM_DEFAULT

public static final int FROM_DEFAULT
When referring to thresholds, are we talking about those from the default thresholds, or ones specific to a subsystem? XXX These could be interned strings, but interning didn't work right in 1.0.4. That is, two "default" strings weren't eq.


FOR_SUBSYSTEM

public static final int FOR_SUBSYSTEM

reasonNames

public static final String[] reasonNames

STARTING_TRACE_BUFFER_SIZE

public static final int STARTING_TRACE_BUFFER_SIZE

STARTING_TRACE_THRESHOLD

public static final int STARTING_TRACE_THRESHOLD

STARTING_LOG_SIZE_THRESHOLD

public static final long STARTING_LOG_SIZE_THRESHOLD

SMALLEST_LOG_SIZE_THRESHOLD

public static final long SMALLEST_LOG_SIZE_THRESHOLD

STARTING_LOG_THRESHOLD

public static final int STARTING_LOG_THRESHOLD

STARTING_LOG_WRITE

public static final boolean STARTING_LOG_WRITE

IRRELEVANT

public static final int IRRELEVANT

ADD

public static final int ADD

OVERWRITE

public static final int OVERWRITE

STARTING_LOG_BACKUP_ACTION

public static final int STARTING_LOG_BACKUP_ACTION

STARTING_LOG_DIR

public static final File STARTING_LOG_DIR

STARTING_LOG_TAG

public static final String STARTING_LOG_TAG

LOG_EXTENSION

public static final String LOG_EXTENSION

DEFAULT_NAME

public static final String DEFAULT_NAME

UNLIMITED_NAME

public static final String UNLIMITED_NAME
Constructor Detail

TraceLog

TraceLog()
Construct the trace log. Queue messages until setup is complete.

Method Detail

accept

public void accept(TraceMessage message)
Accept a message for the log. It will be discarded if both writing and the queue are turned off.

Specified by:
accept in interface TraceMessageAcceptor

acceptBypassingQueue

private void acceptBypassingQueue(TraceMessage message)
that we will Take a message and log it. The queue of pending messages maintained before setup is complete is bypassed, because this is the method used to drain that queue.


beginLogging

private void beginLogging()
Call to initialize a log when logging is just beginning (or resuming after having been turned off). There is no current log, so nothing is written to it. If the pending log cannot be opened, standard output is used as the log. In any case, the queue is drained just before the method returns.


changeBackupFileHandling

void changeBackupFileHandling(String newBehavior)
Change how a full logfile handles its backup files. "one" or "1" means that there will be at most one backup file, which will be overwritten if needed. "many" means a new backup file with a new name should be created each time the base file fills up. Has effect when the next log file fills up.


changeDir

void changeDir(String value)
Change the default directory in which logfiles live. Has effect only when a new logfile is opened.


changeName

void changeName(String value)
Explicitly set the name of the next logfile to open. Overrides the effect of "TraceLog_dir" only if the given name is absolute. Has effect only when a new logfile is opened.


changeSize

void changeSize(String value)
Change the new maximum allowable size for a logfile. Has effect on the current logfile. Note that the trace system does not prevent the log from exceeding this size; it only opens a new log file as soon as it does.


changeTag

void changeTag(String value)
Change the 'tag' (base of filename) that logfiles have. Has effect only when a new logfile is opened.


changeWrite

void changeWrite(String value)
The meaning of changeWrite is complicated. Here are the cases when it's used to turn writing ON.

If setup is still in progress, the state variable 'myWrite' is used to note that logging should begin when setupIsComplete() is called.

If setup is complete, logging should begin immediately. If logging has already begun, this is a no-op.

Here are the cases for turning writing OFF.

If setup is not complete, the state variable 'myWrite' informs setupIsComplete() that logging should not begin.

If setup is complete, logging is stopped. However, if it was already stopped, the call is a no-op.

There would be some merit in having a state machine implement all this.


drainQueue

private final void drainQueue()
Deal with messages on the queue. If the log is turned on (myWrite is true), they are written. Otherwise, they are discarded. It is safe to call this routine without knowing whether queuing is in progress.


handleFullLog

private void handleFullLog()
Call when the logfile fills up. Reopens the same log file.

Standard output can never fill up, so this routine is a no-op when the current size of text sent to standard out exceeds the maximum, except that the current size is reset to zero.


hotSwap

private void hotSwap()
Call to switch to a log when another - with a different name - is currently being used. If the pending log cannot be opened, the current log continues to be used.

Before the old log is closed, a USAGE message is logged, directing the reader to the new log. Trace messages may be queued while the swap is happening, but the queue is drained before the method returns.

This routine is never called when the logfile fills - it's only used when explicitly reopening a log file. (TraceLog_reopen=true).


isAcceptingMessages

private final boolean isAcceptingMessages()
The log accepts messages if the "TraceLog_write" property was set. Before setup is completed, it also accepts and queues up messages. When setup is complete, it either posts or discards those queued messages, depending on what the user wants.

Queuing also happens transitorily while logs are being switched.


isQueuing

private final boolean isQueuing()

reopen

void reopen(String ignored)
The gist of this routine is that it shuts down the current log and reopens a new one (possibly with the same name, possibly with a different name). There are some special cases, because this routine could be called before setup is complete (though using TraceLog_reopen in the initial Properties is deprecated).

When it's called before setup is complete and writing is not enabled, the behavior is the same as TraceLog_write [the preferred interface].

When it's called before setup is complete and writing is enabled, the effect is that of calling TraceLog_write twice (a warning).

When it's called after setup is complete and writing is not enabled, the behavior is the same as calling TraceLog_write [again, the preferred interface, because you're not "reopening" anything].

When it's called after setup is complete and writing is enabled; this is the way it's supposed to be used. The current log is closed and the pending log is opened.


setupIsComplete

public void setupIsComplete()
Call this only after all properties have been processed. It begins logging, but only if TraceLog_write or TraceLog_reopen have been used, or if the default behavior is to write.

Specified by:
setupIsComplete in interface TraceMessageAcceptor

shutdownAndSwap

private void shutdownAndSwap()
Call to initialize a log when the same file is already open. The old file must be closed before it can be renamed to a backup version. (This is either a Windows or java.io restriction.) If the pending log cannot be opened, standard output is used.

Before the old log is closed, a USAGE message is logged, directing the reader to the new log. Trace messages may be queued while the swap is happening, but the queue is drained before the method returns.

This routine can be called to backup a full logfile, or to explicitly reopen the same logfile (via TraceLog_reopen=true).


startQueuing

private final void startQueuing()
Redirect trace messages to a queue. Used while switching to a new log file, or before setup is complete.

It is harmless to call this routine twice.



comments?