private RecoveryStartInformation createRecoveryInformation( LogPosition logPosition, long firstTxId ) { return new RecoveryStartInformation( logPosition, firstTxId ); } }
private long getNumberOfTransactionToRecover( RecoveryStartInformation recoveryStartInformation, CommittedTransactionRepresentation lastReversedTransaction ) { return lastReversedTransaction.getCommitEntry().getTxId() - recoveryStartInformation.getFirstTxIdAfterLastCheckPoint() + 1; } }
@Test public void shouldReturnUnspecifiedIfThereIsNoNeedForRecovery() { // given when( tailScanner.getTailInformation() ).thenReturn( new LogTailScanner.LogTailInformation( false, NO_TRANSACTION_ID, logVersion, currentLogVersion, LogEntryVersion.CURRENT ) ); // when RecoveryStartInformation recoveryStartInformation = new RecoveryStartInformationProvider( tailScanner, monitor ).get(); // then verify( monitor ).noCommitsAfterLastCheckPoint( null ); assertEquals( LogPosition.UNSPECIFIED, recoveryStartInformation.getRecoveryPosition() ); assertEquals( NO_TRANSACTION_ID, recoveryStartInformation.getFirstTxIdAfterLastCheckPoint() ); assertFalse( recoveryStartInformation.isRecoveryRequired() ); }
if ( !recoveryStartInformation.isRecoveryRequired() ) LogPosition recoveryPosition = recoveryStartInformation.getRecoveryPosition();
public boolean isRecoveryRequiredAt( DatabaseLayout databaseLayout ) throws IOException { // We need config to determine where the logical log files are if ( !NeoStores.isStorePresent( pageCache, databaseLayout ) ) { return false; } LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>(); LogFiles logFiles = LogFilesBuilder.activeFilesBuilder( databaseLayout, fs, pageCache ) .withConfig( config ) .withLogEntryReader( reader ).build(); LogTailScanner tailScanner = new LogTailScanner( logFiles, reader, monitors ); return new RecoveryStartInformationProvider( tailScanner, NO_MONITOR ).get().isRecoveryRequired(); }
@Test public void shouldRecoverFromStartOfLogZeroIfThereAreNoCheckPointAndOldestLogIsVersionZero() { // given when( tailScanner.getTailInformation() ).thenReturn( new LogTailInformation( true, 10L, INITIAL_LOG_VERSION, currentLogVersion, LogEntryVersion.CURRENT ) ); // when RecoveryStartInformation recoveryStartInformation = new RecoveryStartInformationProvider( tailScanner, monitor ).get(); // then verify( monitor ).noCheckPointFound(); assertEquals( LogPosition.start( INITIAL_LOG_VERSION ), recoveryStartInformation.getRecoveryPosition() ); assertEquals( 10L, recoveryStartInformation.getFirstTxIdAfterLastCheckPoint() ); assertTrue( recoveryStartInformation.isRecoveryRequired() ); }
if ( !recoveryStartInformation.isRecoveryRequired() ) LogPosition recoveryPosition = recoveryStartInformation.getRecoveryPosition();
public boolean isRecoveryRequiredAt( DatabaseLayout databaseLayout ) throws IOException { // We need config to determine where the logical log files are if ( !NeoStores.isStorePresent( pageCache, databaseLayout ) ) { return false; } LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>(); LogFiles logFiles = LogFilesBuilder.activeFilesBuilder( databaseLayout, fs, pageCache ) .withConfig( config ) .withLogEntryReader( reader ).build(); LogTailScanner tailScanner = new LogTailScanner( logFiles, reader, monitors ); return new RecoveryStartInformationProvider( tailScanner, NO_MONITOR ).get().isRecoveryRequired(); }
@Test public void shouldReturnLogPositionToRecoverFromIfNeeded() { // given LogPosition checkPointLogPosition = new LogPosition( 1L, 4242 ); when( tailScanner.getTailInformation() ) .thenReturn( new LogTailInformation( new CheckPoint( checkPointLogPosition ), true, 10L, logVersion, currentLogVersion, LogEntryVersion.CURRENT ) ); // when RecoveryStartInformation recoveryStartInformation = new RecoveryStartInformationProvider( tailScanner, monitor ).get(); // then verify( monitor ).commitsAfterLastCheckPoint( checkPointLogPosition, 10L ); assertEquals( checkPointLogPosition, recoveryStartInformation.getRecoveryPosition() ); assertEquals( 10L, recoveryStartInformation.getFirstTxIdAfterLastCheckPoint() ); assertTrue( recoveryStartInformation.isRecoveryRequired() ); }
@Override public RecoveryStartInformation getRecoveryStartInformation() { return new RecoveryStartInformation( LogPosition.start( 0 ), 1 ); }
private long getNumberOfTransactionToRecover( RecoveryStartInformation recoveryStartInformation, CommittedTransactionRepresentation lastReversedTransaction ) { return lastReversedTransaction.getCommitEntry().getTxId() - recoveryStartInformation.getFirstTxIdAfterLastCheckPoint() + 1; } }
@Test public void reportProgressOnRecovery() throws Throwable { RecoveryService recoveryService = mock( RecoveryService.class, Answers.RETURNS_MOCKS ); CorruptedLogsTruncator logsTruncator = mock( CorruptedLogsTruncator.class ); RecoveryMonitor recoveryMonitor = mock( RecoveryMonitor.class ); TransactionCursor reverseTransactionCursor = mock( TransactionCursor.class ); TransactionCursor transactionCursor = mock( TransactionCursor.class ); CommittedTransactionRepresentation transactionRepresentation = mock( CommittedTransactionRepresentation.class ); int transactionsToRecover = 5; int expectedMax = transactionsToRecover * 2; int lastCommittedTransactionId = 14; LogPosition recoveryStartPosition = LogPosition.start( 0 ); int firstTxIdAfterLastCheckPoint = 10; RecoveryStartInformation startInformation = new RecoveryStartInformation( recoveryStartPosition, firstTxIdAfterLastCheckPoint ); when( reverseTransactionCursor.next() ).thenAnswer( new NextTransactionAnswer( transactionsToRecover ) ); when( transactionCursor.next() ).thenAnswer( new NextTransactionAnswer( transactionsToRecover ) ); when( reverseTransactionCursor.get() ).thenReturn( transactionRepresentation ); when( transactionCursor.get() ).thenReturn( transactionRepresentation ); when( transactionRepresentation.getCommitEntry() ).thenReturn( new LogEntryCommit( lastCommittedTransactionId, 1L ) ); when( recoveryService.getRecoveryStartInformation() ).thenReturn( startInformation ); when( recoveryService.getTransactionsInReverseOrder( recoveryStartPosition ) ).thenReturn( reverseTransactionCursor ); when( recoveryService.getTransactions( recoveryStartPosition ) ).thenReturn( transactionCursor ); AssertableProgressReporter progressReporter = new AssertableProgressReporter( expectedMax ); Recovery recovery = new Recovery( recoveryService, logsTruncator, recoveryMonitor, progressReporter, true ); recovery.init(); progressReporter.verify(); }
private RecoveryStartInformation createRecoveryInformation( LogPosition logPosition, long firstTxId ) { return new RecoveryStartInformation( logPosition, firstTxId ); } }