1
2
3
4
5
6
7
8
9
10
11
12 package ch.qos.logback.core.rolling;
13
14 import static ch.qos.logback.core.CoreConstants.MANUAL_URL_PREFIX;
15
16 import java.io.File;
17 import java.time.Instant;
18
19 import ch.qos.logback.core.CoreConstants;
20 import ch.qos.logback.core.joran.spi.NoAutoStart;
21 import ch.qos.logback.core.rolling.helper.ArchiveRemover;
22 import ch.qos.logback.core.rolling.helper.CompressionMode;
23 import ch.qos.logback.core.rolling.helper.FileFilterUtil;
24 import ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover;
25 import ch.qos.logback.core.util.Duration;
26 import ch.qos.logback.core.util.FileSize;
27
28
29
30
31
32
33
34
35
36
37 @NoAutoStart
38 public class SizeAndTimeBasedFileNamingAndTriggeringPolicy<E> extends TimeBasedFileNamingAndTriggeringPolicyBase<E> {
39
40 enum Usage {
41 EMBEDDED, DIRECT
42 }
43
44 volatile int currentPeriodsCounter = 0;
45 FileSize maxFileSize;
46
47 Duration checkIncrement = null;
48
49 static String MISSING_INT_TOKEN = "Missing integer token, that is %i, in FileNamePattern [";
50 static String MISSING_DATE_TOKEN = "Missing date token, that is %d, in FileNamePattern [";
51
52 private final Usage usage;
53
54
55
56 public SizeAndTimeBasedFileNamingAndTriggeringPolicy() {
57 this(Usage.DIRECT);
58 }
59
60 public SizeAndTimeBasedFileNamingAndTriggeringPolicy(Usage usage) {
61 this.usage = usage;
62 }
63
64 public LengthCounter lengthCounter = new LengthCounterBase();
65
66
67
68 @Override
69 public void start() {
70
71 super.start();
72
73 if (usage == Usage.DIRECT) {
74 addWarn(CoreConstants.SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED);
75 addWarn("For more information see " + MANUAL_URL_PREFIX + "appenders.html#SizeAndTimeBasedRollingPolicy");
76 }
77
78 if (!super.isErrorFree())
79 return;
80
81 if (maxFileSize == null) {
82 addError("maxFileSize property is mandatory.");
83 withErrors();
84 }
85
86
87
88
89 if (!validateDateAndIntegerTokens()) {
90 withErrors();
91 return;
92 }
93
94 archiveRemover = createArchiveRemover();
95 archiveRemover.setContext(context);
96
97
98
99
100 String regex = tbrp.fileNamePattern.toRegexForFixedDate(dateInCurrentPeriod);
101 String stemRegex = FileFilterUtil.afterLastSlash(regex);
102
103 computeCurrentPeriodsHighestCounterValue(stemRegex);
104
105 if (isErrorFree()) {
106 started = true;
107 }
108 }
109
110 private boolean validateDateAndIntegerTokens() {
111 boolean inError = false;
112 if (tbrp.fileNamePattern.getIntegerTokenConverter() == null) {
113 inError = true;
114 addError(MISSING_INT_TOKEN + tbrp.fileNamePatternStr + "]");
115 addError(CoreConstants.SEE_MISSING_INTEGER_TOKEN);
116 }
117 if (tbrp.fileNamePattern.getPrimaryDateTokenConverter() == null) {
118 inError = true;
119 addError(MISSING_DATE_TOKEN + tbrp.fileNamePatternStr + "]");
120 }
121
122 return !inError;
123 }
124
125 protected ArchiveRemover createArchiveRemover() {
126 return new SizeAndTimeBasedArchiveRemover(tbrp.fileNamePattern, rc);
127 }
128
129 void computeCurrentPeriodsHighestCounterValue(final String stemRegex) {
130 File file = new File(getCurrentPeriodsFileNameWithoutCompressionSuffix());
131 File parentDir = file.getParentFile();
132
133 File[] matchingFileArray = FileFilterUtil.filesInFolderMatchingStemRegex(parentDir, stemRegex);
134
135 if (matchingFileArray == null || matchingFileArray.length == 0) {
136 currentPeriodsCounter = 0;
137 return;
138 }
139 currentPeriodsCounter = FileFilterUtil.findHighestCounter(matchingFileArray, stemRegex);
140
141
142
143 if (tbrp.getParentsRawFileProperty() != null || (tbrp.compressionMode != CompressionMode.NONE)) {
144
145 currentPeriodsCounter++;
146 }
147 }
148
149 @Override
150 public boolean isTriggeringEvent(File activeFile, final E event) {
151
152 long currentTime = getCurrentTime();
153 long localNextCheck = atomicNextCheck.get();
154
155
156 if (currentTime >= localNextCheck) {
157 long nextCheckCandidate = computeNextCheck(currentTime);
158 atomicNextCheck.set(nextCheckCandidate);
159 Instant instantInElapsedPeriod = dateInCurrentPeriod;
160 elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(
161 instantInElapsedPeriod, currentPeriodsCounter);
162 currentPeriodsCounter = 0;
163 setDateInCurrentPeriod(currentTime);
164 lengthCounter.reset();
165 return true;
166 }
167
168 boolean result = checkSizeBasedTrigger(activeFile, currentTime);
169 if(result)
170 lengthCounter.reset();
171 return result;
172 }
173
174 private boolean checkSizeBasedTrigger(File activeFile, long currentTime) {
175
176
177
178
179
180 if (activeFile == null) {
181 addWarn("activeFile == null");
182 return false;
183 }
184 if (maxFileSize == null) {
185 addWarn("maxFileSize = null");
186 return false;
187 }
188
189
190
191 if (lengthCounter.getLength() >= maxFileSize.getSize()) {
192
193 elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(dateInCurrentPeriod,
194 currentPeriodsCounter);
195 currentPeriodsCounter++;
196
197 return true;
198 }
199
200 return false;
201 }
202
203 public Duration getCheckIncrement() {
204 return null;
205 }
206
207 public void setCheckIncrement(Duration checkIncrement) {
208 addWarn("Since version 1.5.8, 'checkIncrement' property has no effect");
209 }
210
211 @Override
212 public String getCurrentPeriodsFileNameWithoutCompressionSuffix() {
213 return tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(dateInCurrentPeriod,
214 currentPeriodsCounter);
215 }
216
217 public void setMaxFileSize(FileSize aMaxFileSize) {
218 this.maxFileSize = aMaxFileSize;
219 }
220
221 @Override
222 public LengthCounter getLengthCounter() {
223 return lengthCounter;
224 }
225 }