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