use of org.neo4j.kernel.ha.HighlyAvailableGraphDatabase in project neo4j by neo4j.
the class TestPullUpdatesApplied method testUpdatesAreWrittenToLogBeforeBeingAppliedToStore.
@Test
public void testUpdatesAreWrittenToLogBeforeBeingAppliedToStore() throws Exception {
int master = getCurrentMaster();
addNode(master);
int toKill = (master + 1) % dbs.length;
HighlyAvailableGraphDatabase dbToKill = dbs[toKill];
final CountDownLatch latch1 = new CountDownLatch(1);
final HighlyAvailableGraphDatabase masterDb = dbs[master];
masterDb.getDependencyResolver().resolveDependency(ClusterClient.class).addClusterListener(new ClusterListener.Adapter() {
@Override
public void leftCluster(InstanceId instanceId, URI member) {
latch1.countDown();
masterDb.getDependencyResolver().resolveDependency(ClusterClient.class).removeClusterListener(this);
}
});
dbToKill.shutdown();
assertTrue("Timeout waiting for instance to leave cluster", latch1.await(60, TimeUnit.SECONDS));
// this will be pulled by tne next start up, applied
addNode(master);
// but not written to log.
File targetDirectory = testDirectory.directory("" + toKill);
// Setup to detect shutdown of separate JVM, required since we don't exit cleanly. That is also why we go
// through the heartbeat and not through the cluster change as above.
final CountDownLatch latch2 = new CountDownLatch(1);
masterDb.getDependencyResolver().resolveDependency(ClusterClient.class).addHeartbeatListener(new HeartbeatListener.Adapter() {
@Override
public void failed(InstanceId server) {
latch2.countDown();
masterDb.getDependencyResolver().resolveDependency(ClusterClient.class).removeHeartbeatListener(this);
}
});
runInOtherJvmToGetExitCode(targetDirectory.getAbsolutePath(), "" + toKill);
assertTrue("Timeout waiting for instance to fail", latch2.await(60, TimeUnit.SECONDS));
// This is to allow other instances to mark the dead instance as failed, otherwise on startup it will be denied.
// TODO This is to demonstrate shortcomings in our design. Fix this, you ugly, ugly hacker
Thread.sleep(15000);
// recovery and branching.
restart(toKill);
boolean hasBranchedData = new File(targetDirectory, "branched").listFiles().length > 0;
assertFalse(hasBranchedData);
}
use of org.neo4j.kernel.ha.HighlyAvailableGraphDatabase in project neo4j by neo4j.
the class TestPullUpdatesApplied method addNode.
private long addNode(int dbId) {
HighlyAvailableGraphDatabase db = dbs[dbId];
long result = -1;
try (Transaction tx = db.beginTx()) {
result = db.createNode().getId();
tx.success();
}
return result;
}
use of org.neo4j.kernel.ha.HighlyAvailableGraphDatabase in project neo4j by neo4j.
the class TransactionConstraintsIT method createdSchemaConstraintsMustBeRetainedAcrossModeSwitches.
@Test
public void createdSchemaConstraintsMustBeRetainedAcrossModeSwitches() throws Throwable {
// GIVEN
// -- a node with a label and a property, and a constraint on those
HighlyAvailableGraphDatabase master = cluster.getMaster();
createConstraint(master, LABEL, PROPERTY_KEY);
createNode(master, PROPERTY_VALUE, LABEL).getId();
// WHEN
cluster.sync();
ClusterManager.RepairKit originalMasterRepairKit = cluster.fail(master);
cluster.await(masterAvailable(master));
takeTheLeadInAnEventualMasterSwitch(cluster.getMaster());
cluster.sync();
originalMasterRepairKit.repair();
cluster.await(allSeesAllAsAvailable());
cluster.sync();
// THEN the constraints should still be in place and enforced
int i = 0;
for (HighlyAvailableGraphDatabase instance : cluster.getAllMembers()) {
try {
createNode(instance, PROPERTY_VALUE, LABEL);
fail("Node with " + PROPERTY_VALUE + " should already exist");
} catch (ConstraintViolationException e) {
// Good, this node should already exist
}
for (int p = 0; p < i - 1; p++) {
try {
createNode(instance, PROPERTY_VALUE + String.valueOf(p), LABEL);
fail("Node with " + PROPERTY_VALUE + String.valueOf(p) + " should already exist");
} catch (ConstraintViolationException e) {
// Good
}
}
createNode(instance, PROPERTY_VALUE + String.valueOf(i), LABEL);
i++;
}
}
use of org.neo4j.kernel.ha.HighlyAvailableGraphDatabase in project neo4j by neo4j.
the class TransactionConstraintsIT method slaveShouldNotBeAbleToModifyNodeDeletedOnMaster.
@Test
public void slaveShouldNotBeAbleToModifyNodeDeletedOnMaster() throws Exception {
// GIVEN
// -- node created on slave
HighlyAvailableGraphDatabase aSlave = cluster.getAnySlave();
Node node = createNode(aSlave, PROPERTY_VALUE);
// -- that node delete on master, but the slave doesn't see it yet
deleteNode(cluster.getMaster(), node.getId());
// WHEN
try (Transaction slaveTransaction = aSlave.beginTx()) {
node.setProperty("name", "test");
fail("Shouldn't be able to modify a node deleted on master");
} catch (NotFoundException e) {
// THEN
// -- the transactions gotten back in the response should delete that node
}
}
use of org.neo4j.kernel.ha.HighlyAvailableGraphDatabase in project neo4j by neo4j.
the class TransactionConstraintsIT method startTxAsSlaveAndFinishItAfterAnotherMasterBeingAvailableShouldNotSucceed.
@Test
public void startTxAsSlaveAndFinishItAfterAnotherMasterBeingAvailableShouldNotSucceed() throws Exception {
// GIVEN
HighlyAvailableGraphDatabase db = getSlaveOnlySlave();
HighlyAvailableGraphDatabase oldMaster;
// WHEN
Transaction tx = db.beginTx();
try {
db.createNode().setProperty("name", "slave");
tx.success();
} finally {
oldMaster = cluster.getMaster();
cluster.shutdown(oldMaster);
// Wait for new master
cluster.await(masterAvailable(oldMaster));
// THEN
assertFinishGetsTransactionFailure(tx);
}
assertFalse(db.isMaster());
assertFalse(oldMaster.isMaster());
// to prevent a deadlock scenario which occurs if this test exists (and @After starts)
// before the db has recovered from its KERNEL_PANIC
awaitFullyOperational(db);
}
Aggregations