/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package org.voltdb; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; import static org.junit.Assert.assertTrue; import java.io.IOException; import org.junit.BeforeClass; import org.junit.Test; import org.voltdb.VoltDB.Configuration; import org.voltdb.client.Client; import org.voltdb.client.ClientFactory; import org.voltdb.client.ClientResponse; import org.voltdb.client.NoConnectionsException; import org.voltdb.client.ProcCallException; import org.voltdb.compiler.VoltProjectBuilder; import org.voltdb.regressionsuites.JUnit4LocalClusterTest; import org.voltdb.regressionsuites.LocalCluster; import org.voltdb.utils.MiscUtils; public class TestMixedPauseModeCluster extends JUnit4LocalClusterTest { static final int K = MiscUtils.isPro() ? 1 : 0; static final String JAR_NAME = "mixed.jar"; static final VoltProjectBuilder m_builder = new VoltProjectBuilder(); private class MixedPauseCluster { LocalCluster m_cluster = null; MixedPauseCluster(String[] modes) { assert (modes != null); m_cluster = new LocalCluster( JAR_NAME, 2, modes.length, K, BackendTarget.NATIVE_EE_JNI); m_cluster.setOverridesForModes(modes); m_cluster.setHasLocalServer(false); m_cluster.setDeploymentAndVoltDBRoot( m_builder.getPathToDeployment(), m_builder.getPathToVoltRoot().getAbsolutePath()); } boolean start() { m_cluster.startUp(); return true; } boolean killAndRejoin(String mode) { try { m_cluster.killSingleHost(2); // just set the override for the last host m_cluster.setOverridesForModes(new String[]{"", "", mode}); return m_cluster.recoverOne(2, 0, ""); } catch (Exception e) { e.printStackTrace(); return false; } } boolean killAndRejoin() { try { m_cluster.killSingleHost(2); return m_cluster.recoverOne(2, 0, ""); } catch (Exception e) { e.printStackTrace(); return false; } } void shutdown() throws InterruptedException { if (m_cluster != null) { m_cluster.shutDown(); } } } @BeforeClass public static void compileCatalog() throws IOException { m_builder.addLiteralSchema("CREATE TABLE V0 (id BIGINT);"); m_builder.configureLogging(null, null, false, false, 200, Integer.MAX_VALUE, null); assertTrue(m_builder.compile(Configuration.getPathToCatalogForTest(JAR_NAME), 2, 3, K)); } void checkSystemInformationClusterState(final Client client) throws IOException, NoConnectionsException, ProcCallException { VoltTable sysinfo = client.callProcedure("@SystemInformation").getResults()[0]; for (int i = 0; i < sysinfo.getRowCount(); i++) { sysinfo.advanceRow(); if (sysinfo.get("KEY", VoltType.STRING).equals("CLUSTERSTATE")) { assertTrue("Paused".equalsIgnoreCase((String) sysinfo.get("VALUE", VoltType.STRING))); } } } void checkClusterDoesNotAllowWrite(Client client) throws IOException, NoConnectionsException, ProcCallException { boolean admin_start = false; try { client.callProcedure("@AdHoc", "insert into V0 values(0);"); } catch (ProcCallException e) { assertEquals("Server did not report itself as unavailable.", ClientResponse.SERVER_UNAVAILABLE, e.getClientResponse().getStatus()); admin_start = true; } assertTrue("Server did not report itself as unavailable.", admin_start); } @Test public void testStartupConfigurations() throws InterruptedException { try { MixedPauseCluster cluster = null; // should work cluster = new MixedPauseCluster(new String[]{"", "paused", ""}); assertTrue(cluster.start()); Client client = ClientFactory.createClient(); client.createConnection(cluster.m_cluster.getListenerAddress(0)); checkSystemInformationClusterState(client); checkClusterDoesNotAllowWrite(client); client.close(); cluster.shutdown(); // should work cluster = new MixedPauseCluster( new String[]{"paused", "", ""}); assertTrue(cluster.start()); client = ClientFactory.createClient(); client.createConnection(cluster.m_cluster.getListenerAddress(0)); checkSystemInformationClusterState(client); checkClusterDoesNotAllowWrite(client); client.close(); cluster.shutdown(); // should work cluster = new MixedPauseCluster( new String[]{"", "", "paused"}); assertTrue(cluster.start()); client = ClientFactory.createClient(); client.createConnection(cluster.m_cluster.getListenerAddress(0)); checkSystemInformationClusterState(client); checkClusterDoesNotAllowWrite(client); client.close(); cluster.shutdown(); // should work cluster = new MixedPauseCluster( new String[]{"paused", "paused", "paused"}); assertTrue(cluster.start()); client = ClientFactory.createClient(); client.createConnection(cluster.m_cluster.getListenerAddress(0)); checkSystemInformationClusterState(client); checkClusterDoesNotAllowWrite(client); client.close(); cluster.shutdown(); } catch (Exception ex) { fail("Failed with: " + ex); } } @Test public void testJoins() throws InterruptedException { if (!MiscUtils.isPro()) { return; } // join tests are pro only try { MixedPauseCluster cluster = null; // test some rejoins cluster = new MixedPauseCluster(new String[]{"paused", "", ""}); assertTrue(cluster.start()); final Client client = ClientFactory.createClient(); client.createConnection(cluster.m_cluster.getListenerAddress(0)); checkSystemInformationClusterState(client); assertTrue(cluster.killAndRejoin()); checkSystemInformationClusterState(client); checkClusterDoesNotAllowWrite(client); assertTrue(cluster.killAndRejoin()); checkSystemInformationClusterState(client); checkClusterDoesNotAllowWrite(client); cluster.shutdown(); } catch (Exception ex) { fail("Failed with: " + ex); } } }