@Test public void shouldRespectCustomLogRotationThreshold() throws Exception { // GIVEN long maxSize = 1000; XaLogicalLog log = new XaLogicalLog( new File("log"), mock(XaResourceManager.class), new FixedSizeXaCommandFactory(), new VersionRespectingXaTransactionFactory(), new DefaultLogBufferFactory(), ephemeralFs.get(), new DevNullLoggingService(), NO_PRUNING, mock(TransactionStateFactory.class), maxSize); log.open(); long initialLogVersion = log.getHighestLogVersion(); // WHEN for (int i = 0; i < 10; i++) { int identifier = log.start(xid, -1, -1); log.writeStartEntry(identifier); log.writeCommand(new FixedSizeXaCommand(100), identifier); log.commitOnePhase(identifier, i + 1, forced); log.done(identifier); } // THEN assertEquals(initialLogVersion + 1, log.getHighestLogVersion()); }
private int logCount() { XaLogicalLog log = neoDataSource().getXaContainer().getLogicalLog(); int count = 0; for (long i = log.getHighestLogVersion() - 1; i >= 0; i--) { if (fs.fileExists(log.getFileName(i))) { count++; } else { break; } } return count; }
@Test public void shouldNotReadExcessivelyFromTheFileChannelWhenRotatingLogWithNoOpenTransactions() throws Exception { // given XaTransactionFactory xaTf = mock(XaTransactionFactory.class); when(xaTf.getAndSetNewVersion()).thenAnswer(new TxVersion(TxVersion.UPDATE_AND_GET)); when(xaTf.getCurrentVersion()).thenAnswer(new TxVersion(TxVersion.GET)); // spy on the file system abstraction so that we can spy on the file channel for the logical log FileSystemAbstraction fs = spy(ephemeralFs.get()); File dir = TargetDirectory.forTest(fs, XaLogicalLogTest.class).directory("log", true); // -- when opening the logical log, spy on the file channel we return and count invocations to // channel.read(*) when(fs.open(new File(dir, "logical.log.1"), "rw")) .thenAnswer( new Answer<FileChannel>() { @Override public FileChannel answer(InvocationOnMock invocation) throws Throwable { FileChannel channel = (FileChannel) invocation.callRealMethod(); return mock( channel.getClass(), withSettings() .spiedInstance(channel) .name("channel") .defaultAnswer(CALLS_REAL_METHODS) .invocationListeners( new InvocationListener() { @Override public void reportInvocation( MethodInvocationReport methodInvocationReport) { if (methodInvocationReport .getInvocation() .toString() .startsWith("channel.read(")) { reads++; } } })); } }); XaLogicalLog xaLogicalLog = new XaLogicalLog( new File(dir, "logical.log"), mock(XaResourceManager.class), mock(XaCommandFactory.class), xaTf, new DefaultLogBufferFactory(), fs, new SingleLoggingService(StringLogger.wrap(output.writer())), LogPruneStrategies.NO_PRUNING, mock(TransactionStateFactory.class), 25 * 1024 * 1024); xaLogicalLog.open(); // -- set the log up with 10 transactions (with no commands, just start and commit) for (int txId = 1; txId <= 10; txId++) { int identifier = xaLogicalLog.start(new XidImpl(XidImpl.getNewGlobalId(), RESOURCE_ID), -1, 0); xaLogicalLog.writeStartEntry(identifier); xaLogicalLog.commitOnePhase(identifier, txId, ForceMode.forced); xaLogicalLog.done(identifier); } // when xaLogicalLog.rotate(); // then assertThat( "should not read excessively from the logical log file channel", reads, lessThan(10)); }