/** * Bootstraps a layout server connected to the specified router. * * @param router Router connected to the node. * @param layout Layout to bootstrap with */ private static void bootstrapLayoutServer(IClientRouter router, Layout layout) throws ExecutionException, InterruptedException, AlreadyBootstrappedException { LayoutClient layoutClient = new LayoutClient(router, layout.getEpoch()); try { CFUtils.getUninterruptibly(layoutClient.bootstrapLayout(layout), AlreadyBootstrappedException.class); } catch (AlreadyBootstrappedException abe) { if (!layoutClient.getLayout().get().equals(layout)) { log.error("BootstrapUtil: Layout Server {}:{} already bootstrapped with different " + "layout.", router.getHost(), router.getPort()); throw abe; } } }
/** * Retrieves the layout from the endpoint, asynchronously. * * @return A future which will be completed with the current layout. */ public CompletableFuture<Layout> getLayout() { return sendMessageWithFuture(CorfuMsgType.LAYOUT_REQUEST.payloadMsg(getEpoch())); }
private Map<String, CompletableFuture<Layout>> getLayoutFutures(List<String> layoutServers) { Map<String, CompletableFuture<Layout>> layoutFuturesMap = new HashMap<>(); // Get layout futures for layout requests from all layout servers. for (String server : layoutServers) { try { // Router creation can throw a NetworkException. IClientRouter router = runtime.getRouter(server); layoutFuturesMap.put(server, new LayoutClient(router, Layout.INVALID_EPOCH).getLayout()); } catch (NetworkException e) { log.error("getClusterStatus: Exception encountered connecting to {}. ", server, e); CompletableFuture<Layout> cf = new CompletableFuture<>(); cf.completeExceptionally(e); layoutFuturesMap.put(server, cf); } } return layoutFuturesMap; }
@Test public void proposeRejectsLowerRanks() throws Exception { Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0); long epoch = layout.getEpoch(); assertThat(client.bootstrapLayout(layout).get()) .isEqualTo(true); assertThat(client.prepare(epoch, RANK_HIGH).get() != null) .isEqualTo(true); assertThatThrownBy(() -> { client.propose(epoch, RANK_LOW, layout).get(); }).hasCauseInstanceOf(OutrankedException.class); assertThat(client.propose(epoch, RANK_HIGH, TestLayoutBuilder.single(SERVERS.PORT_0)).get()) .isEqualTo(true); }
@Test public void commitReturnsAck() throws Exception { Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0); long epoch = layout.getEpoch(); assertThat(client.bootstrapLayout(layout).get()) .isEqualTo(true); assertThat(client.prepare(epoch, RANK_HIGH).get() != null) .isEqualTo(true); final long TEST_EPOCH = 777; layout.setEpoch(TEST_EPOCH); assertThat(client.committed(TEST_EPOCH, layout).get()) .isEqualTo(true); }
@Test public void bootstrapServerInstallsNewLayout() throws Exception { Layout l = TestLayoutBuilder.single(SERVERS.PORT_0); assertThat(client.bootstrapLayout(l).get()) .isEqualTo(true); assertThat(client.getLayout().get().asJSONString()) .isEqualTo(l.asJSONString()); }
/** * Setup a cluster of 1 node. Bootstrap the node with a wrong layout. * Bootstrap the cluster using the BootstrapUtil. It should assert that the node already * bootstrapped is with the wrong layout and then fail with the AlreadyBootstrappedException. */ @Test public void test1NodeBootstrapWithWrongBootstrappedLayoutServer() throws Exception { // Set up cluster of 1 node. final int PORT_0 = 9000; Process corfuServer_1 = runPersistentServer(corfuSingleNodeHost, PORT_0, false); final Layout layout = getLayout(1); final int retries = 3; IClientRouter router = new NettyClientRouter(NodeLocator .parseString(corfuSingleNodeHost + ":" + PORT_0), CorfuRuntime.CorfuRuntimeParameters.builder().build()); router.addClient(new LayoutHandler()).addClient(new BaseHandler()); Layout wrongLayout = new Layout(layout); wrongLayout.getLayoutServers().add("localhost:9005"); retryBootstrapOperation(() -> CFUtils.getUninterruptibly( new LayoutClient(router, layout.getEpoch()).bootstrapLayout(wrongLayout))); assertThatThrownBy(() -> BootstrapUtil.bootstrap(layout, retries, PARAMETERS.TIMEOUT_SHORT)) .hasCauseInstanceOf(AlreadyBootstrappedException.class); shutdownCorfuServer(corfuServer_1); }
@Test public void prepareRejectsLowerRanks() throws Exception { Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0); assertThat(client.bootstrapLayout(layout).get()) .isEqualTo(true); long epoch = layout.getEpoch(); assertThat(client.prepare(epoch, RANK_HIGH).get() != null) .isEqualTo(true); assertThatThrownBy(() -> { client.prepare(epoch, RANK_LOW).get(); }).hasCauseInstanceOf(OutrankedException.class); assertThatThrownBy(() -> { client.prepare(epoch, 2L).get(); }).hasCauseInstanceOf(OutrankedException.class); }
/** * Get the layout from a particular layout server requested by a Layout request message stamped * with the epoch from the specified layout. * * @param layout Layout epoch to stamp the layout request. * @param endpoint Layout Server endpoint to request the layout from. * @return Completable future which returns the result of the RPC request. */ private CompletableFuture<Layout> getLayoutFromServer(Layout layout, String endpoint) { CompletableFuture<Layout> completableFuture = new CompletableFuture<>(); try { completableFuture = getCorfuRuntime() .getLayoutView() .getRuntimeLayout(layout) .getLayoutClient(endpoint) .getLayout(); } catch (Exception e) { completableFuture.completeExceptionally(e); } return completableFuture; }
.getRuntimeLayout(updatedLayout) .getLayoutClient(layoutServer) .committed(updatedLayout.getEpoch(), updatedLayout) .get(); if (result) {
@Override public LayoutClient getClient(long epoch) { return new LayoutClient(router, epoch); }
@Test public void cannotBootstrapServerTwice() throws Exception { assertThat(client.bootstrapLayout(TestLayoutBuilder.single(SERVERS.PORT_0)).get()) .isEqualTo(true); assertThatThrownBy(() -> client.bootstrapLayout(TestLayoutBuilder.single(SERVERS.PORT_0)).get()) .hasCauseInstanceOf(AlreadyBootstrappedException.class); }
/** * Informs the server that the proposal (layout) has been committed to a quorum. * * @param epoch epoch affiliated with the layout. * @param layout Layout to be committed. * @return True, if the commit was successful. */ public CompletableFuture<Boolean> committed(long epoch, Layout layout) { return sendMessageWithFuture(CorfuMsgType.LAYOUT_COMMITTED .payloadMsg(new LayoutCommittedRequest(epoch, layout))); }
try { cf = getRuntimeLayout().getLayoutClient(x).propose(epoch, rank, layout); } catch (NetworkException e) { cf.completeExceptionally(e);
try { cf = getRuntimeLayout().getLayoutClient(x).prepare(epoch, rank); } catch (Exception e) { cf.completeExceptionally(e);
@Test public void proposeRejectsAlreadyProposed() throws Exception { Layout layout = TestLayoutBuilder.single(SERVERS.PORT_0); long epoch = layout.getEpoch(); assertThat(client.bootstrapLayout(layout).get()) .isEqualTo(true); assertThat(client.prepare(epoch, RANK_HIGH).get() != null) .isEqualTo(true); client.propose(epoch, RANK_HIGH, layout).get(); assertThatThrownBy(() -> { client.propose(epoch, RANK_LOW, layout).get(); }).hasCauseInstanceOf(OutrankedException.class); assertThatThrownBy(() -> { client.propose(epoch, RANK_HIGH, layout).get(); }).hasCauseInstanceOf(OutrankedException.class); }
@Test public void canGetNewLayoutInDifferentEpoch() throws Exception { Layout l = TestLayoutBuilder.single(SERVERS.PORT_0); final long NEW_EPOCH = 42L; l.setEpoch(NEW_EPOCH); assertThat(client.bootstrapLayout(l).get()) .isEqualTo(true); assertThat(client.getLayout().get().getEpoch()) .isEqualTo(NEW_EPOCH); }
new LayoutClient(router, Layout.INVALID_EPOCH).getLayout();
/** * Setup a cluster of 1 node. Bootstrap the nodes. * Bootstrap the cluster using the BootstrapUtil. It should assert that the node already * bootstrapped is with the same layout and then bootstrap the cluster. */ @Test public void test1NodeBootstrapWithBootstrappedNode() throws Exception { // Set up cluster of 1 nodes. final int PORT_0 = 9000; Process corfuServer_1 = runPersistentServer(corfuSingleNodeHost, PORT_0, false); final Layout layout = getLayout(1); final int retries = 5; IClientRouter router = new NettyClientRouter(NodeLocator .parseString(corfuSingleNodeHost + ":" + PORT_0), CorfuRuntime.CorfuRuntimeParameters.builder().build()); router.addClient(new LayoutHandler()).addClient(new BaseHandler()); retryBootstrapOperation(() -> CFUtils.getUninterruptibly( new LayoutClient(router, layout.getEpoch()).bootstrapLayout(layout))); retryBootstrapOperation(() -> CFUtils.getUninterruptibly( new ManagementClient(router, layout.getEpoch()).bootstrapManagement(layout))); BootstrapUtil.bootstrap(layout, retries, PARAMETERS.TIMEOUT_SHORT); CorfuRuntime corfuRuntime = createDefaultRuntime(); assertThat(corfuRuntime.getLayoutView().getLayout().equals(layout)).isTrue(); shutdownCorfuServer(corfuServer_1); }