use of org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction in project neo4j by neo4j.
the class SingleFilePageSwapperTest method mustHandleMischiefInPositionedRead.
@Test
public void mustHandleMischiefInPositionedRead() throws Exception {
int bytesTotal = 512;
byte[] data = new byte[bytesTotal];
ThreadLocalRandom.current().nextBytes(data);
PageSwapperFactory factory = createSwapperFactory();
factory.setFileSystemAbstraction(getFs());
File file = getFile();
PageSwapper swapper = createSwapper(factory, file, bytesTotal, NO_CALLBACK, true);
try {
swapper.write(0, new ByteBufferPage(wrap(data)));
} finally {
swapper.close();
}
RandomAdversary adversary = new RandomAdversary(0.5, 0.0, 0.0);
factory.setFileSystemAbstraction(new AdversarialFileSystemAbstraction(adversary, getFs()));
swapper = createSwapper(factory, file, bytesTotal, NO_CALLBACK, false);
ByteBufferPage page = createPage(bytesTotal);
try {
for (int i = 0; i < 10_000; i++) {
clear(page);
assertThat(swapper.read(0, page), is((long) bytesTotal));
assertThat(array(page.buffer), is(data));
}
} finally {
swapper.close();
}
}
use of org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction in project neo4j by neo4j.
the class SingleFilePageSwapperTest method mustHandleMischiefInPositionedWrite.
@Test
public void mustHandleMischiefInPositionedWrite() throws Exception {
int bytesTotal = 512;
byte[] data = new byte[bytesTotal];
ThreadLocalRandom.current().nextBytes(data);
ByteBufferPage zeroPage = createPage(bytesTotal);
clear(zeroPage);
File file = getFile();
PageSwapperFactory factory = createSwapperFactory();
RandomAdversary adversary = new RandomAdversary(0.5, 0.0, 0.0);
factory.setFileSystemAbstraction(new AdversarialFileSystemAbstraction(adversary, getFs()));
PageSwapper swapper = createSwapper(factory, file, bytesTotal, NO_CALLBACK, true);
ByteBufferPage page = createPage(bytesTotal);
try {
for (int i = 0; i < 10_000; i++) {
adversary.setProbabilityFactor(0);
swapper.write(0, zeroPage);
page.putBytes(data, 0, 0, data.length);
adversary.setProbabilityFactor(1);
assertThat(swapper.write(0, page), is((long) bytesTotal));
clear(page);
adversary.setProbabilityFactor(0);
swapper.read(0, page);
assertThat(array(page.buffer), is(data));
}
} finally {
swapper.close();
}
}
use of org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction in project neo4j by neo4j.
the class SingleFilePageSwapperTest method mustHandleMischiefInPositionedVectoredRead.
@Test
public void mustHandleMischiefInPositionedVectoredRead() throws Exception {
int bytesTotal = 512;
int bytesPerPage = 32;
int pageCount = bytesTotal / bytesPerPage;
byte[] data = new byte[bytesTotal];
ThreadLocalRandom.current().nextBytes(data);
PageSwapperFactory factory = createSwapperFactory();
factory.setFileSystemAbstraction(getFs());
File file = getFile();
PageSwapper swapper = createSwapper(factory, file, bytesTotal, NO_CALLBACK, true);
try {
swapper.write(0, new ByteBufferPage(wrap(data)));
} finally {
swapper.close();
}
RandomAdversary adversary = new RandomAdversary(0.5, 0.0, 0.0);
factory.setFileSystemAbstraction(new AdversarialFileSystemAbstraction(adversary, getFs()));
swapper = createSwapper(factory, file, bytesPerPage, NO_CALLBACK, false);
ByteBufferPage[] pages = new ByteBufferPage[pageCount];
for (int i = 0; i < pageCount; i++) {
pages[i] = createPage(bytesPerPage);
}
byte[] temp = new byte[bytesPerPage];
try {
for (int i = 0; i < 10_000; i++) {
for (ByteBufferPage page : pages) {
clear(page);
}
assertThat(swapper.read(0, pages, 0, pages.length), is((long) bytesTotal));
for (int j = 0; j < pageCount; j++) {
System.arraycopy(data, j * bytesPerPage, temp, 0, bytesPerPage);
assertThat(array(pages[j].buffer), is(temp));
}
}
} finally {
swapper.close();
}
}
use of org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction in project neo4j by neo4j.
the class BatchingTransactionAppenderConcurrencyTest method shouldHaveAllConcurrentAppendersSeePanic.
/*
* There was an issue where if multiple concurrent appending threads did append and they moved on
* to await a force, where the force would fail and the one doing the force would raise a panic...
* the other threads may not notice the panic and move on to mark those transactions as committed
* and notice the panic later (which would be too late).
*/
@Test
public void shouldHaveAllConcurrentAppendersSeePanic() throws Throwable {
// GIVEN
Adversary adversary = new ClassGuardedAdversary(new CountingAdversary(1, true), failMethod(BatchingTransactionAppender.class, "force"));
EphemeralFileSystemAbstraction efs = new EphemeralFileSystemAbstraction();
File directory = new File("dir").getCanonicalFile();
efs.mkdirs(directory);
FileSystemAbstraction fs = new AdversarialFileSystemAbstraction(adversary, efs);
life.add(new FileSystemLifecycleAdapter(fs));
DatabaseHealth databaseHealth = new DatabaseHealth(mock(DatabasePanicEventGenerator.class), NullLog.getInstance());
PhysicalLogFiles logFiles = new PhysicalLogFiles(directory, fs);
LogFile logFile = life.add(new PhysicalLogFile(fs, logFiles, kibiBytes(10), transactionIdStore::getLastCommittedTransactionId, new DeadSimpleLogVersionRepository(0), new PhysicalLogFile.Monitor.Adapter(), logHeaderCache));
final BatchingTransactionAppender appender = life.add(new BatchingTransactionAppender(logFile, logRotation, transactionMetadataCache, transactionIdStore, legacyIndexTransactionOrdering, databaseHealth));
life.start();
// WHEN
int numberOfAppenders = 10;
final CountDownLatch trap = new CountDownLatch(numberOfAppenders);
final LogAppendEvent beforeForceTrappingEvent = new LogAppendEvent.Empty() {
@Override
public LogForceWaitEvent beginLogForceWait() {
trap.countDown();
awaitLatch(trap);
return super.beginLogForceWait();
}
};
Race race = new Race();
for (int i = 0; i < numberOfAppenders; i++) {
race.addContestant(() -> {
try {
// Append to the log, the LogAppenderEvent will have all of the appending threads
// do wait for all of the other threads to start the force thing
appender.append(tx(), beforeForceTrappingEvent);
fail("No transaction should be considered appended");
} catch (IOException e) {
// Good, we know that this test uses an adversarial file system which will throw
// an exception in BatchingTransactionAppender#force, and since all these transactions
// will append and be forced in the same batch, where the force will fail then
// all these transactions should fail. If there's any transaction not failing then
// it just didn't notice the panic, which would be potentially hazardous.
}
});
}
// THEN perform the race. The relevant assertions are made inside the contestants.
race.go();
}
use of org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction in project neo4j by neo4j.
the class PartialTransactionFailureIT method concurrentlyCommittingTransactionsMustNotRotateOutLoggedCommandsOfFailingTransaction.
@Test
public void concurrentlyCommittingTransactionsMustNotRotateOutLoggedCommandsOfFailingTransaction() throws Exception {
final ClassGuardedAdversary adversary = new ClassGuardedAdversary(new CountingAdversary(1, false), Command.RelationshipCommand.class);
adversary.disable();
File storeDir = dir.graphDbDir();
final Map<String, String> params = stringMap(GraphDatabaseSettings.pagecache_memory.name(), "8m");
final EmbeddedGraphDatabase db = new TestEmbeddedGraphDatabase(storeDir, params) {
@Override
protected void create(File storeDir, Map<String, String> params, GraphDatabaseFacadeFactory.Dependencies dependencies) {
new GraphDatabaseFacadeFactory(DatabaseInfo.COMMUNITY, CommunityEditionModule::new) {
@Override
protected PlatformModule createPlatform(File storeDir, Config config, Dependencies dependencies, GraphDatabaseFacade graphDatabaseFacade) {
return new PlatformModule(storeDir, config, databaseInfo, dependencies, graphDatabaseFacade) {
@Override
protected FileSystemAbstraction createFileSystemAbstraction() {
return new AdversarialFileSystemAbstraction(adversary);
}
};
}
}.initFacade(storeDir, params, dependencies, this);
}
};
Node a, b, c, d;
try (Transaction tx = db.beginTx()) {
a = db.createNode();
b = db.createNode();
c = db.createNode();
d = db.createNode();
tx.success();
}
adversary.enable();
CountDownLatch latch = new CountDownLatch(1);
Thread t1 = new Thread(createRelationship(db, a, b, latch), "T1");
Thread t2 = new Thread(createRelationship(db, c, d, latch), "T2");
t1.start();
t2.start();
// Wait for both threads to get going
t1.join(10);
t2.join(10);
latch.countDown();
// Wait for the transactions to finish
t1.join(25000);
t2.join(25000);
db.shutdown();
// We should observe the store in a consistent state
EmbeddedGraphDatabase db2 = new TestEmbeddedGraphDatabase(storeDir, params);
try (Transaction tx = db2.beginTx()) {
Node x = db2.getNodeById(a.getId());
Node y = db2.getNodeById(b.getId());
Node z = db2.getNodeById(c.getId());
Node w = db2.getNodeById(d.getId());
Iterator<Relationship> itrRelX = x.getRelationships().iterator();
Iterator<Relationship> itrRelY = y.getRelationships().iterator();
Iterator<Relationship> itrRelZ = z.getRelationships().iterator();
Iterator<Relationship> itrRelW = w.getRelationships().iterator();
if (itrRelX.hasNext() != itrRelY.hasNext()) {
fail("Node x and y have inconsistent relationship counts");
} else if (itrRelX.hasNext()) {
Relationship rel = itrRelX.next();
assertEquals(rel, itrRelY.next());
assertFalse(itrRelX.hasNext());
assertFalse(itrRelY.hasNext());
}
if (itrRelZ.hasNext() != itrRelW.hasNext()) {
fail("Node z and w have inconsistent relationship counts");
} else if (itrRelZ.hasNext()) {
Relationship rel = itrRelZ.next();
assertEquals(rel, itrRelW.next());
assertFalse(itrRelZ.hasNext());
assertFalse(itrRelW.hasNext());
}
} finally {
db2.shutdown();
}
}
Aggregations