From bc972fc979823b837c4227ee9998e500d8b6c23d Mon Sep 17 00:00:00 2001 From: Andrew Purtell Date: Fri, 19 May 2017 14:50:31 -0700 Subject: [PATCH] PHOENIX-3808 Implement chaos tests using HBase's hbase-it facility --- .../phoenix/end2end/BigLinkedListIT.java | 226 ++++++++++++++++++ .../phoenix/end2end/End2EndTestDriver.java | 116 ++++++++- .../end2end/chaos/actions/BaseAction.java | 38 +++ .../CompactRandomRegionOfTableAction.java | 84 +++++++ .../chaos/actions/CompactTableAction.java | 67 ++++++ .../FlushRandomRegionOfTableAction.java | 72 ++++++ .../chaos/actions/FlushTableAction.java | 59 +++++ ...rgeRandomAdjacentRegionsOfTableAction.java | 73 ++++++ .../MoveRandomRegionOfTableAction.java | 68 ++++++ .../actions/MoveRegionsOfTableAction.java | 98 ++++++++ .../chaos/actions/SnapshotTableAction.java | 56 +++++ .../actions/SplitAllRegionOfTableAction.java | 76 ++++++ .../SplitRandomRegionOfTableAction.java | 72 ++++++ .../chaos/factories/CalmMonkeyFactory.java | 31 +++ .../chaos/factories/MonkeyFactory.java | 88 +++++++ .../chaos/factories/NoKillMonkeyFactory.java | 126 ++++++++++ .../factories/ServerKillingMonkeyFactory.java | 77 ++++++ .../SlowDeterministicMonkeyFactory.java | 167 +++++++++++++ .../apache/phoenix/util/ReadOnlyProps.java | 15 +- 19 files changed, 1600 insertions(+), 9 deletions(-) create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/BigLinkedListIT.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/BaseAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactRandomRegionOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushRandomRegionOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MergeRandomAdjacentRegionsOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRandomRegionOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRegionsOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SnapshotTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitAllRegionOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitRandomRegionOfTableAction.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/CalmMonkeyFactory.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/MonkeyFactory.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/NoKillMonkeyFactory.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/ServerKillingMonkeyFactory.java create mode 100644 phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/SlowDeterministicMonkeyFactory.java diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BigLinkedListIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BigLinkedListIT.java new file mode 100644 index 00000000000..b9ae96cfc6c --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BigLinkedListIT.java @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.end2end; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.query.QueryServicesOptions; +import org.apache.phoenix.util.ReadOnlyProps; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Maps; + +/** + * This is an integration test borrowed from goraci, written by Keith Turner, + * which is in turn inspired by the Accumulo test called continous ingest (ci). + * The original source code can be found here: + * https://github.com/keith-turner/goraci + * https://github.com/enis/goraci/ + * + * Apache Accumulo [0] has a simple test suite that verifies that data is not + * lost at scale. This test suite is called continuous ingest. This test runs + * many ingest clients that continually create linked lists containing 25 + * million nodes. At some point the clients are stopped and a map reduce job is + * run to ensure no linked list has a hole. A hole indicates data was lost.·· + * + * The nodes in the linked list are random. This causes each linked list to + * spread across the table. Therefore if one part of a table loses data, then it + * will be detected by references in another part of the table. + * + * THE ANATOMY OF THE TEST + * + * Below is rough sketch of how data is written. For specific details look at + * the Generator code. + * + * 1 Write out 1 million nodes· 2 Flush the client· 3 Write out 1 million that + * reference previous million· 4 If this is the 25th set of 1 million nodes, + * then update 1st set of million to point to last· 5 goto 1 + * + * The key is that nodes only reference flushed nodes. Therefore a node should + * never reference a missing node, even if the ingest client is killed at any + * point in time. + * + * When running this test suite w/ Accumulo there is a script running in + * parallel called the Aggitator that randomly and continuously kills server + * processes.·· The outcome was that many data loss bugs were found in Accumulo + * by doing this.· This test suite can also help find bugs that impact uptime + * and stability when· run for days or weeks.·· + * + * When generating data, its best to have each map task generate a multiple of + * 25 million. The reason for this is that circular linked list are generated + * every 25M. Not generating a multiple in 25M will result in some nodes in the + * linked list not having references. The loss of an unreferenced node can not + * be detected. + * + * Some ASCII art time: + *

+ * [ . . . ] represents one batch of random longs of length WIDTH + *

+ *                _________________________
+ *               |                  ______ |
+ *               |                 |      ||
+ *             .-+-----------------+-----.||
+ *             | |                 |     |||
+ * first   = [ . . . . . . . . . . . ]   |||
+ *             ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^     |||
+ *             | | | | | | | | | | |     |||
+ * prev    = [ . . . . . . . . . . . ]   |||
+ *             ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^     |||
+ *             | | | | | | | | | | |     |||
+ * current = [ . . . . . . . . . . . ]   |||
+ *                                       |||
+ * ...                                   |||
+ *                                       |||
+ * last    = [ . . . . . . . . . . . ]   |||
+ *             ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^_____|||
+ *             |                 |________||
+ *             |___________________________|
+ * 
+ */ +public class BigLinkedListIT extends BaseOwnClusterIT { + + static final Log LOG = LogFactory.getLog(BigLinkedListIT.class); + + protected static String TABLE_NAME_KEY = "BigLinkedListIT.table"; + protected static String DEFAULT_TABLE_NAME = "BigLinkedListIT"; + + protected static final String NUM_ITERATIONS_KEY = "BigLinkedListIT.iterations"; + protected static final int DEFAULT_NUM_ITERATIONS = 1; + + protected static final String NUM_MAPPERS_KEY = "BigLinkedListIT.map.tasks"; + protected static final int DEFAULT_NUM_MAPPERS = 1; + + protected static final String NUM_REDUCERS_KEY = "BigLinkedListIT.reduce.tasks"; + protected static final int DEFAULT_NUM_REDUCERS = 1; + + protected static final String OUTPUT_DIR_KEY = "BigLinkedListIT.output.dir"; + protected static final String DEFAULT_OUTPUT_DIR = "/tmp/BigLinkedListIT"; + + /** How many rows to write per map task. This has to be a multiple of 25M */ + protected static final String GENERATOR_NUM_ROWS_PER_MAP_KEY = + "BigLinkedListIT.generator.num_rows"; + protected static final long DEFAULT_GENERATOR_NUM_ROWS_PER_MAP = 25000000; + + protected static final String GENERATOR_WIDTH_KEY = "BigLinkedListIT.generator.width"; + protected static final int DEFAULT_GENERATOR_WIDTH = 1000000; + + protected static final String GENERATOR_WRAP_KEY = "BigLinkedListIT.generator.wrap"; + protected static final int DEFAULT_GENERATOR_WRAP = 25; + + public static Map getServerProperties() { + Map serverProps = Maps.newHashMap(); + serverProps.put(QueryServices.EXTRA_JDBC_ARGUMENTS_ATTRIB, + QueryServicesOptions.DEFAULT_EXTRA_JDBC_ARGUMENTS); + // TODO: Configuration properties for site conf go here + return serverProps; + } + + public static Map getTestProperties() { + Map testProps = Maps.newHashMap(); + // Global properties + testProps.put(TABLE_NAME_KEY, System.getProperty(TABLE_NAME_KEY, DEFAULT_TABLE_NAME)); + testProps.put(NUM_ITERATIONS_KEY, System.getProperty(NUM_ITERATIONS_KEY, + Integer.toString(DEFAULT_NUM_ITERATIONS))); + testProps.put(NUM_MAPPERS_KEY, System.getProperty(NUM_MAPPERS_KEY, + Integer.toString(DEFAULT_NUM_MAPPERS))); + testProps.put(NUM_REDUCERS_KEY, System.getProperty(NUM_REDUCERS_KEY, + Integer.toString(DEFAULT_NUM_REDUCERS))); + testProps.put(OUTPUT_DIR_KEY, System.getProperty(OUTPUT_DIR_KEY, DEFAULT_OUTPUT_DIR)); + // Generator properties + testProps.put(GENERATOR_NUM_ROWS_PER_MAP_KEY, + System.getProperty(GENERATOR_NUM_ROWS_PER_MAP_KEY, + Long.toString(DEFAULT_GENERATOR_NUM_ROWS_PER_MAP))); + testProps.put(GENERATOR_WIDTH_KEY, System.getProperty(GENERATOR_WIDTH_KEY, + Integer.toString(DEFAULT_GENERATOR_WIDTH))); + testProps.put(GENERATOR_WRAP_KEY, System.getProperty(GENERATOR_WRAP_KEY, + Integer.toString(DEFAULT_GENERATOR_WRAP))); + return testProps; + } + + static String getTableName(ReadOnlyProps props) { + return props.get(TABLE_NAME_KEY, DEFAULT_TABLE_NAME); + } + + @BeforeClass + public static void doSetup() throws Exception { + setUpTestDriver(new ReadOnlyProps(getServerProperties().entrySet().iterator()), + ReadOnlyProps.EMPTY_PROPS); + } + + @Test + public void testBigLinkedList() throws Exception { + ReadOnlyProps testProps = new ReadOnlyProps(getTestProperties().entrySet().iterator()); + createSchema(testProps); + int numIterations = Integer.valueOf(testProps.get(NUM_ITERATIONS_KEY)); + int numMappers = Integer.parseInt(testProps.get(NUM_MAPPERS_KEY)); + long numNodes = Long.parseLong(testProps.get(GENERATOR_NUM_ROWS_PER_MAP_KEY)); + String outputDir = testProps.get(testProps.get(OUTPUT_DIR_KEY)); + int numReducers = Integer.parseInt(testProps.get(NUM_REDUCERS_KEY)); + int width = Integer.parseInt(testProps.get(GENERATOR_WIDTH_KEY)); + int wrapMultiplier = Integer.parseInt(testProps.get(GENERATOR_WRAP_KEY)); + long expectedNumNodes = 0; + for (int i = 0; i < numIterations; i++) { + LOG.info("Starting iteration = " + i); + runGenerator(numMappers, numNodes, outputDir, width, wrapMultiplier); + expectedNumNodes += numMappers * numNodes; + runVerify(outputDir, numReducers, expectedNumNodes); + } + } + + private void runGenerator(int numMappers, long numNodes, String outputDir, int width, + int wrapMultiplier) throws Exception { + // TODO Auto-generated method stub + } + + private void runVerify(String outputDir, int numReducers, long expectedNumNodes) + throws Exception { + // TODO Auto-generated method stub + } + + static void createSchema(ReadOnlyProps testProps) throws SQLException { + final String tableName = getTableName(testProps); + try (Connection conn = DriverManager.getConnection(getUrl())) { + try (Statement stmt = conn.createStatement()) { + stmt.execute( + String.format("CREATE TABLE %s (ID BIGINT NOT NULL" + + ", PREV BIGINT NOT NULL" + + ", CLIENT VARCHAR NOT NULL" + + ", COUNT INTEGER" + + " CONSTRAINT PK PRIMARY KEY(ID))", + tableName)); + } + } + } + + static class CINode { + byte[] key; + byte[] prev; + String client; + long count; + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java index feb506fddc0..f2de02cfaa4 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java @@ -23,17 +23,25 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Properties; import java.util.Set; +import java.util.StringTokenizer; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.commons.cli.CommandLine; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hbase.AuthUtil; +import org.apache.hadoop.hbase.ChoreService; import org.apache.hadoop.hbase.ClassFinder; import org.apache.hadoop.hbase.ClassFinder.FileNameFilter; import org.apache.hadoop.hbase.ClassTestFinder; import org.apache.hadoop.hbase.IntegrationTestingUtility; +import org.apache.hadoop.hbase.ScheduledChore; +import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey; import org.apache.hadoop.hbase.util.AbstractHBaseTool; import org.apache.hadoop.util.ToolRunner; +import org.apache.phoenix.end2end.chaos.factories.MonkeyFactory; import org.junit.internal.TextListener; import org.junit.runner.Description; import org.junit.runner.JUnitCore; @@ -51,10 +59,17 @@ public class End2EndTestDriver extends AbstractHBaseTool { private static final Logger LOG = LoggerFactory.getLogger(End2EndTestDriver.class); private static final String SHORT_REGEX_ARG = "r"; private static final String SKIP_TESTS = "n"; - + private static final String MONKEY_ARG = "m"; + private static final String MONKEY_LONG_ARG = "monkey"; + private static final String MONKEY_PROPS_LONG_ARG = "monkeyProps"; + private static final String DEFINE_ARG = "D"; + private End2EndTestFilter end2endTestFilter = new End2EndTestFilter(); private boolean skipTests = false; - + private ChoreService choreService; + private String monkeyToUse; + private Properties monkeyProps; + private ChaosMonkey monkey; public static void main(String[] args) throws Exception { int ret = ToolRunner.run(new End2EndTestDriver(), args); @@ -113,6 +128,10 @@ protected void addOptions() { ".*end2end.*"); addOptNoArg(SKIP_TESTS, "Print list of End2End test suits without running them."); + addOptWithArg(MONKEY_ARG, MONKEY_LONG_ARG, "Which chaos monkey to run. Default: none"); + addOptWithArg(MONKEY_PROPS_LONG_ARG, "The properties file for specifying chaos " + + "monkey properties."); + addOptWithArg(DEFINE_ARG, "Define a property for the test, e.g. -Dkey=value"); } @Override @@ -122,6 +141,38 @@ protected void processOptions(CommandLine cmd) { end2endTestFilter.setPattern(testFilterString); } skipTests = cmd.hasOption(SKIP_TESTS); + if (cmd.hasOption(MONKEY_ARG)) { + monkeyToUse = cmd.getOptionValue(MONKEY_ARG); + monkeyProps = new Properties(); + if (cmd.hasOption(MONKEY_PROPS_LONG_ARG)) { + String monkeyPropsFile = cmd.getOptionValue(MONKEY_PROPS_LONG_ARG); + if (StringUtils.isNotEmpty(monkeyPropsFile)) { + try { + monkeyProps.load(this.getClass().getClassLoader().getResourceAsStream(monkeyPropsFile)); + } catch (IOException e) { + System.err.println(e); + System.exit(EXIT_FAILURE); + } + } + } + } + // XXX: Do we need this? + if (cmd.hasOption(DEFINE_ARG)) { + for (String opt: cmd.getOptionValues(DEFINE_ARG)) { + StringTokenizer tok = new StringTokenizer(opt, "="); + if (!tok.hasMoreTokens()) { + System.err.println("Invalid parameter: " + opt); + continue; + } + String key = tok.nextToken(); + if (!tok.hasMoreTokens()) { + System.err.println("Invalid value for key '" + key + "'"); + continue; + } + String value = tok.nextToken(); + System.setProperty(key, value); + } + } } /** @@ -202,12 +253,61 @@ protected int doWork() throws Exception { for (Class aClass : classes) { System.out.println(" " + aClass); } - if(skipTests) return 0; - - JUnitCore junit = new JUnitCore(); - junit.addListener(new End2EndTestListenter(System.out)); - Result result = junit.run(classes); - return result.wasSuccessful() ? 0 : 1; + if (skipTests) { + return 0; + } + + startAuthChore(); + try { + // Use no chaos monkey unless one was specified on the command line + if (monkeyToUse != null) { + startMonkey(monkeyToUse, monkeyProps); + } + try { + JUnitCore junit = new JUnitCore(); + junit.addListener(new End2EndTestListenter(System.out)); + Result result = junit.run(classes); + return result.wasSuccessful() ? 0 : 1; + } finally { + stopMonkey(); + } + } finally { + stopAuthChore(); + } + } + + protected void startAuthChore() throws IOException { + ScheduledChore authChore = AuthUtil.getAuthChore(conf); + if (authChore != null) { + choreService = new ChoreService("INTEGRATION_TEST"); + choreService.scheduleChore(authChore); + } + } + + protected void stopAuthChore() { + if (choreService != null) { + choreService.shutdown(); + } } + + protected void startMonkey(String monkeyToUse, Properties monkeyProps) throws Exception { + MonkeyFactory factory = MonkeyFactory.getFactory(monkeyToUse); + if (factory == null) { + factory = MonkeyFactory.getFactory(MonkeyFactory.SLOW_DETERMINISTIC); + } + monkey = factory + .setProperties(monkeyProps) + .setUtil(new IntegrationTestingUtility(conf)) + .build(); + monkey.start(); + } + + protected void stopMonkey() throws InterruptedException { + if (monkey != null && !monkey.isStopped()) { + monkey.stop("Ending test"); + monkey.waitForStop(); + } + } + } diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/BaseAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/BaseAction.java new file mode 100644 index 00000000000..d71440c6ddc --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/BaseAction.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.io.IOException; + +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.chaos.actions.Action; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.client.Admin; + +public class BaseAction extends Action { + + public TableName getRandomTable() throws IOException { + return getRandomTable(context.getHBaseIntegrationTestingUtility().getHBaseAdmin()); + } + + public TableName getRandomTable(Admin admin) throws IOException { + return PolicyBasedChaosMonkey.selectRandomItem(admin.listTableNames()); + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactRandomRegionOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactRandomRegionOfTableAction.java new file mode 100644 index 00000000000..34598d02e55 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactRandomRegionOfTableAction.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.util.List; + +import org.apache.commons.lang.math.RandomUtils; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.client.Admin; + +public class CompactRandomRegionOfTableAction extends BaseAction { + + private final int majorRatio; + private final long sleepTime; + + public CompactRandomRegionOfTableAction(float majorRatio) { + this(-1, majorRatio); + } + + public CompactRandomRegionOfTableAction(long sleepTime, float majorRatio) { + this.majorRatio = (int) (100 * majorRatio); + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the compaction if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + boolean major = RandomUtils.nextInt(100) < majorRatio; + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Compact random region of table " + + tableName + ", major=" + major); + List regions = admin.getTableRegions(tableName); + if (regions == null || regions.isEmpty()) { + LOG.info("Table " + tableName + " doesn't have regions to compact"); + return; + } + + HRegionInfo region = PolicyBasedChaosMonkey.selectRandomItem( + regions.toArray(new HRegionInfo[regions.size()])); + + try { + if (major) { + LOG.debug("Major compacting region " + region.getRegionNameAsString()); + admin.majorCompactRegion(region.getRegionName()); + } else { + LOG.debug("Compacting region " + region.getRegionNameAsString()); + admin.compactRegion(region.getRegionName()); + } + } catch (Exception ex) { + LOG.warn("Compaction failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactTableAction.java new file mode 100644 index 00000000000..6ea120f2542 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/CompactTableAction.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import org.apache.commons.lang.math.RandomUtils; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; + +public class CompactTableAction extends BaseAction { + + private final float majorRatio; + private final long sleepTime; + + public CompactTableAction(float majorRatio) { + this(-1, majorRatio); + } + + public CompactTableAction(long sleepTime, float majorRatio) { + this.sleepTime = sleepTime; + this.majorRatio = majorRatio; + } + + @Override + public void perform() throws Exception { + // Don't try the compaction if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + boolean major = RandomUtils.nextInt(100) < majorRatio; + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Compact table " + tableName + ", major=" + major); + try { + if (major) { + admin.majorCompact(tableName); + } else { + admin.compact(tableName); + } + } catch (Exception ex) { + LOG.warn("Compaction failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushRandomRegionOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushRandomRegionOfTableAction.java new file mode 100644 index 00000000000..cd794f9ebcc --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushRandomRegionOfTableAction.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.util.List; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.client.Admin; + +public class FlushRandomRegionOfTableAction extends BaseAction { + + private final long sleepTime; + + public FlushRandomRegionOfTableAction() { + this(-1); + } + + public FlushRandomRegionOfTableAction(long sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the flush if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Flush random region of table " + tableName); + List regions = admin.getTableRegions(tableName); + if (regions == null || regions.isEmpty()) { + LOG.info("Table " + tableName + " doesn't have regions to flush"); + return; + } + + HRegionInfo region = PolicyBasedChaosMonkey.selectRandomItem( + regions.toArray(new HRegionInfo[regions.size()])); + LOG.debug("Flushing region " + region.getRegionNameAsString()); + try { + admin.flushRegion(region.getRegionName()); + } catch (Exception ex) { + LOG.warn("Flush failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushTableAction.java new file mode 100644 index 00000000000..2a55c574fc6 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/FlushTableAction.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; + +public class FlushTableAction extends BaseAction { + + private final long sleepTime; + + public FlushTableAction() { + this(-1); + } + + public FlushTableAction(long sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the flush if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Flush table " + tableName); + try { + admin.flush(tableName); + } catch (Exception ex) { + LOG.warn("Flush failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MergeRandomAdjacentRegionsOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MergeRandomAdjacentRegionsOfTableAction.java new file mode 100644 index 00000000000..cc5415cda83 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MergeRandomAdjacentRegionsOfTableAction.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.util.List; + +import org.apache.commons.lang.math.RandomUtils; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; + +public class MergeRandomAdjacentRegionsOfTableAction extends BaseAction { + + private final long sleepTime; + + public MergeRandomAdjacentRegionsOfTableAction() { + this(-1); + } + + public MergeRandomAdjacentRegionsOfTableAction(long sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the merge if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Merge random adjacent regions of table " + tableName); + List regions = admin.getTableRegions(tableName); + if (regions == null || regions.size() < 2) { + LOG.info("Table " + tableName + " doesn't have enough regions to merge"); + return; + } + + int i = RandomUtils.nextInt(regions.size() - 1); + HRegionInfo a = regions.get(i++); + HRegionInfo b = regions.get(i); + LOG.debug("Merging " + a.getRegionNameAsString() + " and " + b.getRegionNameAsString()); + try { + admin.mergeRegions(a.getEncodedNameAsBytes(), b.getEncodedNameAsBytes(), false); + } catch (Exception ex) { + LOG.warn("Merge failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRandomRegionOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRandomRegionOfTableAction.java new file mode 100644 index 00000000000..d381bfb33ff --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRandomRegionOfTableAction.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.util.List; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.client.Admin; + +public class MoveRandomRegionOfTableAction extends BaseAction { + + private final long sleepTime; + + public MoveRandomRegionOfTableAction() { + this(-1); + } + + public MoveRandomRegionOfTableAction(long sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the move if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Move random region of table " + tableName); + List regions = admin.getTableRegions(tableName); + if (regions == null || regions.isEmpty()) { + LOG.info("Table " + tableName + " doesn't have regions to move"); + return; + } + + HRegionInfo region = PolicyBasedChaosMonkey.selectRandomItem( + regions.toArray(new HRegionInfo[regions.size()])); + LOG.debug("Unassigning region " + region.getRegionNameAsString()); + admin.unassign(region.getRegionName(), false); + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRegionsOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRegionsOfTableAction.java new file mode 100644 index 00000000000..ed23175f06e --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/MoveRegionsOfTableAction.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang.math.RandomUtils; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.chaos.factories.MonkeyConstants; +import org.apache.hadoop.hbase.client.Admin; +import org.apache.hadoop.hbase.util.Bytes; + +public class MoveRegionsOfTableAction extends BaseAction { + + private final long sleepTime; + private final long maxTime; + + public MoveRegionsOfTableAction() { + this(-1, MonkeyConstants.DEFAULT_MOVE_REGIONS_MAX_TIME); + } + + public MoveRegionsOfTableAction(long sleepTime, long maxSleepTime) { + this.sleepTime = sleepTime; + this.maxTime = maxSleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the move if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + + Collection serversList = admin.getClusterStatus().getServers(); + ServerName[] servers = serversList.toArray(new ServerName[serversList.size()]); + + LOG.info("Performing action: Move regions of table " + tableName); + List regions = admin.getTableRegions(tableName); + if (regions == null || regions.isEmpty()) { + LOG.info("Table " + tableName + " doesn't have regions to move"); + return; + } + + Collections.shuffle(regions); + + long start = System.currentTimeMillis(); + for (HRegionInfo regionInfo: regions) { + + // Don't try the move if we're stopping + if (context.isStopping()) { + return; + } + + try { + String destServerName = + servers[RandomUtils.nextInt(servers.length)].getServerName(); + LOG.debug("Moving " + regionInfo.getRegionNameAsString() + " to " + destServerName); + admin.move(regionInfo.getEncodedNameAsBytes(), Bytes.toBytes(destServerName)); + } catch (Exception ex) { + LOG.warn("Move failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + // put a limit on max num regions. Otherwise, this won't finish + // with a sleep time of 10sec, 100 regions will finish in 16min + if (System.currentTimeMillis() - start > maxTime) { + break; + } + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SnapshotTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SnapshotTableAction.java new file mode 100644 index 00000000000..63fac265eab --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SnapshotTableAction.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; + +public class SnapshotTableAction extends BaseAction { + + private final long sleepTime; + + public SnapshotTableAction() { + this(-1); + } + + public SnapshotTableAction(int sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the snapshot if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + String snapshotName = tableName + "-it-" + System.currentTimeMillis(); + + LOG.info("Performing action: Snapshot table " + tableName); + admin.snapshot(snapshotName, tableName); + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitAllRegionOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitAllRegionOfTableAction.java new file mode 100644 index 00000000000..f3020ca29ce --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitAllRegionOfTableAction.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.io.IOException; +import java.util.concurrent.ThreadLocalRandom; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; + +public class SplitAllRegionOfTableAction extends BaseAction { + + private static final int DEFAULT_MAX_SPLITS = 3; + private static final String MAX_SPLIT_KEY = "hbase.chaosmonkey.action.maxFullTableSplits"; + + private long sleepTime; + private int maxFullTableSplits = DEFAULT_MAX_SPLITS; + private int splits; + + public SplitAllRegionOfTableAction() { + this(-1); + } + + public SplitAllRegionOfTableAction(long sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void init(ActionContext context) throws IOException { + super.init(context); + this.maxFullTableSplits = getConf().getInt(MAX_SPLIT_KEY, DEFAULT_MAX_SPLITS); + } + + @Override + public void perform() throws Exception { + // Don't try the split if we're stopping + if (context.isStopping()) { + return; + } + + // Don't always split. This should allow splitting of a full table later in the run + if (ThreadLocalRandom.current().nextDouble() + < (((double) splits) / ((double) maxFullTableSplits)) / ((double) 2)) { + splits++; + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + LOG.info("Performing action: Split all regions of " + tableName); + admin.split(tableName); + } else { + LOG.info("Skipping split of all regions."); + } + + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitRandomRegionOfTableAction.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitRandomRegionOfTableAction.java new file mode 100644 index 00000000000..1bca6678779 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/actions/SplitRandomRegionOfTableAction.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.actions; + +import java.util.List; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.client.Admin; + +public class SplitRandomRegionOfTableAction extends BaseAction { + + private final long sleepTime; + + public SplitRandomRegionOfTableAction() { + this(-1); + } + + public SplitRandomRegionOfTableAction(int sleepTime) { + this.sleepTime = sleepTime; + } + + @Override + public void perform() throws Exception { + // Don't try the split if we're stopping + if (context.isStopping()) { + return; + } + + HBaseTestingUtility util = context.getHBaseIntegrationTestingUtility(); + Admin admin = util.getHBaseAdmin(); + TableName tableName = getRandomTable(admin); + + LOG.info("Performing action: Split random region of table " + tableName); + List regions = admin.getTableRegions(tableName); + if (regions == null || regions.isEmpty()) { + LOG.info("Table " + tableName + " doesn't have regions to split"); + return; + } + + HRegionInfo region = PolicyBasedChaosMonkey.selectRandomItem( + regions.toArray(new HRegionInfo[regions.size()])); + LOG.debug("Splitting region " + region.getRegionNameAsString()); + try { + admin.splitRegion(region.getRegionName()); + } catch (Exception ex) { + LOG.warn("Split failed, might be caused by other chaos: " + ex.getMessage()); + } + if (sleepTime > 0) { + Thread.sleep(sleepTime); + } + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/CalmMonkeyFactory.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/CalmMonkeyFactory.java new file mode 100644 index 00000000000..bb2199d76f6 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/CalmMonkeyFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.factories; + +import org.apache.hadoop.hbase.chaos.monkies.CalmChaosMonkey; +import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey; + +public class CalmMonkeyFactory extends MonkeyFactory { + + @Override + public ChaosMonkey build() { + return new CalmChaosMonkey(); + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/MonkeyFactory.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/MonkeyFactory.java new file mode 100644 index 00000000000..88e1b297843 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/MonkeyFactory.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.factories; + +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.IntegrationTestingUtility; +import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey; +import org.apache.hadoop.hbase.util.ReflectionUtils; + +import com.google.common.collect.ImmutableMap; + +/** + * Phoenix specific monkey factory. Supports a set of chaos monkeys that use + * hbase-it chaos actions but in combinations that make sense for Phoenix tests. + *

For example, Phoenix utilizes multiple tables for global secondary indexes + * so we cannot not use monkeys that can protect only a single table while + * deleting others randomly. Nor can we use monkeys that mutate schema randomly. + * When building our monkeys we avoid such actions. + */ +public abstract class MonkeyFactory { + + private static final Log LOG = LogFactory.getLog(MonkeyFactory.class); + + public static final String CALM = "calm"; + public static final String SLOW_DETERMINISTIC = "slowDeterministic"; + public static final String SERVER_KILLING = "serverKilling"; + public static final String NO_KILL = "noKill"; + + protected Properties properties; + protected IntegrationTestingUtility util; + + private static Map FACTORIES = ImmutableMap.builder() + .put(CALM, new CalmMonkeyFactory()) + .put(SLOW_DETERMINISTIC, new SlowDeterministicMonkeyFactory()) + .put(SERVER_KILLING, new ServerKillingMonkeyFactory()) + .put(NO_KILL, new NoKillMonkeyFactory()) + .build(); + + public abstract ChaosMonkey build(); + + public MonkeyFactory setProperties(Properties props) { + this.properties = props; + return this; + } + + public MonkeyFactory setUtil(IntegrationTestingUtility util) { + this.util = util; + return this; + } + + public static MonkeyFactory getFactory(String factoryName) { + MonkeyFactory fact = FACTORIES.get(factoryName); + if (fact == null && factoryName != null && !factoryName.isEmpty()) { + Class klass = null; + try { + klass = Class.forName(factoryName); + if (klass != null) { + fact = (MonkeyFactory) ReflectionUtils.newInstance(klass); + } + } catch (Exception e) { + LOG.error("Error trying to create " + factoryName + " could not load it by class name"); + return null; + } + } + return fact; + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/NoKillMonkeyFactory.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/NoKillMonkeyFactory.java new file mode 100644 index 00000000000..1db010bde21 --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/NoKillMonkeyFactory.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.factories; + +import org.apache.hadoop.hbase.chaos.actions.Action; +import org.apache.hadoop.hbase.chaos.actions.DumpClusterStatusAction; +import org.apache.hadoop.hbase.chaos.factories.MonkeyConstants; +import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.chaos.policies.CompositeSequentialPolicy; +import org.apache.hadoop.hbase.chaos.policies.DoActionsOncePolicy; +import org.apache.hadoop.hbase.chaos.policies.PeriodicRandomActionPolicy; +import org.apache.phoenix.end2end.chaos.actions.CompactRandomRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.CompactTableAction; +import org.apache.phoenix.end2end.chaos.actions.FlushRandomRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.FlushTableAction; +import org.apache.phoenix.end2end.chaos.actions.MergeRandomAdjacentRegionsOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.MoveRandomRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.MoveRegionsOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.SnapshotTableAction; +import org.apache.phoenix.end2end.chaos.actions.SplitAllRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.SplitRandomRegionOfTableAction; + +public class NoKillMonkeyFactory extends MonkeyFactory { + + private long action1Period; + private long action2Period; + private long action3Period; + private long action4Period; + private long moveRegionsMaxTime; + private long moveRegionsSleepTime; + private long moveRandomRegionSleepTime; + private float compactTableRatio; + private float compactRandomRegionRatio; + + @Override + public ChaosMonkey build() { + + loadProperties(); + + // Actions such as compact/flush a table/region, + // move one region around. They are not so destructive, + // can be executed more frequently. + Action[] actions1 = new Action[] { + new CompactTableAction(compactTableRatio), + new CompactRandomRegionOfTableAction(compactRandomRegionRatio), + new FlushTableAction(), + new FlushRandomRegionOfTableAction(), + new MoveRandomRegionOfTableAction() + }; + + // Actions such as split/merge/snapshot. + Action[] actions2 = new Action[] { + new SplitRandomRegionOfTableAction(), + new MergeRandomAdjacentRegionsOfTableAction(), + new SnapshotTableAction(), + }; + + // Destructive actions to mess things around. + Action[] actions3 = new Action[] { + new MoveRegionsOfTableAction(moveRegionsSleepTime, moveRegionsMaxTime), + new MoveRandomRegionOfTableAction(moveRandomRegionSleepTime), + new SplitAllRegionOfTableAction(), + }; + + // Action to log more info for debugging + Action[] actions4 = new Action[] { + new DumpClusterStatusAction() + }; + + return new PolicyBasedChaosMonkey(util, + new PeriodicRandomActionPolicy(action1Period, actions1), + new PeriodicRandomActionPolicy(action2Period, actions2), + new CompositeSequentialPolicy( + new DoActionsOncePolicy(action3Period, actions3), + new PeriodicRandomActionPolicy(action3Period, actions3)), + new PeriodicRandomActionPolicy(action4Period, actions4)); + } + + private void loadProperties() { + action1Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.PERIODIC_ACTION1_PERIOD, + MonkeyConstants.DEFAULT_PERIODIC_ACTION1_PERIOD + "")); + action2Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.PERIODIC_ACTION2_PERIOD, + MonkeyConstants.DEFAULT_PERIODIC_ACTION2_PERIOD + "")); + action3Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.COMPOSITE_ACTION3_PERIOD, + MonkeyConstants.DEFAULT_COMPOSITE_ACTION3_PERIOD + "")); + action4Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.PERIODIC_ACTION4_PERIOD, + MonkeyConstants.DEFAULT_PERIODIC_ACTION4_PERIOD + "")); + moveRegionsMaxTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.MOVE_REGIONS_MAX_TIME, + MonkeyConstants.DEFAULT_MOVE_REGIONS_MAX_TIME + "")); + moveRegionsSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.MOVE_REGIONS_SLEEP_TIME, + MonkeyConstants.DEFAULT_MOVE_REGIONS_SLEEP_TIME + "")); + moveRandomRegionSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.MOVE_RANDOM_REGION_SLEEP_TIME, + MonkeyConstants.DEFAULT_MOVE_RANDOM_REGION_SLEEP_TIME + "")); + compactTableRatio = Float.parseFloat(this.properties.getProperty( + MonkeyConstants.COMPACT_TABLE_ACTION_RATIO, + MonkeyConstants.DEFAULT_COMPACT_TABLE_ACTION_RATIO + "")); + compactRandomRegionRatio = Float.parseFloat(this.properties.getProperty( + MonkeyConstants.COMPACT_RANDOM_REGION_RATIO, + MonkeyConstants.DEFAULT_COMPACT_RANDOM_REGION_RATIO + "")); + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/ServerKillingMonkeyFactory.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/ServerKillingMonkeyFactory.java new file mode 100644 index 00000000000..520c2db473c --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/ServerKillingMonkeyFactory.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.factories; + +import org.apache.hadoop.hbase.chaos.actions.Action; +import org.apache.hadoop.hbase.chaos.actions.DumpClusterStatusAction; +import org.apache.hadoop.hbase.chaos.actions.ForceBalancerAction; +import org.apache.hadoop.hbase.chaos.actions.RestartActiveMasterAction; +import org.apache.hadoop.hbase.chaos.actions.RestartRandomRsAction; +import org.apache.hadoop.hbase.chaos.actions.RestartRsHoldingMetaAction; +import org.apache.hadoop.hbase.chaos.factories.MonkeyConstants; +import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.chaos.policies.CompositeSequentialPolicy; +import org.apache.hadoop.hbase.chaos.policies.DoActionsOncePolicy; +import org.apache.hadoop.hbase.chaos.policies.PeriodicRandomActionPolicy; + +public class ServerKillingMonkeyFactory extends MonkeyFactory { + + private long restartRandomRSSleepTime; + private long restartActiveMasterSleepTime; + private long restartRsHoldingMetaSleepTime; + + @Override + public ChaosMonkey build() { + + loadProperties(); + + // Destructive actions to mess things around. Cannot run batch restart + Action[] actions1 = new Action[] { + new RestartRandomRsAction(restartRandomRSSleepTime), + new RestartActiveMasterAction(restartActiveMasterSleepTime), + new RestartRsHoldingMetaAction(restartRsHoldingMetaSleepTime), + new ForceBalancerAction() + }; + + // Action to log more info for debugging + Action[] actions2 = new Action[] { + new DumpClusterStatusAction() + }; + + return new PolicyBasedChaosMonkey(util, + new CompositeSequentialPolicy( + new DoActionsOncePolicy(60 * 1000, actions1), + new PeriodicRandomActionPolicy(60 * 1000, actions1)), + new PeriodicRandomActionPolicy(60 * 1000, actions2)); + } + + private void loadProperties() { + restartRandomRSSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.RESTART_RANDOM_RS_SLEEP_TIME, + MonkeyConstants.DEFAULT_RESTART_RANDOM_RS_SLEEP_TIME + "")); + restartActiveMasterSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.RESTART_ACTIVE_MASTER_SLEEP_TIME, + MonkeyConstants.DEFAULT_RESTART_ACTIVE_MASTER_SLEEP_TIME + "")); + restartRsHoldingMetaSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.RESTART_RS_HOLDING_META_SLEEP_TIME, + MonkeyConstants.DEFAULT_RESTART_RS_HOLDING_META_SLEEP_TIME + "")); + } + +} diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/SlowDeterministicMonkeyFactory.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/SlowDeterministicMonkeyFactory.java new file mode 100644 index 00000000000..3806a33676c --- /dev/null +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/chaos/factories/SlowDeterministicMonkeyFactory.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.end2end.chaos.factories; + +import org.apache.hadoop.hbase.chaos.actions.Action; +import org.apache.hadoop.hbase.chaos.actions.BatchRestartRsAction; +import org.apache.hadoop.hbase.chaos.actions.DumpClusterStatusAction; +import org.apache.hadoop.hbase.chaos.actions.RestartActiveMasterAction; +import org.apache.hadoop.hbase.chaos.actions.RestartRandomRsAction; +import org.apache.hadoop.hbase.chaos.actions.RestartRsHoldingMetaAction; +import org.apache.hadoop.hbase.chaos.actions.RollingBatchRestartRsAction; +import org.apache.hadoop.hbase.chaos.factories.MonkeyConstants; +import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey; +import org.apache.hadoop.hbase.chaos.monkies.PolicyBasedChaosMonkey; +import org.apache.hadoop.hbase.chaos.policies.CompositeSequentialPolicy; +import org.apache.hadoop.hbase.chaos.policies.DoActionsOncePolicy; +import org.apache.hadoop.hbase.chaos.policies.PeriodicRandomActionPolicy; +import org.apache.phoenix.end2end.chaos.actions.CompactRandomRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.CompactTableAction; +import org.apache.phoenix.end2end.chaos.actions.FlushRandomRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.FlushTableAction; +import org.apache.phoenix.end2end.chaos.actions.MergeRandomAdjacentRegionsOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.MoveRandomRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.MoveRegionsOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.SnapshotTableAction; +import org.apache.phoenix.end2end.chaos.actions.SplitAllRegionOfTableAction; +import org.apache.phoenix.end2end.chaos.actions.SplitRandomRegionOfTableAction; + +public class SlowDeterministicMonkeyFactory extends MonkeyFactory { + + private long action1Period; + private long action2Period; + private long action3Period; + private long action4Period; + private long moveRegionsMaxTime; + private long moveRegionsSleepTime; + private long moveRandomRegionSleepTime; + private long restartRandomRSSleepTime; + private long batchRestartRSSleepTime; + private float batchRestartRSRatio; + private long restartActiveMasterSleepTime; + private long rollingBatchRestartRSSleepTime; + private float rollingBatchRestartRSRatio; + private long restartRsHoldingMetaSleepTime; + private float compactTableRatio; + private float compactRandomRegionRatio; + + @Override + public ChaosMonkey build() { + + loadProperties(); + + // Actions such as compact/flush a table/region, + // move one region around. They are not so destructive, + // can be executed more frequently. + Action[] actions1 = new Action[] { + new CompactTableAction(compactTableRatio), + new CompactRandomRegionOfTableAction(compactRandomRegionRatio), + new FlushTableAction(), + new FlushRandomRegionOfTableAction(), + new MoveRandomRegionOfTableAction() + }; + + // Actions such as split/merge/snapshot. + // They should not cause data loss, or unreliability + // such as region stuck in transition. + Action[] actions2 = new Action[] { + new SplitRandomRegionOfTableAction(), + new MergeRandomAdjacentRegionsOfTableAction(), + new SnapshotTableAction(), + }; + + // Destructive actions to mess things around. + Action[] actions3 = new Action[] { + new MoveRegionsOfTableAction(moveRegionsSleepTime, moveRegionsMaxTime), + new MoveRandomRegionOfTableAction(moveRandomRegionSleepTime), + new RestartRandomRsAction(restartRandomRSSleepTime), + new BatchRestartRsAction(batchRestartRSSleepTime, batchRestartRSRatio), + new RestartActiveMasterAction(restartActiveMasterSleepTime), + new RollingBatchRestartRsAction(rollingBatchRestartRSSleepTime, + rollingBatchRestartRSRatio), + new RestartRsHoldingMetaAction(restartRsHoldingMetaSleepTime), + new SplitAllRegionOfTableAction(), + }; + + // Action to log more info for debugging + Action[] actions4 = new Action[] { + new DumpClusterStatusAction() + }; + + return new PolicyBasedChaosMonkey(util, + new PeriodicRandomActionPolicy(action1Period, actions1), + new PeriodicRandomActionPolicy(action2Period, actions2), + new CompositeSequentialPolicy( + new DoActionsOncePolicy(action3Period, actions3), + new PeriodicRandomActionPolicy(action3Period, actions3)), + new PeriodicRandomActionPolicy(action4Period, actions4)); + } + + private void loadProperties() { + action1Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.PERIODIC_ACTION1_PERIOD, + MonkeyConstants.DEFAULT_PERIODIC_ACTION1_PERIOD + "")); + action2Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.PERIODIC_ACTION2_PERIOD, + MonkeyConstants.DEFAULT_PERIODIC_ACTION2_PERIOD + "")); + action3Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.COMPOSITE_ACTION3_PERIOD, + MonkeyConstants.DEFAULT_COMPOSITE_ACTION3_PERIOD + "")); + action4Period = Long.parseLong(this.properties.getProperty( + MonkeyConstants.PERIODIC_ACTION4_PERIOD, + MonkeyConstants.DEFAULT_PERIODIC_ACTION4_PERIOD + "")); + moveRegionsMaxTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.MOVE_REGIONS_MAX_TIME, + MonkeyConstants.DEFAULT_MOVE_REGIONS_MAX_TIME + "")); + moveRegionsSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.MOVE_REGIONS_SLEEP_TIME, + MonkeyConstants.DEFAULT_MOVE_REGIONS_SLEEP_TIME + "")); + moveRandomRegionSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.MOVE_RANDOM_REGION_SLEEP_TIME, + MonkeyConstants.DEFAULT_MOVE_RANDOM_REGION_SLEEP_TIME + "")); + restartRandomRSSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.RESTART_RANDOM_RS_SLEEP_TIME, + MonkeyConstants.DEFAULT_RESTART_RANDOM_RS_SLEEP_TIME + "")); + batchRestartRSSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.BATCH_RESTART_RS_SLEEP_TIME, + MonkeyConstants.DEFAULT_BATCH_RESTART_RS_SLEEP_TIME + "")); + batchRestartRSRatio = Float.parseFloat(this.properties.getProperty( + MonkeyConstants.BATCH_RESTART_RS_RATIO, + MonkeyConstants.DEFAULT_BATCH_RESTART_RS_RATIO + "")); + restartActiveMasterSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.RESTART_ACTIVE_MASTER_SLEEP_TIME, + MonkeyConstants.DEFAULT_RESTART_ACTIVE_MASTER_SLEEP_TIME + "")); + rollingBatchRestartRSSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.ROLLING_BATCH_RESTART_RS_SLEEP_TIME, + MonkeyConstants.DEFAULT_ROLLING_BATCH_RESTART_RS_SLEEP_TIME + "")); + rollingBatchRestartRSRatio = Float.parseFloat(this.properties.getProperty( + MonkeyConstants.ROLLING_BATCH_RESTART_RS_RATIO, + MonkeyConstants.DEFAULT_ROLLING_BATCH_RESTART_RS_RATIO + "")); + restartRsHoldingMetaSleepTime = Long.parseLong(this.properties.getProperty( + MonkeyConstants.RESTART_RS_HOLDING_META_SLEEP_TIME, + MonkeyConstants.DEFAULT_RESTART_RS_HOLDING_META_SLEEP_TIME + "")); + compactTableRatio = Float.parseFloat(this.properties.getProperty( + MonkeyConstants.COMPACT_TABLE_ACTION_RATIO, + MonkeyConstants.DEFAULT_COMPACT_TABLE_ACTION_RATIO + "")); + compactRandomRegionRatio = Float.parseFloat(this.properties.getProperty( + MonkeyConstants.COMPACT_RANDOM_REGION_RATIO, + MonkeyConstants.DEFAULT_COMPACT_RANDOM_REGION_RATIO + "")); + } + +} diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ReadOnlyProps.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ReadOnlyProps.java index d6950a20ca4..05b89ac8229 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/ReadOnlyProps.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ReadOnlyProps.java @@ -33,7 +33,6 @@ import com.google.common.base.Objects; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.Maps; /** @@ -320,4 +319,18 @@ public ReadOnlyProps addAll(Properties overrides) { } return this; } + + /** + * Converts these read-only properties into a java.util.Properties object. + * @return Java properties + */ + public Properties toProperties() { + Properties props = new Properties(); + Iterator> i = iterator(); + while (i.hasNext()) { + Entry e = i.next(); + props.put(e.getKey(), e.getValue()); + } + return props; + } }