本文主要研究一下rocketmq的RollingFileAppenderjava
org/apache/rocketmq/logging/inner/LoggingBuilder.javagit
public static class RollingFileAppender extends FileAppender { protected long maxFileSize = 10 * 1024 * 1024; protected int maxBackupIndex = 1; private long nextRollover = 0; public RollingFileAppender() { super(); } public int getMaxBackupIndex() { return maxBackupIndex; } public long getMaximumFileSize() { return maxFileSize; } //...... public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException { super.setFile(fileName, append, this.bufferedIO, this.bufferSize); if (append) { File f = new File(fileName); ((CountingQuietWriter) qw).setCount(f.length()); } } public void setMaxBackupIndex(int maxBackups) { this.maxBackupIndex = maxBackups; } public void setMaximumFileSize(long maxFileSize) { this.maxFileSize = maxFileSize; } protected void setQWForFiles(Writer writer) { this.qw = new CountingQuietWriter(writer, this); } protected void subAppend(LoggingEvent event) { super.subAppend(event); if (fileName != null && qw != null) { long size = ((CountingQuietWriter) qw).getCount(); if (size >= maxFileSize && size >= nextRollover) { rollOver(); } } } protected class CountingQuietWriter extends QuietWriter { protected long count; public CountingQuietWriter(Writer writer, Appender appender) { super(writer, appender); } public void write(String string) { try { out.write(string); count += string.length(); } catch (IOException e) { appender.handleError("Write failure.", e, Appender.CODE_WRITE_FAILURE); } } public long getCount() { return count; } public void setCount(long count) { this.count = count; } } }
org/apache/rocketmq/logging/inner/LoggingBuilder.javagithub
public void rollOver() { File target; File file; if (qw != null) { long size = ((CountingQuietWriter) qw).getCount(); SysLogger.debug("rolling over count=" + size); nextRollover = size + maxFileSize; } SysLogger.debug("maxBackupIndex=" + maxBackupIndex); boolean renameSucceeded = true; if (maxBackupIndex > 0) { file = new File(fileName + '.' + maxBackupIndex); if (file.exists()) { renameSucceeded = file.delete(); } for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) { file = new File(fileName + "." + i); if (file.exists()) { target = new File(fileName + '.' + (i + 1)); SysLogger.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); } } if (renameSucceeded) { target = new File(fileName + "." + 1); this.closeFile(); // keep windows happy. file = new File(fileName); SysLogger.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); if (!renameSucceeded) { try { this.setFile(fileName, true, bufferedIO, bufferSize); } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } SysLogger.error("setFile(" + fileName + ", true) call failed.", e); } } } } if (renameSucceeded) { try { this.setFile(fileName, false, bufferedIO, bufferSize); nextRollover = 0; } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } SysLogger.error("setFile(" + fileName + ", false) call failed.", e); } } }
RollingFileAppender在每次append的時候,都會先append數據,而後再判斷是否超出文件大小限制,超出了再執行rollOver操做,對既有文件進行重命名,而後從新生成新的文件。注意這裏沒有進行同步操做,所以須要最外層調用的方法有同步併發控制。apache