1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.rolling;
15
16 import static ch.qos.logback.core.CoreConstants.CODES_URL;
17
18 import java.io.File;
19 import java.time.Instant;
20 import java.util.Date;
21 import java.util.Locale;
22 import java.util.TimeZone;
23 import java.util.concurrent.atomic.AtomicLong;
24
25 import ch.qos.logback.core.CoreConstants;
26 import ch.qos.logback.core.rolling.helper.ArchiveRemover;
27 import ch.qos.logback.core.rolling.helper.DateTokenConverter;
28 import ch.qos.logback.core.rolling.helper.RollingCalendar;
29 import ch.qos.logback.core.spi.ContextAwareBase;
30
31
32
33
34
35
36
37
38
39
40
41 abstract public class TimeBasedFileNamingAndTriggeringPolicyBase<E> extends ContextAwareBase
42 implements TimeBasedFileNamingAndTriggeringPolicy<E> {
43
44 static private String COLLIDING_DATE_FORMAT_URL = CODES_URL + "#rfa_collision_in_dateFormat";
45
46 protected TimeBasedRollingPolicy<E> tbrp;
47
48 protected ArchiveRemover archiveRemover = null;
49 protected String elapsedPeriodsFileName;
50 protected RollingCalendar rc;
51
52 protected long artificialCurrentTime = -1;
53
54 protected AtomicLong atomicNextCheck = new AtomicLong(0);
55 protected Instant dateInCurrentPeriod = null;
56
57 protected boolean started = false;
58 protected boolean errorFree = true;
59
60 public boolean isStarted() {
61 return started;
62 }
63
64 public void start() {
65 DateTokenConverter<Object> dtc = tbrp.fileNamePattern.getPrimaryDateTokenConverter();
66 if (dtc == null) {
67 throw new IllegalStateException(
68 "FileNamePattern [" + tbrp.fileNamePattern.getPattern() + "] does not contain a valid DateToken");
69 }
70
71 if (dtc.getZoneId() != null) {
72 TimeZone tz = TimeZone.getTimeZone(dtc.getZoneId());
73 rc = new RollingCalendar(dtc.getDatePattern(), tz, Locale.getDefault());
74 } else {
75 rc = new RollingCalendar(dtc.getDatePattern());
76 }
77 addInfo("The date pattern is '" + dtc.getDatePattern() + "' from file name pattern '"
78 + tbrp.fileNamePattern.getPattern() + "'.");
79 rc.printPeriodicity(this);
80
81 if (!rc.isCollisionFree()) {
82 addError(
83 "The date format in FileNamePattern will result in collisions in the names of archived log files.");
84 addError(CoreConstants.MORE_INFO_PREFIX + COLLIDING_DATE_FORMAT_URL);
85 withErrors();
86 return;
87 }
88
89 long timestamp = getCurrentTime();
90 setDateInCurrentPeriod(timestamp);
91
92 if (tbrp.getParentsRawFileProperty() != null) {
93 File currentFile = new File(tbrp.getParentsRawFileProperty());
94 if (currentFile.exists() && currentFile.canRead()) {
95 timestamp = currentFile.lastModified();
96 setDateInCurrentPeriod(timestamp);
97 }
98 }
99 addInfo("Setting initial period to " + dateInCurrentPeriod);
100 long nextCheck = computeNextCheck(timestamp);
101 atomicNextCheck.set(nextCheck);
102 }
103
104 public void stop() {
105 started = false;
106 }
107
108 protected long computeNextCheck(long timestamp) {
109 return rc.getNextTriggeringDate(Instant.ofEpochMilli(timestamp)).toEpochMilli();
110 }
111
112 public String getElapsedPeriodsFileName() {
113 return elapsedPeriodsFileName;
114 }
115
116 public String getCurrentPeriodsFileNameWithoutCompressionSuffix() {
117 return tbrp.fileNamePatternWithoutCompSuffix.convert(dateInCurrentPeriod);
118 }
119
120 protected void setDateInCurrentPeriod(long timestamp) {
121 dateInCurrentPeriod = Instant.ofEpochMilli(timestamp);
122 }
123
124 public void setCurrentTime(long timeInMillis) {
125 artificialCurrentTime = timeInMillis;
126 }
127
128 public long getCurrentTime() {
129
130 if (artificialCurrentTime >= 0) {
131 return artificialCurrentTime;
132 } else {
133 return System.currentTimeMillis();
134 }
135 }
136
137 public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy<E> _tbrp) {
138 this.tbrp = _tbrp;
139
140 }
141
142 public ArchiveRemover getArchiveRemover() {
143 return archiveRemover;
144 }
145
146 protected void withErrors() {
147 errorFree = false;
148 }
149
150 protected boolean isErrorFree() {
151 return errorFree;
152 }
153
154 }