Skip to content

Commit

Permalink
Add linktolatest option for RollingFileWriter
Browse files Browse the repository at this point in the history
  • Loading branch information
pabl0rg committed Jun 1, 2020
1 parent f7bf925 commit 5e62235
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand All @@ -43,6 +44,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 +74,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 = removeLinkToLatest(path.getAllFiles());

String fileName;
boolean append;
Expand All @@ -96,7 +99,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);
}

private List<File> removeLinkToLatest(final List<File> files) {
if (linkToLatest != null) {
String linkToLatestAbsolutePath = linkToLatest.resolve();
List<File> symlink = new ArrayList<File>();
for (File file : files) {
if (file.getAbsolutePath().equals(linkToLatestAbsolutePath)) {
symlink.add(file);
break;
}
}
files.removeAll(symlink);
}
return files;
}

private ByteArrayWriter createByteArrayWriterAndLinkLatest(final String fileName, final boolean append, final boolean buffered,
final boolean threadSafe, final boolean shared) throws FileNotFoundException {
ByteArrayWriter writer = AbstractFormatPatternWriter.createByteArrayWriter(fileName, append, buffered, threadSafe, shared);
if (linkToLatest != null) {
String logFile = new File(fileName).getAbsolutePath();
String linkFile = new File(linkToLatest.resolve()).getAbsolutePath();
try {
Process process = Runtime.getRuntime().exec(new String[]{"ln", "-sf", logFile, linkFile});
try {
process.waitFor();
} catch (InterruptedException intEx) {
InternalLogger.log(Level.WARN, intEx, "Interrupted while creating symlink '" + linkFile + "'");
}
process.destroy();
} catch (IOException exception) {
InternalLogger.log(Level.ERROR, exception, "Failed to create symlink '" + linkFile + "'");
}
}
return writer;
}

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

List<File> existingFiles = removeLinkToLatest(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,92 @@ public void isRegistered() throws IOException {
assertThat(writer).isInstanceOf(RollingFileWriter.class);
}


/**
* Verifies that symlink to new log segment is created at startup.
*
* @throws IOException
* Failed access to temporary folder or files
*/
@Test
public void createSymlinkToLatestAtStartUp() throws IOException {
File file1 = folder.newFile("0");
File file2 = folder.newFile("1");
File file3 = folder.newFile("2");
File file4 = folder.newFile("3");
File linkToLatest = folder.newFile("latest");

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

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: 1MB");
properties.put("backups", "2");

RollingFileWriter writer = new RollingFileWriter(properties);
try {
assertThat(linkToLatest.getCanonicalPath()).isEqualTo(file4.getCanonicalPath());
assertThat(file1).doesNotExist();
assertThat(file2).exists();
assertThat(file3).exists();
assertThat(file4).exists();
} finally {
writer.close();
}
}

/**
* 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 5e62235

Please sign in to comment.