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ülcü 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. */ CompositeRollingAppender()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 */ CompositeRollingAppender(Layout layout, String filename, String datePattern)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 */ CompositeRollingAppender(Layout layout, String filename, boolean append)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 */ CompositeRollingAppender(Layout layout, String filename, String datePattern, boolean append)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 */ CompositeRollingAppender(Layout layout, String filename)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 */ setDatePattern(String pattern)209 public void setDatePattern(String pattern) { 210 datePattern = pattern; 211 } 212 213 /** Returns the value of the <b>DatePattern</b> option. */ getDatePattern()214 public String getDatePattern() { 215 return datePattern; 216 } 217 218 /** 219 Returns the value of the <b>maxSizeRollBackups</b> option. 220 */ getMaxSizeRollBackups()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 */ getMaximumFileSize()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 */ setMaxSizeRollBackups(int maxBackups)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 */ setMaxFileSize(long maxFileSize)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 */ setMaximumFileSize(long maxFileSize)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 */ setMaxFileSize(String value)298 public void setMaxFileSize(String value) { 299 maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1); 300 } 301 setQWForFiles(Writer writer)302 protected void setQWForFiles(Writer writer) { 303 qw = new CountingQuietWriter(writer, errorHandler); 304 } 305 306 //Taken verbatum from DailyRollingFileAppender computeCheckPeriod()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 */ subAppend(LoggingEvent event)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 setFile(String file)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 */ setFile(String fileName, boolean append)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 getCountDirection()378 public int getCountDirection() { 379 return countDirection; 380 } 381 setCountDirection(int direction)382 public void setCountDirection(int direction) { 383 countDirection = direction; 384 } 385 getRollingStyle()386 public int getRollingStyle () { 387 return rollingStyle; 388 } 389 setRollingStyle(int style)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 */ getStaticLogFileName()423 public boolean getStaticLogFileName() { 424 return staticLogFileName; 425 } 426 setStaticLogFileName(boolean s)427 public void setStaticLogFileName(boolean s) { 428 staticLogFileName = s; 429 } 430 setStaticLogFileName(String value)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 */ existingInit()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 */ activateOptions()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 */ rollOverTime()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 */ rollFile(String from, String to)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 */ deleteFile(String fileName)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 rollOverSize()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 }