Skip to content

Commit 93bd8a9

Browse files
author
Mike Dobozy
committed
Fix for #139.
1 parent bfaf68e commit 93bd8a9

File tree

3 files changed

+456
-17
lines changed

3 files changed

+456
-17
lines changed

ext/src/main/java/org/jboss/logmanager/ext/handlers/PeriodicRotatingFileHandler.java

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919

2020
package org.jboss.logmanager.ext.handlers;
2121

22+
import org.jboss.logmanager.ExtLogRecord;
23+
import org.jboss.logmanager.handlers.FileHandler;
24+
2225
import java.io.File;
2326
import java.io.FileNotFoundException;
2427
import java.io.IOException;
28+
import java.nio.file.Files;
29+
import java.nio.file.Path;
2530
import java.text.SimpleDateFormat;
26-
import java.util.Calendar;
27-
import java.util.Date;
28-
import java.util.TimeZone;
31+
import java.util.*;
2932
import java.util.logging.ErrorManager;
30-
31-
import org.jboss.logmanager.ExtLogRecord;
32-
import org.jboss.logmanager.handlers.FileHandler;
33+
import java.util.regex.Pattern;
34+
import java.util.stream.Collectors;
35+
import java.util.stream.IntStream;
3336

3437
/**
3538
* A file handler which rotates the log at a preset time interval. The interval is determined by the content of the
@@ -44,6 +47,13 @@ public class PeriodicRotatingFileHandler extends FileHandler {
4447
private TimeZone timeZone = TimeZone.getDefault();
4548
private SuffixRotator suffixRotator = SuffixRotator.EMPTY;
4649

50+
private enum PruningStrategy { NONE, PERIODS, SIZE };
51+
52+
private String pruneSize;
53+
private long pruneSizeResolved = 0L;
54+
private PruningStrategy pruningStrategy = PruningStrategy.NONE;
55+
56+
4757
/**
4858
* Construct a new instance with no formatter and no output file.
4959
*/
@@ -198,9 +208,72 @@ private void rollOver() {
198208
suffixRotator.rotate(getErrorManager(), file.toPath(), nextSuffix);
199209
// start new file
200210
setFile(file);
211+
212+
if (pruneSizeResolved > 0) {
213+
pruneFiles(file);
214+
}
215+
201216
} catch (IOException e) {
202217
reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE);
203218
}
219+
220+
}
221+
222+
private void pruneFiles(File baseFile) throws IOException {
223+
224+
synchronized (outputLock) {
225+
226+
String baseName = baseFile.getName();
227+
Path parent = baseFile.toPath().getParent();
228+
String suffixPattern = this.getSuffixRotator().getDatePattern();
229+
230+
Pattern namePattern = Pattern.compile("^" + Pattern.quote(baseName) + ".*$");
231+
232+
/*
233+
* Pruneable files are files in the current file's directory that are:
234+
*
235+
* a) regular (not symlinks, dirs, or hidden)
236+
* b) not the current log
237+
* c) match the current file syntax
238+
* d) at a max depth of 1 (files in nested dirs aren't considered)
239+
*/
240+
List<File> pruneables = Files
241+
.find(parent, 1, (p, a) ->
242+
a.isRegularFile() &&
243+
!p.getFileName().toString().equals(baseName) &&
244+
namePattern.matcher(p.getFileName().toString()).matches()
245+
)
246+
.map(Path::toFile)
247+
.filter(File::canWrite)
248+
.sorted(Comparator.comparingLong(File::lastModified).thenComparing(File::getName))
249+
.collect(Collectors.toList());
250+
251+
if (pruningStrategy == PruningStrategy.SIZE) {
252+
long total = pruneables.stream().mapToLong(File::length).sum();
253+
if (total > pruneSizeResolved) {
254+
for (int i = 0, size = pruneables.size(); i < size && total > pruneSizeResolved; i++) {
255+
long fsize = pruneables.get(i).length();
256+
try {
257+
Files.deleteIfExists(pruneables.get(i).toPath());
258+
} catch (IOException ex) {
259+
reportError("Unable to prune log file", ex, ErrorManager.GENERIC_FAILURE);
260+
}
261+
total -= fsize;
262+
}
263+
}
264+
} else if (pruningStrategy == PruningStrategy.PERIODS) {
265+
int periods = Long.valueOf(pruneSizeResolved).intValue();
266+
if (pruneables.size() > periods) {
267+
for (int i = 0; i < periods; i++) {
268+
try {
269+
Files.deleteIfExists(pruneables.get(i).toPath());
270+
} catch (IOException ex) {
271+
reportError("Unable to prune log file", ex, ErrorManager.GENERIC_FAILURE);
272+
}
273+
}
274+
}
275+
}
276+
}
204277
}
205278

206279
private void calcNextRollover(final long fromTime) {
@@ -293,6 +366,28 @@ public void setTimeZone(final TimeZone timeZone) {
293366
this.timeZone = timeZone;
294367
}
295368

369+
public String getPruneSize() {
370+
return pruneSize;
371+
}
372+
373+
public void setPruneSize(String pruneSize) {
374+
this.pruneSize = pruneSize;
375+
try {
376+
if (pruneSize.endsWith("p") || pruneSize.endsWith("P")) {
377+
pruningStrategy = PruningStrategy.PERIODS;
378+
pruneSizeResolved = Long.parseLong(pruneSize.substring(0, pruneSize.length() - 1));
379+
} else {
380+
pruningStrategy = PruningStrategy.SIZE;
381+
pruneSizeResolved = Long.parseLong(pruneSize);
382+
}
383+
} catch (NumberFormatException e) {
384+
reportError("Unable to parse prune size", e, ErrorManager.FORMAT_FAILURE);
385+
}
386+
if (pruneSizeResolved < 0) {
387+
reportError("Prune size must be positive", null, ErrorManager.GENERIC_FAILURE);
388+
}
389+
}
390+
296391
private static <T extends Comparable<? super T>> T min(T a, T b) {
297392
return a.compareTo(b) <= 0 ? a : b;
298393
}

0 commit comments

Comments
 (0)