You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ri...@apache.org on 2007/03/22 18:36:16 UTC

svn commit: r521363 - in /incubator/qpid/branches/M2/java: broker/etc/log4j.xml broker/src/main/java/org/apache/log4j/QpidCompositeRollingAppender.java integrationtests/

Author: ritchiem
Date: Thu Mar 22 10:36:15 2007
New Revision: 521363

URL: http://svn.apache.org/viewvc?view=rev&rev=521363
Log:
Updated the new Log4j appender to compress the backup files and move them to a new location.(Compression occurs async so as not to slow down the main program). Enable the logger in the log4j.xml Disabled by default.

Modified:
    incubator/qpid/branches/M2/java/broker/etc/log4j.xml
    incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/log4j/QpidCompositeRollingAppender.java
    incubator/qpid/branches/M2/java/integrationtests/   (props changed)

Modified: incubator/qpid/branches/M2/java/broker/etc/log4j.xml
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/broker/etc/log4j.xml?view=diff&rev=521363&r1=521362&r2=521363
==============================================================================
--- incubator/qpid/branches/M2/java/broker/etc/log4j.xml (original)
+++ incubator/qpid/branches/M2/java/broker/etc/log4j.xml Thu Mar 22 10:36:15 2007
@@ -21,20 +21,43 @@
  -->
 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-    <appender name="FileAppender" class="org.apache.log4j.QpidCompositeRollingAppender">
-        <param name="staticLogFileName" value="false"/>
+    <appender name="ArchivingFileAppender" class="org.apache.log4j.QpidCompositeRollingAppender">
+        <!-- Ensure that logs allways have the dateFormat set-->
+        <param name="StaticLogFileName" value="false"/>
         <param name="File" value="${QPID_WORK}/log/${logprefix}qpid${logsuffix}.log"/>
         <param name="Append" value="false"/>
         <!-- Change the direction so newer files have bigger numbers -->
         <!-- So log.1 is written then log.2 etc This prevents a lot of file renames at log rollover -->
         <param name="CountDirection" value="1"/>
-        <!--param name="MaxFileSize" value="1000"/ Use default 10MB -->
+        <!-- Use default 10MB -->
+        <!--param name="MaxFileSize" value="100000"/-->
         <param name="DatePattern" value="'.'yyyy-MM-dd-HH-mm"/>
         <!-- Unlimited number of backups -->
         <param name="MaxSizeRollBackups" value="-1"/>
+        <!-- Compress(gzip) the backup files-->
+        <param name="CompressBackupFiles" value="true"/>
+        <!-- Compress the backup files using a second thread -->
+        <param name="CompressAsync" value="true"/>
+        <!-- Start at zero numbered files-->
+        <param name="ZeroBased" value="true"/>
+        <!-- Backup Location -->
+        <param name="backupFilesToPath" value="${QPID_WORK}/backup/log"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
+            <!--param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/-->
+        </layout>
+    </appender>
+
+        <appender name="FileAppender" class="org.apache.log4j.FileAppender">
+        <param name="staticLogFileName" value="false"/>
+
+        <param name="File" value="${QPID_WORK}/log/${logprefix}qpid${logsuffix}.log"/>
+        <param name="Append" value="false"/>
 
         <layout class="org.apache.log4j.PatternLayout">
             <param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/>
+
         </layout>
     </appender>
 
@@ -47,18 +70,20 @@
 
     <!--<category name="org.apache.qpid.server.store">
         <priority value="debug"/>
-    </category>
+    </category-->
 
-    <category name="org.apache.qpid.server.queue">
+    <!--category name="org.apache.qpid.server.queue">
         <priority value="debug"/>
-    </category>
+    </category-->
 
-    <category name="org.apache.qpid.server.txn">
+    <!--category name="org.apache.qpid.server.txn">
         <priority value="debug"/>
     </category>-->
+
     <root>
         <priority value="info"/>
         <appender-ref ref="STDOUT"/>
         <appender-ref ref="FileAppender"/>
+        <!--appender-ref ref="ArchivingFileAppender"/-->
     </root>
 </log4j:configuration>

Modified: incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/log4j/QpidCompositeRollingAppender.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/log4j/QpidCompositeRollingAppender.java?view=diff&rev=521363&r1=521362&r2=521363
==============================================================================
--- incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/log4j/QpidCompositeRollingAppender.java (original)
+++ incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/log4j/QpidCompositeRollingAppender.java Thu Mar 22 10:36:15 2007
@@ -24,687 +24,976 @@
 import org.apache.log4j.helpers.CountingQuietWriter;
 import org.apache.log4j.helpers.LogLog;
 import org.apache.log4j.spi.LoggingEvent;
+import org.apache.qpid.framing.FieldTable;
 
 import java.util.Date;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.zip.GZIPOutputStream;
 import java.text.SimpleDateFormat;
 import java.io.IOException;
 import java.io.Writer;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 
 /**
- *  <p>CompositeRollingAppender combines RollingFileAppender and DailyRollingFileAppender<br>
- *  It can function as either or do both at the same time (making size
- *  based rolling files like RollingFileAppender until a data/time boundary
- *  is crossed at which time it rolls all of those files as per the DailyRollingFileAppender)
- *  based on the setting for <code>rollingStyle</code>.<br>
- *  <br>
- *  To use CompositeRollingAppender to roll log files as they reach a certain
- *  size (like RollingFileAppender), set rollingStyle=1 (@see config.size)<br>
- *  To use CompositeRollingAppender to roll log files at certain time intervals
- *  (daily for example), set rollingStyle=2 and a datePattern (@see config.time)<br>
- *  To have CompositeRollingAppender roll log files at a certain size AND rename those
- *  according to time intervals, set rollingStyle=3 (@see config.composite)<br>
+ * <p>CompositeRollingAppender combines RollingFileAppender and DailyRollingFileAppender<br> It can function as either
+ * or do both at the same time (making size based rolling files like RollingFileAppender until a data/time boundary is
+ * crossed at which time it rolls all of those files as per the DailyRollingFileAppender) based on the setting for
+ * <code>rollingStyle</code>.<br> <br> To use CompositeRollingAppender to roll log files as they reach a certain size
+ * (like RollingFileAppender), set rollingStyle=1 (@see config.size)<br> To use CompositeRollingAppender to roll log
+ * files at certain time intervals (daily for example), set rollingStyle=2 and a datePattern (@see config.time)<br> To
+ * have CompositeRollingAppender roll log files at a certain size AND rename those according to time intervals, set
+ * rollingStyle=3 (@see config.composite)<br>
  *
- *  <p>A of few additional optional features have been added:<br>
- *  -- Attach date pattern for current log file (@see staticLogFileName)<br>
- *  -- Backup number increments for newer files (@see countDirection)<br>
- *  -- Infinite number of backups by file size (@see maxSizeRollBackups)<br>
- *  <br>
- *  <p>A few notes and warnings:  For large or infinite number of backups
- *  countDirection > 0 is highly recommended, with staticLogFileName = false if
- *  time based rolling is also used -- this will reduce the number of file renamings
- *  to few or none.  Changing staticLogFileName or countDirection without clearing
- *  the directory could have nasty side effects.  If Date/Time based rolling
- *  is enabled, CompositeRollingAppender will attempt to roll existing files
- *  in the directory without a date/time tag based on the last modified date
- *  of the base log files last modification.<br>
- *  <br>
- *  <p>A maximum number of backups based on date/time boundries would be nice
- *  but is not yet implemented.<br>
+ * <p>A of few additional optional features have been added:<br> -- Attach date pattern for current log file (@see
+ * staticLogFileName)<br> -- Backup number increments for newer files (@see countDirection)<br> -- Infinite number of
+ * backups by file size (@see maxSizeRollBackups)<br> <br> <p>A few notes and warnings:  For large or infinite number of
+ * backups countDirection > 0 is highly recommended, with staticLogFileName = false if time based rolling is also used
+ * -- this will reduce the number of file renamings to few or none.  Changing staticLogFileName or countDirection
+ * without clearing the directory could have nasty side effects.  If Date/Time based rolling is enabled,
+ * CompositeRollingAppender will attempt to roll existing files in the directory without a date/time tag based on the
+ * last modified date of the base log files last modification.<br> <br> <p>A maximum number of backups based on
+ * date/time boundries would be nice but is not yet implemented.<br>
  *
- *  @author Kevin Steppe
- *  @author Heinz Richter
- *  @author Eirik Lygre
- *  @author Ceki G&uuml;lc&uuml;
- *  @author Martin Ritchie 
+ * @author Kevin Steppe
+ * @author Heinz Richter
+ * @author Eirik Lygre
+ * @author Ceki G&uuml;lc&uuml;
+ * @author Martin Ritchie
  */
 public class QpidCompositeRollingAppender extends FileAppender
 {
-	// The code assumes that the following 'time' constants are in a increasing
-	// sequence.
-	static final int TOP_OF_TROUBLE=-1;
-	static final int TOP_OF_MINUTE = 0;
-	static final int TOP_OF_HOUR   = 1;
-	static final int HALF_DAY      = 2;
-	static final int TOP_OF_DAY    = 3;
-	static final int TOP_OF_WEEK   = 4;
-	static final int TOP_OF_MONTH  = 5;
-
-	/** Style of rolling to use */
-	static final int BY_SIZE = 1;
-	static final int BY_DATE = 2;
-	static final int BY_COMPOSITE = 3;
-
-	//Not currently used
-	static final String S_BY_SIZE = "Size";
-	static final String S_BY_DATE = "Date";
-	static final String S_BY_COMPOSITE = "Composite";
-
-	/**
-	 The date pattern. By default, the pattern is set to
-	 "'.'yyyy-MM-dd" meaning daily rollover.
-	*/
-	private String datePattern = "'.'yyyy-MM-dd";
-
-	/**	 The actual formatted filename that is currently being written to
-	     or will be the file transferred to on roll over
-		 (based on staticLogFileName). */
-	private String scheduledFilename = null;
-
-	/** The timestamp when we shall next recompute the filename. */
-	private long nextCheck = System.currentTimeMillis () - 1;
-
-	/** Holds date of last roll over */
-	Date now = new Date();
-
-	SimpleDateFormat sdf;
-
-	/** Helper class to determine next rollover time */
-	RollingCalendar rc = new RollingCalendar();
-
-	/** Current period for roll overs */
-	int checkPeriod = TOP_OF_TROUBLE;
-
-	/**	 The default maximum file size is 10MB. */
-	protected long maxFileSize = 10*1024*1024;
-
-	/**	 There is zero backup files by default. */
-	protected int maxSizeRollBackups = 0;
-	/** How many sized based backups have been made so far */
-	protected int curSizeRollBackups = 0;
-
-	/** not yet implemented */
-	protected int maxTimeRollBackups = -1;
-	protected int curTimeRollBackups = 0;
-
-	/** By default newer files have lower numbers. (countDirection < 0)
-	 *  ie. log.1 is most recent, log.5 is the 5th backup, etc...
-	 *  countDirection > 0 does the opposite ie.
-	 *  log.1 is the first backup made, log.5 is the 5th backup made, etc.
-	 *  For infinite backups use countDirection > 0 to reduce rollOver costs.
-	 */
-	protected int countDirection = -1;
-
-	/** Style of rolling to Use.  BY_SIZE (1), BY_DATE(2), BY COMPOSITE(3) */
-	protected int rollingStyle = BY_COMPOSITE;
-	protected boolean rollDate = true;
-	protected boolean rollSize = true;
-
-	/** By default file.log is always the current file.  Optionally
-	 *  file.log.yyyy-mm-dd for current formated datePattern can by the currently
-	 *  logging file (or file.log.curSizeRollBackup or even
-	 *  file.log.yyyy-mm-dd.curSizeRollBackup) This will make time based roll
-	 *  overs with a large number of backups much faster -- it won't have to
-	 *  rename all the backups!
-	 */
-	protected boolean staticLogFileName = true;
-
-	/** FileName provided in configuration.  Used for rolling properly */
-	protected String baseFileName;
+    // The code assumes that the following 'time' constants are in a increasing
+    // sequence.
+    static final int TOP_OF_TROUBLE = -1;
+    static final int TOP_OF_MINUTE = 0;
+    static final int TOP_OF_HOUR = 1;
+    static final int HALF_DAY = 2;
+    static final int TOP_OF_DAY = 3;
+    static final int TOP_OF_WEEK = 4;
+    static final int TOP_OF_MONTH = 5;
+
+    /** Style of rolling to use */
+    static final int BY_SIZE = 1;
+    static final int BY_DATE = 2;
+    static final int BY_COMPOSITE = 3;
+
+    //Not currently used
+    static final String S_BY_SIZE = "Size";
+    static final String S_BY_DATE = "Date";
+    static final String S_BY_COMPOSITE = "Composite";
+
+    /** The date pattern. By default, the pattern is set to "'.'yyyy-MM-dd" meaning daily rollover. */
+    private String datePattern = "'.'yyyy-MM-dd";
+
+    /**
+     * The actual formatted filename that is currently being written to or will be the file transferred to on roll over
+     * (based on staticLogFileName).
+     */
+    private String scheduledFilename = null;
+
+    /** The timestamp when we shall next recompute the filename. */
+    private long nextCheck = System.currentTimeMillis() - 1;
+
+    /** Holds date of last roll over */
+    Date now = new Date();
+
+    SimpleDateFormat sdf;
+
+    /** Helper class to determine next rollover time */
+    RollingCalendar rc = new RollingCalendar();
+
+    /** Current period for roll overs */
+    int checkPeriod = TOP_OF_TROUBLE;
+
+    /** The default maximum file size is 10MB. */
+    protected long maxFileSize = 10 * 1024 * 1024;
+
+    /** There is zero backup files by default. */
+    protected int maxSizeRollBackups = 0;
+    /** How many sized based backups have been made so far */
+    protected int curSizeRollBackups = 0;
+
+    /** not yet implemented */
+    protected int maxTimeRollBackups = -1;
+    protected int curTimeRollBackups = 0;
+
+    /**
+     * By default newer files have lower numbers. (countDirection < 0) ie. log.1 is most recent, log.5 is the 5th
+     * backup, etc... countDirection > 0 does the opposite ie. log.1 is the first backup made, log.5 is the 5th backup
+     * made, etc. For infinite backups use countDirection > 0 to reduce rollOver costs.
+     */
+    protected int countDirection = -1;
+
+    /** Style of rolling to Use.  BY_SIZE (1), BY_DATE(2), BY COMPOSITE(3) */
+    protected int rollingStyle = BY_COMPOSITE;
+    protected boolean rollDate = true;
+    protected boolean rollSize = true;
+
+    /**
+     * By default file.log is always the current file.  Optionally file.log.yyyy-mm-dd for current formated datePattern
+     * can by the currently logging file (or file.log.curSizeRollBackup or even file.log.yyyy-mm-dd.curSizeRollBackup)
+     * This will make time based roll overs with a large number of backups much faster -- it won't have to rename all
+     * the backups!
+     */
+    protected boolean staticLogFileName = true;
+
+    /** FileName provided in configuration.  Used for rolling properly */
+    protected String baseFileName;
+
+
+    /** Do we want to .gz our backup files. */
+    protected boolean compress = false;
+
+    /** Do we want to use a second thread when compressing our backup files. */
+    protected boolean compressAsync = false;
+
+    /** Do we want to start numbering files at zero. */
+    protected boolean zeroBased = false;
+
+    /** Path provided in configuration.  Used for moving backup files to */
+    protected String backupFilesToPath = null;
+    private final ConcurrentLinkedQueue<CompressJob> _compress = new ConcurrentLinkedQueue<CompressJob>();
+    private AtomicBoolean _compressing = new AtomicBoolean(false);
 
     /** The default constructor does nothing. */
-	public QpidCompositeRollingAppender()  {
+    public QpidCompositeRollingAppender()
+    {
+    }
+
+    /**
+     * Instantiate a <code>CompositeRollingAppender</code> and open the file designated by <code>filename</code>. The
+     * opened filename will become the ouput destination for this appender.
+     */
+    public QpidCompositeRollingAppender(Layout layout, String filename,
+                                        String datePattern) throws IOException
+    {
+        this(layout, filename, datePattern, true);
+    }
+
+    /**
+     * Instantiate a CompositeRollingAppender and open the file designated by <code>filename</code>. The opened filename
+     * will become the ouput destination for this appender.
+     *
+     * <p>If the <code>append</code> parameter is true, the file will be appended to. Otherwise, the file desginated by
+     * <code>filename</code> will be truncated before being opened.
+     */
+    public QpidCompositeRollingAppender(Layout layout, String filename, boolean append)
+            throws IOException
+    {
+        super(layout, filename, append);
+    }
+
+    /**
+     * Instantiate a CompositeRollingAppender and open the file designated by <code>filename</code>. The opened filename
+     * will become the ouput destination for this appender.
+     */
+    public QpidCompositeRollingAppender(Layout layout, String filename,
+                                        String datePattern, boolean append) throws IOException
+    {
+        super(layout, filename, append);
+        this.datePattern = datePattern;
+        activateOptions();
+    }
+
+    /**
+     * Instantiate a CompositeRollingAppender and open the file designated by <code>filename</code>. The opened filename
+     * will become the output destination for this appender.
+     *
+     * <p>The file will be appended to.  DatePattern is default.
+     */
+    public QpidCompositeRollingAppender(Layout layout, String filename) throws IOException
+    {
+        super(layout, filename);
+    }
+
+    /**
+     * The <b>DatePattern</b> takes a string in the same format as expected by {@link java.text.SimpleDateFormat}. This
+     * options determines the rollover schedule.
+     */
+    public void setDatePattern(String pattern)
+    {
+        datePattern = pattern;
+    }
+
+    /** Returns the value of the <b>DatePattern</b> option. */
+    public String getDatePattern()
+    {
+        return datePattern;
+    }
+
+    /** Returns the value of the <b>maxSizeRollBackups</b> option. */
+    public int getMaxSizeRollBackups()
+    {
+        return maxSizeRollBackups;
+    }
+
+    /**
+     * Get the maximum size that the output file is allowed to reach before being rolled over to backup files.
+     *
+     * @since 1.1
+     */
+    public long getMaximumFileSize()
+    {
+        return maxFileSize;
+    }
+
+    /**
+     * <p>Set the maximum number of backup files to keep around based on file size.
+     *
+     * <p>The <b>MaxSizeRollBackups</b> option determines how many backup files are kept before the oldest is erased.
+     * This option takes an integer value. If set to zero, then there will be no backup files and the log file will be
+     * truncated when it reaches <code>MaxFileSize</code>.  If a negative number is supplied then no deletions will be
+     * made.  Note that this could result in very slow performance as a large number of files are rolled over unless
+     * {@link #setCountDirection} up is used.
+     *
+     * <p>The maximum applys to -each- time based group of files and -not- the total. Using a daily roll the maximum
+     * total files would be (#days run) * (maxSizeRollBackups)
+     */
+    public void setMaxSizeRollBackups(int maxBackups)
+    {
+        maxSizeRollBackups = maxBackups;
+    }
+
+    /**
+     * Set the maximum size that the output file is allowed to reach before being rolled over to backup files.
+     *
+     * <p>This method is equivalent to {@link #setMaxFileSize} except that it is required for differentiating the setter
+     * taking a <code>long</code> argument from the setter taking a <code>String</code> argument by the JavaBeans {@link
+     * java.beans.Introspector Introspector}.
+     *
+     * @see #setMaxFileSize(String)
+     */
+    public void setMaxFileSize(long maxFileSize)
+    {
+        this.maxFileSize = maxFileSize;
+    }
+
+    /**
+     * Set the maximum size that the output file is allowed to reach before being rolled over to backup files.
+     *
+     * <p>This method is equivalent to {@link #setMaxFileSize} except that it is required for differentiating the setter
+     * taking a <code>long</code> argument from the setter taking a <code>String</code> argument by the JavaBeans {@link
+     * java.beans.Introspector Introspector}.
+     *
+     * @see #setMaxFileSize(String)
+     */
+    public void setMaximumFileSize(long maxFileSize)
+    {
+        this.maxFileSize = maxFileSize;
+    }
+
+    /**
+     * Set the maximum size that the output file is allowed to reach before being rolled over to backup files.
+     *
+     * <p>In configuration files, the <b>MaxFileSize</b> option takes an long integer in the range 0 - 2^63. You can
+     * specify the value with the suffixes "KB", "MB" or "GB" so that the integer is interpreted being expressed
+     * respectively in kilobytes, megabytes or gigabytes. For example, the value "10KB" will be interpreted as 10240.
+     */
+    public void setMaxFileSize(String value)
+    {
+        maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
     }
 
-	/**
-	 Instantiate a <code>CompositeRollingAppender</code> and open the
-	 file designated by <code>filename</code>. The opened filename will
-	 become the ouput destination for this appender.
-	*/
-	public QpidCompositeRollingAppender(Layout layout, String filename,
-				   String datePattern) throws IOException
-    {
-	    this(layout, filename, datePattern, true);
-	}
-
-	/**
-	 Instantiate a CompositeRollingAppender and open the file designated by
-	 <code>filename</code>. The opened filename will become the ouput
-	 destination for this appender.
-
-	 <p>If the <code>append</code> parameter is true, the file will be
-	 appended to. Otherwise, the file desginated by
-	 <code>filename</code> will be truncated before being opened.
-	*/
-	public QpidCompositeRollingAppender(Layout layout, String filename, boolean append)
-									  throws IOException {
-	    super(layout, filename, append);
-	}
-
-	/**
-	 Instantiate a CompositeRollingAppender and open the file designated by
-	 <code>filename</code>. The opened filename will become the ouput
-	 destination for this appender.
-	*/
-	public QpidCompositeRollingAppender(Layout layout, String filename,
-				   String datePattern, boolean append) throws IOException {
-	    super(layout, filename, append);
-	    this.datePattern = datePattern;
-		activateOptions();
-	}
-	/**
-	 Instantiate a CompositeRollingAppender and open the file designated by
-	 <code>filename</code>. The opened filename will become the output
-	 destination for this appender.
-
-	 <p>The file will be appended to.  DatePattern is default.
-	*/
-	public QpidCompositeRollingAppender(Layout layout, String filename) throws IOException {
-	    super(layout, filename);
-	}
-
-	/**
-	 The <b>DatePattern</b> takes a string in the same format as
-	 expected by {@link java.text.SimpleDateFormat}. This options determines the
-	 rollover schedule.
-	*/
-	public void setDatePattern(String pattern) {
-	    datePattern = pattern;
-	}
-
-	/** Returns the value of the <b>DatePattern</b> option. */
-	public String getDatePattern() {
-	    return datePattern;
-	}
-
-	/**
-	 Returns the value of the <b>maxSizeRollBackups</b> option.
-	*/
-	public int getMaxSizeRollBackups() {
-	    return maxSizeRollBackups;
-	}
-
-	/**
-	 Get the maximum size that the output file is allowed to reach
-	 before being rolled over to backup files.
-
-	 @since 1.1
-	*/
-	public long getMaximumFileSize() {
-		return maxFileSize;
-	}
-
-	/**
-	 <p>Set the maximum number of backup files to keep around based on file size.
-
-	 <p>The <b>MaxSizeRollBackups</b> option determines how many backup
-	 files are kept before the oldest is erased. This option takes
-	 an integer value. If set to zero, then there will be no
-	 backup files and the log file will be truncated when it reaches
-	 <code>MaxFileSize</code>.  If a negative number is supplied then
-	 no deletions will be made.  Note that this could result in
-	 very slow performance as a large number of files are rolled over unless
-	 {@link #setCountDirection} up is used.
-
-	 <p>The maximum applys to -each- time based group of files and -not- the total.
-	 Using a daily roll the maximum total files would be (#days run) * (maxSizeRollBackups)
-
-	*/
-	public void setMaxSizeRollBackups(int maxBackups) {
-	    maxSizeRollBackups = maxBackups;
-	}
-
-	/**
-	 Set the maximum size that the output file is allowed to reach
-	 before being rolled over to backup files.
-
-	 <p>This method is equivalent to {@link #setMaxFileSize} except
-	 that it is required for differentiating the setter taking a
-	 <code>long</code> argument from the setter taking a
-	 <code>String</code> argument by the JavaBeans {@link
-	 java.beans.Introspector Introspector}.
-
-	 @see #setMaxFileSize(String)
-	*/
-	public void setMaxFileSize(long maxFileSize) {
-	   this.maxFileSize = maxFileSize;
-	}
-
-	/**
-	 Set the maximum size that the output file is allowed to reach
-	 before being rolled over to backup files.
-
-	 <p>This method is equivalent to {@link #setMaxFileSize} except
-	 that it is required for differentiating the setter taking a
-	 <code>long</code> argument from the setter taking a
-	 <code>String</code> argument by the JavaBeans {@link
-	 java.beans.Introspector Introspector}.
-
-	 @see #setMaxFileSize(String)
-	*/
-	public void setMaximumFileSize(long maxFileSize) {
-		this.maxFileSize = maxFileSize;
-	}
-
-	/**
-	 Set the maximum size that the output file is allowed to reach
-	 before being rolled over to backup files.
-
-	 <p>In configuration files, the <b>MaxFileSize</b> option takes an
-	 long integer in the range 0 - 2^63. You can specify the value
-	 with the suffixes "KB", "MB" or "GB" so that the integer is
-	 interpreted being expressed respectively in kilobytes, megabytes
-	 or gigabytes. For example, the value "10KB" will be interpreted
-	 as 10240.
-	*/
-	public void setMaxFileSize(String value) {
-	    maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
-	}
-
-	protected void setQWForFiles(Writer writer) {
-	    qw = new CountingQuietWriter(writer, errorHandler);
-	}
-
-	//Taken verbatum from DailyRollingFileAppender
-	int computeCheckPeriod() {
-		RollingCalendar c = new RollingCalendar();
-		// set sate to 1970-01-01 00:00:00 GMT
-		Date epoch = new Date(0);
-		if(datePattern != null) {
-			for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
-				String r0 = sdf.format(epoch);
-				c.setType(i);
-				Date next = new Date(c.getNextCheckMillis(epoch));
-				String r1 = sdf.format(next);
-				//LogLog.debug("Type = "+i+", r0 = "+r0+", r1 = "+r1);
-				if(r0 != null && r1 != null && !r0.equals(r1)) {
-					return i;
-				}
-			}
-		}
-		return TOP_OF_TROUBLE; // Deliberately head for trouble...
-	}
-
-	//Now for the new stuff
-	/**
-	 * Handles append time behavior for CompositeRollingAppender.  This checks
-	 * if a roll over either by date (checked first) or time (checked second)
-	 * is need and then appends to the file last.
-	*/
-	protected void subAppend(LoggingEvent event) {
-
-		if (rollDate) {
-			long n = System.currentTimeMillis();
-			if (n >= nextCheck) {
-				now.setTime(n);
-				nextCheck = rc.getNextCheckMillis(now);
-
-				rollOverTime();
-			}
-		}
-
-		if (rollSize) {
-			if ((fileName != null) && ((CountingQuietWriter) qw).getCount() >= maxFileSize) {
-			    rollOverSize();
-			}
-		}
-
-		super.subAppend(event);
-	}
-
-	public void setFile(String file)
-	{
-		baseFileName = file.trim();
-		fileName = file.trim();
-	}
-
-	/**
-	 * Creates and opens the file for logging.  If <code>staticLogFileName</code>
-	 * is false then the fully qualified name is determined and used.
-	 */
-	public synchronized void setFile(String fileName, boolean append) throws IOException {
-		if (!staticLogFileName) {
-		    scheduledFilename = fileName = fileName.trim() + sdf.format(now);
-			if (countDirection > 0) {
-				scheduledFilename = fileName = fileName + '.' + (++curSizeRollBackups);
-			}
-		}
+    protected void setQWForFiles(Writer writer)
+    {
+        qw = new CountingQuietWriter(writer, errorHandler);
+    }
+
+    //Taken verbatum from DailyRollingFileAppender
+    int computeCheckPeriod()
+    {
+        RollingCalendar c = new RollingCalendar();
+        // set sate to 1970-01-01 00:00:00 GMT
+        Date epoch = new Date(0);
+        if (datePattern != null)
+        {
+            for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++)
+            {
+                String r0 = sdf.format(epoch);
+                c.setType(i);
+                Date next = new Date(c.getNextCheckMillis(epoch));
+                String r1 = sdf.format(next);
+                //LogLog.debug("Type = "+i+", r0 = "+r0+", r1 = "+r1);
+                if (r0 != null && r1 != null && !r0.equals(r1))
+                {
+                    return i;
+                }
+            }
+        }
+        return TOP_OF_TROUBLE; // Deliberately head for trouble...
+    }
+
+    //Now for the new stuff
+    /**
+     * Handles append time behavior for CompositeRollingAppender.  This checks if a roll over either by date (checked
+     * first) or time (checked second) is need and then appends to the file last.
+     */
+    protected void subAppend(LoggingEvent event)
+    {
+
+        if (rollDate)
+        {
+            long n = System.currentTimeMillis();
+            if (n >= nextCheck)
+            {
+                now.setTime(n);
+                nextCheck = rc.getNextCheckMillis(now);
+
+                rollOverTime();
+            }
+        }
+
+        if (rollSize)
+        {
+            if ((fileName != null) && ((CountingQuietWriter) qw).getCount() >= maxFileSize)
+            {
+                rollOverSize();
+            }
+        }
+
+        super.subAppend(event);
+    }
+
+    public void setFile(String file)
+    {
+        baseFileName = file.trim();
+        fileName = file.trim();
+    }
+
+    /**
+     * Creates and opens the file for logging.  If <code>staticLogFileName</code> is false then the fully qualified name
+     * is determined and used.
+     */
+    public synchronized void setFile(String fileName, boolean append) throws IOException
+    {
+        if (!staticLogFileName)
+        {
+            scheduledFilename = fileName = fileName.trim() + sdf.format(now);
+            if (countDirection > 0)
+            {
+                scheduledFilename = fileName = fileName + '.' + (++curSizeRollBackups);
+            }
+        }
 
         super.setFile(fileName, append, bufferedIO, bufferSize);
 
-        if(append) {
-		  File f = new File(fileName);
-		  ((CountingQuietWriter) qw).setCount(f.length());
-		}
-	}
-
-	public int getCountDirection() {
-		return countDirection;
-	}
-
-	public void setCountDirection(int direction) {
-		countDirection = direction;
-	}
+        if (append)
+        {
+            File f = new File(fileName);
+            ((CountingQuietWriter) qw).setCount(f.length());
+        }
+    }
+
+    public int getCountDirection()
+    {
+        return countDirection;
+    }
+
+    public void setCountDirection(int direction)
+    {
+        countDirection = direction;
+    }
 
-	public int getRollingStyle () {
+    public int getRollingStyle()
+    {
         return rollingStyle;
-	}
+    }
 
-	public void setRollingStyle(int style) {
-	    rollingStyle = style;
-		switch (rollingStyle) {
-			case BY_SIZE:
-				 rollDate = false;
-				 rollSize = true;
-				 break;
-			case BY_DATE:
-				 rollDate = true;
-				 rollSize = false;
-				 break;
-			case BY_COMPOSITE:
-				 rollDate = true;
-				 rollSize = true;
-				 break;
-			default:
-				errorHandler.error("Invalid rolling Style, use 1 (by size only), 2 (by date only) or 3 (both)");
-		}
-	}
-
-/*
-	public void setRollingStyle(String style) {
-		if (style == S_BY_SIZE) {
-		    rollingStyle = BY_SIZE;
-		}
-		else if (style == S_BY_DATE) {
-		    rollingStyle = BY_DATE;
-		}
-		else if (style == S_BY_COMPOSITE) {
-			rollingStyle = BY_COMPOSITE;
-		}
-	}
-*/
-	public boolean getStaticLogFileName() {
-	    return staticLogFileName;
-	}
-
-	public void setStaticLogFileName(boolean s) {
-		staticLogFileName = s;
-	}
-
-	public void setStaticLogFileName(String value) {
-		setStaticLogFileName(OptionConverter.toBoolean(value, true));
-	}
-
-	/**
-	 *  Initializes based on exisiting conditions at time of <code>
-	 *  activateOptions</code>.  The following is done:<br>
-	 *  <br>
-	 *	A) determine curSizeRollBackups<br>
-	 *	B) determine curTimeRollBackups (not implemented)<br>
-	 *	C) initiates a roll over if needed for crossing a date boundary since
-	 *  the last run.
-	 */
-	protected void existingInit() {
-
-		curSizeRollBackups = 0;
-		curTimeRollBackups = 0;
-
-		//part A starts here
-		String filter;
-		if (staticLogFileName || !rollDate) {
-			filter = baseFileName + ".*";
-		}
-		else {
-			filter = scheduledFilename + ".*";
-		}
-
-		File f = new File(baseFileName);
-		f = f.getParentFile();
-		if (f == null)
-		   f = new File(".");
-
-		LogLog.debug("Searching for existing files in: " + f);
-		String[] files = f.list();
-
-		if (files != null) {
-			for (int i = 0; i < files.length; i++) {
-				if (!files[i].startsWith(baseFileName))
-				   continue;
-
-				int index = files[i].lastIndexOf(".");
-
-				if (staticLogFileName) {
-				   int endLength = files[i].length() - index;
-				   if (baseFileName.length() + endLength != files[i].length()) {
-					   //file is probably scheduledFilename + .x so I don't care
-					   continue;
-				   }
-				}
-
-				try {
-					int backup = Integer.parseInt(files[i].substring(index + 1, files[i].length()));
-					LogLog.debug("From file: " + files[i] + " -> " + backup);
-					if (backup > curSizeRollBackups)
-					   curSizeRollBackups = backup;
-				}
-				catch (Exception e) {
-					//this happens when file.log -> file.log.yyyy-mm-dd which is normal
-					//when staticLogFileName == false
-					LogLog.debug("Encountered a backup file not ending in .x " + files[i]);
-				}
-			}
-		}
-		LogLog.debug("curSizeRollBackups starts at: " + curSizeRollBackups);
-		//part A ends here
-
-		//part B not yet implemented
-
-		//part C
-		if (staticLogFileName && rollDate) {
-			File old = new File(baseFileName);
-			if (old.exists()) {
-				Date last = new Date(old.lastModified());
-				if (!(sdf.format(last).equals(sdf.format(now)))) {
-					scheduledFilename = baseFileName + sdf.format(last);
-					LogLog.debug("Initial roll over to: " + scheduledFilename);
-					rollOverTime();
-				}
-			}
-		}
-		LogLog.debug("curSizeRollBackups after rollOver at: " + curSizeRollBackups);
-		//part C ends here
-
-	}
-
-	/**
-	 * Sets initial conditions including date/time roll over information, first check,
-	 * scheduledFilename, and calls <code>existingInit</code> to initialize
-	 * the current # of backups.
-	 */
-	public void activateOptions() {
-
-	    //REMOVE removed rollDate from boolean to enable Alex's change
-		if(datePattern != null) {
-			now.setTime(System.currentTimeMillis());
-			sdf = new SimpleDateFormat(datePattern);
-			int type = computeCheckPeriod();
-			//printPeriodicity(type);
-			rc.setType(type);
-			//next line added as this removes the name check in rollOver
-			nextCheck = rc.getNextCheckMillis(now);
-		} else {
-			if (rollDate)
-			    LogLog.error("Either DatePattern or rollingStyle options are not set for ["+
-			      name+"].");
-		}
-
-		existingInit();
-
-		super.activateOptions();
-
-		if (rollDate && fileName != null && scheduledFilename == null)
-			scheduledFilename = fileName + sdf.format(now);
-	}
-
-	/**
-	 Rollover the file(s) to date/time tagged file(s).
-	 Opens the new file (through setFile) and resets curSizeRollBackups.
-	*/
-	protected void rollOverTime() {
-
-	    curTimeRollBackups++;
-
-		//delete the old stuff here
-
-		if (staticLogFileName) {
-			/* Compute filename, but only if datePattern is specified */
-			if (datePattern == null) {
-				errorHandler.error("Missing DatePattern option in rollOver().");
-				return;
-			}
-
-			//is the new file name equivalent to the 'current' one
-			//something has gone wrong if we hit this -- we should only
-			//roll over if the new file will be different from the old
-			String dateFormat = sdf.format(now);
-			if (scheduledFilename.equals(fileName + dateFormat)) {
-				errorHandler.error("Compare " + scheduledFilename + " : " + fileName + dateFormat);
-				return;
-			}
-
-			// close current file, and rename it to datedFilename
-			this.closeFile();
-
-			//we may have to roll over a large number of backups here
-	        String from, to;
-			for (int i = 1; i <= curSizeRollBackups; i++) {
-				from = fileName + '.' + i;
-				to = scheduledFilename + '.' + i;
-				rollFile(from, to);
-	        }
-
-			rollFile(fileName, scheduledFilename);
-		}
-
-		try {
-			// This will also close the file. This is OK since multiple
-			// close operations are safe.
-			curSizeRollBackups = 0; //We're cleared out the old date and are ready for the new
-
-			//new scheduled name
-			scheduledFilename = fileName + sdf.format(now);
-			this.setFile(baseFileName, false);
-		}
-		catch(IOException e) {
-			errorHandler.error("setFile("+fileName+", false) call failed.");
-		}
-
-	}
-
-	/** Renames file <code>from</code> to file <code>to</code>.  It
-	 *  also checks for existence of target file and deletes if it does.
-	 */
-	protected static void rollFile(String from, String to) {
-		File target = new File(to);
-		if (target.exists()) {
-			LogLog.debug("deleting existing target file: " + target);
-			target.delete();
-		}
-
-		File file = new File(from);
-		file.renameTo(target);
-		LogLog.debug(from +" -> "+ to);
-	}
-
-	/** Delete's the specified file if it exists */
-	protected static void deleteFile(String fileName) {
-		File file = new File(fileName);
-		if (file.exists()) {
-		   file.delete();
-		}
-	}
-
-	/**
-	 Implements roll overs base on file size.
-
-	 <p>If the maximum number of size based backups is reached
-	 (<code>curSizeRollBackups == maxSizeRollBackups</code) then the oldest
-	 file is deleted -- it's index determined by the sign of countDirection.<br>
-	 If <code>countDirection</code> < 0, then files
-	 {<code>File.1</code>, ..., <code>File.curSizeRollBackups -1</code>}
-	 are renamed to {<code>File.2</code>, ...,
-	 <code>File.curSizeRollBackups</code>}.	 Moreover, <code>File</code> is
-	 renamed <code>File.1</code> and closed.<br>
-
-	 A new file is created to receive further log output.
-
-	 <p>If <code>maxSizeRollBackups</code> is equal to zero, then the
-	 <code>File</code> is truncated with no backup files created.
-
-	 <p>If <code>maxSizeRollBackups</code> < 0, then <code>File</code> is
-	 renamed if needed and no files are deleted.
-	*/
-
-	// synchronization not necessary since doAppend is alreasy synched
-	protected void rollOverSize() {
-		File file;
-
-		this.closeFile(); // keep windows happy.
-
-		LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount());
-		LogLog.debug("maxSizeRollBackups = " + maxSizeRollBackups);
-		LogLog.debug("curSizeRollBackups = " + curSizeRollBackups);
-		LogLog.debug("countDirection = " + countDirection);
-
-		// If maxBackups <= 0, then there is no file renaming to be done.
-		if (maxSizeRollBackups != 0) {
-
-			if (countDirection < 0) {
-				// Delete the oldest file, to keep Windows happy.
-				if (curSizeRollBackups == maxSizeRollBackups) {
-				    deleteFile(fileName + '.' + maxSizeRollBackups);
-					curSizeRollBackups--;
-				}
-
-				// Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
-				for (int i = curSizeRollBackups; i >= 1; i--) {
-					rollFile((fileName + "." + i), (fileName + '.' + (i + 1)));
-				}
-
-				curSizeRollBackups++;
-				// Rename fileName to fileName.1
-				rollFile(fileName, fileName + ".1");
-
-			} //REMOVE This code branching for Alexander Cerna's request
-			else if (countDirection == 0) {
-				//rollFile based on date pattern
-				curSizeRollBackups++;
-				now.setTime(System.currentTimeMillis());
-				scheduledFilename = fileName + sdf.format(now);
-				rollFile(fileName, scheduledFilename);
-			}
-			else { //countDirection > 0
-				if (curSizeRollBackups >= maxSizeRollBackups && maxSizeRollBackups > 0) {
-					//delete the first and keep counting up.
-					int oldestFileIndex = curSizeRollBackups - maxSizeRollBackups + 1;
-					deleteFile(fileName + '.' + oldestFileIndex);
-				}
-
-				if (staticLogFileName) {
-					curSizeRollBackups++;
-					rollFile(fileName, fileName + '.' + curSizeRollBackups);
-				}
-			}
-		}
-
-		try {
-			// This will also close the file. This is OK since multiple
-			// close operations are safe.
-			this.setFile(baseFileName, false);
-		}
-		catch(IOException e) {
-			LogLog.error("setFile("+fileName+", false) call failed.", e);
-		}
-	}
+    public void setRollingStyle(int style)
+    {
+        rollingStyle = style;
+        switch (rollingStyle)
+        {
+            case BY_SIZE:
+                rollDate = false;
+                rollSize = true;
+                break;
+            case BY_DATE:
+                rollDate = true;
+                rollSize = false;
+                break;
+            case BY_COMPOSITE:
+                rollDate = true;
+                rollSize = true;
+                break;
+            default:
+                errorHandler.error("Invalid rolling Style, use 1 (by size only), 2 (by date only) or 3 (both)");
+        }
+    }
+
+    /*
+        public void setRollingStyle(String style) {
+            if (style == S_BY_SIZE) {
+                rollingStyle = BY_SIZE;
+            }
+            else if (style == S_BY_DATE) {
+                rollingStyle = BY_DATE;
+            }
+            else if (style == S_BY_COMPOSITE) {
+                rollingStyle = BY_COMPOSITE;
+            }
+        }
+    */
+    public boolean getStaticLogFileName()
+    {
+        return staticLogFileName;
+    }
+
+    public void setStaticLogFileName(boolean s)
+    {
+        staticLogFileName = s;
+    }
+
+    public void setStaticLogFileName(String value)
+    {
+        setStaticLogFileName(OptionConverter.toBoolean(value, true));
+    }
+
+    public boolean getCompressBackupFiles()
+    {
+        return compress;
+    }
 
+    public void setCompressBackupFiles(boolean c)
+    {
+        compress = c;
+    }
+
+    public boolean getCompressAsync()
+    {
+        return compressAsync;
+    }
+
+    public void setCompressAsync(boolean c)
+    {
+        compressAsync = c;
+        if (compressAsync)
+        {
+            executor = Executors.newFixedThreadPool(1);
+
+            compressor = new Compressor();            
+        }
+    }
+
+
+    public boolean getZeroBased()
+    {
+        return zeroBased;
+    }
+
+    public void setZeroBased(boolean z)
+    {
+        zeroBased = z;
+    }
+
+    public String getBackupFilesToPath()
+    {
+        return backupFilesToPath;
+    }
+
+    public void setbackupFilesToPath(String path)
+    {
+        File td = new File(path);
+        if (!td.exists())
+        {
+            td.mkdirs();
+        }
+        backupFilesToPath = path;
+    }
+
+    /**
+     * Initializes based on exisiting conditions at time of <code> activateOptions</code>.  The following is done:<br>
+     * <br> A) determine curSizeRollBackups<br> B) determine curTimeRollBackups (not implemented)<br> C) initiates a
+     * roll over if needed for crossing a date boundary since the last run.
+     */
+    protected void existingInit()
+    {
+
+        if (zeroBased)
+        {
+            curSizeRollBackups = -1;
+        }
+        curTimeRollBackups = 0;
+
+        //part A starts here
+        String filter;
+        if (staticLogFileName || !rollDate)
+        {
+            filter = baseFileName + ".*";
+        }
+        else
+        {
+            filter = scheduledFilename + ".*";
+        }
+
+        File f = new File(baseFileName);
+        f = f.getParentFile();
+        if (f == null)
+        {
+            f = new File(".");
+        }
+
+        LogLog.debug("Searching for existing files in: " + f);
+        String[] files = f.list();
+
+        if (files != null)
+        {
+            for (int i = 0; i < files.length; i++)
+            {
+                if (!files[i].startsWith(baseFileName))
+                {
+                    continue;
+                }
+
+                int index = files[i].lastIndexOf(".");
+
+                if (staticLogFileName)
+                {
+                    int endLength = files[i].length() - index;
+                    if (baseFileName.length() + endLength != files[i].length())
+                    {
+                        //file is probably scheduledFilename + .x so I don't care
+                        continue;
+                    }
+                }
+
+                try
+                {
+                    int backup = Integer.parseInt(files[i].substring(index + 1, files[i].length()));
+                    LogLog.debug("From file: " + files[i] + " -> " + backup);
+                    if (backup > curSizeRollBackups)
+                    {
+                        curSizeRollBackups = backup;
+                    }
+                }
+                catch (Exception e)
+                {
+                    //this happens when file.log -> file.log.yyyy-mm-dd which is normal
+                    //when staticLogFileName == false
+                    LogLog.debug("Encountered a backup file not ending in .x " + files[i]);
+                }
+            }
+        }
+        LogLog.debug("curSizeRollBackups starts at: " + curSizeRollBackups);
+        //part A ends here
+
+        //part B not yet implemented
+
+        //part C
+        if (staticLogFileName && rollDate)
+        {
+            File old = new File(baseFileName);
+            if (old.exists())
+            {
+                Date last = new Date(old.lastModified());
+                if (!(sdf.format(last).equals(sdf.format(now))))
+                {
+                    scheduledFilename = baseFileName + sdf.format(last);
+                    LogLog.debug("Initial roll over to: " + scheduledFilename);
+                    rollOverTime();
+                }
+            }
+        }
+        LogLog.debug("curSizeRollBackups after rollOver at: " + curSizeRollBackups);
+        //part C ends here
+
+    }
+
+    /**
+     * Sets initial conditions including date/time roll over information, first check, scheduledFilename, and calls
+     * <code>existingInit</code> to initialize the current # of backups.
+     */
+    public void activateOptions()
+    {
+
+        //REMOVE removed rollDate from boolean to enable Alex's change
+        if (datePattern != null)
+        {
+            now.setTime(System.currentTimeMillis());
+            sdf = new SimpleDateFormat(datePattern);
+            int type = computeCheckPeriod();
+            //printPeriodicity(type);
+            rc.setType(type);
+            //next line added as this removes the name check in rollOver
+            nextCheck = rc.getNextCheckMillis(now);
+        }
+        else
+        {
+            if (rollDate)
+            {
+                LogLog.error("Either DatePattern or rollingStyle options are not set for [" +
+                             name + "].");
+            }
+        }
+
+        existingInit();
+
+        if (rollDate && fileName != null && scheduledFilename == null)
+        {
+            scheduledFilename = fileName + sdf.format(now);
+        }
+
+        try
+        {
+            this.setFile(fileName, true);
+        }
+        catch (IOException e)
+        {
+            errorHandler.error("Cannot set file name:" + fileName);
+        }
+
+        super.activateOptions();
+    }
+
+    /**
+     * Rollover the file(s) to date/time tagged file(s). Opens the new file (through setFile) and resets
+     * curSizeRollBackups.
+     */
+    protected void rollOverTime()
+    {
+
+        curTimeRollBackups++;
+
+        this.closeFile(); // keep windows happy.
+
+        //delete the old stuff here
+
+        if (staticLogFileName)
+        {
+            /* Compute filename, but only if datePattern is specified */
+            if (datePattern == null)
+            {
+                errorHandler.error("Missing DatePattern option in rollOver().");
+                return;
+            }
+
+            //is the new file name equivalent to the 'current' one
+            //something has gone wrong if we hit this -- we should only
+            //roll over if the new file will be different from the old
+            String dateFormat = sdf.format(now);
+            if (scheduledFilename.equals(fileName + dateFormat))
+            {
+                errorHandler.error("Compare " + scheduledFilename + " : " + fileName + dateFormat);
+                return;
+            }
+
+            // close current file, and rename it to datedFilename
+            this.closeFile();
+
+            //we may have to roll over a large number of backups here
+            String from, to;
+            for (int i = 1; i <= curSizeRollBackups; i++)
+            {
+                from = fileName + '.' + i;
+                to = scheduledFilename + '.' + i;
+                rollFile(from, to, false);
+            }
+
+            rollFile(fileName, scheduledFilename, compress);
+        }
+        else
+        {
+            if (compress)
+            {
+                compress(fileName);
+            }
+        }
+
+        try
+        {
+            // This will also close the file. This is OK since multiple
+            // close operations are safe.
+            curSizeRollBackups = 0; //We're cleared out the old date and are ready for the new
+
+            //new scheduled name
+            scheduledFilename = fileName + sdf.format(now);
+            this.setFile(baseFileName, false);
+        }
+        catch (IOException e)
+        {
+            errorHandler.error("setFile(" + fileName + ", false) call failed.");
+        }
+
+    }
+
+    /**
+     * Renames file <code>from</code> to file <code>to</code>.  It also checks for existence of target file and deletes
+     * if it does.
+     */
+    protected void rollFile(String from, String to, boolean compress)
+    {
+        if (from.equals(to))
+        {
+            if (compress)
+            {
+                LogLog.debug("Attempting to compress file with same output name.");
+            }
+            return;
+        }
+        File target = new File(to);
+        if (target.exists())
+        {
+            LogLog.debug("deleting existing target file: " + target);
+            target.delete();
+        }
+
+        File file = new File(from);
+        if (compress)
+        {
+            compress(file, target);
+        }
+        else
+        {
+            if (!file.getPath().equals(target.getPath()))
+            {
+                file.renameTo(target);
+            }
+        }
+        LogLog.debug(from + " -> " + to);
+    }
+
+
+    protected void compress(String file)
+    {
+        File f = new File(file);
+        compress(f, f);
+    }
+
+    private void compress(File from, File target)
+    {
+        if (compressAsync)
+        {
+            synchronized (_compress)
+            {
+                _compress.offer(new CompressJob(from, target));
+            }
+            startCompression();
+        }
+        else
+        {
+            doCompress(from, target);
+        }
+    }
+
+    private void startCompression()
+    {
+        if (_compressing.compareAndSet(false, true))
+        {
+            executor.execute(compressor);
+        }
+    }
+
+    /** Delete's the specified file if it exists */
+    protected static void deleteFile(String fileName)
+    {
+        File file = new File(fileName);
+        if (file.exists())
+        {
+            file.delete();
+        }
+    }
+
+    /**
+     * Implements roll overs base on file size.
+     *
+     * <p>If the maximum number of size based backups is reached (<code>curSizeRollBackups == maxSizeRollBackups</code)
+     * then the oldest file is deleted -- it's index determined by the sign of countDirection.<br> If
+     * <code>countDirection</code> < 0, then files {<code>File.1</code>, ..., <code>File.curSizeRollBackups -1</code>}
+     * are renamed to {<code>File.2</code>, ..., <code>File.curSizeRollBackups</code>}.	 Moreover, <code>File</code> is
+     * renamed <code>File.1</code> and closed.<br>
+     *
+     * A new file is created to receive further log output.
+     *
+     * <p>If <code>maxSizeRollBackups</code> is equal to zero, then the <code>File</code> is truncated with no backup
+     * files created.
+     *
+     * <p>If <code>maxSizeRollBackups</code> < 0, then <code>File</code> is renamed if needed and no files are deleted.
+     */
+
+    // synchronization not necessary since doAppend is alreasy synched
+    protected void rollOverSize()
+    {
+        File file;
+
+        this.closeFile(); // keep windows happy.
+
+        LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount());
+        LogLog.debug("maxSizeRollBackups = " + maxSizeRollBackups);
+        LogLog.debug("curSizeRollBackups = " + curSizeRollBackups);
+        LogLog.debug("countDirection = " + countDirection);
+
+        // If maxBackups <= 0, then there is no file renaming to be done.
+        if (maxSizeRollBackups != 0)
+        {
+
+            if (countDirection < 0)
+            {
+                // Delete the oldest file, to keep Windows happy.
+                if (curSizeRollBackups == maxSizeRollBackups)
+                {
+                    deleteFile(fileName + '.' + maxSizeRollBackups);
+                    curSizeRollBackups--;
+                }
+
+                // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
+                for (int i = curSizeRollBackups; i >= 1; i--)
+                {
+                    rollFile((fileName + "." + i), (fileName + '.' + (i + 1)), false);
+                }
+
+                curSizeRollBackups++;
+                // Rename fileName to fileName.1
+                rollFile(fileName, fileName + ".1", compress);
+
+            } //REMOVE This code branching for Alexander Cerna's request
+            else if (countDirection == 0)
+            {
+                //rollFile based on date pattern
+                curSizeRollBackups++;
+                now.setTime(System.currentTimeMillis());
+                scheduledFilename = fileName + sdf.format(now);
+                rollFile(fileName, scheduledFilename, compress);
+            }
+            else
+            { //countDirection > 0
+                if (curSizeRollBackups >= maxSizeRollBackups && maxSizeRollBackups > 0)
+                {
+                    //delete the first and keep counting up.
+                    int oldestFileIndex = curSizeRollBackups - maxSizeRollBackups + 1;
+                    deleteFile(fileName + '.' + oldestFileIndex);
+                }
+
+                if (staticLogFileName)
+                {
+                    curSizeRollBackups++;
+                    rollFile(fileName, fileName + '.' + curSizeRollBackups, compress);
+                }
+                else
+                {
+                    if (compress)
+                    {
+                        compress(fileName);
+                    }
+                }
+            }
+        }
+
+        try
+        {
+            // This will also close the file. This is OK since multiple
+            // close operations are safe.
+            this.setFile(baseFileName, false);
+        }
+        catch (IOException e)
+        {
+            LogLog.error("setFile(" + fileName + ", false) call failed.", e);
+        }
+    }
+
+    protected synchronized void doCompress(File from, File to)
+    {
+        String toFile;
+        if (backupFilesToPath == null)
+        {
+            toFile = to.getPath() + ".gz";
+        }
+        else
+        {
+            toFile = backupFilesToPath + System.getProperty("file.separator") + to.getName() + ".gz";
+        }
+
+        File target = new File(toFile);
+        if (target.exists())
+        {
+            LogLog.debug("deleting existing target file: " + target);
+            target.delete();
+        }
+
+        try
+        {
+            // Create the GZIP output stream
+            GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(target));
+
+            // Open the input file
+            FileInputStream in = new FileInputStream(from);
+
+            // Transfer bytes from the input file to the GZIP output stream
+            byte[] buf = new byte[1024];
+            int len;
+            while ((len = in.read(buf)) > 0)
+            {
+                out.write(buf, 0, len);
+            }
+            in.close();
+
+            // Complete the GZIP file
+            out.finish();
+            out.close();
+            // Remove old file.
+            from.delete();
+        }
+        catch (IOException e)
+        {
+            if (target.exists())
+            {
+                target.delete();
+            }
+            rollFile(from.getPath(), to.getPath(), false);
+        }
+    }
+
+    private class CompressJob
+    {
+        File _from, _to;
+
+        CompressJob(File from, File to)
+        {
+            _from = from;
+            _to = to;
+        }
+
+        File getFrom()
+        {
+            return _from;
+        }
+
+        File getTo()
+        {
+            return _to;
+        }
+    }
+
+    Compressor compressor = null;
+
+    Executor executor;
+
+    private class Compressor implements Runnable
+    {
+        public void run()
+        {
+            boolean running = true;
+            while (running)
+            {
+                CompressJob job = _compress.poll();
+
+                doCompress(job.getFrom(), job.getTo());
+
+                synchronized (_compress)
+                {
+                    if (_compress.isEmpty())
+                    {
+                        running = false;
+                        _compressing.set(false);
+                    }
+                }
+            }
+
+        }
+    }
 }

Propchange: incubator/qpid/branches/M2/java/integrationtests/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Mar 22 10:36:15 2007
@@ -1 +1,2 @@
 *.iml
+target