use of org.corfudb.runtime.view.Layout in project CorfuDB by CorfuDB.
the class LayoutServerTest method testReboot.
@Test
public void testReboot() throws Exception {
String serviceDir = PARAMETERS.TEST_TEMP_DIR;
LayoutServer s1 = getDefaultServer(serviceDir);
setServer(s1);
Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0);
final long NEW_EPOCH = 99L;
layout.setEpoch(NEW_EPOCH);
bootstrapServer(layout);
// Reboot, then check that our epoch 100 layout is still there.
//s1.reboot();
requestLayout(NEW_EPOCH);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_RESPONSE);
Assertions.assertThat(((LayoutMsg) getLastMessage()).getLayout().getEpoch()).isEqualTo(NEW_EPOCH);
s1.shutdown();
for (int i = 0; i < PARAMETERS.NUM_ITERATIONS_LOW; i++) {
LayoutServer s2 = getDefaultServer(serviceDir);
setServer(s2);
commitReturnsAck(s2, i, NEW_EPOCH + 1);
s2.shutdown();
}
}
use of org.corfudb.runtime.view.Layout in project CorfuDB by CorfuDB.
the class LayoutServerTest method checkLayoutPersisted.
/**
* Verifies that a layout is persisted across server reboots.
*
* @throws Exception
*/
@Test
public void checkLayoutPersisted() throws Exception {
//serviceDirectory from which all instances of corfu server are to be booted.
String serviceDir = PARAMETERS.TEST_TEMP_DIR;
LayoutServer s1 = getDefaultServer(serviceDir);
Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0);
bootstrapServer(layout);
Layout newLayout = TestLayoutBuilder.single(SERVERS.PORT_0);
final long OLD_EPOCH = 0;
final long NEW_EPOCH = 100;
newLayout.setEpoch(NEW_EPOCH);
setEpoch(NEW_EPOCH);
// Start the process of electing a new layout. But that layout will not take effect
// till it is committed.
sendPrepare(NEW_EPOCH, 1);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_PREPARE_ACK);
sendPropose(NEW_EPOCH, 1, newLayout);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.ACK);
assertThat(s1).isInEpoch(NEW_EPOCH);
assertThat(s1).isPhase1Rank(new Rank(1L, AbstractServerTest.testClientId));
assertThat(s1).isPhase2Rank(new Rank(1L, AbstractServerTest.testClientId));
s1.shutdown();
LayoutServer s2 = getDefaultServer(serviceDir);
this.router.reset();
this.router.addServer(s2);
assertThat(s2).isInEpoch(NEW_EPOCH);
assertThat(s2).isPhase1Rank(new Rank(1L, AbstractServerTest.testClientId));
assertThat(s2).isPhase2Rank(new Rank(1L, AbstractServerTest.testClientId));
// request layout using the old epoch.
requestLayout(OLD_EPOCH);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_RESPONSE);
Assertions.assertThat(((LayoutMsg) getLastMessage()).getLayout().getEpoch()).isEqualTo(0);
// request layout using the new epoch.
requestLayout(NEW_EPOCH);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_RESPONSE);
Assertions.assertThat(((LayoutMsg) getLastMessage()).getLayout().getEpoch()).isEqualTo(0);
}
use of org.corfudb.runtime.view.Layout in project CorfuDB by CorfuDB.
the class LayoutServerTest method checkMessagesValidatedAgainstPhase2PersistedData.
/**
* Validates that the layout server accept or rejects incoming phase2 messages based on
* the last persisted phase1 and phase2 data.
* If persisted phase1 rank does not match the LAYOUT_PROPOSE message then the server did not
* take part in the prepare phase. It should reject this message.
* If the persisted phase2 rank is the same as incoming message, it will be rejected as it is a
* duplicate message.
*
* @throws Exception
*/
@Test
public void checkMessagesValidatedAgainstPhase2PersistedData() throws Exception {
String serviceDir = PARAMETERS.TEST_TEMP_DIR;
LayoutServer s1 = getDefaultServer(serviceDir);
Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0);
bootstrapServer(layout);
long newEpoch = layout.getEpoch() + 1;
Layout newLayout = TestLayoutBuilder.single(SERVERS.PORT_0);
newLayout.setEpoch(newEpoch);
setEpoch(newEpoch);
assertThat(s1).isInEpoch(newEpoch);
// validate phase 1
sendPrepare(newEpoch, HIGH_RANK);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_PREPARE_ACK);
assertThat(s1).isPhase1Rank(new Rank(HIGH_RANK, AbstractServerTest.testClientId));
s1.shutdown();
LayoutServer s2 = getDefaultServer(serviceDir);
assertThat(s2).isInEpoch(newEpoch);
assertThat(s2).isPhase1Rank(new Rank(HIGH_RANK, AbstractServerTest.testClientId));
//new LAYOUT_PROPOSE message with a lower phase2 rank should be rejected
sendPropose(newEpoch, HIGH_RANK - 1, newLayout);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_PROPOSE_REJECT);
//new LAYOUT_PROPOSE message with a rank that does not match LAYOUT_PREPARE should be rejected
sendPropose(newEpoch, HIGH_RANK + 1, newLayout);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.LAYOUT_PROPOSE_REJECT);
//new LAYOUT_PROPOSE message with same rank as phase1 should be accepted
sendPropose(newEpoch, HIGH_RANK, newLayout);
Assertions.assertThat(getLastMessage().getMsgType()).isEqualTo(CorfuMsgType.ACK);
assertThat(s2).isProposedLayout(newLayout);
s2.shutdown();
// data should survive the reboot.
LayoutServer s3 = getDefaultServer(serviceDir);
assertThat(s3).isInEpoch(newEpoch);
assertThat(s3).isPhase1Rank(new Rank(HIGH_RANK, AbstractServerTest.testClientId));
assertThat(s3).isProposedLayout(newLayout);
}
use of org.corfudb.runtime.view.Layout in project CorfuDB by CorfuDB.
the class QCLayout method main.
public static String[] main(String[] args) {
if (args != null && args.length > 0 && args[0].contentEquals("reboot")) {
LayoutServer ls = CorfuServer.getLayoutServer();
if (ls != null) {
ls.shutdown();
CorfuServer.addLayoutServer();
return replyOk();
} else {
return replyErr("No active layout server");
}
}
// Parse the options given, using docopt.
Map<String, Object> opts = new Docopt(USAGE).withVersion(GitRepositoryState.getRepositoryState().describe).parse(args);
// Configure base options
// configureBase(opts);
// Parse host address and port
String addressport = (String) opts.get("<address>:<port>");
String host = addressport.split(":")[0];
Integer port = Integer.parseInt(addressport.split(":")[1]);
String qapp = (String) opts.get("<qapp>");
String addressportPrefix = "";
if (qapp != null) {
addressportPrefix = qapp;
}
NettyClientRouter router;
if ((router = routers.get(addressportPrefix + addressport)) == null) {
// Create a client router and get layout.
log.trace("Creating router for {} ++ {}:{}", addressportPrefix, port);
router = new NettyClientRouter(host, port);
router.addClient(new BaseClient()).addClient(new LayoutClient()).start();
routers.putIfAbsent(addressportPrefix + addressport, router);
}
router = routers.get(addressportPrefix + addressport);
Long epoch = 0L;
if (opts.get("--epoch") != null) {
epoch = Long.parseLong((String) opts.get("--epoch"));
log.trace("Specify router's epoch as " + epoch);
router.setEpoch(epoch);
} else {
try {
Layout l = router.getClient(LayoutClient.class).getLayout().get();
if (l != null) {
log.trace("Set router's epoch to " + l.getEpoch());
router.setEpoch(l.getEpoch());
} else {
log.trace("Cannot set router's epoch");
}
} catch (Exception e) {
return replyErr("ERROR Exception getting initial epoch " + e.getCause());
}
}
if ((Boolean) opts.get("getClientID")) {
String clientID = router.getClientID().toString();
return replyOk(clientID);
} else if ((Boolean) opts.get("query")) {
try {
Layout l = router.getClient(LayoutClient.class).getLayout().get();
Gson gs = new GsonBuilder().setPrettyPrinting().create();
return replyOk("layout: " + gs.toJson(l));
} catch (ExecutionException ex) {
if (ex.getCause().getClass() == WrongEpochException.class) {
WrongEpochException we = (WrongEpochException) ex.getCause();
return replyErr("Exception during query", ex.getCause().toString(), "correctEpoch: " + we.getCorrectEpoch(), "stack: " + ExceptionUtils.getStackTrace(ex));
} else {
return replyErr("Exception during query", ex.getCause().toString(), "stack: " + ExceptionUtils.getStackTrace(ex));
}
} catch (Exception e) {
return replyErr("ERROR Exception getting layout" + e);
}
} else if ((Boolean) opts.get("bootstrap")) {
Layout l = getLayout(opts);
log.debug("Bootstrapping with layout {}", l);
try {
if (router.getClient(LayoutClient.class).bootstrapLayout(l).get()) {
router.getClient(ManagementClient.class).bootstrapManagement(l).get();
return replyOk();
} else {
return replyErr("NACK");
}
} catch (ExecutionException ex) {
return replyErr("Exception bootstrapping layout", ex.getCause().toString());
} catch (Exception e) {
return replyErr("Exception bootstrapping layout", e.toString());
}
} else if ((Boolean) opts.get("set_epoch")) {
log.debug("Set epoch with new epoch={}", epoch);
try {
CorfuRuntime rt;
if ((rt = setEpochRTs.get(addressport)) == null) {
log.trace("Creating CorfuRuntime for set_epoch for {} ", addressport);
rt = new CorfuRuntime().addLayoutServer(addressport);
setEpochRTs.putIfAbsent(addressport, rt);
}
rt = setEpochRTs.get(addressport);
// Construct a layout that contains just enough to allow .moveServersToEpoch()
// to send SET_EPOCH to our desired endpoint.
List<String> ls = new ArrayList(1);
ls.add(addressport);
List<String> none1 = new ArrayList(0);
List<Layout.LayoutSegment> none2 = new ArrayList(0);
Layout tmpLayout = new Layout(ls, none1, none2, epoch);
tmpLayout.setRuntime(rt);
tmpLayout.moveServersToEpoch();
return replyOk();
} catch (WrongEpochException we) {
return replyErr("Exception during set_epoch", we.getCause() == null ? "WrongEpochException" : we.getCause().toString(), "correctEpoch: " + we.getCorrectEpoch(), "stack: " + ExceptionUtils.getStackTrace(we));
} catch (Exception e) {
return replyErr("Exception during set_epoch", e.toString(), ExceptionUtils.getStackTrace(e));
}
} else if ((Boolean) opts.get("prepare")) {
long rank = Long.parseLong((String) opts.get("--rank"));
log.debug("Prepare with new rank={}", rank);
try {
LayoutPrepareResponse r = router.getClient(LayoutClient.class).prepare(epoch, rank).get();
Layout r_layout = r.getLayout();
if (r_layout == null) {
return replyOk("ignored: ignored");
} else {
return replyOk("layout: " + r_layout.asJSONString());
}
} catch (ExecutionException ex) {
if (ex.getCause().getClass() == OutrankedException.class) {
OutrankedException oe = (OutrankedException) ex.getCause();
return replyErr("Exception during prepare", ex.getCause().toString(), "newRank: " + Long.toString(oe.getNewRank()), "layout: " + (oe.getLayout() == null ? "" : oe.getLayout().asJSONString()));
} else if (ex.getCause().getClass() == WrongEpochException.class) {
WrongEpochException we = (WrongEpochException) ex.getCause();
return replyErr("Exception during prepare", ex.getCause().toString(), "correctEpoch: " + we.getCorrectEpoch(), "stack: " + ExceptionUtils.getStackTrace(ex));
} else {
return replyErr("Exception during prepare", ex.getCause().toString(), "stack: " + ExceptionUtils.getStackTrace(ex));
}
} catch (Exception e) {
return replyErr("Exception during prepare", e.toString(), ExceptionUtils.getStackTrace(e));
}
} else if ((Boolean) opts.get("propose")) {
long rank = Long.parseLong((String) opts.get("--rank"));
Layout l = getLayout(opts);
log.debug("Propose with new rank={}, layout={}", rank, l);
try {
if (router.getClient(LayoutClient.class).propose(l.getEpoch(), rank, l).get()) {
return replyOk();
} else {
return replyErr("NACK");
}
} catch (ExecutionException ex) {
if (ex.getCause().getClass() == OutrankedException.class) {
OutrankedException oe = (OutrankedException) ex.getCause();
return replyErr("Exception during propose", ex.getCause().toString(), "newRank: " + Long.toString(oe.getNewRank()), "stack: " + ExceptionUtils.getStackTrace(ex));
} else if (ex.getCause().getClass() == WrongEpochException.class) {
WrongEpochException we = (WrongEpochException) ex.getCause();
return replyErr("Exception during propose", ex.getCause().toString(), "correctEpoch: " + we.getCorrectEpoch(), "stack: " + ExceptionUtils.getStackTrace(ex));
} else {
return replyErr("Exception during propose", ex.getCause().toString(), "stack: " + ExceptionUtils.getStackTrace(ex));
}
} catch (Exception e) {
return replyErr("Exception during propose", e.toString(), "stack: " + ExceptionUtils.getStackTrace(e));
}
} else if ((Boolean) opts.get("committed")) {
long rank = Long.parseLong((String) opts.get("--rank"));
Layout l = getLayout(opts);
log.debug("Propose with new rank={}", rank);
try {
if (router.getClient(LayoutClient.class).committed(l.getEpoch(), l).get()) {
return replyOk();
} else {
return replyErr("NACK");
}
} catch (ExecutionException ex) {
if (ex.getCause().getClass() == WrongEpochException.class) {
WrongEpochException we = (WrongEpochException) ex.getCause();
return replyErr("Exception during commit", ex.getCause().toString(), "correctEpoch: " + we.getCorrectEpoch(), "stack: " + ExceptionUtils.getStackTrace(ex));
} else {
return replyErr("Exception during commit", ex.getCause().toString(), "stack: " + ExceptionUtils.getStackTrace(ex));
}
} catch (Exception e) {
return replyErr("Exception during commit", e.toString(), "stack: " + ExceptionUtils.getStackTrace(e));
}
}
return replyErr("Hush, compiler.");
}
use of org.corfudb.runtime.view.Layout in project CorfuDB by CorfuDB.
the class AbstractReplicationProtocolTest method canWriteRead.
/** Check if we can write and then read the value
* that was written.
*/
@Test
@SuppressWarnings("unchecked")
public void canWriteRead() throws Exception {
setupNodes();
//begin tests
final CorfuRuntime r = getDefaultRuntime();
final IReplicationProtocol rp = getProtocol();
final Layout layout = r.getLayoutView().getLayout();
LogData data = getLogData(0, "hello world".getBytes());
rp.write(layout, data);
ILogData read = rp.read(layout, 0);
assertThat(read.getType()).isEqualTo(DataType.DATA);
assertThat(read.getGlobalAddress()).isEqualTo(0);
assertThat(read.getPayload(r)).isEqualTo("hello world".getBytes());
}
Aggregations