diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 32f3e672185..31575993edb 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -73,11 +73,15 @@
commons-math3
3.3
-
- org.apache.phoenix.thirdparty
- phoenix-shaded-commons-cli
-
-
+
+ com.google.code.gson
+ gson
+ 2.8.6
+
+
+ org.apache.phoenix.thirdparty
+ phoenix-shaded-commons-cli
+
junit
@@ -133,7 +137,7 @@
- src/main/resources
+ src/it/resources
config
@@ -221,7 +225,7 @@
org.apache.phoenix:phoenix-pherf
- com.google.guava:guava
+ org.apache.phoenix.thirdparty:phoenix-shaded-guava
com.googlecode.java-diff-utils:diffutils
org.apache.commons:commons-lang3
org.apache.commons:commons-math3
@@ -230,6 +234,8 @@
org.apache.commons:commons-csv
commons-lang:commons-lang
commons-io:commons-io
+ com.google.code.gson:gson
+ com.lmax:disruptor
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/PherfMainIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/PherfMainIT.java
index 57aaae14e44..c71fda5a1f2 100644
--- a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/PherfMainIT.java
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/PherfMainIT.java
@@ -23,6 +23,7 @@
import org.apache.phoenix.pherf.result.ResultValue;
import org.apache.phoenix.pherf.result.file.ResultFileDetails;
import org.apache.phoenix.pherf.result.impl.CSVFileResultHandler;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/ResultBaseTestIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/ResultBaseTestIT.java
index fe1f2ea6f88..75d6f6b1063 100644
--- a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/ResultBaseTestIT.java
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/ResultBaseTestIT.java
@@ -25,6 +25,7 @@
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
import org.apache.phoenix.pherf.configuration.XMLConfigParser;
import org.apache.phoenix.pherf.result.ResultUtil;
import org.apache.phoenix.pherf.schema.SchemaReader;
@@ -37,9 +38,9 @@
import org.junit.experimental.categories.Category;
@Category(NeedsOwnMiniClusterTest.class)
-public class ResultBaseTestIT extends BaseTest {
- protected static final String matcherScenario = ".*scenario/.*test.*xml";
- protected static final String matcherSchema = ".*datamodel/.*test.*sql";
+public class ResultBaseTestIT extends ParallelStatsDisabledIT {
+ protected static final String matcherScenario = ".*scenario/.*test_scenario.*xml";
+ protected static final String matcherSchema = ".*datamodel/.*test_schema.*sql";
protected static PhoenixUtil util = PhoenixUtil.create(true);
protected static Properties properties;
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/SchemaReaderIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/SchemaReaderIT.java
index 901c92f9f4c..c5a93fe4b8a 100644
--- a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/SchemaReaderIT.java
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/SchemaReaderIT.java
@@ -78,7 +78,7 @@ public void testSchemaReader() {
private void assertApplySchemaTest() {
try {
util.setZookeeper("localhost");
- SchemaReader reader = new SchemaReader(util, ".*datamodel/.*test.*sql");
+ SchemaReader reader = new SchemaReader(util, ".*datamodel/.*test_schema.*sql");
List resources = new ArrayList<>(reader.getResourceList());
assertTrue("Could not pull list of schema files.", resources.size() > 0);
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantOperationBaseIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantOperationBaseIT.java
new file mode 100644
index 00000000000..bcdbdcaef35
--- /dev/null
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantOperationBaseIT.java
@@ -0,0 +1,79 @@
+/*
+ * 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.pherf.workload.mt.tenantoperation;
+
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.pherf.PherfConstants;
+import org.apache.phoenix.pherf.XMLConfigParserTest;
+import org.apache.phoenix.pherf.configuration.DataModel;
+import org.apache.phoenix.pherf.configuration.XMLConfigParser;
+import org.apache.phoenix.pherf.schema.SchemaReader;
+import org.apache.phoenix.pherf.util.PhoenixUtil;
+import org.junit.BeforeClass;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class MultiTenantOperationBaseIT extends ParallelStatsDisabledIT {
+ enum TestOperationGroup {
+ upsertOp, queryOp1, queryOp2, idleOp, udfOp
+ }
+
+ static enum TestTenantGroup {
+ tg1, tg2, tg3
+ }
+ protected static final String matcherScenario = ".*scenario/.*test_mt_workload.*xml";
+ protected static final String matcherSchema = ".*datamodel/.*test_schema_mt*.*sql";
+
+ protected static PhoenixUtil util = PhoenixUtil.create(true);
+ protected static Properties properties;
+ protected static SchemaReader reader;
+ protected static XMLConfigParser parser;
+ protected static List resources;
+
+ @BeforeClass public static synchronized void setUp() throws Exception {
+ PherfConstants constants = PherfConstants.create();
+ properties = constants.getProperties(PherfConstants.PHERF_PROPERTIES, false);
+
+ PhoenixUtil.setZookeeper("localhost");
+ reader = new SchemaReader(util, matcherSchema);
+ parser = new XMLConfigParser(matcherScenario);
+ reader.applySchema();
+ resources = new ArrayList<>(reader.getResourceList());
+
+ assertTrue("Could not pull list of schema files.", resources.size() > 0);
+ assertNotNull("Could not read schema file.", reader.resourceToString(resources.get(0)));
+
+ }
+
+ public DataModel readTestDataModel(String resourceName) throws Exception {
+ URL scenarioUrl = XMLConfigParserTest.class.getResource(resourceName);
+ assertNotNull(scenarioUrl);
+ Path p = Paths.get(scenarioUrl.toURI());
+ return XMLConfigParser.readDataModel(p);
+ }
+
+}
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationIT.java
new file mode 100644
index 00000000000..737080a9632
--- /dev/null
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationIT.java
@@ -0,0 +1,112 @@
+/*
+ * 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.pherf.workload.mt.tenantoperation;
+
+import org.apache.phoenix.pherf.configuration.DataModel;
+import org.apache.phoenix.pherf.configuration.LoadProfile;
+import org.apache.phoenix.pherf.configuration.Scenario;
+import org.apache.phoenix.pherf.util.PhoenixUtil;
+import org.apache.phoenix.pherf.workload.mt.Operation;
+import org.apache.phoenix.pherf.workload.mt.OperationStats;
+import org.apache.phoenix.thirdparty.com.google.common.base.Function;
+import org.apache.phoenix.thirdparty.com.google.common.base.Supplier;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests focused on tenant operations and their validations
+ */
+public class TenantOperationIT extends MultiTenantOperationBaseIT {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TenantOperationIT.class);
+
+ @Test
+ public void testVariousOperations() throws Exception {
+ int numTenantGroups = 3;
+ int numOpGroups = 5;
+ int numRuns = 10;
+ int numOperations = 10;
+
+ PhoenixUtil pUtil = PhoenixUtil.create();
+ DataModel model = readTestDataModel("/scenario/test_mt_workload.xml");
+ for (Scenario scenario : model.getScenarios()) {
+ LOGGER.debug(String.format("Testing %s", scenario.getName()));
+ LoadProfile loadProfile = scenario.getLoadProfile();
+ assertEquals("tenant group size is not as expected: ",
+ numTenantGroups, loadProfile.getTenantDistribution().size());
+ assertEquals("operation group size is not as expected: ",
+ numOpGroups, loadProfile.getOpDistribution().size());
+
+ TenantOperationFactory opFactory = new TenantOperationFactory(pUtil, model, scenario);
+ TenantOperationEventGenerator evtGen = new TenantOperationEventGenerator(
+ opFactory.getOperations(), model, scenario);
+
+ assertEquals("operation group size from the factory is not as expected: ",
+ numOpGroups, opFactory.getOperations().size());
+
+ int numRowsInserted = 0;
+ for (int i = 0; i < numRuns; i++) {
+ int ops = numOperations;
+ loadProfile.setNumOperations(ops);
+ while (ops-- > 0) {
+ TenantOperationInfo info = evtGen.next();
+ Supplier> opSupplier =
+ opFactory.getOperationSupplier(info);
+ OperationStats stats = opSupplier.get().apply(info);
+ LOGGER.info(pUtil.getGSON().toJson(stats));
+ if (info.getOperation().getType() == Operation.OperationType.PRE_RUN) continue;
+ switch (TestOperationGroup.valueOf(info.getOperationGroupId())) {
+ case upsertOp:
+ assertTrue(opSupplier.getClass()
+ .isAssignableFrom(UpsertOperationSupplier.class));
+ numRowsInserted += stats.getRowCount();
+ break;
+ case queryOp1:
+ case queryOp2:
+ assertTrue(opFactory.getOperationSupplier(info).getClass()
+ .isAssignableFrom(QueryOperationSupplier.class));
+
+ // expected row count == num rows inserted
+ assertEquals(numRowsInserted, stats.getRowCount());
+ break;
+ case idleOp:
+ assertTrue(opFactory.getOperationSupplier(info).getClass()
+ .isAssignableFrom(IdleTimeOperationSupplier.class));
+ assertEquals(0, stats.getRowCount());
+ // expected think time (no-op) to be ~50ms
+ assertTrue(40 < stats.getDurationInMs() && stats.getDurationInMs() < 60);
+ break;
+ case udfOp:
+ assertTrue(opFactory.getOperationSupplier(info).getClass()
+ .isAssignableFrom(UserDefinedOperationSupplier.class));
+ assertEquals(0, stats.getRowCount());
+ break;
+ default:
+ Assert.fail();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationWorkloadIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationWorkloadIT.java
new file mode 100644
index 00000000000..c6d4dfdf201
--- /dev/null
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationWorkloadIT.java
@@ -0,0 +1,166 @@
+/*
+ * 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.pherf.workload.mt.tenantoperation;
+
+import com.clearspring.analytics.util.Lists;
+import org.apache.phoenix.thirdparty.com.google.common.base.Function;
+import org.apache.phoenix.thirdparty.com.google.common.base.Supplier;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Maps;
+import com.lmax.disruptor.LifecycleAware;
+import com.lmax.disruptor.WorkHandler;
+import org.apache.phoenix.pherf.configuration.DataModel;
+import org.apache.phoenix.pherf.configuration.Scenario;
+import org.apache.phoenix.pherf.util.PhoenixUtil;
+import org.apache.phoenix.pherf.workload.Workload;
+import org.apache.phoenix.pherf.workload.mt.OperationStats;
+import org.apache.phoenix.pherf.workload.mt.tenantoperation.TenantOperationWorkload.TenantOperationEvent;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests focused on tenant operation workloads {@link TenantOperationWorkload}
+ * and workload handlers {@link WorkHandler}
+ */
+public class TenantOperationWorkloadIT extends MultiTenantOperationBaseIT {
+
+ private static class EventCountingWorkHandler implements
+ WorkHandler, LifecycleAware {
+ private final String handlerId;
+ private final TenantOperationFactory tenantOperationFactory;
+ private static final Logger LOGGER = LoggerFactory.getLogger(EventCountingWorkHandler.class);
+ private final Map latches;
+ public EventCountingWorkHandler(TenantOperationFactory tenantOperationFactory,
+ String handlerId, Map latches) {
+ this.handlerId = handlerId;
+ this.tenantOperationFactory = tenantOperationFactory;
+ this.latches = latches;
+ }
+
+ @Override public void onStart() {}
+
+ @Override public void onShutdown() {}
+
+ @Override public void onEvent(TenantOperationEvent event)
+ throws Exception {
+ TenantOperationInfo input = event.getTenantOperationInfo();
+ Supplier>
+ opSupplier = tenantOperationFactory.getOperationSupplier(input);
+ OperationStats stats = opSupplier.get().apply(input);
+ LOGGER.info(tenantOperationFactory.getPhoenixUtil().getGSON().toJson(stats));
+ assertEquals(0, stats.getStatus());
+ latches.get(handlerId).countDown();
+ }
+ }
+
+ @Test
+ public void testWorkloadWithOneHandler() throws Exception {
+ int numOpGroups = 5;
+ int numHandlers = 1;
+ int totalOperations = 50;
+ int perHandlerCount = 50;
+
+ ExecutorService executor = null;
+ try {
+ executor = Executors.newFixedThreadPool(numHandlers);
+ PhoenixUtil pUtil = PhoenixUtil.create();
+ DataModel model = readTestDataModel("/scenario/test_mt_workload.xml");
+ for (Scenario scenario : model.getScenarios()) {
+ // Set the total number of operations for this load profile
+ scenario.getLoadProfile().setNumOperations(totalOperations);
+ TenantOperationFactory opFactory = new TenantOperationFactory(pUtil, model, scenario);
+ assertEquals("operation group size from the factory is not as expected: ",
+ numOpGroups, opFactory.getOperations().size());
+
+ // populate the handlers and countdown latches.
+ String handlerId = String.format("%s.%d", InetAddress.getLocalHost().getHostName(), numHandlers);
+ List workers = Lists.newArrayList();
+ Map latches = Maps.newConcurrentMap();
+ workers.add(new EventCountingWorkHandler(opFactory, handlerId, latches));
+ latches.put(handlerId, new CountDownLatch(perHandlerCount));
+ // submit the workload
+ Workload workload = new TenantOperationWorkload(pUtil, model, scenario, workers, properties);
+ Future status = executor.submit(workload.execute());
+ // Just make sure there are no exceptions
+ status.get();
+
+ // Wait for the handlers to count down
+ for (Map.Entry latch : latches.entrySet()) {
+ assertTrue(latch.getValue().await(60, TimeUnit.SECONDS));
+ }
+ }
+ } finally {
+ if (executor != null) {
+ executor.shutdown();
+ }
+ }
+ }
+
+ @Test
+ public void testWorkloadWithManyHandlers() throws Exception {
+ int numOpGroups = 5;
+ int numHandlers = 5;
+ int totalOperations = 500;
+ int perHandlerCount = 50;
+
+ ExecutorService executor = Executors.newFixedThreadPool(numHandlers);
+ PhoenixUtil pUtil = PhoenixUtil.create();
+ DataModel model = readTestDataModel("/scenario/test_mt_workload.xml");
+ for (Scenario scenario : model.getScenarios()) {
+ // Set the total number of operations for this load profile
+ scenario.getLoadProfile().setNumOperations(totalOperations);
+ TenantOperationFactory opFactory = new TenantOperationFactory(pUtil, model, scenario);
+ assertEquals("operation group size from the factory is not as expected: ",
+ numOpGroups, opFactory.getOperations().size());
+
+ // populate the handlers and countdown latches.
+ List workers = Lists.newArrayList();
+ Map latches = Maps.newConcurrentMap();
+ for (int i=0;i latch : latches.entrySet()) {
+ assertTrue(latch.getValue().await(60, TimeUnit.SECONDS));
+ }
+ }
+ executor.shutdown();
+ }
+
+}
diff --git a/phoenix-pherf/src/main/resources/datamodel/create_prod_test_unsalted.sql b/phoenix-pherf/src/it/resources/datamodel/create_prod_test_unsalted.sql
similarity index 100%
rename from phoenix-pherf/src/main/resources/datamodel/create_prod_test_unsalted.sql
rename to phoenix-pherf/src/it/resources/datamodel/create_prod_test_unsalted.sql
diff --git a/phoenix-pherf/src/main/resources/hbase-site.xml b/phoenix-pherf/src/it/resources/hbase-site.xml
similarity index 100%
rename from phoenix-pherf/src/main/resources/hbase-site.xml
rename to phoenix-pherf/src/it/resources/hbase-site.xml
diff --git a/phoenix-pherf/src/main/resources/scenario/prod_test_unsalted_scenario.xml b/phoenix-pherf/src/it/resources/scenario/prod_test_unsalted_scenario.xml
similarity index 100%
rename from phoenix-pherf/src/main/resources/scenario/prod_test_unsalted_scenario.xml
rename to phoenix-pherf/src/it/resources/scenario/prod_test_unsalted_scenario.xml
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
index cae3213f5c7..c042689b0fd 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/Pherf.java
@@ -24,7 +24,8 @@
import java.util.List;
import java.util.Properties;
-import com.google.common.annotations.VisibleForTesting;
+import org.apache.phoenix.thirdparty.com.google.common.annotations.VisibleForTesting;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Lists;
import org.apache.phoenix.thirdparty.org.apache.commons.cli.CommandLine;
import org.apache.phoenix.thirdparty.org.apache.commons.cli.CommandLineParser;
import org.apache.phoenix.thirdparty.org.apache.commons.cli.HelpFormatter;
@@ -33,6 +34,8 @@
import org.apache.phoenix.thirdparty.org.apache.commons.cli.PosixParser;
import org.apache.phoenix.pherf.PherfConstants.CompareType;
import org.apache.phoenix.pherf.PherfConstants.GeneratePhoenixStats;
+import org.apache.phoenix.pherf.configuration.DataModel;
+import org.apache.phoenix.pherf.configuration.Scenario;
import org.apache.phoenix.pherf.configuration.XMLConfigParser;
import org.apache.phoenix.pherf.jmx.MonitorManager;
import org.apache.phoenix.pherf.result.ResultUtil;
@@ -40,6 +43,7 @@
import org.apache.phoenix.pherf.util.GoogleChartGenerator;
import org.apache.phoenix.pherf.util.PhoenixUtil;
import org.apache.phoenix.pherf.util.ResourceList;
+import org.apache.phoenix.pherf.workload.mt.tenantoperation.TenantOperationWorkload;
import org.apache.phoenix.pherf.workload.QueryExecutor;
import org.apache.phoenix.pherf.workload.Workload;
import org.apache.phoenix.pherf.workload.WorkloadExecutor;
@@ -60,6 +64,8 @@ public class Pherf {
"HBase Zookeeper address for connection. Default: localhost");
options.addOption("q", "query", false, "Executes multi-threaded query sets");
options.addOption("listFiles", false, "List available resource files");
+ options.addOption("mt", "multi-tenant", false,
+ "Multi tenanted workloads based on load profiles.");
options.addOption("l", "load", false,
"Pre-loads data according to specified configuration values.");
options.addOption("scenarioFile", true,
@@ -103,6 +109,7 @@ public class Pherf {
private final String queryHint;
private final Properties properties;
private final boolean preLoadData;
+ private final boolean multiTenantWorkload;
private final String dropPherfTablesRegEx;
private final boolean executeQuerySets;
private final boolean isFunctional;
@@ -148,6 +155,7 @@ public Pherf(String[] args) throws Exception {
properties.setProperty(PherfConstants.LOG_PER_NROWS_NAME, getLogPerNRow(command));
preLoadData = command.hasOption("l");
+ multiTenantWorkload = command.hasOption("mt");
executeQuerySets = command.hasOption("q");
zookeeper = command.getOptionValue("z", "localhost");
queryHint = command.getOptionValue("hint", null);
@@ -288,17 +296,37 @@ public void run() throws Exception {
}
// Schema and Data Load
- if (preLoadData) {
+ if (preLoadData || multiTenantWorkload) {
LOGGER.info("\nStarting Data Load...");
- Workload workload = new WriteWorkload(parser, generateStatistics);
+ List newWorkloads = Lists.newArrayList();
try {
- workloadExecutor.add(workload);
+ if (multiTenantWorkload) {
+ for (DataModel model : parser.getDataModels()) {
+ for (Scenario scenario : model.getScenarios()) {
+ Workload workload = new TenantOperationWorkload(phoenixUtil,
+ model, scenario, properties);
+ newWorkloads.add(workload);
+ }
+ }
+ } else {
+ newWorkloads.add(new WriteWorkload(parser, generateStatistics));
+ }
+
+ if (newWorkloads.isEmpty()) {
+ throw new IllegalArgumentException("Found no new workload");
+ }
+
+ for (Workload workload : newWorkloads) {
+ workloadExecutor.add(workload);
+ }
// Wait for dataLoad to complete
- workloadExecutor.get(workload);
+ workloadExecutor.get();
} finally {
- if (null != workload) {
- workload.complete();
+ if (!newWorkloads.isEmpty()) {
+ for (Workload workload : newWorkloads) {
+ workload.complete();
+ }
}
}
} else {
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/DataTypeMapping.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/DataTypeMapping.java
index 129bdc22ee4..3bbe7289ca2 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/DataTypeMapping.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/DataTypeMapping.java
@@ -30,7 +30,9 @@ public enum DataTypeMapping {
VARCHAR_ARRAY("VARCHAR ARRAY", Types.ARRAY),
VARBINARY("VARBINARY", Types.VARBINARY),
TIMESTAMP("TIMESTAMP", Types.TIMESTAMP),
+ BOOLEAN("BOOLEAN", Types.BOOLEAN),
BIGINT("BIGINT", Types.BIGINT),
+ UNSIGNED_INT("UNSIGNED_INT", Types.INTEGER),
TINYINT("TINYINT", Types.TINYINT);
private final String sType;
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/IdleTime.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/IdleTime.java
new file mode 100644
index 00000000000..37d6e15b847
--- /dev/null
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/IdleTime.java
@@ -0,0 +1,47 @@
+/*
+ * 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.pherf.configuration;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public class IdleTime {
+
+ private String id;
+ private long idleTime = 0;
+
+ @XmlAttribute
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @XmlAttribute
+ public long getIdleTime() {
+ return idleTime;
+ }
+
+ public void setIdleTime(long idleTime) {
+ this.idleTime = idleTime;
+ }
+}
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/LoadProfile.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/LoadProfile.java
new file mode 100644
index 00000000000..3116244eb22
--- /dev/null
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/LoadProfile.java
@@ -0,0 +1,113 @@
+/*
+ * 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.pherf.configuration;
+
+import javax.xml.bind.annotation.XmlType;
+import java.util.List;
+
+@XmlType
+public class LoadProfile {
+ private static final int MIN_BATCH_SIZE = 1;
+ private static final String DEFAULT_TENANT_ID_FMT = "00D%s%07d";
+ private static final int DEFAULT_GROUP_ID_LEN = 5;
+ private static final int DEFAULT_TENANT_ID_LEN = 15;
+
+ // Holds the batch size to be used in upserts.
+ private int batchSize;
+ // Holds the number of operations to be generated.
+ private long numOperations;
+ /**
+ * Holds the format to be used when generating tenantIds.
+ * TenantId format should typically have 2 parts -
+ * 1. string fmt - that hold the tenant group id.
+ * 2. int fmt - that holds a random number between 1 and max tenants
+ * for e.g DEFAULT_TENANT_ID_FMT = "00D%s%07d";
+ */
+ private String tenantIdFormat;
+ private int groupIdLength;
+ private int tenantIdLength;
+ // Holds the desired tenant distribution for this load.
+ private List tenantDistribution;
+ // Holds the desired operation distribution for this load.
+ private List opDistribution;
+
+ public LoadProfile() {
+ this.batchSize = MIN_BATCH_SIZE;
+ this.numOperations = Long.MAX_VALUE;
+ this.tenantIdFormat = DEFAULT_TENANT_ID_FMT;
+ this.tenantIdLength = DEFAULT_TENANT_ID_LEN;
+ this.groupIdLength = DEFAULT_GROUP_ID_LEN;
+ }
+
+ public String getTenantIdFormat() {
+ return tenantIdFormat;
+ }
+
+ public void setTenantIdFormat(String tenantIdFormat) {
+ this.tenantIdFormat = tenantIdFormat;
+ }
+
+ public int getTenantIdLength() {
+ return tenantIdLength;
+ }
+
+ public void setTenantIdLength(int tenantIdLength) {
+ this.tenantIdLength = tenantIdLength;
+ }
+
+ public int getGroupIdLength() {
+ return groupIdLength;
+ }
+
+ public void setGroupIdLength(int groupIdLength) {
+ this.groupIdLength = groupIdLength;
+ }
+
+ public int getBatchSize() {
+ return batchSize;
+ }
+
+ public void setBatchSize(int batchSize) {
+ this.batchSize = batchSize;
+ }
+
+ public long getNumOperations() {
+ return numOperations;
+ }
+
+ public void setNumOperations(long numOperations) {
+ this.numOperations = numOperations;
+ }
+
+ public List getTenantDistribution() {
+ return tenantDistribution;
+ }
+
+ public void setTenantDistribution(List tenantDistribution) {
+ this.tenantDistribution = tenantDistribution;
+ }
+
+ public List getOpDistribution() {
+ return opDistribution;
+ }
+
+ public void setOpDistribution(List opDistribution) {
+ this.opDistribution = opDistribution;
+ }
+}
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/OperationGroup.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/OperationGroup.java
new file mode 100644
index 00000000000..31545b279dc
--- /dev/null
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/OperationGroup.java
@@ -0,0 +1,44 @@
+/*
+ * 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.pherf.configuration;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+public class OperationGroup {
+ private String id;
+ private int weight;
+
+ @XmlAttribute
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @XmlAttribute
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+}
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Query.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Query.java
index 5f28134e629..c47798cc013 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Query.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Query.java
@@ -18,23 +18,23 @@
package org.apache.phoenix.pherf.configuration;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import org.apache.phoenix.pherf.rules.RulesApplier;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
-
-import org.apache.phoenix.pherf.rules.RulesApplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
@XmlType
public class Query {
+ private String id;
+ private String queryGroup;
+ private String tenantId;
private String statement;
private Long expectedAggregateRowCount;
- private String tenantId;
private String ddl;
- private String queryGroup;
- private String id;
+ private boolean useGlobalConnection;
private Pattern pattern;
private long timeoutDuration = Long.MAX_VALUE;
@@ -51,20 +51,24 @@ public Query() {
public String getStatement() {
return statement;
}
-
- public String getDynamicStatement(RulesApplier ruleApplier, Scenario scenario) throws Exception {
- String ret = this.statement;
- String needQuotes = "";
- Matcher m = pattern.matcher(ret);
- while(m.find()) {
- String dynamicField = m.group(0).replace("[", "").replace("]", "");
- Column dynamicColumn = ruleApplier.getRule(dynamicField, scenario);
- needQuotes = (dynamicColumn.getType() == DataTypeMapping.CHAR || dynamicColumn
- .getType() == DataTypeMapping.VARCHAR) ? "'" : "";
- ret = ret.replace("[" + dynamicField + "]",
- needQuotes + ruleApplier.getDataValue(dynamicColumn).getValue() + needQuotes);
- }
- return ret;
+
+ public String getDynamicStatement(RulesApplier ruleApplier, Scenario scenario)
+ throws Exception {
+ String ret = this.statement;
+ String needQuotes = "";
+ Matcher m = pattern.matcher(ret);
+ while (m.find()) {
+ String dynamicField = m.group(0).replace("[", "").replace("]", "");
+ Column dynamicColumn = ruleApplier.getRule(dynamicField, scenario);
+ needQuotes =
+ (dynamicColumn.getType() == DataTypeMapping.CHAR
+ || dynamicColumn.getType() == DataTypeMapping.VARCHAR) ? "'" : "";
+ ret =
+ ret.replace("[" + dynamicField + "]",
+ needQuotes + ruleApplier.getDataValue(dynamicColumn).getValue()
+ + needQuotes);
+ }
+ return ret;
}
public void setStatement(String statement) {
@@ -160,6 +164,14 @@ public void setId(String id) {
this.id = id;
}
+ @XmlAttribute
+ public boolean isUseGlobalConnection() {
+ return useGlobalConnection;
+ }
+
+ public void setUseGlobalConnection(boolean useGlobalConnection) {
+ this.useGlobalConnection = useGlobalConnection;
+ }
@XmlAttribute
public long getTimeoutDuration() {
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
index 53b2d250325..32cfc1e47f5 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Scenario.java
@@ -27,7 +27,7 @@
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
-import com.google.common.base.Preconditions;
+import org.apache.phoenix.thirdparty.com.google.common.base.Preconditions;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.phoenix.pherf.util.PhoenixUtil;
@@ -36,15 +36,19 @@ public class Scenario {
private String tableName;
private int rowCount;
private Map phoenixProperties;
+ private WriteParams writeParams = null;
private DataOverride dataOverride;
private List querySet = new ArrayList<>();
- private WriteParams writeParams = null;
+ private List upsertSet = new ArrayList<>();
+ private List idleTimes = new ArrayList<>();
+ private List udfs = new ArrayList<>();
+ private LoadProfile loadProfile = null;
+
private String name;
private String tenantId;
private List preScenarioDdls;
private List postScenarioDdls;
-
-
+
public Scenario() {
}
@@ -194,6 +198,7 @@ public void setWriteParams(WriteParams writeParams) {
this.writeParams = writeParams;
}
+
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
@@ -232,4 +237,43 @@ public List getPostScenarioDdls() {
public void setPostScenarioDdls(List postScenarioDdls) {
this.postScenarioDdls = postScenarioDdls;
}
+
+ public List getUpserts() {
+ return upsertSet;
+ }
+
+ @XmlElementWrapper(name = "upserts")
+ @XmlElement(name = "upsert")
+ public void setUpserts(List upsertSet) {
+ this.upsertSet = upsertSet;
+ }
+
+ public List getIdleTimes() {
+ return idleTimes;
+ }
+
+ @XmlElementWrapper(name = "idleTimes")
+ @XmlElement(name = "idleTime")
+ public void setIdleTimes(List idleTimes) {
+ this.idleTimes = idleTimes;
+ }
+
+ public List getUdfs() {
+ return udfs;
+ }
+
+ @XmlElementWrapper(name = "udfs")
+ @XmlElement(name = "udf")
+ public void setUdfs(List udfs) {
+ this.udfs = udfs;
+ }
+
+
+ public LoadProfile getLoadProfile() {
+ return loadProfile;
+ }
+
+ public void setLoadProfile(LoadProfile loadProfile) {
+ this.loadProfile = loadProfile;
+ }
}
\ No newline at end of file
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/TenantGroup.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/TenantGroup.java
new file mode 100644
index 00000000000..06569170cc1
--- /dev/null
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/TenantGroup.java
@@ -0,0 +1,52 @@
+/*
+ * 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.pherf.configuration;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+public class TenantGroup {
+ private String id;
+ private int weight;
+ private int numTenants;
+
+ @XmlAttribute
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @XmlAttribute
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+
+ @XmlAttribute
+ public int getNumTenants() { return numTenants; }
+
+ public void setNumTenants(int numTenants) { this.numTenants = numTenants; }
+
+
+}
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Upsert.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Upsert.java
new file mode 100644
index 00000000000..dfbe9e628a9
--- /dev/null
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/Upsert.java
@@ -0,0 +1,135 @@
+/*
+ * 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.pherf.configuration;
+
+import org.apache.phoenix.pherf.rules.RulesApplier;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Upsert {
+
+ private String id;
+ private String upsertGroup;
+ private String statement;
+ private List columns;
+ private boolean useGlobalConnection;
+ private Pattern pattern;
+ private long timeoutDuration = Long.MAX_VALUE;
+
+ public Upsert() {
+ pattern = Pattern.compile("\\[.*?\\]");
+ }
+
+ public String getDynamicStatement(RulesApplier ruleApplier, Scenario scenario)
+ throws Exception {
+ String ret = this.statement;
+ String needQuotes = "";
+ Matcher m = pattern.matcher(ret);
+ while (m.find()) {
+ String dynamicField = m.group(0).replace("[", "").replace("]", "");
+ Column dynamicColumn = ruleApplier.getRule(dynamicField, scenario);
+ needQuotes =
+ (dynamicColumn.getType() == DataTypeMapping.CHAR
+ || dynamicColumn.getType() == DataTypeMapping.VARCHAR) ? "'" : "";
+ ret = ret.replace("[" + dynamicField + "]",
+ needQuotes + ruleApplier.getDataValue(dynamicColumn).getValue()
+ + needQuotes);
+ }
+ return ret;
+ }
+
+ /**
+ * upsertGroup attribute is just a string value to help correlate upserts across sets or files.
+ * This helps to make sense of reporting results.
+ *
+ * @return the group id
+ */
+ @XmlAttribute
+ public String getUpsertGroup() {
+ return upsertGroup;
+ }
+
+ public void setUpsertGroup(String upsertGroup) {
+ this.upsertGroup = upsertGroup;
+ }
+
+
+ /**
+ * Upsert ID, Use UUID if none specified
+ *
+ * @return
+ */
+ @XmlAttribute
+ public String getId() {
+ if (null == this.id) {
+ this.id = java.util.UUID.randomUUID().toString();
+ }
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public List getColumns() {
+ return columns;
+ }
+
+ public void setColumns(List columns) {
+ this.columns = columns;
+ }
+
+ @XmlAttribute
+ public boolean isUseGlobalConnection() {
+ return useGlobalConnection;
+ }
+
+ public void setUseGlobalConnection(boolean useGlobalConnection) {
+ this.useGlobalConnection = useGlobalConnection;
+ }
+
+ @XmlAttribute
+ public long getTimeoutDuration() {
+ return this.timeoutDuration;
+ }
+
+ public void setTimeoutDuration(long timeoutDuration) {
+ this.timeoutDuration = timeoutDuration;
+ }
+
+ public String getStatement() {
+ return statement;
+ }
+
+ public void setStatement(String statement) {
+ // normalize statement - merge all consecutive spaces into one
+ this.statement = statement.replaceAll("\\s+", " ");
+ }
+
+ public List getColumn() {
+ return columns;
+ }
+
+ public void setColumn(List columns) {
+ this.columns = columns;
+ }
+}
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/UserDefined.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/UserDefined.java
new file mode 100644
index 00000000000..8350d576037
--- /dev/null
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/configuration/UserDefined.java
@@ -0,0 +1,55 @@
+/*
+ * 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.pherf.configuration;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import java.util.List;
+
+@XmlType
+public class UserDefined {
+ String id;
+ String clazzName;
+ List args;
+
+ @XmlAttribute
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getClazzName() {
+ return clazzName;
+ }
+
+ public void setClazzName(String clazzName) {
+ this.clazzName = clazzName;
+ }
+
+ public List getArgs() {
+ return args;
+ }
+
+ public void setArgs(List args) {
+ this.args = args;
+ }
+}
diff --git a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/rules/RulesApplier.java b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/rules/RulesApplier.java
index b066e00adc9..aeb3ec5693d 100644
--- a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/rules/RulesApplier.java
+++ b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/rules/RulesApplier.java
@@ -18,8 +18,9 @@
package org.apache.phoenix.pherf.rules;
-import com.google.common.base.Preconditions;
+import org.apache.phoenix.thirdparty.com.google.common.base.Preconditions;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.math3.random.RandomDataGenerator;
import org.apache.phoenix.pherf.PherfConstants;
@@ -51,6 +52,7 @@ public class RulesApplier {
private final Random rndVal;
private final RandomDataGenerator randomDataGenerator;
+ private final DataModel dataModel;
private final XMLConfigParser parser;
private final List