Home » apache-log4j-1.2.15 » org.apache » log4j » [javadoc | source]
    1   package org.apache.log4j;
    2   
    3   /*
    4    * Licensed to the Apache Software Foundation (ASF) under one or more
    5    * contributor license agreements.  See the NOTICE file distributed with
    6    * this work for additional information regarding copyright ownership.
    7    * The ASF licenses this file to You under the Apache License, Version 2.0
    8    * (the "License"); you may not use this file except in compliance with
    9    * the License.  You may obtain a copy of the License at
   10    * 
   11    *      http://www.apache.org/licenses/LICENSE-2.0
   12    * 
   13    * Unless required by applicable law or agreed to in writing, software
   14    * distributed under the License is distributed on an "AS IS" BASIS,
   15    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   16    * See the License for the specific language governing permissions and
   17    * limitations under the License.
   18    */
   19   
   20   import org.apache.log4j.RollingCalendar;
   21   import org.apache.log4j.helpers.OptionConverter;
   22   import org.apache.log4j.helpers.QuietWriter;
   23   import org.apache.log4j.helpers.CountingQuietWriter;
   24   import org.apache.log4j.helpers.LogLog;
   25   import org.apache.log4j.spi.LoggingEvent;
   26   
   27   import java.util.Date;
   28   import java.io.IOException;
   29   import java.io.Writer;
   30   import java.text.SimpleDateFormat;
   31   import java.io.File;
   32   import java.io.FilenameFilter;
   33   
   34   /**
   35    *  <p>CompositeRollingAppender combines RollingFileAppender and DailyRollingFileAppender<br>
   36    *  It can function as either or do both at the same time (making size
   37    *  based rolling files like RollingFileAppender until a data/time boundary
   38    *  is crossed at which time it rolls all of those files as per the DailyRollingFileAppender)
   39    *  based on the setting for <code>rollingStyle</code>.<br>
   40    *  <br>
   41    *  To use CompositeRollingAppender to roll log files as they reach a certain
   42    *  size (like RollingFileAppender), set rollingStyle=1 (@see config.size)<br>
   43    *  To use CompositeRollingAppender to roll log files at certain time intervals
   44    *  (daily for example), set rollingStyle=2 and a datePattern (@see config.time)<br>
   45    *  To have CompositeRollingAppender roll log files at a certain size AND rename those
   46    *  according to time intervals, set rollingStyle=3 (@see config.composite)<br>
   47    *
   48    *  <p>A of few additional optional features have been added:<br>
   49    *  -- Attach date pattern for current log file (@see staticLogFileName)<br>
   50    *  -- Backup number increments for newer files (@see countDirection)<br>
   51    *  -- Infinite number of backups by file size (@see maxSizeRollBackups)<br>
   52    *  <br>
   53    *  <p>A few notes and warnings:  For large or infinite number of backups
   54    *  countDirection > 0 is highly recommended, with staticLogFileName = false if
   55    *  time based rolling is also used -- this will reduce the number of file renamings
   56    *  to few or none.  Changing staticLogFileName or countDirection without clearing
   57    *  the directory could have nasty side effects.  If Date/Time based rolling
   58    *  is enabled, CompositeRollingAppender will attempt to roll existing files
   59    *  in the directory without a date/time tag based on the last modified date
   60    *  of the base log files last modification.<br>
   61    *  <br>
   62    *  <p>A maximum number of backups based on date/time boundries would be nice
   63    *  but is not yet implemented.<br>
   64    *
   65    *  @author Kevin Steppe
   66    *  @author Heinz Richter
   67    *  @author Eirik Lygre
   68    *  @author Ceki G&uuml;lc&uuml;
   69    */
   70   public class CompositeRollingAppender extends org.apache.log4j.FileAppender
   71   {
   72   	// The code assumes that the following 'time' constants are in a increasing
   73   	// sequence.
   74   	static final int TOP_OF_TROUBLE=-1;
   75   	static final int TOP_OF_MINUTE = 0;
   76   	static final int TOP_OF_HOUR   = 1;
   77   	static final int HALF_DAY      = 2;
   78   	static final int TOP_OF_DAY    = 3;
   79   	static final int TOP_OF_WEEK   = 4;
   80   	static final int TOP_OF_MONTH  = 5;
   81   
   82   	/** Style of rolling to use */
   83   	static final int BY_SIZE = 1;
   84   	static final int BY_DATE = 2;
   85   	static final int BY_COMPOSITE = 3;
   86   
   87   	//Not currently used
   88   	static final String S_BY_SIZE = "Size";
   89   	static final String S_BY_DATE = "Date";
   90   	static final String S_BY_COMPOSITE = "Composite";
   91   
   92   	/**
   93   	 The date pattern. By default, the pattern is set to
   94   	 "'.'yyyy-MM-dd" meaning daily rollover.
   95   	*/
   96   	private String datePattern = "'.'yyyy-MM-dd";
   97   
   98   	/**	 The actual formatted filename that is currently being written to
   99   	     or will be the file transferred to on roll over
  100   		 (based on staticLogFileName). */
  101   	private String scheduledFilename = null;
  102   
  103   	/** The timestamp when we shall next recompute the filename. */
  104   	private long nextCheck = System.currentTimeMillis () - 1;
  105   
  106   	/** Holds date of last roll over */
  107   	Date now = new Date();
  108   
  109   	SimpleDateFormat sdf;
  110   
  111   	/** Helper class to determine next rollover time */
  112   	RollingCalendar rc = new RollingCalendar();
  113   
  114   	/** Current period for roll overs */
  115   	int checkPeriod = TOP_OF_TROUBLE;
  116   
  117   	/**	 The default maximum file size is 10MB. */
  118   	protected long maxFileSize = 10*1024*1024;
  119   
  120   	/**	 There is zero backup files by default. */
  121   	protected int maxSizeRollBackups = 0;
  122   	/** How many sized based backups have been made so far */
  123   	protected int curSizeRollBackups = 0;
  124   
  125   	/** not yet implemented */
  126   	protected int maxTimeRollBackups = -1;
  127   	protected int curTimeRollBackups = 0;
  128   
  129   	/** By default newer files have lower numbers. (countDirection < 0)
  130   	 *  ie. log.1 is most recent, log.5 is the 5th backup, etc...
  131   	 *  countDirection > 0 does the opposite ie.
  132   	 *  log.1 is the first backup made, log.5 is the 5th backup made, etc.
  133   	 *  For infinite backups use countDirection > 0 to reduce rollOver costs.
  134   	 */
  135   	protected int countDirection = -1;
  136   
  137   	/** Style of rolling to Use.  BY_SIZE (1), BY_DATE(2), BY COMPOSITE(3) */
  138   	protected int rollingStyle = BY_COMPOSITE;
  139   	protected boolean rollDate = true;
  140   	protected boolean rollSize = true;
  141   
  142   	/** By default file.log is always the current file.  Optionally
  143   	 *  file.log.yyyy-mm-dd for current formated datePattern can by the currently
  144   	 *  logging file (or file.log.curSizeRollBackup or even
  145   	 *  file.log.yyyy-mm-dd.curSizeRollBackup) This will make time based roll
  146   	 *  overs with a large number of backups much faster -- it won't have to
  147   	 *  rename all the backups!
  148   	 */
  149   	protected boolean staticLogFileName = true;
  150   
  151   	/** FileName provided in configuration.  Used for rolling properly */
  152   	protected String baseFileName;
  153   
  154       /** The default constructor does nothing. */
  155   	public CompositeRollingAppender()  {
  156       }
  157   
  158   	/**
  159   	 Instantiate a <code>CompositeRollingAppender</code> and open the
  160   	 file designated by <code>filename</code>. The opened filename will
  161   	 become the ouput destination for this appender.
  162   	*/
  163   	public CompositeRollingAppender (Layout layout, String filename,
  164   				   String datePattern) throws IOException {
  165   	    this(layout, filename, datePattern, true);
  166   	}
  167   
  168   	/**
  169   	 Instantiate a CompositeRollingAppender and open the file designated by
  170   	 <code>filename</code>. The opened filename will become the ouput
  171   	 destination for this appender.
  172   
  173   	 <p>If the <code>append</code> parameter is true, the file will be
  174   	 appended to. Otherwise, the file desginated by
  175   	 <code>filename</code> will be truncated before being opened.
  176   	*/
  177   	public CompositeRollingAppender(Layout layout, String filename, boolean append)
  178   									  throws IOException {
  179   	    super(layout, filename, append);
  180   	}
  181   
  182   	/**
  183   	 Instantiate a CompositeRollingAppender and open the file designated by
  184   	 <code>filename</code>. The opened filename will become the ouput
  185   	 destination for this appender.
  186   	*/
  187   	public CompositeRollingAppender (Layout layout, String filename,
  188   				   String datePattern, boolean append) throws IOException {
  189   	    super(layout, filename, append);
  190   	    this.datePattern = datePattern;
  191   		activateOptions();
  192   	}
  193   	/**
  194   	 Instantiate a CompositeRollingAppender and open the file designated by
  195   	 <code>filename</code>. The opened filename will become the output
  196   	 destination for this appender.
  197   
  198   	 <p>The file will be appended to.  DatePattern is default.
  199   	*/
  200   	public CompositeRollingAppender(Layout layout, String filename) throws IOException {
  201   	    super(layout, filename);
  202   	}
  203   
  204   	/**
  205   	 The <b>DatePattern</b> takes a string in the same format as
  206   	 expected by {@link SimpleDateFormat}. This options determines the
  207   	 rollover schedule.
  208   	*/
  209   	public void setDatePattern(String pattern) {
  210   	    datePattern = pattern;
  211   	}
  212   
  213   	/** Returns the value of the <b>DatePattern</b> option. */
  214   	public String getDatePattern() {
  215   	    return datePattern;
  216   	}
  217   
  218   	/**
  219   	 Returns the value of the <b>maxSizeRollBackups</b> option.
  220   	*/
  221   	public int getMaxSizeRollBackups() {
  222   	    return maxSizeRollBackups;
  223   	}
  224   
  225   	/**
  226   	 Get the maximum size that the output file is allowed to reach
  227   	 before being rolled over to backup files.
  228   
  229   	 @since 1.1
  230   	*/
  231   	public long getMaximumFileSize() {
  232   		return maxFileSize;
  233   	}
  234   
  235   	/**
  236   	 <p>Set the maximum number of backup files to keep around based on file size.
  237   
  238   	 <p>The <b>MaxSizeRollBackups</b> option determines how many backup
  239   	 files are kept before the oldest is erased. This option takes
  240   	 an integer value. If set to zero, then there will be no
  241   	 backup files and the log file will be truncated when it reaches
  242   	 <code>MaxFileSize</code>.  If a negative number is supplied then
  243   	 no deletions will be made.  Note that this could result in
  244   	 very slow performance as a large number of files are rolled over unless
  245   	 {@link #setCountDirection} up is used.
  246   
  247   	 <p>The maximum applys to -each- time based group of files and -not- the total.
  248   	 Using a daily roll the maximum total files would be (#days run) * (maxSizeRollBackups)
  249   
  250   	*/
  251   	public void setMaxSizeRollBackups(int maxBackups) {
  252   	    maxSizeRollBackups = maxBackups;
  253   	}
  254   
  255   	/**
  256   	 Set the maximum size that the output file is allowed to reach
  257   	 before being rolled over to backup files.
  258   
  259   	 <p>This method is equivalent to {@link #setMaxFileSize} except
  260   	 that it is required for differentiating the setter taking a
  261   	 <code>long</code> argument from the setter taking a
  262   	 <code>String</code> argument by the JavaBeans {@link
  263   	 java.beans.Introspector Introspector}.
  264   
  265   	 @see #setMaxFileSize(String)
  266   	*/
  267   	public void setMaxFileSize(long maxFileSize) {
  268   	   this.maxFileSize = maxFileSize;
  269   	}
  270   
  271   	/**
  272   	 Set the maximum size that the output file is allowed to reach
  273   	 before being rolled over to backup files.
  274   
  275   	 <p>This method is equivalent to {@link #setMaxFileSize} except
  276   	 that it is required for differentiating the setter taking a
  277   	 <code>long</code> argument from the setter taking a
  278   	 <code>String</code> argument by the JavaBeans {@link
  279   	 java.beans.Introspector Introspector}.
  280   
  281   	 @see #setMaxFileSize(String)
  282   	*/
  283   	public void setMaximumFileSize(long maxFileSize) {
  284   		this.maxFileSize = maxFileSize;
  285   	}
  286   
  287   	/**
  288   	 Set the maximum size that the output file is allowed to reach
  289   	 before being rolled over to backup files.
  290   
  291   	 <p>In configuration files, the <b>MaxFileSize</b> option takes an
  292   	 long integer in the range 0 - 2^63. You can specify the value
  293   	 with the suffixes "KB", "MB" or "GB" so that the integer is
  294   	 interpreted being expressed respectively in kilobytes, megabytes
  295   	 or gigabytes. For example, the value "10KB" will be interpreted
  296   	 as 10240.
  297   	*/
  298   	public void setMaxFileSize(String value) {
  299   	    maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
  300   	}
  301   
  302   	protected void setQWForFiles(Writer writer) {
  303   	    qw = new CountingQuietWriter(writer, errorHandler);
  304   	}
  305   
  306   	//Taken verbatum from DailyRollingFileAppender
  307   	int computeCheckPeriod() {
  308   		RollingCalendar c = new RollingCalendar();
  309   		// set sate to 1970-01-01 00:00:00 GMT
  310   		Date epoch = new Date(0);
  311   		if(datePattern != null) {
  312   			for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
  313   				String r0 = sdf.format(epoch);
  314   				c.setType(i);
  315   				Date next = new Date(c.getNextCheckMillis(epoch));
  316   				String r1 = sdf.format(next);
  317   				//LogLog.debug("Type = "+i+", r0 = "+r0+", r1 = "+r1);
  318   				if(r0 != null && r1 != null && !r0.equals(r1)) {
  319   					return i;
  320   				}
  321   			}
  322   		}
  323   		return TOP_OF_TROUBLE; // Deliberately head for trouble...
  324   	}
  325   
  326   	//Now for the new stuff
  327   	/**
  328   	 * Handles append time behavior for CompositeRollingAppender.  This checks
  329   	 * if a roll over either by date (checked first) or time (checked second)
  330   	 * is need and then appends to the file last.
  331   	*/
  332   	protected void subAppend(LoggingEvent event) {
  333   
  334   		if (rollDate) {
  335   			long n = System.currentTimeMillis();
  336   			if (n >= nextCheck) {
  337   				now.setTime(n);
  338   				nextCheck = rc.getNextCheckMillis(now);
  339   
  340   				rollOverTime();
  341   			}
  342   		}
  343   
  344   		if (rollSize) {
  345   			if ((fileName != null) && ((CountingQuietWriter) qw).getCount() >= maxFileSize) {
  346   			    rollOverSize();
  347   			}
  348   		}
  349   
  350   		super.subAppend(event);
  351   	}
  352   
  353   	public void setFile(String file)
  354   	{
  355   		baseFileName = file.trim();
  356   		fileName = file.trim();
  357   	}
  358   
  359   	/**
  360   	 * Creates and opens the file for logging.  If <code>staticLogFileName</code>
  361   	 * is false then the fully qualified name is determined and used.
  362   	 */
  363   	public synchronized void setFile(String fileName, boolean append) throws IOException {
  364   		if (!staticLogFileName) {
  365   		    scheduledFilename = fileName = fileName.trim() + sdf.format(now);
  366   			if (countDirection > 0) {
  367   				scheduledFilename = fileName = fileName + '.' + (++curSizeRollBackups);
  368   			}
  369   		}
  370   
  371   		super.setFile(fileName, append);
  372   		if(append) {
  373   		  File f = new File(fileName);
  374   		  ((CountingQuietWriter) qw).setCount(f.length());
  375   		}
  376   	}
  377   
  378   	public int getCountDirection() {
  379   		return countDirection;
  380   	}
  381   
  382   	public void setCountDirection(int direction) {
  383   		countDirection = direction;
  384   	}
  385   
  386   	public int getRollingStyle () {
  387           return rollingStyle;
  388   	}
  389   
  390   	public void setRollingStyle(int style) {
  391   	    rollingStyle = style;
  392   		switch (rollingStyle) {
  393   			case BY_SIZE:
  394   				 rollDate = false;
  395   				 rollSize = true;
  396   				 break;
  397   			case BY_DATE:
  398   				 rollDate = true;
  399   				 rollSize = false;
  400   				 break;
  401   			case BY_COMPOSITE:
  402   				 rollDate = true;
  403   				 rollSize = true;
  404   				 break;
  405   			default:
  406   				errorHandler.error("Invalid rolling Style, use 1 (by size only), 2 (by date only) or 3 (both)");
  407   		}
  408   	}
  409   
  410   /*
  411   	public void setRollingStyle(String style) {
  412   		if (style == S_BY_SIZE) {
  413   		    rollingStyle = BY_SIZE;
  414   		}
  415   		else if (style == S_BY_DATE) {
  416   		    rollingStyle = BY_DATE;
  417   		}
  418   		else if (style == S_BY_COMPOSITE) {
  419   			rollingStyle = BY_COMPOSITE;
  420   		}
  421   	}
  422   */
  423   	public boolean getStaticLogFileName() {
  424   	    return staticLogFileName;
  425   	}
  426   
  427   	public void setStaticLogFileName(boolean s) {
  428   		staticLogFileName = s;
  429   	}
  430   
  431   	public void setStaticLogFileName(String value) {
  432   		setStaticLogFileName(OptionConverter.toBoolean(value, true));
  433   	}
  434   
  435   	/**
  436   	 *  Initializes based on exisiting conditions at time of <code>
  437   	 *  activateOptions</code>.  The following is done:<br>
  438   	 *  <br>
  439   	 *	A) determine curSizeRollBackups<br>
  440   	 *	B) determine curTimeRollBackups (not implemented)<br>
  441   	 *	C) initiates a roll over if needed for crossing a date boundary since
  442   	 *  the last run.
  443   	 */
  444   	protected void existingInit() {
  445   
  446   		curSizeRollBackups = 0;
  447   		curTimeRollBackups = 0;
  448   
  449   		//part A starts here
  450   		String filter;
  451   		if (staticLogFileName || !rollDate) {
  452   			filter = baseFileName + ".*";
  453   		}
  454   		else {
  455   			filter = scheduledFilename + ".*";
  456   		}
  457   
  458   		File f = new File(baseFileName);
  459   		f = f.getParentFile();
  460   		if (f == null)
  461   		   f = new File(".");
  462   
  463   		LogLog.debug("Searching for existing files in: " + f);
  464   		String[] files = f.list();
  465   
  466   		if (files != null) {
  467   			for (int i = 0; i < files.length; i++) {
  468   				if (!files[i].startsWith(baseFileName))
  469   				   continue;
  470   
  471   				int index = files[i].lastIndexOf(".");
  472   
  473   				if (staticLogFileName) {
  474   				   int endLength = files[i].length() - index;
  475   				   if (baseFileName.length() + endLength != files[i].length()) {
  476   					   //file is probably scheduledFilename + .x so I don't care
  477   					   continue;
  478   				   }
  479   				}
  480   
  481   				try {
  482   					int backup = Integer.parseInt(files[i].substring(index + 1, files[i].length()));
  483   					LogLog.debug("From file: " + files[i] + " -> " + backup);
  484   					if (backup > curSizeRollBackups)
  485   					   curSizeRollBackups = backup;
  486   				}
  487   				catch (Exception e) {
  488   					//this happens when file.log -> file.log.yyyy-mm-dd which is normal
  489   					//when staticLogFileName == false
  490   					LogLog.debug("Encountered a backup file not ending in .x " + files[i]);
  491   				}
  492   			}
  493   		}
  494   		LogLog.debug("curSizeRollBackups starts at: " + curSizeRollBackups);
  495   		//part A ends here
  496   
  497   		//part B not yet implemented
  498   
  499   		//part C
  500   		if (staticLogFileName && rollDate) {
  501   			File old = new File(baseFileName);
  502   			if (old.exists()) {
  503   				Date last = new Date(old.lastModified());
  504   				if (!(sdf.format(last).equals(sdf.format(now)))) {
  505   					scheduledFilename = baseFileName + sdf.format(last);
  506   					LogLog.debug("Initial roll over to: " + scheduledFilename);
  507   					rollOverTime();
  508   				}
  509   			}
  510   		}
  511   		LogLog.debug("curSizeRollBackups after rollOver at: " + curSizeRollBackups);
  512   		//part C ends here
  513   
  514   	}
  515   
  516   	/**
  517   	 * Sets initial conditions including date/time roll over information, first check,
  518   	 * scheduledFilename, and calls <code>existingInit</code> to initialize
  519   	 * the current # of backups.
  520   	 */
  521   	public void activateOptions() {
  522   
  523   	    //REMOVE removed rollDate from boolean to enable Alex's change
  524   		if(datePattern != null) {
  525   			now.setTime(System.currentTimeMillis());
  526   			sdf = new SimpleDateFormat(datePattern);
  527   			int type = computeCheckPeriod();
  528   			//printPeriodicity(type);
  529   			rc.setType(type);
  530   			//next line added as this removes the name check in rollOver
  531   			nextCheck = rc.getNextCheckMillis(now);
  532   		} else {
  533   			if (rollDate)
  534   			    LogLog.error("Either DatePattern or rollingStyle options are not set for ["+
  535   			      name+"].");
  536   		}
  537   
  538   		existingInit();
  539   
  540   		super.activateOptions();
  541   
  542   		if (rollDate && fileName != null && scheduledFilename == null)
  543   			scheduledFilename = fileName + sdf.format(now);
  544   	}
  545   
  546   	/**
  547   	 Rollover the file(s) to date/time tagged file(s).
  548   	 Opens the new file (through setFile) and resets curSizeRollBackups.
  549   	*/
  550   	protected void rollOverTime() {
  551   
  552   	    curTimeRollBackups++;
  553   
  554   		//delete the old stuff here
  555   
  556   		if (staticLogFileName) {
  557   			/* Compute filename, but only if datePattern is specified */
  558   			if (datePattern == null) {
  559   				errorHandler.error("Missing DatePattern option in rollOver().");
  560   				return;
  561   			}
  562   
  563   			//is the new file name equivalent to the 'current' one
  564   			//something has gone wrong if we hit this -- we should only
  565   			//roll over if the new file will be different from the old
  566   			String dateFormat = sdf.format(now);
  567   			if (scheduledFilename.equals(fileName + dateFormat)) {
  568   				errorHandler.error("Compare " + scheduledFilename + " : " + fileName + dateFormat);
  569   				return;
  570   			}
  571   
  572   			// close current file, and rename it to datedFilename
  573   			this.closeFile();
  574   
  575   			//we may have to roll over a large number of backups here
  576   	        String from, to;
  577   			for (int i = 1; i <= curSizeRollBackups; i++) {
  578   				from = fileName + '.' + i;
  579   				to = scheduledFilename + '.' + i;
  580   				rollFile(from, to);
  581   	        }
  582   
  583   			rollFile(fileName, scheduledFilename);
  584   		}
  585   
  586   		try {
  587   			// This will also close the file. This is OK since multiple
  588   			// close operations are safe.
  589   			curSizeRollBackups = 0; //We're cleared out the old date and are ready for the new
  590   
  591   			//new scheduled name
  592   			scheduledFilename = fileName + sdf.format(now);
  593   			this.setFile(baseFileName, false);
  594   		}
  595   		catch(IOException e) {
  596   			errorHandler.error("setFile("+fileName+", false) call failed.");
  597   		}
  598   
  599   	}
  600   
  601   	/** Renames file <code>from</code> to file <code>to</code>.  It
  602   	 *  also checks for existence of target file and deletes if it does.
  603   	 */
  604   	protected static void rollFile(String from, String to) {
  605   		File target = new File(to);
  606   		if (target.exists()) {
  607   			LogLog.debug("deleting existing target file: " + target);
  608   			target.delete();
  609   		}
  610   
  611   		File file = new File(from);
  612   		file.renameTo(target);
  613   		LogLog.debug(from +" -> "+ to);
  614   	}
  615   
  616   	/** Delete's the specified file if it exists */
  617   	protected static void deleteFile(String fileName) {
  618   		File file = new File(fileName);
  619   		if (file.exists()) {
  620   		   file.delete();
  621   		}
  622   	}
  623   
  624   	/**
  625   	 Implements roll overs base on file size.
  626   
  627   	 <p>If the maximum number of size based backups is reached
  628   	 (<code>curSizeRollBackups == maxSizeRollBackups</code) then the oldest
  629   	 file is deleted -- it's index determined by the sign of countDirection.<br>
  630   	 If <code>countDirection</code> < 0, then files
  631   	 {<code>File.1</code>, ..., <code>File.curSizeRollBackups -1</code>}
  632   	 are renamed to {<code>File.2</code>, ...,
  633   	 <code>File.curSizeRollBackups</code>}.	 Moreover, <code>File</code> is
  634   	 renamed <code>File.1</code> and closed.<br>
  635   
  636   	 A new file is created to receive further log output.
  637   
  638   	 <p>If <code>maxSizeRollBackups</code> is equal to zero, then the
  639   	 <code>File</code> is truncated with no backup files created.
  640   
  641   	 <p>If <code>maxSizeRollBackups</code> < 0, then <code>File</code> is
  642   	 renamed if needed and no files are deleted.
  643   	*/
  644   
  645   	// synchronization not necessary since doAppend is alreasy synched
  646   	protected void rollOverSize() {
  647   		File file;
  648   
  649   		this.closeFile(); // keep windows happy.
  650   
  651   		LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount());
  652   		LogLog.debug("maxSizeRollBackups = " + maxSizeRollBackups);
  653   		LogLog.debug("curSizeRollBackups = " + curSizeRollBackups);
  654   		LogLog.debug("countDirection = " + countDirection);
  655   
  656   		// If maxBackups <= 0, then there is no file renaming to be done.
  657   		if (maxSizeRollBackups != 0) {
  658   
  659   			if (countDirection < 0) {
  660   				// Delete the oldest file, to keep Windows happy.
  661   				if (curSizeRollBackups == maxSizeRollBackups) {
  662   				    deleteFile(fileName + '.' + maxSizeRollBackups);
  663   					curSizeRollBackups--;
  664   				}
  665   
  666   				// Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
  667   				for (int i = curSizeRollBackups; i >= 1; i--) {
  668   					rollFile((fileName + "." + i), (fileName + '.' + (i + 1)));
  669   				}
  670   
  671   				curSizeRollBackups++;
  672   				// Rename fileName to fileName.1
  673   				rollFile(fileName, fileName + ".1");
  674   
  675   			} //REMOVE This code branching for Alexander Cerna's request
  676   			else if (countDirection == 0) {
  677   				//rollFile based on date pattern
  678   				curSizeRollBackups++;
  679   				now.setTime(System.currentTimeMillis());
  680   				scheduledFilename = fileName + sdf.format(now);
  681   				rollFile(fileName, scheduledFilename);
  682   			}
  683   			else { //countDirection > 0
  684   				if (curSizeRollBackups >= maxSizeRollBackups && maxSizeRollBackups > 0) {
  685   					//delete the first and keep counting up.
  686   					int oldestFileIndex = curSizeRollBackups - maxSizeRollBackups + 1;
  687   					deleteFile(fileName + '.' + oldestFileIndex);
  688   				}
  689   
  690   				if (staticLogFileName) {
  691   					curSizeRollBackups++;
  692   					rollFile(fileName, fileName + '.' + curSizeRollBackups);
  693   				}
  694   			}
  695   		}
  696   
  697   		try {
  698   			// This will also close the file. This is OK since multiple
  699   			// close operations are safe.
  700   			this.setFile(baseFileName, false);
  701   		}
  702   		catch(IOException e) {
  703   			LogLog.error("setFile("+fileName+", false) call failed.", e);
  704   		}
  705   	}
  706   
  707   }

Save This Page
Home » apache-log4j-1.2.15 » org.apache » log4j » [javadoc | source]