use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class RecoveryIT method shouldForceRecoveryEvenThoughNotSeeminglyRequired.
@Test
void shouldForceRecoveryEvenThoughNotSeeminglyRequired() throws Exception {
// given
GraphDatabaseAPI db = createDatabase();
generateSomeData(db);
DatabaseLayout layout = db.databaseLayout();
managementService.shutdown();
assertFalse(isRecoveryRequired(layout));
// Make an ID generator, say for the node store, dirty
DefaultIdGeneratorFactory idGeneratorFactory = new DefaultIdGeneratorFactory(fileSystem, immediate(), "my db");
try (IdGenerator idGenerator = idGeneratorFactory.open(pageCache, layout.idNodeStore(), IdType.NODE, () -> 0L, /*will not be used*/
10_000, writable(), Config.defaults(), NULL, Sets.immutable.empty())) {
// Merely opening a marker will make the backing GBPTree dirty
idGenerator.marker(NULL).close();
}
assertFalse(isRecoveryRequired(layout));
assertTrue(idGeneratorIsDirty(layout.idNodeStore(), IdType.NODE));
// when
MutableBoolean recoveryRunEvenThoughNoCommitsAfterLastCheckpoint = new MutableBoolean();
RecoveryStartInformationProvider.Monitor monitor = new RecoveryStartInformationProvider.Monitor() {
@Override
public void noCommitsAfterLastCheckPoint(LogPosition logPosition) {
recoveryRunEvenThoughNoCommitsAfterLastCheckpoint.setTrue();
}
};
Monitors monitors = new Monitors();
monitors.addMonitorListener(monitor);
Recovery.performRecovery(fileSystem, pageCache, EMPTY, Config.defaults(), layout, defaultStorageEngine(), true, nullLogProvider(), monitors, Iterables.cast(Services.loadAll(ExtensionFactory.class)), Optional.empty(), null, INSTANCE, Clock.systemUTC());
// then
assertFalse(idGeneratorIsDirty(layout.idNodeStore(), IdType.NODE));
assertTrue(recoveryRunEvenThoughNoCommitsAfterLastCheckpoint.booleanValue());
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class DatabaseFileListingTest method shouldListNeostoreFiles.
@Test
void shouldListNeostoreFiles() throws Exception {
DatabaseLayout layout = database.getDatabaseLayout();
Set<Path> expectedFiles = layout.storeFiles();
// there was no rotation
ResourceIterator<StoreFileMetadata> storeFiles = database.listStoreFiles(false);
Set<Path> listedStoreFiles = storeFiles.stream().map(StoreFileMetadata::path).collect(Collectors.toSet());
assertEquals(expectedFiles, listedStoreFiles);
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class LabelScanStoreTxApplyRaceIT method shouldStressIt.
/**
* The test case is basically loads of concurrent CREATE/DELETE NODE or sometimes just CREATE, keeping the created node in an array
* for dedicated deleter threads to pick up and delete as fast as they can see them. This concurrently with large creation transactions.
*/
@Test
void shouldStressIt() throws Throwable {
// given
Race race = new Race().withMaxDuration(5, TimeUnit.SECONDS);
AtomicReferenceArray<Node> nodeHeads = new AtomicReferenceArray<>(NUMBER_OF_CREATORS);
for (int i = 0; i < NUMBER_OF_CREATORS; i++) {
race.addContestant(creator(nodeHeads, i));
}
race.addContestants(NUMBER_OF_DELETORS, deleter(nodeHeads));
// when
race.go();
// then
DatabaseLayout dbLayout = db.databaseLayout();
managementService.shutdown();
assertTrue(new ConsistencyCheckService().runFullConsistencyCheck(dbLayout, defaults(GraphDatabaseSettings.neo4j_home, testDirectory.homePath()), NONE, new Log4jLogProvider(System.out), false, new ConsistencyFlags(true, true, true)).isSuccessful());
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class IndexRecoveryIT method snapshotFs.
private void snapshotFs(Path snapshotDir) {
try {
DatabaseLayout layout = databaseLayout;
FileUtils.copyDirectory(layout.databaseDirectory(), snapshotDir.resolve("data"));
FileUtils.copyDirectory(layout.getTransactionLogsDirectory(), snapshotDir.resolve("transactions"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
use of org.neo4j.io.layout.DatabaseLayout 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();
}
}
Aggregations