use of org.corfudb.runtime.CorfuRuntime in project CorfuDB by CorfuDB.
the class ManagementViewTest method removeSingleNodeFailure.
/**
* Scenario with 3 nodes: SERVERS.PORT_0, SERVERS.PORT_1 and SERVERS.PORT_2.
* We fail SERVERS.PORT_1 and then wait for one of the other two servers to
* handle this failure, propose a new layout and we assert on the epoch change.
* The failure is handled by removing the failed node.
*
* @throws Exception
*/
@Test
public void removeSingleNodeFailure() throws Exception {
// Creating server contexts with PurgeFailurePolicies.
ServerContext sc0 = new ServerContextBuilder().setSingle(false).setServerRouter(new TestServerRouter(SERVERS.PORT_0)).setPort(SERVERS.PORT_0).build();
ServerContext sc1 = new ServerContextBuilder().setSingle(false).setServerRouter(new TestServerRouter(SERVERS.PORT_1)).setPort(SERVERS.PORT_1).build();
ServerContext sc2 = new ServerContextBuilder().setSingle(false).setServerRouter(new TestServerRouter(SERVERS.PORT_2)).setPort(SERVERS.PORT_2).build();
sc0.setFailureHandlerPolicy(new PurgeFailurePolicy());
sc1.setFailureHandlerPolicy(new PurgeFailurePolicy());
sc2.setFailureHandlerPolicy(new PurgeFailurePolicy());
addServer(SERVERS.PORT_0, sc0);
addServer(SERVERS.PORT_1, sc1);
addServer(SERVERS.PORT_2, sc2);
Layout l = new TestLayoutBuilder().setEpoch(1L).addLayoutServer(SERVERS.PORT_0).addLayoutServer(SERVERS.PORT_1).addLayoutServer(SERVERS.PORT_2).addSequencer(SERVERS.PORT_0).buildSegment().buildStripe().addLogUnit(SERVERS.PORT_0).addLogUnit(SERVERS.PORT_2).addToSegment().addToLayout().build();
bootstrapAllServers(l);
CorfuRuntime corfuRuntime = new CorfuRuntime();
l.getLayoutServers().forEach(corfuRuntime::addLayoutServer);
corfuRuntime.connect();
// Initiating all failure handlers.
for (String server : l.getAllServers()) {
corfuRuntime.getRouter(server).getClient(ManagementClient.class).initiateFailureHandler().get();
}
// Setting aggressive timeouts
setAggressiveTimeouts(l, corfuRuntime, getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), getManagementServer(SERVERS.PORT_1).getCorfuRuntime(), getManagementServer(SERVERS.PORT_2).getCorfuRuntime());
// Adding a rule on SERVERS.PORT_1 to drop all packets
addServerRule(SERVERS.PORT_1, new TestRule().always().drop());
getManagementServer(SERVERS.PORT_1).shutdown();
for (int i = 0; i < PARAMETERS.NUM_ITERATIONS_LOW; i++) {
corfuRuntime.invalidateLayout();
if (corfuRuntime.getLayoutView().getLayout().getEpoch() == 2L) {
break;
}
Thread.sleep(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
}
Layout l2 = corfuRuntime.getLayoutView().getLayout();
assertThat(l2.getEpoch()).isEqualTo(2L);
assertThat(l2.getLayoutServers().size()).isEqualTo(2);
assertThat(l2.getLayoutServers().contains(SERVERS.ENDPOINT_1)).isFalse();
}
use of org.corfudb.runtime.CorfuRuntime in project CorfuDB by CorfuDB.
the class ManagementViewTest method invokeFailureHandler.
/**
* Scenario with 2 nodes: SERVERS.PORT_0 and SERVERS.PORT_1.
* We fail SERVERS.PORT_0 and then listen to intercept the message
* sent by SERVERS.PORT_1's client to the server to handle the failure.
*
* @throws Exception
*/
@Test
public void invokeFailureHandler() throws Exception {
// Boolean flag turned to true when the MANAGEMENT_FAILURE_DETECTED message
// is sent by the Management client to its server.
final Semaphore failureDetected = new Semaphore(1, true);
addServer(SERVERS.PORT_0);
addServer(SERVERS.PORT_1);
Layout l = new TestLayoutBuilder().setEpoch(1L).addLayoutServer(SERVERS.PORT_0).addLayoutServer(SERVERS.PORT_1).addSequencer(SERVERS.PORT_0).buildSegment().buildStripe().addLogUnit(SERVERS.PORT_0).addLogUnit(SERVERS.PORT_1).addToSegment().addToLayout().build();
bootstrapAllServers(l);
CorfuRuntime corfuRuntime = new CorfuRuntime();
l.getLayoutServers().forEach(corfuRuntime::addLayoutServer);
corfuRuntime.connect();
corfuRuntime.getRouter(SERVERS.ENDPOINT_1).getClient(ManagementClient.class).initiateFailureHandler().get();
// Set aggressive timeouts.
setAggressiveTimeouts(l, corfuRuntime, getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), getManagementServer(SERVERS.PORT_1).getCorfuRuntime());
failureDetected.acquire();
// Adding a rule on SERVERS.PORT_0 to drop all packets
addServerRule(SERVERS.PORT_0, new TestRule().always().drop());
getManagementServer(SERVERS.PORT_0).shutdown();
// Adding a rule on SERVERS.PORT_1 to toggle the flag when it sends the
// MANAGEMENT_FAILURE_DETECTED message.
addClientRule(getManagementServer(SERVERS.PORT_1).getCorfuRuntime(), new TestRule().matches(corfuMsg -> {
if (corfuMsg.getMsgType().equals(CorfuMsgType.MANAGEMENT_FAILURE_DETECTED)) {
failureDetected.release();
}
return true;
}));
assertThat(failureDetected.tryAcquire(PARAMETERS.TIMEOUT_NORMAL.toNanos(), TimeUnit.NANOSECONDS)).isEqualTo(true);
}
use of org.corfudb.runtime.CorfuRuntime in project CorfuDB by CorfuDB.
the class ManagementViewTest method handleTransientFailure.
/**
* Scenario with 3 nodes: SERVERS.PORT_0, SERVERS.PORT_1 and SERVERS.PORT_2.
* Simulate transient failure of a server leading to a partial seal.
* Allow the management server to detect the partial seal and correct this.
* <p>
* Part 1.
* The partial seal causes SERVERS.PORT_0 to be at epoch 2 whereas,
* SERVERS.PORT_1 & SERVERS.PORT_2 fail to receive this message and are stuck at epoch 1.
* <p>
* Part 2.
* All the 3 servers are now functional and receive all messages.
* <p>
* Part 3.
* The PING message gets rejected by the partially sealed router (WrongEpoch)
* and the management server realizes of the partial seal and corrects this
* by issuing another failure detected message.
*
* @throws Exception
*/
@Test
public void handleTransientFailure() throws Exception {
// Boolean flag turned to true when the MANAGEMENT_FAILURE_DETECTED message
// is sent by the Management client to its server.
final Semaphore failureDetected = new Semaphore(2, true);
addServer(SERVERS.PORT_0);
addServer(SERVERS.PORT_1);
addServer(SERVERS.PORT_2);
Layout l = new TestLayoutBuilder().setEpoch(1L).addLayoutServer(SERVERS.PORT_0).addLayoutServer(SERVERS.PORT_1).addLayoutServer(SERVERS.PORT_2).addSequencer(SERVERS.PORT_0).buildSegment().setReplicationMode(Layout.ReplicationMode.QUORUM_REPLICATION).buildStripe().addLogUnit(SERVERS.PORT_0).addLogUnit(SERVERS.PORT_1).addLogUnit(SERVERS.PORT_2).addToSegment().addToLayout().build();
bootstrapAllServers(l);
CorfuRuntime corfuRuntime = getRuntime(l).connect();
// Initiate SERVERS.ENDPOINT_0 failureHandler
corfuRuntime.getRouter(SERVERS.ENDPOINT_0).getClient(ManagementClient.class).initiateFailureHandler().get();
// Set aggressive timeouts.
setAggressiveTimeouts(l, corfuRuntime, getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), getManagementServer(SERVERS.PORT_1).getCorfuRuntime(), getManagementServer(SERVERS.PORT_2).getCorfuRuntime());
failureDetected.acquire(2);
// Only allow SERVERS.PORT_0 to manage failures.
getManagementServer(SERVERS.PORT_1).shutdown();
getManagementServer(SERVERS.PORT_2).shutdown();
// PART 1.
// Prevent ENDPOINT_1 from sealing.
addClientRule(getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), SERVERS.ENDPOINT_1, new TestRule().matches(corfuMsg -> corfuMsg.getMsgType().equals(CorfuMsgType.SET_EPOCH)).drop());
// Simulate ENDPOINT_2 failure from ENDPOINT_0 (only Management Server)
addClientRule(getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), SERVERS.ENDPOINT_2, new TestRule().matches(corfuMsg -> true).drop());
// Adding a rule on SERVERS.PORT_1 to toggle the flag when it sends the
// MANAGEMENT_FAILURE_DETECTED message.
addClientRule(getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), new TestRule().matches(corfuMsg -> {
if (corfuMsg.getMsgType().equals(CorfuMsgType.MANAGEMENT_FAILURE_DETECTED)) {
failureDetected.release();
}
return true;
}));
// Go ahead when sealing of ENDPOINT_0 takes place.
for (int i = 0; i < PARAMETERS.NUM_ITERATIONS_LOW; i++) {
if (getServerRouter(SERVERS.PORT_0).getServerEpoch() == 2L) {
failureDetected.release();
break;
}
Thread.sleep(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
}
assertThat(failureDetected.tryAcquire(2, PARAMETERS.TIMEOUT_NORMAL.toNanos(), TimeUnit.NANOSECONDS)).isEqualTo(true);
addClientRule(getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), new TestRule().matches(corfuMsg -> corfuMsg.getMsgType().equals(CorfuMsgType.MANAGEMENT_FAILURE_DETECTED)).drop());
// Assert that only a partial seal was successful.
// ENDPOINT_0 sealed. ENDPOINT_1 & ENDPOINT_2 not sealed.
assertThat(getServerRouter(SERVERS.PORT_0).getServerEpoch()).isEqualTo(2L);
assertThat(getServerRouter(SERVERS.PORT_1).getServerEpoch()).isEqualTo(1L);
assertThat(getServerRouter(SERVERS.PORT_2).getServerEpoch()).isEqualTo(1L);
assertThat(getLayoutServer(SERVERS.PORT_0).getCurrentLayout().getEpoch()).isEqualTo(1L);
assertThat(getLayoutServer(SERVERS.PORT_1).getCurrentLayout().getEpoch()).isEqualTo(1L);
assertThat(getLayoutServer(SERVERS.PORT_2).getCurrentLayout().getEpoch()).isEqualTo(1L);
// PART 2.
// Simulate normal operations for all servers and clients.
clearClientRules(getManagementServer(SERVERS.PORT_0).getCorfuRuntime());
// PART 3.
// Allow management server to detect partial seal and correct this issue.
addClientRule(getManagementServer(SERVERS.PORT_0).getCorfuRuntime(), new TestRule().matches(corfuMsg -> {
if (corfuMsg.getMsgType().equals(CorfuMsgType.MANAGEMENT_FAILURE_DETECTED)) {
failureDetected.release(2);
}
return true;
}));
assertThat(failureDetected.tryAcquire(2, PARAMETERS.TIMEOUT_NORMAL.toNanos(), TimeUnit.NANOSECONDS)).isEqualTo(true);
for (int i = 0; i < PARAMETERS.NUM_ITERATIONS_LOW; i++) {
Thread.sleep(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
// Assert successful seal of all servers.
if (getServerRouter(SERVERS.PORT_0).getServerEpoch() == 2L || getServerRouter(SERVERS.PORT_1).getServerEpoch() == 2L || getServerRouter(SERVERS.PORT_2).getServerEpoch() == 2L || getLayoutServer(SERVERS.PORT_0).getCurrentLayout().getEpoch() == 2L || getLayoutServer(SERVERS.PORT_1).getCurrentLayout().getEpoch() == 2L || getLayoutServer(SERVERS.PORT_2).getCurrentLayout().getEpoch() == 2L) {
return;
}
}
fail();
}
use of org.corfudb.runtime.CorfuRuntime in project CorfuDB by CorfuDB.
the class ObjectsViewTest method unrelatedStreamDoesNotConflict.
@Test
@SuppressWarnings("unchecked")
public void unrelatedStreamDoesNotConflict() throws Exception {
//begin tests
CorfuRuntime r = getDefaultRuntime();
Map<String, String> smrMap = r.getObjectsView().build().setStreamName("map a").setTypeToken(new TypeToken<SMRMap<String, String>>() {
}).open();
IStreamView streamB = r.getStreamsView().get(CorfuRuntime.getStreamID("b"));
smrMap.put("a", "b");
streamB.append(new SMREntry("hi", new Object[] { "hello" }, Serializers.PRIMITIVE));
//this TX should not conflict
assertThat(smrMap).doesNotContainKey("b");
r.getObjectsView().TXBegin();
String b = smrMap.get("a");
smrMap.put("b", b);
r.getObjectsView().TXEnd();
assertThat(smrMap).containsEntry("b", "b");
}
use of org.corfudb.runtime.CorfuRuntime in project CorfuDB by CorfuDB.
the class TXsFromTwoRuntimesTest method staggeredTXsNoConflict.
@Test
public void staggeredTXsNoConflict() throws Exception {
final int nTXs = 5;
final Semaphore sem0 = new Semaphore(0), sem1 = new Semaphore(0);
// create two parallel worlds, with separate runtimes.
// both instantiate the same shared map
//
final Thread thread1 = new Thread(() -> {
CorfuRuntime myruntime = new CorfuRuntime(getDefaultEndpoint());
myruntime.connect();
ISMRMap<Integer, Integer> mymap = myruntime.getObjectsView().build().setStreamName(// stream name
"nonidepmpotentmaptest").setTypeToken(// object TokenType class
new TypeToken<SMRMap<Integer, Integer>>() {
}).open();
assertThat(mymap.get("world1")).isEqualTo(null);
for (int t = 0; t < nTXs; t++) {
myruntime.getObjectsView().TXBegin();
mymap.put(nTXs + t, t);
myruntime.getObjectsView().TXEnd();
}
// expect to see nTXS entries in this map
assertThat(mymap.size()).isEqualTo(nTXs);
// now allow for thread0 to commit its own transaction
sem0.release();
// next, wait for the commit to have completed
try {
sem1.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
// expect to (still) see nTXS+1 entries in this map
assertThat(mymap.size()).isEqualTo(nTXs + 1);
assertThat(mymap.get(0)).isEqualTo(0);
});
final Thread thread0 = new Thread(() -> {
CorfuRuntime myruntime = new CorfuRuntime(getDefaultEndpoint());
myruntime.connect();
ISMRMap<Integer, Integer> mymap = myruntime.getObjectsView().build().setStreamName(// stream name
"nonidepmpotentmaptest").setTypeToken(// object TokenType class
new TypeToken<SMRMap<Integer, Integer>>() {
}).open();
// start a transaction and then hand over to thread 1
myruntime.getObjectsView().TXBegin();
assertThat(mymap.get(0)).isEqualTo(null);
mymap.computeIfAbsent(0, (K) -> {
// should be computed deterministically, does it?
return mymap.size();
});
// enable thread1: it will do nTXS increments on the stream
thread1.start();
boolean isAbort = false;
try {
// wait for thread 1 to do its work;
// completion is indicated thru sem0
sem0.acquire();
myruntime.getObjectsView().TXEnd();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TransactionAbortedException te) {
isAbort = true;
}
// release thread1 to complete
sem1.release();
// expect to abort
assertThat(isAbort).isFalse();
// this currently fails, due to incorrect sync on commit in VersionLockedObject
// expect to see nTXs+1 entries on the stream
assertThat(mymap.size()).isEqualTo(nTXs + 1);
assertThat(mymap.get(0)).isEqualTo(0);
});
thread0.start();
final long WAIT_TIME = 10000;
try {
thread0.join(WAIT_TIME);
thread1.join(WAIT_TIME);
} catch (InterruptedException ie) {
throw new RuntimeException();
}
}
Aggregations