private TransactionToApply mockedTransaction() { TransactionRepresentation transaction = mock( TransactionRepresentation.class ); when( transaction.additionalHeader() ).thenReturn( new byte[0] ); return new TransactionToApply( transaction ); } }
TransactionCommitment commitment = appendToLog( tx.transactionRepresentation(), transactionId ); tx.commitment( commitment, transactionId ); tx.logPosition( commitment.logPosition() ); tx = tx.next(); lastTransactionId = transactionId;
private void matchAgainstExpectedTransactionIdIfAny( long transactionId, TransactionToApply tx ) { long expectedTransactionId = tx.transactionId(); if ( expectedTransactionId != TRANSACTION_ID_NOT_SPECIFIED ) { if ( transactionId != expectedTransactionId ) { IllegalStateException ex = new IllegalStateException( "Received " + tx.transactionRepresentation() + " with txId:" + expectedTransactionId + " to be applied, but appending it ended up generating an unexpected txId:" + transactionId ); databaseHealth.panic( ex ); throw ex; } } }
private void close( TransactionToApply batch ) { while ( batch != null ) { if ( batch.commitment().markedAsCommitted() ) { batch.commitment().publishAsClosed(); } batch.close(); batch = batch.next(); } } }
private void publishAsCommitted( TransactionToApply batch ) { while ( batch != null ) { batch.commitment().publishAsCommitted(); batch = batch.next(); } }
private static TransactionToApply tx( Collection<StorageCommand> commands ) { TransactionToApply tx = new TransactionToApply( transactionRepresentation( commands ) ); tx.commitment( NO_COMMITMENT, 0 ); return tx; }
private static TransactionToApply toApply( Collection<TransactionRepresentation> transactions ) { TransactionToApply first = null; TransactionToApply last = null; for ( TransactionRepresentation transactionRepresentation : transactions ) { TransactionToApply transaction = new TransactionToApply( transactionRepresentation ); if ( first == null ) { first = last = transaction; } else { last.next( transaction ); last = transaction; } } return first; }
@Override public boolean visit( CommittedTransactionRepresentation transaction ) throws Exception { TransactionRepresentation txRepresentation = transaction.getTransactionRepresentation(); long txId = transaction.getCommitEntry().getTxId(); TransactionToApply tx = new TransactionToApply( txRepresentation, txId ); tx.commitment( NO_COMMITMENT, txId ); tx.logPosition( transaction.getStartEntry().getStartPosition() ); storageEngine.apply( tx, mode ); return false; }
private static TransactionCommitProcess newRememberingCommitProcess( final TransactionRepresentation[] slot ) throws TransactionFailureException { TransactionCommitProcess commitProcess = mock( TransactionCommitProcess.class ); when( commitProcess.commit( any( TransactionToApply.class ), any( CommitEvent.class ), any( TransactionApplicationMode.class ) ) ) .then( invocation -> { slot[0] = ((TransactionToApply) invocation.getArgument( 0 )).transactionRepresentation(); return 1L; } ); return commitProcess; }
@Override public long commit( TransactionToApply batch, CommitEvent commitEvent, TransactionApplicationMode mode ) { assert transaction == null : "Designed to only allow one transaction"; assert batch.next() == null : "Designed to only allow one transaction"; transaction = batch.transactionRepresentation(); return ++txId; } }
TransactionToApply transaction = new TransactionToApply( tx ); transaction.onClose( txId -> callback.accept( Result.of( txId ) ) ); queue.queue( transaction );
@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() ); }
@Before public void setup() { when( transactionToApply.transactionId() ).thenReturn( 1L ); when( indexingService.convertToIndexUpdates( any(), eq( EntityType.NODE ) ) ).thenAnswer( o -> Iterables.empty() ); }
public void queue( TransactionToApply transaction ) throws Exception { if ( isEmpty() ) { first = last = transaction; } else { last.next( transaction ); last = transaction; } if ( ++size == maxSize ) { empty(); } }
@Override public void commitment( Commitment commitment, long transactionId ) { // TODO Perhaps odd to override this method here just to be able to call txHandler? super.commitment( commitment, transactionId ); txHandler.accept( transactionId ); } } );
private static TransactionToApply newTransactionThatFailsWith( Exception error ) throws IOException { TransactionRepresentation transaction = mock( TransactionRepresentation.class ); when( transaction.additionalHeader() ).thenReturn( new byte[0] ); // allow to build validated index updates but fail on actual tx application doThrow( error ).when( transaction ).accept( any() ); long txId = ThreadLocalRandom.current().nextLong( 0, 1000 ); TransactionToApply txToApply = new TransactionToApply( transaction ); FakeCommitment commitment = new FakeCommitment( txId, mock( TransactionIdStore.class ) ); commitment.setHasExplicitIndexChanges( false ); txToApply.commitment( commitment, txId ); return txToApply; }
private TransactionToApply batchOf( TransactionRepresentation... transactions ) { TransactionToApply first = null; TransactionToApply last = null; for ( TransactionRepresentation transaction : transactions ) { TransactionToApply tx = new TransactionToApply( transaction ); if ( first == null ) { first = last = tx; } else { last.next( tx ); last = tx; } } return first; } }
@Override public boolean visit( CommittedTransactionRepresentation transaction ) throws Exception { TransactionRepresentation txRepresentation = transaction.getTransactionRepresentation(); long txId = transaction.getCommitEntry().getTxId(); TransactionToApply tx = new TransactionToApply( txRepresentation, txId ); tx.commitment( NO_COMMITMENT, txId ); tx.logPosition( transaction.getStartEntry().getStartPosition() ); storageEngine.apply( tx, mode ); return false; }
/** * Simply calls through to the {@link TransactionRepresentation#accept(Visitor)} method for each {@link * TransactionToApply} given. This assumes that the {@link BatchTransactionApplier} will return {@link * TransactionApplier}s which actually do the work and that the transaction has all the relevant data. * * @param applier to use * @param transactions to apply */ public static void apply( BatchTransactionApplier applier, TransactionToApply... transactions ) throws Exception { for ( TransactionToApply tx : transactions ) { try ( TransactionApplier txApplier = applier.startTx( tx, new LockGroup() ) ) { tx.transactionRepresentation().accept( txApplier ); } } applier.close(); }
private void verifyIndex( TransactionToApply tx ) throws Exception { try ( IndexReader reader = index.newReader() ) { NodeVisitor visitor = new NodeVisitor(); for ( int i = 0; tx != null; i++ ) { tx.transactionRepresentation().accept( visitor.clear() ); Value propertyValue = propertyValue( id, base + i ); IndexQuery.ExactPredicate query = IndexQuery.exact( descriptor.getPropertyId(), propertyValue ); LongIterator hits = reader.query( query ); assertEquals( "Index doesn't contain " + visitor.nodeId + " " + propertyValue, visitor.nodeId, hits.next() ); assertFalse( hits.hasNext() ); tx = tx.next(); } } } }