/** * Test method for * {@link org.apache.logging.log4j.core.appender.rolling.RollingRandomAccessFileManager#writeBytes(byte[], int, int)} . */ @Test public void testWrite_dataExceedingBufferSize() throws IOException { final File file = File.createTempFile("log4j2", "test"); file.deleteOnExit(); try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) { final OutputStream os = NullOutputStream.getInstance(); final boolean append = false; final boolean flushNow = false; final long triggerSize = 0; final long time = System.currentTimeMillis(); final TriggeringPolicy triggerPolicy = new SizeBasedTriggeringPolicy(triggerSize); final RolloverStrategy rolloverStrategy = null; final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(null, raf, file.getName(), Strings.EMPTY, os, append, flushNow, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, triggerSize, time, triggerPolicy, rolloverStrategy, null, null, null, null, null, true); final int size = RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3 + 1; final byte[] data = new byte[size]; manager.write(data, 0, data.length, flushNow); // no exception assertEquals(RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3 + 1, raf.length()); manager.flush(); assertEquals(size, raf.length()); // all data written to file now } }
@Test public void testConfigurableBufferSize() throws IOException { final File file = File.createTempFile("log4j2", "test"); file.deleteOnExit(); try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) { final OutputStream os = NullOutputStream.getInstance(); final boolean append = false; final boolean flushNow = false; final long triggerSize = 0; final long time = System.currentTimeMillis(); final TriggeringPolicy triggerPolicy = new SizeBasedTriggeringPolicy(triggerSize); final int bufferSize = 4 * 1024; assertNotEquals(bufferSize, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE); final RolloverStrategy rolloverStrategy = null; final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(null, raf, file.getName(), Strings.EMPTY, os, append, flushNow, bufferSize, triggerSize, time, triggerPolicy, rolloverStrategy, null, null, null, null, null, true); // check the resulting buffer size is what was requested assertEquals(bufferSize, manager.getBufferSize()); } }
@Test public void testFileTimeBasedOnFileModifiedTimeWhenAppendIsTrue() throws IOException { final File file = File.createTempFile("log4j2", "test"); file.deleteOnExit(); LockSupport.parkNanos(1000000); // 1 millisec final boolean isAppend = true; assertThat(file, lastModified(beforeNow())); final RollingRandomAccessFileManager manager = RollingRandomAccessFileManager.getRollingRandomAccessFileManager( // file.getAbsolutePath(), Strings.EMPTY, isAppend, true, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, new SizeBasedTriggeringPolicy(Long.MAX_VALUE), // null, null, null, null, null, null, null); assertThat(file, lastModified(equalTo(manager.getFileTime()))); }
/** * Test method for * {@link org.apache.logging.log4j.core.appender.rolling.RollingRandomAccessFileManager#writeBytes(byte[], int, int)} */ @Test public void testWrite_multiplesOfBufferSize() throws IOException { final File file = File.createTempFile("log4j2", "test"); file.deleteOnExit(); try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) { final OutputStream os = NullOutputStream.getInstance(); final boolean append = false; final boolean flushNow = false; final long triggerSize = Long.MAX_VALUE; final long time = System.currentTimeMillis(); final TriggeringPolicy triggerPolicy = new SizeBasedTriggeringPolicy(triggerSize); final RolloverStrategy rolloverStrategy = null; final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(null, raf, file.getName(), Strings.EMPTY, os, append, flushNow, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, triggerSize, time, triggerPolicy, rolloverStrategy, null, null, null, null, null, true); final int size = RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3; final byte[] data = new byte[size]; manager.write(data, 0, data.length, flushNow); // no buffer overflow exception // buffer is full but not flushed yet assertEquals(RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3, raf.length()); } }
@Test public void testAppendDoesNotOverwriteExistingFile() throws IOException { final boolean isAppend = true; final File file = File.createTempFile("log4j2", "test"); file.deleteOnExit(); assertThat(file, isEmpty()); final byte[] bytes = new byte[4 * 1024]; // create existing file FileOutputStream fos = null; try { fos = new FileOutputStream(file); fos.write(bytes, 0, bytes.length); fos.flush(); } finally { Closer.closeSilently(fos); } assertThat("all flushed to disk", file, hasLength(bytes.length)); final boolean immediateFlush = true; final RollingRandomAccessFileManager manager = RollingRandomAccessFileManager.getRollingRandomAccessFileManager( // file.getAbsolutePath(), Strings.EMPTY, isAppend, immediateFlush, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, new SizeBasedTriggeringPolicy(Long.MAX_VALUE), // null, null, null, null, null, null, null); manager.write(bytes, 0, bytes.length, immediateFlush); final int expected = bytes.length * 2; assertThat("appended, not overwritten", file, hasLength(expected)); }
@Override protected synchronized void writeToDestination(final byte[] bytes, final int offset, final int length) { try { if (randomAccessFile == null) { String fileName = getFileName(); File file = new File(fileName); FileUtils.makeParentDirs(file); createFileAfterRollover(fileName); } randomAccessFile.write(bytes, offset, length); size += length; } catch (final IOException ex) { final String msg = "Error writing to RandomAccessFile " + getName(); throw new AppenderLoggingException(msg, ex); } }
final RollingRandomAccessFileManager rrm = new RollingRandomAccessFileManager(data.getLoggerContext(), raf, name, data.pattern, NullOutputStream.getInstance(), data.append, data.immediateFlush, data.bufferSize, size, time, data.policy, data.strategy, data.advertiseURI, data.layout, data.filePermissions, data.fileOwner, data.fileGroup, writeHeader); if (rrm.isAttributeViewEnabled()) { rrm.defineAttributeView(file.toPath());
final int bufferSize = getBufferSize(); final RollingRandomAccessFileManager manager = RollingRandomAccessFileManager .getRollingRandomAccessFileManager(fileName, filePattern, append, immediateFlush, bufferSize, policy, strategy, advertiseURI, layout, filePermissions, fileOwner, fileGroup, getConfiguration()); manager.initialize();
@Override protected void createFileAfterRollover() throws IOException { createFileAfterRollover(getFileName()); }
public static RollingRandomAccessFileManager getRollingRandomAccessFileManager(final String fileName, final String filePattern, final boolean isAppend, final boolean immediateFlush, final int bufferSize, final TriggeringPolicy policy, final RolloverStrategy strategy, final String advertiseURI, final Layout<? extends Serializable> layout, final String filePermissions, final String fileOwner, final String fileGroup, final Configuration configuration) { if (strategy instanceof DirectWriteRolloverStrategy && fileName != null) { LOGGER.error("The fileName attribute must not be specified with the DirectWriteRolloverStrategy"); return null; } final String name = fileName == null ? filePattern : fileName; return narrow(RollingRandomAccessFileManager.class, getManager(name, new FactoryData(fileName, filePattern, isAppend, immediateFlush, bufferSize, policy, strategy, advertiseURI, layout, filePermissions, fileOwner, fileGroup, configuration), FACTORY)); }
/** * Returns the size of the file manager's buffer. * @return the buffer size */ public int getBufferSize() { return getManager().getBufferSize(); }
/** * Write the log entry rolling over the file when required. * * @param event The LogEvent. */ @Override public void append(final LogEvent event) { final RollingRandomAccessFileManager manager = getManager(); manager.checkRollover(event); // Leverage the nice batching behaviour of async Loggers/Appenders: // we can signal the file manager that it needs to flush the buffer // to disk at the end of a batch. // From a user's point of view, this means that all log events are // _always_ available in the log file, without incurring the overhead // of immediateFlush=true. manager.setEndOfBatch(event.isEndOfBatch()); // FIXME manager's EndOfBatch threadlocal can be deleted // LOG4J2-1292 utilize gc-free Layout.encode() method: taken care of in superclass super.append(event); }
@Override public synchronized void flush() { flushBuffer(byteBuffer); }
@Test public void testFileTimeBasedOnSystemClockWhenAppendIsFalse() throws IOException { final File file = File.createTempFile("log4j2", "test"); file.deleteOnExit(); LockSupport.parkNanos(1000000); // 1 millisec // append is false deletes the file if it exists final boolean isAppend = false; final long expectedMin = System.currentTimeMillis(); final long expectedMax = expectedMin + 500; assertThat(file, lastModified(lessThanOrEqualTo(expectedMin))); final RollingRandomAccessFileManager manager = RollingRandomAccessFileManager.getRollingRandomAccessFileManager( // file.getAbsolutePath(), Strings.EMPTY, isAppend, true, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, new SizeBasedTriggeringPolicy(Long.MAX_VALUE), // null, null, null, null, null, null, null); assertTrue(manager.getFileTime() < expectedMax); assertTrue(manager.getFileTime() >= expectedMin); }