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 import java.util.Date;
19
20 import ch.qos.logback.core.CoreConstants;
21 import ch.qos.logback.core.joran.spi.NoAutoStart;
22 import ch.qos.logback.core.rolling.helper.ArchiveRemover;
23 import ch.qos.logback.core.rolling.helper.CompressionMode;
24 import ch.qos.logback.core.rolling.helper.FileFilterUtil;
25 import ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover;
26 import ch.qos.logback.core.util.Duration;
27 import ch.qos.logback.core.util.FileSize;
28 import ch.qos.logback.core.util.DefaultInvocationGate;
29 import ch.qos.logback.core.util.InvocationGate;
30 import ch.qos.logback.core.util.SimpleInvocationGate;
31
32
33
34
35
36
37
38
39
40
41 @NoAutoStart
42 public class SizeAndTimeBasedFNATP<E> extends TimeBasedFileNamingAndTriggeringPolicyBase<E> {
43
44 enum Usage {
45 EMBEDDED, DIRECT
46 }
47
48 volatile int currentPeriodsCounter = 0;
49 FileSize maxFileSize;
50
51 Duration checkIncrement = null;
52
53 static String MISSING_INT_TOKEN = "Missing integer token, that is %i, in FileNamePattern [";
54 static String MISSING_DATE_TOKEN = "Missing date token, that is %d, in FileNamePattern [";
55
56 private final Usage usage;
57
58 InvocationGate invocationGate = new SimpleInvocationGate();
59
60 public SizeAndTimeBasedFNATP() {
61 this(Usage.DIRECT);
62 }
63
64 public SizeAndTimeBasedFNATP(Usage usage) {
65 this.usage = usage;
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 if (checkIncrement != null)
87 invocationGate = new SimpleInvocationGate(checkIncrement);
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
165 return true;
166 }
167
168 return checkSizeBasedTrigger(activeFile, currentTime);
169 }
170
171 private boolean checkSizeBasedTrigger(File activeFile, long currentTime) {
172
173 if (invocationGate.isTooSoon(currentTime)) {
174 return false;
175 }
176
177 if (activeFile == null) {
178 addWarn("activeFile == null");
179 return false;
180 }
181 if (maxFileSize == null) {
182 addWarn("maxFileSize = null");
183 return false;
184 }
185 if (activeFile.length() >= maxFileSize.getSize()) {
186
187 elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(dateInCurrentPeriod,
188 currentPeriodsCounter);
189 currentPeriodsCounter++;
190 return true;
191 }
192
193 return false;
194 }
195
196 public Duration getCheckIncrement() {
197 return checkIncrement;
198 }
199
200 public void setCheckIncrement(Duration checkIncrement) {
201 this.checkIncrement = checkIncrement;
202 }
203
204 @Override
205 public String getCurrentPeriodsFileNameWithoutCompressionSuffix() {
206 return tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(dateInCurrentPeriod,
207 currentPeriodsCounter);
208 }
209
210 public void setMaxFileSize(FileSize aMaxFileSize) {
211 this.maxFileSize = aMaxFileSize;
212 }
213
214 }