@Test public void shouldReturnNewestTransactionId() { when( transactionIdStore.getLastClosedTransactionId() ).thenReturn( 42L ); when( transactionIdStore.getLastCommittedTransactionId() ).thenReturn( 4242L ); assertEquals( 4242L, transactionIdTracker.newestEncounteredTxId() ); } }
@Test public void shouldReturnImmediatelyForBaseTxIdOrLess() throws Exception { // when transactionIdTracker.awaitUpToDate( BASE_TX_ID, ofSeconds( 5 ) ); // then verify( transactionIdStore, never() ).awaitClosedTransactionId( anyLong(), anyLong() ); }
private void mockTxIdStore() { long[] triggerCommittedTransaction = {transactionId, logPosition.getLogVersion(), logPosition.getByteOffset()}; when( txIdStore.getLastClosedTransaction() ).thenReturn( triggerCommittedTransaction ); when( txIdStore.getLastClosedTransactionId() ).thenReturn( initialTransactionId, transactionId, transactionId ); }
transactionIdStore().awaitClosedTransactionId( oldestAcceptableTxId, timeout.toMillis() ); transactionIdStore().getLastClosedTransactionId() );
FlushablePositionAwareChannel channel = spy( new InMemoryClosableChannel() ); IOException failure = new IOException( failureMessage ); final Flushable flushable = mock( Flushable.class ); doAnswer( invocation -> } ).when( channel ).prepareForFlush(); doThrow( failure ).when( flushable ).flush(); when( logFile.getWriter() ).thenReturn( channel ); TransactionMetadataCache metadataCache = new TransactionMetadataCache(); TransactionIdStore transactionIdStore = mock( TransactionIdStore.class ); when( transactionIdStore.nextCommittingTransactionId() ).thenReturn( txId ); Mockito.reset( databaseHealth ); TransactionAppender appender = life.add( new BatchingTransactionAppender( logFiles, NO_ROTATION, TransactionRepresentation transaction = mock( TransactionRepresentation.class ); when( transaction.additionalHeader() ).thenReturn( new byte[0] ); try verify( transactionIdStore, times( 1 ) ).nextCommittingTransactionId(); verify( transactionIdStore, never() ).transactionClosed( eq( txId ), anyLong(), anyLong() ); verify( databaseHealth ).panic( failure );
String failureMessage = "Forces a failure"; FlushablePositionAwareChannel channel = spy( new PositionAwarePhysicalFlushableChannel( mock( PhysicalLogVersionedStoreChannel.class ) ) ); IOException failure = new IOException( failureMessage ); when( channel.putInt( anyInt() ) ).thenThrow( failure ); when( logFile.getWriter() ).thenReturn( channel ); when( transactionIdStore.nextCommittingTransactionId() ).thenReturn( txId ); Mockito.reset( databaseHealth ); TransactionAppender appender = life.add( createTransactionAppender() ); verify( transactionIdStore, times( 1 ) ).nextCommittingTransactionId(); verify( transactionIdStore, never() ).transactionClosed( eq( txId ), anyLong(), anyLong() ); verify( databaseHealth ).panic( failure );
@Test public void shouldCloseTransactionRegardlessOfWhetherOrNotItAppliedCorrectly() throws Exception { // GIVEN TransactionIdStore transactionIdStore = mock( TransactionIdStore.class ); TransactionAppender appender = new TestableTransactionAppender( transactionIdStore ); long txId = 11; when( transactionIdStore.nextCommittingTransactionId() ).thenReturn( txId ); IOException rootCause = new IOException( "Mock exception" ); StorageEngine storageEngine = mock( StorageEngine.class ); doThrow( new IOException( rootCause ) ).when( storageEngine ).apply( any( TransactionToApply.class ), any( TransactionApplicationMode.class ) ); TransactionCommitProcess commitProcess = new TransactionRepresentationCommitProcess( appender, storageEngine ); TransactionToApply transaction = mockedTransaction(); // WHEN try { commitProcess.commit( transaction, commitEvent, INTERNAL ); } catch ( TransactionFailureException e ) { assertThat( e.getMessage(), containsString( "Could not apply the transaction to the store" ) ); assertTrue( contains( e, rootCause.getMessage(), rootCause.getClass() ) ); } // THEN // we can't verify transactionCommitted since that's part of the TransactionAppender, which we have mocked verify( transactionIdStore, times( 1 ) ).transactionClosed( eq( txId ), anyLong(), anyLong() ); }
@Test public void shouldKernelPanicIfTransactionIdsMismatch() throws Throwable { // Given BatchingTransactionAppender appender = life.add( createTransactionAppender() ); when( transactionIdStore.nextCommittingTransactionId() ).thenReturn( 42L ); TransactionToApply batch = new TransactionToApply( mock( TransactionRepresentation.class ), 43L ); // When try { appender.append( batch, LogAppendEvent.NULL ); fail( "should have thrown " ); } catch ( IllegalStateException ex ) { // Then verify( databaseHealth, times( 1 ) ).panic( ex ); } }
@Test public void shouldSuccessfullyCommitTransactionWithNoCommands() throws Exception { // GIVEN long txId = 11; long commitTimestamp = System.currentTimeMillis(); TransactionIdStore transactionIdStore = mock( TransactionIdStore.class ); TransactionAppender appender = new TestableTransactionAppender( transactionIdStore ); when( transactionIdStore.nextCommittingTransactionId() ).thenReturn( txId ); StorageEngine storageEngine = mock( StorageEngine.class ); TransactionCommitProcess commitProcess = new TransactionRepresentationCommitProcess( appender, storageEngine ); PhysicalTransactionRepresentation noCommandTx = new PhysicalTransactionRepresentation( Collections.emptyList() ); noCommandTx.setHeader( new byte[0], -1, -1, -1, -1, -1, -1 ); // WHEN commitProcess.commit( new TransactionToApply( noCommandTx ), commitEvent, INTERNAL ); verify( transactionIdStore ).transactionCommitted( txId, FakeCommitment.CHECKSUM, FakeCommitment.TIMESTAMP ); }
private static TransactionIdStore fixedTxIdStore( long lastClosedTransactionId ) { TransactionIdStore txIdStore = mock( TransactionIdStore.class ); when( txIdStore.getLastClosedTransactionId() ).thenReturn( lastClosedTransactionId ); return txIdStore; }
@Test public void shouldAppendBatchOfTransactions() throws Exception { // GIVEN when( logFile.getWriter() ).thenReturn( channel ); TransactionAppender appender = life.add( createTransactionAppender() ); when( transactionIdStore.nextCommittingTransactionId() ).thenReturn( 2L, 3L, 4L ); TransactionToApply batch = batchOf( transaction( singleCreateNodeCommand( 0 ), new byte[0], 0, 0, 0, 1, 0 ), transaction( singleCreateNodeCommand( 1 ), new byte[0], 0, 0, 0, 1, 0 ), transaction( singleCreateNodeCommand( 2 ), new byte[0], 0, 0, 0, 1, 0 ) ); // WHEN appender.append( batch, logAppendEvent ); // THEN TransactionToApply tx = batch; assertEquals( 2L, tx.transactionId() ); tx = tx.next(); assertEquals( 3L, tx.transactionId() ); tx = tx.next(); assertEquals( 4L, tx.transactionId() ); assertNull( tx.next() ); }
private static KernelTransactions newKernelTransactions( Locks locks, StorageEngine storageEngine, TransactionCommitProcess commitProcess, boolean testKernelTransactions ) { LifeSupport life = new LifeSupport(); life.start(); TransactionIdStore transactionIdStore = mock( TransactionIdStore.class ); when( transactionIdStore.getLastCommittedTransaction() ).thenReturn( new TransactionId( 0, 0, 0 ) ); Tracers tracers = new Tracers( "null", NullLog.getInstance(), new Monitors(), mock( JobScheduler.class ), clock ); StatementLocksFactory statementLocksFactory = new SimpleStatementLocksFactory( locks ); StatementOperationParts statementOperations = mock( StatementOperationParts.class ); KernelTransactions transactions; if ( testKernelTransactions ) { transactions = createTestTransactions( storageEngine, commitProcess, transactionIdStore, tracers, statementLocksFactory, statementOperations, clock, databaseAvailabilityGuard ); } else { transactions = createTransactions( storageEngine, commitProcess, transactionIdStore, tracers, statementLocksFactory, statementOperations, clock, databaseAvailabilityGuard ); } transactions.start(); return transactions; }
when( logFile.getWriter() ).thenReturn( channel ); TransactionAppender appender = life.add( createTransactionAppender() ); latestCommittedTxWhenStarted, timeCommitted, -1 ); when( transactionIdStore.getLastCommittedTransactionId() ).thenReturn( latestCommittedTxWhenStarted );
@Test public void shouldWaitForRequestedVersion() throws Exception { // given long version = 5L; // when transactionIdTracker.awaitUpToDate( version, DEFAULT_DURATION ); // then verify( transactionIdStore ).awaitClosedTransactionId( version, DEFAULT_DURATION.toMillis() ); }
@Test public void shouldPropagateTimeoutException() throws Exception { // given long version = 5L; TimeoutException timeoutException = new TimeoutException(); doThrow( timeoutException ).when( transactionIdStore ).awaitClosedTransactionId( anyLong(), anyLong() ); try { // when transactionIdTracker.awaitUpToDate( version + 1, ofMillis( 50 ) ); fail( "should have thrown" ); } catch ( TransactionFailureException ex ) { // then assertEquals( Status.Transaction.InstanceStateChanged, ex.status() ); assertEquals( timeoutException, ex.getCause() ); } }
public long lastClosedTxId() { return gdb.getDependencyResolver().resolveDependency( TransactionIdStore.class ).getLastClosedTransactionId(); }
private static long lastCommittedTxId( GraphDatabaseAPI db ) { TransactionIdStore txIdStore = db.getDependencyResolver().resolveDependency( TransactionIdStore.class ); return txIdStore.getLastCommittedTransactionId(); }
@Test public void shouldIdentifyTransactionWithNetZeroChangesAsReadOnly() { // GIVEN a transaction that has seen some changes, where all those changes result in a net 0 change set // a good way of producing such state is to add a label to an existing node, and then remove it. GraphDatabaseAPI db = dbr.getGraphDatabaseAPI(); TransactionIdStore txIdStore = db.getDependencyResolver().resolveDependency( TransactionIdStore.class ); long startTxId = txIdStore.getLastCommittedTransactionId(); Node node = createEmptyNode( db ); try ( Transaction tx = db.beginTx() ) { node.addLabel( TestLabels.LABEL_ONE ); node.removeLabel( TestLabels.LABEL_ONE ); tx.success(); } // WHEN closing that transaction // THEN it should not have been committed assertEquals( "Expected last txId to be what it started at + 2 (1 for the empty node, and one for the label)", startTxId + 2, txIdStore.getLastCommittedTransactionId() ); }
@Override public long getLastCommittedTxId() { NeoStoreDataSource neoStoreDataSource = xadsm.getDataSource(); if ( neoStoreDataSource == null ) { return -1; } return neoStoreDataSource.getDependencyResolver().resolveDependency( TransactionIdStore.class ) .getLastCommittedTransactionId(); } }
/** * Find the id of the Newest Encountered Transaction (NET) that could have been seen on this server. * We expect the returned id to be sent back the client and ultimately supplied to * {@link #awaitUpToDate(long, Duration)} on this server, or on a different server in the cluster. * * @return id of the Newest Encountered Transaction (NET). */ public long newestEncounteredTxId() { // return the "last committed" because it is the newest id // "last closed" will return the last gap-free id, pottentially for some old transaction because there might be other committing transactions return transactionIdStore().getLastCommittedTransactionId(); } }