Skip to content

Commit

Permalink
Merge pull request #150 from pabl0rg/add-link-to-latest
Browse files Browse the repository at this point in the history
Add linktolatest option for RollingFileWriter
  • Loading branch information
pmwmedia authored Jun 23, 2020
2 parents 9384b52 + a1bb571 commit a4556eb
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 5 deletions.
7 changes: 6 additions & 1 deletion tinylog-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@
<groupId>org.tinylog</groupId>
<artifactId>tinylog-api</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-annotations</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>

<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.tinylog.Level;
import org.tinylog.configuration.ServiceLoader;
import org.tinylog.core.LogEntry;
Expand All @@ -43,6 +47,7 @@ public final class RollingFileWriter extends AbstractFormatPatternWriter {
private final int backups;
private final boolean buffered;
private final boolean writingThread;
private final DynamicPath linkToLatest;
private final Charset charset;

private ByteArrayWriter writer;
Expand Down Expand Up @@ -72,8 +77,9 @@ public RollingFileWriter(final Map<String, String> properties) throws FileNotFou
path = new DynamicPath(getFileName(properties));
policies = createPolicies(properties.get("policies"));
backups = properties.containsKey("backups") ? Integer.parseInt(properties.get("backups")) : -1;
linkToLatest = properties.containsKey("latest") ? new DynamicPath(properties.get("latest")) : null;

List<File> files = path.getAllFiles();
List<File> files = filterOutSymlinks(path.getAllFiles());

String fileName;
boolean append;
Expand All @@ -96,7 +102,43 @@ public RollingFileWriter(final Map<String, String> properties) throws FileNotFou
charset = getCharset(properties);
buffered = Boolean.parseBoolean(properties.get("buffered"));
writingThread = Boolean.parseBoolean(properties.get("writingthread"));
writer = createByteArrayWriter(fileName, append, buffered, false, false);
writer = createByteArrayWriterAndLinkLatest(fileName, append, buffered, false, false);
}

@IgnoreJRERequirement
private static List<File> filterOutSymlinks(final List<File> files) {
if (!RuntimeProvider.isAndroid()) {
List<File> symlinks = new ArrayList<File>();
for (File file : files) {
if (Files.isSymbolicLink(file.toPath())) {
symlinks.add(file);
}
}
files.removeAll(symlinks);
}
return files;
}

@IgnoreJRERequirement
private ByteArrayWriter createByteArrayWriterAndLinkLatest(final String fileName, final boolean append, final boolean buffered,
final boolean threadSafe, final boolean shared) throws FileNotFoundException {
ByteArrayWriter writer = createByteArrayWriter(fileName, append, buffered, threadSafe, shared);
if (linkToLatest != null) {
File logFile = new File(fileName);
File linkFile = new File(linkToLatest.resolve());
if (!RuntimeProvider.isAndroid()) {
try {
Path linkPath = linkFile.toPath();
Files.delete(linkPath);
Files.createSymbolicLink(linkPath, logFile.toPath());
} catch (IOException exception) {
InternalLogger.log(Level.ERROR, exception, "Failed to create symlink '" + linkFile + "'");
}
} else {
InternalLogger.log(Level.WARN, "Cannot create symlink to latest log segment on Android");
}
}
return writer;
}

@Override
Expand Down Expand Up @@ -145,9 +187,11 @@ private void internalWrite(final byte[] data) throws IOException {
if (!canBeContinued(data, policies)) {
writer.close();

List<File> existingFiles = filterOutSymlinks(path.getAllFiles());
deleteBackups(existingFiles, backups);

String fileName = path.resolve();
deleteBackups(path.getAllFiles(), backups);
writer = createByteArrayWriter(fileName, false, buffered, false, false);
writer = createByteArrayWriterAndLinkLatest(fileName, false, buffered, false, false);

for (Policy policy : policies) {
policy.reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,4 +481,53 @@ public void isRegistered() throws IOException {
assertThat(writer).isInstanceOf(RollingFileWriter.class);
}

/**
* Verifies that obsolete backup files will be deleted when rolling log file.
*
* @throws IOException
* Failed access to temporary folder or files
*/
@Test
public void updateSymlinkToLatestAtRollOver() throws IOException {
File file1 = folder.newFile("0");
File file2 = folder.newFile("1");
File file3 = folder.newFile("2");
File file4 = folder.newFile("3");
File file5 = folder.newFile("4");
File linkToLatest = folder.newFile("latest");

file1.setLastModified(0);
file2.setLastModified(1000);
file3.setLastModified(2000);
file4.setLastModified(3000);
file5.delete();

Map<String, String> properties = new HashMap<>();
properties.put("file", new File(folder.getRoot(), "{count}").getAbsolutePath());
properties.put("latest", linkToLatest.getAbsolutePath());
properties.put("format", "{message}");
properties.put("policies", "size: 10");
properties.put("backups", "3");

RollingFileWriter writer = new RollingFileWriter(properties);

assertThat(file1).exists();
assertThat(file2).exists();
assertThat(file3).exists();
assertThat(file4).exists();
assertThat(file5).doesNotExist();

writer.write(LogEntryBuilder.empty().message("First").create());
writer.write(LogEntryBuilder.empty().message("Second").create());

assertThat(file1).doesNotExist();
assertThat(file2).exists();
assertThat(file3).exists();
assertThat(file4).hasContent("First" + NEW_LINE);
assertThat(file5).hasContent("Second" + NEW_LINE);

assertThat(linkToLatest.getCanonicalPath()).isEqualTo(file5.getCanonicalPath());

writer.close();
}
}

0 comments on commit a4556eb

Please sign in to comment.