001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.rolling; 015 016import static ch.qos.logback.core.CoreConstants.CODES_URL; 017 018import java.io.File; 019import java.time.Instant; 020import java.time.ZoneId; 021import java.util.Locale; 022import java.util.TimeZone; 023import java.util.concurrent.atomic.AtomicLong; 024 025import ch.qos.logback.core.CoreConstants; 026import ch.qos.logback.core.rolling.helper.ArchiveRemover; 027import ch.qos.logback.core.rolling.helper.DateTokenConverter; 028import ch.qos.logback.core.rolling.helper.RollingCalendar; 029import ch.qos.logback.core.spi.ContextAwareBase; 030 031/** 032 * Base implementation of {@link TimeBasedFileNamingAndTriggeringPolicy}. 033 * 034 * <p>See also derived classes {@link DefaultTimeBasedFileNamingAndTriggeringPolicy} and 035 * {@link SizeAndTimeBasedFileNamingAndTriggeringPolicy}. 036 * 037 * </p> 038 * 039 * @param <E> 040 */ 041abstract public class TimeBasedFileNamingAndTriggeringPolicyBase<E> extends ContextAwareBase 042 implements TimeBasedFileNamingAndTriggeringPolicy<E> { 043 044 static private String COLLIDING_DATE_FORMAT_URL = CODES_URL + "#rfa_collision_in_dateFormat"; 045 046 protected TimeBasedRollingPolicy<E> tbrp; 047 048 protected ArchiveRemover archiveRemover = null; 049 protected String elapsedPeriodsFileName; 050 protected RollingCalendar rc; 051 052 protected long artificialCurrentTime = -1; 053 054 protected AtomicLong atomicNextCheck = new AtomicLong(0); 055 protected Instant dateInCurrentPeriod = null; 056 057 protected boolean started = false; 058 protected boolean errorFree = true; 059 060 protected ZoneId zoneId = ZoneId.systemDefault(); 061 062 public boolean isStarted() { 063 return started; 064 } 065 066 public void start() { 067 DateTokenConverter<Object> dtc = tbrp.fileNamePattern.getPrimaryDateTokenConverter(); 068 if (dtc == null) { 069 throw new IllegalStateException( 070 "FileNamePattern [" + tbrp.fileNamePattern.getPattern() + "] does not contain a valid DateToken"); 071 } 072 073 if (dtc.getZoneId() != null) { 074 this.zoneId = dtc.getZoneId(); 075 TimeZone tz = TimeZone.getTimeZone(zoneId); 076 rc = new RollingCalendar(dtc.getDatePattern(), tz, Locale.getDefault()); 077 } else { 078 rc = new RollingCalendar(dtc.getDatePattern()); 079 } 080 addInfo("The date pattern is '" + dtc.getDatePattern() + "' from file name pattern '" 081 + tbrp.fileNamePattern.getPattern() + "'."); 082 rc.printPeriodicity(this); 083 084 if (!rc.isCollisionFree()) { 085 addError( 086 "The date format in FileNamePattern will result in collisions in the names of archived log files."); 087 addError(CoreConstants.MORE_INFO_PREFIX + COLLIDING_DATE_FORMAT_URL); 088 withErrors(); 089 return; 090 } 091 092 long timestamp = getCurrentTime(); 093 setDateInCurrentPeriod(timestamp); 094 095 if (tbrp.getParentsRawFileProperty() != null) { 096 File currentFile = new File(tbrp.getParentsRawFileProperty()); 097 if (currentFile.canRead()) { 098 timestamp = currentFile.lastModified(); 099 setDateInCurrentPeriod(timestamp); 100 } 101 } 102 addInfo("Setting initial period to " + dateInCurrentPeriod); 103 long nextCheck = computeNextCheck(timestamp); 104 atomicNextCheck.set(nextCheck); 105 } 106 107 public void stop() { 108 started = false; 109 } 110 111 protected long computeNextCheck(long timestamp) { 112 return rc.getNextTriggeringDate(Instant.ofEpochMilli(timestamp)).toEpochMilli(); 113 } 114 115 public String getElapsedPeriodsFileName() { 116 return elapsedPeriodsFileName; 117 } 118 119 public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { 120 return tbrp.fileNamePatternWithoutCompSuffix.convert(dateInCurrentPeriod); 121 } 122 123 protected void setDateInCurrentPeriod(long timestamp) { 124 dateInCurrentPeriod = Instant.ofEpochMilli(timestamp); 125 } 126 127 public void setCurrentTime(long timeInMillis) { 128 artificialCurrentTime = timeInMillis; 129 } 130 131 public long getCurrentTime() { 132 // if time is forced return the time set by user 133 if (artificialCurrentTime >= 0) { 134 return artificialCurrentTime; 135 } else { 136 return System.currentTimeMillis(); 137 } 138 } 139 140 public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy<E> _tbrp) { 141 this.tbrp = _tbrp; 142 143 } 144 145 public ArchiveRemover getArchiveRemover() { 146 return archiveRemover; 147 } 148 149 protected void withErrors() { 150 errorFree = false; 151 } 152 153 protected boolean isErrorFree() { 154 return errorFree; 155 } 156 157}