@Test public void shouldFailIfThereAreNoCheckPointsAndOldestLogVersionInNotZero() { // given long oldestLogVersionFound = 1L; when( tailScanner.getTailInformation() ).thenReturn( new LogTailScanner.LogTailInformation( true, 10L, oldestLogVersionFound, currentLogVersion, LogEntryVersion.CURRENT ) ); // when try { new RecoveryStartInformationProvider( tailScanner, monitor ).get(); } catch ( UnderlyingStorageException ex ) { // then final String expectedMessage = "No check point found in any log file from version " + oldestLogVersionFound + " to " + logVersion; assertEquals( expectedMessage, ex.getMessage() ); } } }
CheckPoint lastCheckPoint = logTailInformation.lastCheckPoint; long txIdAfterLastCheckPoint = logTailInformation.firstTxIdAfterLastCheckPoint; if ( !logTailInformation.commitsAfterLastCheckpoint() )
return new LogTailInformation( corruptedTransactionLogs || startRecordAfterCheckpoint, oldestStartEntryTransaction, oldestVersionFound, highestLogVersion, latestLogEntryVersion );
CheckPoint lastCheckPoint = logTailInformation.lastCheckPoint; long txIdAfterLastCheckPoint = logTailInformation.firstTxIdAfterLastCheckPoint; if ( !logTailInformation.commitsAfterLastCheckpoint() )
private Result checkCleanShutDownByCheckPoint() { // check version try { if ( !tailScanner.getTailInformation().commitsAfterLastCheckpoint() ) { return new Result( Result.Outcome.ok, null, null ); } } catch ( Throwable throwable ) { // ignore exception and return db not cleanly shutdown } return new Result( Result.Outcome.storeNotCleanlyShutDown, null, null ); }
protected LogTailInformation checkpointTailInformation( long highestLogVersion, LogEntryStart latestStartEntry, long oldestVersionFound, LogEntryVersion latestLogEntryVersion, CheckPoint latestCheckPoint, boolean corruptedTransactionLogs ) throws IOException { LogPosition checkPointLogPosition = latestCheckPoint.getLogPosition(); ExtractedTransactionRecord transactionRecord = extractFirstTxIdAfterPosition( checkPointLogPosition, highestLogVersion ); long firstTxIdAfterPosition = transactionRecord.getId(); boolean startRecordAfterCheckpoint = (firstTxIdAfterPosition != NO_TRANSACTION_ID) || ((latestStartEntry != null) && (latestStartEntry.getStartPosition().compareTo( latestCheckPoint.getLogPosition() ) >= 0)); boolean corruptedLogs = transactionRecord.isFailure() || corruptedTransactionLogs; return new LogTailInformation( latestCheckPoint, corruptedLogs || startRecordAfterCheckpoint, firstTxIdAfterPosition, oldestVersionFound, highestLogVersion, latestLogEntryVersion ); }
return new LogTailInformation( corruptedTransactionLogs || startRecordAfterCheckpoint, oldestStartEntryTransaction, oldestVersionFound, highestLogVersion, latestLogEntryVersion );
public static void removeCheckPointFromTxLog( FileSystemAbstraction fileSystem, File databaseDirectory ) throws IOException { LogFiles logFiles = LogFilesBuilder.logFilesBasedOnlyBuilder( databaseDirectory, fileSystem ).build(); LogEntryReader<ReadableClosablePositionAwareChannel> logEntryReader = new VersionAwareLogEntryReader<>(); LogTailScanner tailScanner = new LogTailScanner( logFiles, logEntryReader, new Monitors() ); LogTailScanner.LogTailInformation logTailInformation = tailScanner.getTailInformation(); if ( logTailInformation.commitsAfterLastCheckpoint() ) { // done already return; } // let's assume there is at least a checkpoint assertNotNull( logTailInformation.lastCheckPoint ); LogPosition logPosition = logTailInformation.lastCheckPoint.getLogPosition(); File logFile = logFiles.getLogFileForVersion( logPosition.getLogVersion() ); fileSystem.truncate( logFile, logPosition.getByteOffset() ); } }
@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() ); }
private Result checkCleanShutDownByCheckPoint() { // check version try { if ( !tailScanner.getTailInformation().commitsAfterLastCheckpoint() ) { return new Result( Result.Outcome.ok, null, null ); } } catch ( Throwable throwable ) { // ignore exception and return db not cleanly shutdown } return new Result( Result.Outcome.storeNotCleanlyShutDown, null, null ); }
@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() ); }
@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() ); }
protected LogTailInformation checkpointTailInformation( long highestLogVersion, LogEntryStart latestStartEntry, long oldestVersionFound, LogEntryVersion latestLogEntryVersion, CheckPoint latestCheckPoint, boolean corruptedTransactionLogs ) throws IOException { LogPosition checkPointLogPosition = latestCheckPoint.getLogPosition(); ExtractedTransactionRecord transactionRecord = extractFirstTxIdAfterPosition( checkPointLogPosition, highestLogVersion ); long firstTxIdAfterPosition = transactionRecord.getId(); boolean startRecordAfterCheckpoint = (firstTxIdAfterPosition != NO_TRANSACTION_ID) || ((latestStartEntry != null) && (latestStartEntry.getStartPosition().compareTo( latestCheckPoint.getLogPosition() ) >= 0)); boolean corruptedLogs = transactionRecord.isFailure() || corruptedTransactionLogs; return new LogTailInformation( latestCheckPoint, corruptedLogs || startRecordAfterCheckpoint, firstTxIdAfterPosition, oldestVersionFound, highestLogVersion, latestLogEntryVersion ); }
private void assertLatestCheckPoint( boolean hasCheckPointEntry, boolean commitsAfterLastCheckPoint, long firstTxIdAfterLastCheckPoint, long logVersion, LogTailInformation logTailInformation ) { assertEquals( hasCheckPointEntry, logTailInformation.lastCheckPoint != null ); assertEquals( commitsAfterLastCheckPoint, logTailInformation.commitsAfterLastCheckpoint() ); if ( commitsAfterLastCheckPoint ) { assertEquals( firstTxIdAfterLastCheckPoint, logTailInformation.firstTxIdAfterLastCheckPoint ); } assertEquals( logVersion, logTailInformation.oldestLogVersionFound ); }