use of org.neo4j.kernel.recovery.Recovery in project neo4j by neo4j.
the class RecoveryTest method recover.
private boolean recover(PhysicalLogFiles logFiles) {
LifeSupport life = new LifeSupport();
Recovery.Monitor monitor = mock(Recovery.Monitor.class);
final AtomicBoolean recoveryRequired = new AtomicBoolean();
try {
StorageEngine storageEngine = mock(StorageEngine.class);
final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
LatestCheckPointFinder finder = new LatestCheckPointFinder(logFiles, fileSystemRule.get(), reader);
TransactionMetadataCache metadataCache = new TransactionMetadataCache(100);
LogHeaderCache logHeaderCache = new LogHeaderCache(10);
LogFile logFile = life.add(new PhysicalLogFile(fileSystemRule.get(), logFiles, 50, () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository, mock(PhysicalLogFile.Monitor.class), logHeaderCache));
LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFile, metadataCache, reader);
life.add(new Recovery(new DefaultRecoverySPI(storageEngine, logFiles, fileSystemRule.get(), logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR) {
@Override
public Visitor<CommittedTransactionRepresentation, Exception> startRecovery() {
recoveryRequired.set(true);
return super.startRecovery();
}
}, monitor));
life.start();
} finally {
life.shutdown();
}
return recoveryRequired.get();
}
use of org.neo4j.kernel.recovery.Recovery in project neo4j by neo4j.
the class RecoveryTest method shouldSeeThatACleanDatabaseShouldNotRequireRecovery.
@Test
public void shouldSeeThatACleanDatabaseShouldNotRequireRecovery() throws Exception {
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
writeSomeData(file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>, IOException>() {
@Override
public boolean visit(Pair<LogEntryWriter, Consumer<LogPositionMarker>> pair) throws IOException {
LogEntryWriter writer = pair.first();
Consumer<LogPositionMarker> consumer = pair.other();
LogPositionMarker marker = new LogPositionMarker();
// last committed tx
consumer.accept(marker);
writer.writeStartEntry(0, 1, 2L, 3L, new byte[0]);
writer.writeCommitEntry(4L, 5L);
// check point
consumer.accept(marker);
writer.writeCheckPointEntry(marker.newPosition());
return true;
}
});
LifeSupport life = new LifeSupport();
Recovery.Monitor monitor = mock(Recovery.Monitor.class);
try {
StorageEngine storageEngine = mock(StorageEngine.class);
final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
LatestCheckPointFinder finder = new LatestCheckPointFinder(logFiles, fileSystemRule.get(), reader);
TransactionMetadataCache metadataCache = new TransactionMetadataCache(100);
LogHeaderCache logHeaderCache = new LogHeaderCache(10);
LogFile logFile = life.add(new PhysicalLogFile(fileSystemRule.get(), logFiles, 50, () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository, mock(PhysicalLogFile.Monitor.class), logHeaderCache));
LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFile, metadataCache, reader);
life.add(new Recovery(new DefaultRecoverySPI(storageEngine, logFiles, fileSystemRule.get(), logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR) {
@Override
public Visitor<CommittedTransactionRepresentation, Exception> startRecovery() {
fail("Recovery should not be required");
// <-- to satisfy the compiler
return null;
}
}, monitor));
life.start();
verifyZeroInteractions(monitor);
} finally {
life.shutdown();
}
}
use of org.neo4j.kernel.recovery.Recovery in project neo4j by neo4j.
the class IndexRecoveryIT method shouldBeAbleToRecoverInTheMiddleOfPopulatingAnIndexWhereLogHasRotated.
@Test
void shouldBeAbleToRecoverInTheMiddleOfPopulatingAnIndexWhereLogHasRotated() throws Exception {
// Given
startDb();
Semaphore populationSemaphore = new Semaphore(0);
Future<Void> killFuture;
try {
when(mockedIndexProvider.getPopulator(any(IndexDescriptor.class), any(IndexSamplingConfig.class), any(), any(), any(TokenNameLookup.class))).thenReturn(indexPopulatorWithControlledCompletionTiming(populationSemaphore));
createSomeData();
createIndex(myLabel);
// And Given
killFuture = killDbInSeparateThread();
int iterations = 0;
do {
rotateLogsAndCheckPoint();
Thread.sleep(10);
} while (iterations++ < 100 && !killFuture.isDone());
} finally {
populationSemaphore.release();
}
killFuture.get();
when(mockedIndexProvider.getInitialState(any(IndexDescriptor.class), any(CursorContext.class))).thenReturn(InternalIndexState.POPULATING);
Semaphore recoverySemaphore = new Semaphore(0);
try {
when(mockedIndexProvider.getPopulator(any(IndexDescriptor.class), any(IndexSamplingConfig.class), any(), any(), any(TokenNameLookup.class))).thenReturn(indexPopulatorWithControlledCompletionTiming(recoverySemaphore));
boolean recoveryRequired = Recovery.isRecoveryRequired(testDirectory.getFileSystem(), databaseLayout, defaults(), INSTANCE);
monitors.addMonitorListener(new MyRecoveryMonitor(recoverySemaphore));
// When
startDb();
try (Transaction transaction = db.beginTx()) {
assertThat(transaction.schema().getIndexes(myLabel)).hasSize(1);
assertThat(transaction.schema().getIndexes(myLabel)).extracting(i -> transaction.schema().getIndexState(i)).containsOnly(Schema.IndexState.POPULATING);
}
// in case if kill was not that fast and killed db after flush there will be no need to do recovery and
// we will not gonna need to get index populators during recovery index service start
verify(mockedIndexProvider, times(recoveryRequired ? 3 : 2)).getPopulator(any(IndexDescriptor.class), any(IndexSamplingConfig.class), any(), any(), any(TokenNameLookup.class));
verify(mockedIndexProvider, never()).getOnlineAccessor(any(IndexDescriptor.class), any(IndexSamplingConfig.class), any(TokenNameLookup.class));
} finally {
recoverySemaphore.release();
}
}
use of org.neo4j.kernel.recovery.Recovery in project neo4j by neo4j.
the class RecoveryTest method shouldRecoverExistingData.
@Test
public void shouldRecoverExistingData() throws Exception {
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
writeSomeData(file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>, IOException>() {
@Override
public boolean visit(Pair<LogEntryWriter, Consumer<LogPositionMarker>> pair) throws IOException {
LogEntryWriter writer = pair.first();
Consumer<LogPositionMarker> consumer = pair.other();
LogPositionMarker marker = new LogPositionMarker();
// last committed tx
consumer.accept(marker);
LogPosition lastCommittedTxPosition = marker.newPosition();
writer.writeStartEntry(0, 1, 2L, 3L, new byte[0]);
lastCommittedTxStartEntry = new LogEntryStart(0, 1, 2L, 3L, new byte[0], lastCommittedTxPosition);
writer.writeCommitEntry(4L, 5L);
lastCommittedTxCommitEntry = new OnePhaseCommit(4L, 5L);
// check point pointing to the previously committed transaction
writer.writeCheckPointEntry(lastCommittedTxPosition);
expectedCheckPointEntry = new CheckPoint(lastCommittedTxPosition);
// tx committed after checkpoint
consumer.accept(marker);
writer.writeStartEntry(0, 1, 6L, 4L, new byte[0]);
expectedStartEntry = new LogEntryStart(0, 1, 6L, 4L, new byte[0], marker.newPosition());
writer.writeCommitEntry(5L, 7L);
expectedCommitEntry = new OnePhaseCommit(5L, 7L);
return true;
}
});
LifeSupport life = new LifeSupport();
Recovery.Monitor monitor = mock(Recovery.Monitor.class);
final AtomicBoolean recoveryRequired = new AtomicBoolean();
try {
StorageEngine storageEngine = mock(StorageEngine.class);
final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
LatestCheckPointFinder finder = new LatestCheckPointFinder(logFiles, fileSystemRule.get(), reader);
LogHeaderCache logHeaderCache = new LogHeaderCache(10);
TransactionMetadataCache metadataCache = new TransactionMetadataCache(100);
LogFile logFile = life.add(new PhysicalLogFile(fileSystemRule.get(), logFiles, 50, () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository, mock(PhysicalLogFile.Monitor.class), logHeaderCache));
LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFile, metadataCache, reader);
life.add(new Recovery(new DefaultRecoverySPI(storageEngine, logFiles, fileSystemRule.get(), logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR) {
private int nr = 0;
@Override
public Visitor<CommittedTransactionRepresentation, Exception> startRecovery() {
recoveryRequired.set(true);
final Visitor<CommittedTransactionRepresentation, Exception> actual = super.startRecovery();
return new Visitor<CommittedTransactionRepresentation, Exception>() {
@Override
public boolean visit(CommittedTransactionRepresentation tx) throws Exception {
actual.visit(tx);
switch(nr++) {
case 0:
assertEquals(lastCommittedTxStartEntry, tx.getStartEntry());
assertEquals(lastCommittedTxCommitEntry, tx.getCommitEntry());
break;
case 1:
assertEquals(expectedStartEntry, tx.getStartEntry());
assertEquals(expectedCommitEntry, tx.getCommitEntry());
break;
default:
fail("Too many recovered transactions");
}
return false;
}
};
}
}, monitor));
life.start();
InOrder order = inOrder(monitor);
order.verify(monitor, times(1)).recoveryRequired(any(LogPosition.class));
order.verify(monitor, times(1)).recoveryCompleted(2);
assertTrue(recoveryRequired.get());
} finally {
life.shutdown();
}
}
use of org.neo4j.kernel.recovery.Recovery in project neo4j by neo4j.
the class NeoStoreDataSource method buildRecovery.
private void buildRecovery(final FileSystemAbstraction fileSystemAbstraction, TransactionIdStore transactionIdStore, LogVersionRepository logVersionRepository, Recovery.Monitor recoveryMonitor, PositionToRecoverFrom.Monitor positionMonitor, final PhysicalLogFiles logFiles, final StartupStatisticsProvider startupStatistics, StorageEngine storageEngine, LogEntryReader<ReadableClosablePositionAwareChannel> logEntryReader, LogicalTransactionStore logicalTransactionStore) {
final LatestCheckPointFinder checkPointFinder = new LatestCheckPointFinder(logFiles, fileSystemAbstraction, logEntryReader);
Recovery.SPI spi = new DefaultRecoverySPI(storageEngine, logFiles, fileSystemAbstraction, logVersionRepository, checkPointFinder, transactionIdStore, logicalTransactionStore, positionMonitor);
Recovery recovery = new Recovery(spi, recoveryMonitor);
monitors.addMonitorListener(new Recovery.Monitor() {
@Override
public void recoveryCompleted(int numberOfRecoveredTransactions) {
startupStatistics.setNumberOfRecoveredTransactions(numberOfRecoveredTransactions);
}
});
life.add(recovery);
}
Aggregations