This is an automated email from the ASF dual-hosted git repository.
yanxinyi pushed a commit to branch 4.x
in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/4.x by this push:
new 5f0c18d PHOENIX-6430 Added support for full row update for tables
when no columns specfied in scenario
5f0c18d is described below
commit 5f0c18d863b2bd0872a703dff35582704a4514a2
Author: jpisaac <[email protected]>
AuthorDate: Fri Apr 2 09:29:49 2021 -0700
PHOENIX-6430 Added support for full row update for tables when no columns
specfied in scenario
---
...T.java => MultiTenantTableOperationBaseIT.java} | 22 +-
.../mt/tenantoperation/MultiTenantTestUtils.java | 267 +++++++++++++++++++++
...IT.java => MultiTenantViewOperationBaseIT.java} | 11 +-
.../mt/tenantoperation/TenantOperationIT.java | 112 ---------
.../tenantoperation/TenantOperationWorkloadIT.java | 166 -------------
.../TenantTableOperationWorkloadIT.java | 72 ++++++
.../TenantViewOperationWorkloadIT.java | 61 +++++
.../apache/phoenix/pherf/configuration/Upsert.java | 22 +-
.../mt/tenantoperation/QueryOperationSupplier.java | 2 +-
.../mt/tenantoperation/TenantOperationFactory.java | 94 +++++---
.../tenantoperation/UpsertOperationSupplier.java | 32 ++-
.../org/apache/phoenix/pherf/ResultBaseTest.java | 5 -
..._mt_table.sql => test_schema_mt_base_table.sql} | 2 +-
...schema_mt_view.sql => test_schema_mt_view1.sql} | 4 +-
...schema_mt_view.sql => test_schema_mt_view2.sql} | 4 +-
...ema_mt_table.sql => test_schema_tbl_simple.sql} | 22 +-
.../test/resources/scenario/test_mt_workload.xml | 95 +++++++-
.../test/resources/scenario/test_tbl_workload.xml | 169 +++++++++++++
18 files changed, 772 insertions(+), 390 deletions(-)
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/MultiTenantTableOperationBaseIT.java
similarity index 81%
copy from
phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantOperationBaseIT.java
copy to
phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantTableOperationBaseIT.java
index f200381..5fe1a9e 100644
---
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/MultiTenantTableOperationBaseIT.java
@@ -19,8 +19,6 @@
package org.apache.phoenix.pherf.workload.mt.tenantoperation;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
import org.apache.phoenix.pherf.PherfConstants;
import org.apache.phoenix.pherf.XMLConfigParserTest;
@@ -28,10 +26,7 @@ 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.After;
-import org.junit.AfterClass;
import org.junit.BeforeClass;
-import org.junit.experimental.categories.Category;
import java.net.URL;
import java.nio.file.Path;
@@ -43,17 +38,10 @@ import java.util.Properties;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-@Category(NeedsOwnMiniClusterTest.class)
-public class MultiTenantOperationBaseIT extends ParallelStatsDisabledIT {
- enum TestOperationGroup {
- upsertOp, queryOp1, queryOp2, idleOp, udfOp
- }
+public class MultiTenantTableOperationBaseIT extends ParallelStatsDisabledIT {
- 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 final String matcherScenario =
".*scenario/.*test_tbl_workload.*xml";
+ protected static final String matcherSchema =
".*datamodel/.*test_schema_tbl*.*sql";
protected static PhoenixUtil util = PhoenixUtil.create(true);
protected static Properties properties;
@@ -83,8 +71,4 @@ public class MultiTenantOperationBaseIT extends
ParallelStatsDisabledIT {
return XMLConfigParser.readDataModel(p);
}
- @AfterClass public static synchronized void tearDown() throws Exception {
- dropNonSystemTables();
- }
-
}
diff --git
a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantTestUtils.java
b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantTestUtils.java
new file mode 100644
index 0000000..873e061
--- /dev/null
+++
b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantTestUtils.java
@@ -0,0 +1,267 @@
+/*
+ * 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.lmax.disruptor.LifecycleAware;
+import com.lmax.disruptor.WorkHandler;
+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.Workload;
+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.apache.phoenix.thirdparty.com.google.common.collect.Lists;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Maps;
+import org.junit.Assert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+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;
+
+public class MultiTenantTestUtils {
+ private static final Logger LOGGER =
LoggerFactory.getLogger(MultiTenantTestUtils.class);
+ enum TestOperationGroup {
+ upsertOp, queryOp1, queryOp2, idleOp, udfOp
+ }
+
+ public void testWorkloadWithOneHandler(Properties properties, DataModel
model,
+ String scenarioName, int expectedTenantGroups, int
expectedOpGroups) throws Exception {
+
+ int numHandlers = 1;
+ int totalOperations = 50;
+ int perHandlerCount = 50;
+
+ ExecutorService executor = null;
+ try {
+ executor = Executors.newFixedThreadPool(numHandlers);
+ PhoenixUtil pUtil = PhoenixUtil.create();
+ for (Scenario scenario : model.getScenarios()) {
+ if (scenarioName != null && !scenarioName.isEmpty()
+ && scenario.getName().compareTo(scenarioName) != 0) {
+ continue;
+ }
+ LOGGER.debug(String.format("Testing %s", scenario.getName()));
+ LoadProfile loadProfile = scenario.getLoadProfile();
+
+ // Set the total number of operations for this load profile
+ loadProfile.setNumOperations(totalOperations);
+ TenantOperationFactory opFactory = new
TenantOperationFactory(pUtil, model,
+ scenario);
+ assertEquals("tenant group size is not as expected: ",
expectedTenantGroups,
+ loadProfile.getTenantDistribution().size());
+ assertEquals("operation group size from the factory is not as
expected: ",
+ expectedOpGroups, opFactory.getOperations().size());
+
+ // populate the handlers and countdown latches.
+ String handlerId = String
+ .format("%s.%d",
InetAddress.getLocalHost().getHostName(), numHandlers);
+ List<WorkHandler> workers = Lists.newArrayList();
+ Map<String, CountDownLatch> 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<String, CountDownLatch> latch :
latches.entrySet()) {
+ assertTrue(latch.getValue().await(60, TimeUnit.SECONDS));
+ }
+ }
+ } finally {
+ if (executor != null) {
+ executor.shutdown();
+ }
+ }
+ }
+
+ public void testWorkloadWithManyHandlers(Properties properties, DataModel
model,
+ String scenarioName, int expectedTenantGroups, int
expectedOpGroups) throws Exception {
+
+ int numHandlers = 5;
+ int totalOperations = 500;
+ int perHandlerCount = 50;
+
+ ExecutorService executor = Executors.newFixedThreadPool(numHandlers);
+ PhoenixUtil pUtil = PhoenixUtil.create();
+ for (Scenario scenario : model.getScenarios()) {
+ if (scenarioName != null && !scenarioName.isEmpty()
+ && scenario.getName().compareTo(scenarioName) != 0) {
+ continue;
+ }
+ LOGGER.debug(String.format("Testing %s", scenario.getName()));
+ LoadProfile loadProfile = scenario.getLoadProfile();
+
+ // Set the total number of operations for this load profile
+ loadProfile.setNumOperations(totalOperations);
+ TenantOperationFactory opFactory = new
TenantOperationFactory(pUtil, model, scenario);
+ assertEquals("tenant group size is not as expected: ",
expectedTenantGroups,
+ loadProfile.getTenantDistribution().size());
+
+ assertEquals("operation group size from the factory is not as
expected: ",
+ expectedOpGroups, opFactory.getOperations().size());
+
+ // populate the handlers and countdown latches.
+ List<WorkHandler> workers = Lists.newArrayList();
+ Map<String, CountDownLatch> latches = Maps.newConcurrentMap();
+ for (int i = 0; i < numHandlers; i++) {
+ String handlerId = String
+ .format("%s.%d",
InetAddress.getLocalHost().getHostName(), i);
+ 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<String, CountDownLatch> latch : latches.entrySet())
{
+ assertTrue(latch.getValue().await(60, TimeUnit.SECONDS));
+ }
+ }
+ executor.shutdown();
+ }
+
+ public void testVariousOperations(Properties properties, DataModel model,
String scenarioName,
+ int expectedTenantGroups, int expectedOpGroups) throws Exception {
+
+ int numRuns = 10;
+ int numOperations = 10;
+
+ PhoenixUtil pUtil = PhoenixUtil.create();
+ for (Scenario scenario : model.getScenarios()) {
+ if (scenarioName != null && !scenarioName.isEmpty()
+ && scenario.getName().compareTo(scenarioName) != 0) {
+ continue;
+ }
+ LOGGER.debug(String.format("Testing %s", scenario.getName()));
+ LoadProfile loadProfile = scenario.getLoadProfile();
+ assertEquals("tenant group size is not as expected: ",
expectedTenantGroups,
+ loadProfile.getTenantDistribution().size());
+ assertEquals("operation group size is not as expected: ",
expectedOpGroups,
+ 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: ",
+ expectedOpGroups, 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<Function<TenantOperationInfo, OperationStats>>
opSupplier = opFactory
+ .getOperationSupplier(info);
+ OperationStats stats = opSupplier.get().apply(info);
+ LOGGER.info(PhoenixUtil.getGSON().toJson(stats));
+ if (info.getOperation().getType() ==
Operation.OperationType.PRE_RUN) continue;
+ assertTrue(stats.getStatus() != -1);
+ 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 > 0
+ // Since the same view/table is being used by many
tests.
+ // Keeping query return values would require lot of
housekeeping
+ assertTrue(stats.getRowCount() > 0);
+ 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();
+ }
+ }
+ }
+ }
+ }
+
+ private static class EventCountingWorkHandler
+ implements
WorkHandler<TenantOperationWorkload.TenantOperationEvent>, LifecycleAware {
+ private final String handlerId;
+ private final TenantOperationFactory tenantOperationFactory;
+ private final Map<String, CountDownLatch> latches;
+
+ public EventCountingWorkHandler(TenantOperationFactory
tenantOperationFactory,
+ String handlerId, Map<String, CountDownLatch> latches) {
+ this.handlerId = handlerId;
+ this.tenantOperationFactory = tenantOperationFactory;
+ this.latches = latches;
+ }
+
+ @Override public void onStart() {
+ }
+
+ @Override public void onShutdown() {
+ }
+
+ @Override public void
onEvent(TenantOperationWorkload.TenantOperationEvent event)
+ throws Exception {
+ TenantOperationInfo input = event.getTenantOperationInfo();
+ Supplier<Function<TenantOperationInfo, OperationStats>>
+ opSupplier
+ = tenantOperationFactory.getOperationSupplier(input);
+ OperationStats stats = opSupplier.get().apply(input);
+ LOGGER.info(PhoenixUtil.getGSON().toJson(stats));
+ assertEquals(0, stats.getStatus());
+ latches.get(handlerId).countDown();
+ }
+ }
+
+}
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/MultiTenantViewOperationBaseIT.java
similarity index 91%
rename from
phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantOperationBaseIT.java
rename to
phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/MultiTenantViewOperationBaseIT.java
index f200381..ba71977 100644
---
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/MultiTenantViewOperationBaseIT.java
@@ -19,7 +19,6 @@
package org.apache.phoenix.pherf.workload.mt.tenantoperation;
-import org.apache.hadoop.hbase.HConstants;
import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
import org.apache.phoenix.pherf.PherfConstants;
@@ -28,7 +27,6 @@ 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.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.experimental.categories.Category;
@@ -44,14 +42,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@Category(NeedsOwnMiniClusterTest.class)
-public class MultiTenantOperationBaseIT extends ParallelStatsDisabledIT {
- enum TestOperationGroup {
- upsertOp, queryOp1, queryOp2, idleOp, udfOp
- }
-
- static enum TestTenantGroup {
- tg1, tg2, tg3
- }
+public class MultiTenantViewOperationBaseIT extends ParallelStatsDisabledIT {
protected static final String matcherScenario =
".*scenario/.*test_mt_workload.*xml";
protected static final String matcherSchema =
".*datamodel/.*test_schema_mt*.*sql";
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
deleted file mode 100644
index 737080a..0000000
---
a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationIT.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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<Function<TenantOperationInfo, OperationStats>>
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
deleted file mode 100644
index c6d4dfd..0000000
---
a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationWorkloadIT.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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<TenantOperationEvent>, LifecycleAware {
- private final String handlerId;
- private final TenantOperationFactory tenantOperationFactory;
- private static final Logger LOGGER =
LoggerFactory.getLogger(EventCountingWorkHandler.class);
- private final Map<String, CountDownLatch> latches;
- public EventCountingWorkHandler(TenantOperationFactory
tenantOperationFactory,
- String handlerId, Map<String, CountDownLatch> 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<Function<TenantOperationInfo, OperationStats>>
- 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<WorkHandler> workers = Lists.newArrayList();
- Map<String, CountDownLatch> 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<String, CountDownLatch> 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<WorkHandler> workers = Lists.newArrayList();
- Map<String, CountDownLatch> latches = Maps.newConcurrentMap();
- for (int i=0;i<numHandlers;i++) {
- String handlerId = String.format("%s.%d",
InetAddress.getLocalHost().getHostName(), i);
- 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<String, CountDownLatch> latch : latches.entrySet())
{
- assertTrue(latch.getValue().await(60, TimeUnit.SECONDS));
- }
- }
- executor.shutdown();
- }
-
-}
diff --git
a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantTableOperationWorkloadIT.java
b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantTableOperationWorkloadIT.java
new file mode 100644
index 0000000..dc98848
--- /dev/null
+++
b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantTableOperationWorkloadIT.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.pherf.workload.mt.tenantoperation;
+
+import com.lmax.disruptor.WorkHandler;
+import org.apache.phoenix.pherf.configuration.DataModel;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests focused on tenant tablee operations and their validations
+ * Tests focused on tenant operation workloads {@link TenantOperationWorkload}
+ * and workload handlers {@link WorkHandler}
+ */
+public class TenantTableOperationWorkloadIT extends
MultiTenantTableOperationBaseIT {
+ private final MultiTenantTestUtils multiTenantTestUtils = new
MultiTenantTestUtils();
+ private final DataModel model;
+
+ public TenantTableOperationWorkloadIT() throws Exception {
+ model = readTestDataModel("/scenario/test_tbl_workload.xml");
+ }
+
+ @Test public void testVariousOperations() throws Exception {
+ int expectedTenantGroups = 1;
+ int expectedWriteOpGroups = 1;
+ int expectedReadOpGroups = 2;
+ multiTenantTestUtils.testVariousOperations(properties, model,
"TEST_TABLE_WRITE",
+ expectedTenantGroups, expectedWriteOpGroups);
+ multiTenantTestUtils.testVariousOperations(properties, model,
"TEST_TABLE_READ",
+ expectedTenantGroups, expectedReadOpGroups);
+ }
+
+ @Test public void testWorkloadWithOneHandler() throws Exception {
+ int expectedTenantGroups = 1;
+ int expectedWriteOpGroups = 1;
+ int expectedReadOpGroups = 2;
+ multiTenantTestUtils.testWorkloadWithOneHandler(properties, model,
"TEST_TABLE_WRITE",
+ expectedTenantGroups, expectedWriteOpGroups);
+ multiTenantTestUtils.testWorkloadWithOneHandler(properties, model,
"TEST_TABLE_READ",
+ expectedTenantGroups, expectedReadOpGroups);
+ }
+
+ @Test public void testWorkloadWithManyHandlers() throws Exception {
+ int expectedTenantGroups = 1;
+ int expectedWriteOpGroups = 1;
+ int expectedReadOpGroups = 2;
+ multiTenantTestUtils.testWorkloadWithManyHandlers(properties, model,
"TEST_TABLE_WRITE",
+ expectedTenantGroups, expectedWriteOpGroups);
+ multiTenantTestUtils.testWorkloadWithManyHandlers(properties, model,
"TEST_TABLE_READ",
+ expectedTenantGroups, expectedReadOpGroups);
+ }
+
+}
diff --git
a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantViewOperationWorkloadIT.java
b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantViewOperationWorkloadIT.java
new file mode 100644
index 0000000..66bbe38
--- /dev/null
+++
b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantViewOperationWorkloadIT.java
@@ -0,0 +1,61 @@
+/*
+ * 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.lmax.disruptor.WorkHandler;
+import org.apache.phoenix.pherf.configuration.DataModel;
+import org.junit.Test;
+
+/**
+ * Tests focused on tenant view operations and their validations
+ * Tests focused on tenant operation workloads {@link TenantOperationWorkload}
+ * and workload handlers {@link WorkHandler}
+ */
+public class TenantViewOperationWorkloadIT extends
MultiTenantViewOperationBaseIT {
+
+ private final MultiTenantTestUtils multiTenantTestUtils = new
MultiTenantTestUtils();
+ private final DataModel model;
+
+ public TenantViewOperationWorkloadIT() throws Exception {
+ model = readTestDataModel("/scenario/test_mt_workload.xml");
+ }
+
+ @Test public void testVariousOperations() throws Exception {
+ int expectedTenantGroups = 3;
+ int expectedOpGroups = 5;
+ multiTenantTestUtils.testVariousOperations(properties, model, null,
+ expectedTenantGroups, expectedOpGroups);
+ }
+
+ @Test public void testWorkloadWithOneHandler() throws Exception {
+ int expectedTenantGroups = 3;
+ int expectedOpGroups = 5;
+ multiTenantTestUtils.testWorkloadWithOneHandler(properties, model,
null,
+ expectedTenantGroups, expectedOpGroups);
+
+ }
+
+ @Test public void testWorkloadWithManyHandlers() throws Exception {
+ int expectedTenantGroups = 3;
+ int expectedOpGroups = 5;
+ multiTenantTestUtils.testWorkloadWithManyHandlers(properties, model,
null,
+ expectedTenantGroups, expectedOpGroups);
+ }
+}
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
index dfbe9e6..810a742 100644
---
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
@@ -19,8 +19,11 @@
package org.apache.phoenix.pherf.configuration;
import org.apache.phoenix.pherf.rules.RulesApplier;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Lists;
import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -30,7 +33,7 @@ public class Upsert {
private String id;
private String upsertGroup;
private String statement;
- private List<Column> columns;
+ private List<Column> column;
private boolean useGlobalConnection;
private Pattern pattern;
private long timeoutDuration = Long.MAX_VALUE;
@@ -90,12 +93,13 @@ public class Upsert {
this.id = id;
}
- public List<Column> getColumns() {
- return columns;
+ public List<Column> getColumn() {
+ if (column == null) return Lists.newArrayList();
+ return column;
}
- public void setColumns(List<Column> columns) {
- this.columns = columns;
+ public void setColumn(List<Column> column) {
+ this.column = column;
}
@XmlAttribute
@@ -124,12 +128,4 @@ public class Upsert {
// normalize statement - merge all consecutive spaces into one
this.statement = statement.replaceAll("\\s+", " ");
}
-
- public List<Column> getColumn() {
- return columns;
- }
-
- public void setColumn(List<Column> columns) {
- this.columns = columns;
- }
}
diff --git
a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/QueryOperationSupplier.java
b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/QueryOperationSupplier.java
index 99188ce..e149661 100644
---
a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/QueryOperationSupplier.java
+++
b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/QueryOperationSupplier.java
@@ -69,7 +69,7 @@ public class QueryOperationSupplier extends
BaseOperationSupplier {
String opName = String.format("%s:%s:%s:%s:%s", scenarioName,
tableName,
opGroup, tenantGroup, input.getTenantId());
- LOGGER.info("\nExecuting query " + query.getStatement());
+ LOGGER.debug("\nExecuting query " + query.getStatement());
long startTime = 0;
int status = 0;
diff --git
a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationFactory.java
b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationFactory.java
index 6e86e14..ee74fad 100644
---
a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationFactory.java
+++
b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/TenantOperationFactory.java
@@ -18,6 +18,7 @@
package org.apache.phoenix.pherf.workload.mt.tenantoperation;
+import org.apache.phoenix.pherf.configuration.Column;
import org.apache.phoenix.thirdparty.com.google.common.base.Charsets;
import org.apache.phoenix.thirdparty.com.google.common.base.Function;
import org.apache.phoenix.thirdparty.com.google.common.base.Supplier;
@@ -49,6 +50,8 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Factory class for operation suppliers.
@@ -94,6 +97,7 @@ public class TenantOperationFactory {
Maps.newEnumMap(Operation.OperationType.class);
private final BloomFilter<TenantView> tenantsLoaded;
+ private ReadWriteLock rwLock = new ReentrantReadWriteLock();
public TenantOperationFactory(PhoenixUtil phoenixUtil, DataModel model,
Scenario scenario) {
this.phoenixUtil = phoenixUtil;
@@ -269,48 +273,15 @@ public class TenantOperationFactory {
// Check if pre run ddls are needed.
if (!tenantsLoaded.mightContain(tenantView)) {
-
- Supplier<Function<TenantOperationInfo, OperationStats>>
preRunOpSupplier =
- operationSuppliers.get(Operation.OperationType.PRE_RUN);
- // Check if the scenario has a PRE_RUN operation.
- if (preRunOpSupplier != null) {
- // Initialize the tenant using the pre scenario ddls.
- final PreScenarioOperation
- operation = new PreScenarioOperation() {
- @Override public List<Ddl> getPreScenarioDdls() {
- List<Ddl> ddls = scenario.getPreScenarioDdls();
- return ddls == null ? Lists.<Ddl>newArrayList() : ddls;
- }
-
- @Override public String getId() {
- return OperationType.PRE_RUN.name();
- }
-
- @Override public OperationType getType() {
- return OperationType.PRE_RUN;
- }
- };
- // Initialize with the pre run operation.
- TenantOperationInfo preRunSample = new TenantOperationInfo(
- input.getModelName(),
- input.getScenarioName(),
- input.getTableName(),
- input.getTenantGroupId(),
- Operation.OperationType.PRE_RUN.name(),
- input.getTenantId(), operation);
-
- try {
- // Run the initialization operation.
- OperationStats stats =
preRunOpSupplier.get().apply(preRunSample);
- LOGGER.info(phoenixUtil.getGSON().toJson(stats));
- } catch (Exception e) {
- LOGGER.error(String.format("Failed to initialize tenant.
[%s, %s] ",
- tenantView.tenantId,
- tenantView.viewName), e);
+ rwLock.writeLock().lock();
+ try {
+ if (!tenantsLoaded.mightContain(tenantView)) {
+ executePreRunOpsForTenant(tenantView, input);
+ tenantsLoaded.put(tenantView);
}
+ } finally {
+ rwLock.writeLock().unlock();
}
-
- tenantsLoaded.put(tenantView);
}
Supplier<Function<TenantOperationInfo, OperationStats>> opSupplier =
@@ -321,4 +292,47 @@ public class TenantOperationFactory {
return opSupplier;
}
+ private void executePreRunOpsForTenant(TenantView tenantView,
TenantOperationInfo input) {
+
+ Supplier<Function<TenantOperationInfo, OperationStats>>
preRunOpSupplier =
+ operationSuppliers.get(Operation.OperationType.PRE_RUN);
+ // Check if the scenario has a PRE_RUN operation.
+ if (preRunOpSupplier != null) {
+ // Initialize the tenant using the pre scenario ddls.
+ final PreScenarioOperation
+ operation = new PreScenarioOperation() {
+ @Override public List<Ddl> getPreScenarioDdls() {
+ List<Ddl> ddls = scenario.getPreScenarioDdls();
+ return ddls == null ? Lists.<Ddl>newArrayList() : ddls;
+ }
+
+ @Override public String getId() {
+ return OperationType.PRE_RUN.name();
+ }
+
+ @Override public OperationType getType() {
+ return OperationType.PRE_RUN;
+ }
+ };
+ // Initialize with the pre run operation.
+ TenantOperationInfo preRunSample = new TenantOperationInfo(
+ input.getModelName(),
+ input.getScenarioName(),
+ input.getTableName(),
+ input.getTenantGroupId(),
+ Operation.OperationType.PRE_RUN.name(),
+ input.getTenantId(), operation);
+
+ try {
+ // Run the initialization operation.
+ OperationStats stats =
preRunOpSupplier.get().apply(preRunSample);
+ LOGGER.info(phoenixUtil.getGSON().toJson(stats));
+ } catch (Exception e) {
+ LOGGER.error(String.format("Failed to initialize tenant. [%s,
%s] ",
+ tenantView.tenantId,
+ tenantView.viewName), e);
+ }
+ }
+ }
+
}
diff --git
a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/UpsertOperationSupplier.java
b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/UpsertOperationSupplier.java
index 30f953b..f7ff24a 100644
---
a/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/UpsertOperationSupplier.java
+++
b/phoenix-pherf/src/main/java/org/apache/phoenix/pherf/workload/mt/tenantoperation/UpsertOperationSupplier.java
@@ -37,17 +37,19 @@ import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.List;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* A supplier of {@link Function} that takes {@link UpsertOperation} as an
input
*/
class UpsertOperationSupplier extends BaseOperationSupplier {
private static final Logger LOGGER =
LoggerFactory.getLogger(UpsertOperationSupplier.class);
+ private ReadWriteLock rwLock = new ReentrantReadWriteLock();
public UpsertOperationSupplier(PhoenixUtil phoenixUtil, DataModel model,
Scenario scenario) {
super(phoenixUtil, model, scenario);
}
-
@Override
public Function<TenantOperationInfo, OperationStats> get() {
return new Function<TenantOperationInfo, OperationStats>() {
@@ -65,7 +67,7 @@ class UpsertOperationSupplier extends BaseOperationSupplier {
final String opGroup = input.getOperationGroupId();
final String tableName = input.getTableName();
final String scenarioName = input.getScenarioName();
- final List<Column> columns = upsert.getColumn();
+
// TODO:
// Ideally the fact that the op needs to executed using global
connection
// needs to be built into the framework and injected during
event generation.
@@ -73,23 +75,39 @@ class UpsertOperationSupplier extends BaseOperationSupplier
{
final boolean isTenantGroupGlobal =
(tenantGroup.compareTo(TenantGroup.DEFAULT_GLOBAL_ID) == 0);
final String tenantId = isTenantGroupGlobal ||
upsert.isUseGlobalConnection() ? null : input.getTenantId();
-
final String opName = String.format("%s:%s:%s:%s:%s",
scenarioName, tableName, opGroup, tenantGroup,
input.getTenantId());
-
long rowsCreated = 0;
long startTime = 0, duration, totalDuration;
int status = 0;
SimpleDateFormat simpleDateFormat = new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
try (Connection connection =
phoenixUtil.getConnection(tenantId)) {
- String sql = phoenixUtil.buildSql(columns, tableName);
+ // If list of columns has not been not provided or lazy
loaded
+ // then use the metadata call to get the column list.
+ if (upsert.getColumn().isEmpty()) {
+ rwLock.writeLock().lock();
+ try {
+ if (upsert.getColumn().isEmpty()) {
+ LOGGER.info("Fetching columns metadata from db
for operation : " + opName);
+ List<Column> allCols =
phoenixUtil.getColumnsFromPhoenix(scenario.getSchemaName(),
+
scenario.getTableNameWithoutSchemaName(),
+ connection);
+ upsert.setColumn(allCols);
+ }
+ } finally {
+ rwLock.writeLock().unlock();
+ }
+ }
+
+ String sql = phoenixUtil.buildSql(upsert.getColumn(),
tableName);
+ LOGGER.info("Operation " + opName + " executing " + sql);
startTime = EnvironmentEdgeManager.currentTimeMillis();
PreparedStatement stmt = null;
try {
stmt = connection.prepareStatement(sql);
for (long i = rowCount; i > 0; i--) {
- LOGGER.debug("Operation " + opName + " executing
");
- stmt = phoenixUtil.buildStatement(rulesApplier,
scenario, columns, stmt, simpleDateFormat);
+ stmt = phoenixUtil.buildStatement(rulesApplier,
scenario, upsert.getColumn(), stmt, simpleDateFormat);
if (useBatchApi) {
stmt.addBatch();
} else {
diff --git
a/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/ResultBaseTest.java
b/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/ResultBaseTest.java
index 531af26..a4b7648 100644
--- a/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/ResultBaseTest.java
+++ b/phoenix-pherf/src/test/java/org/apache/phoenix/pherf/ResultBaseTest.java
@@ -18,15 +18,10 @@
package org.apache.phoenix.pherf;
-import org.apache.commons.io.FileUtils;
import org.apache.phoenix.pherf.result.ResultUtil;
-import org.apache.phoenix.pherf.workload.mt.tenantoperation.TenantOperationIT;
import org.junit.AfterClass;
import org.junit.BeforeClass;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.io.File;
import java.util.Properties;
public class ResultBaseTest {
diff --git
a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_base_table.sql
similarity index 94%
copy from phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
copy to phoenix-pherf/src/test/resources/datamodel/test_schema_mt_base_table.sql
index b6791bf..184180a 100644
--- a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_base_table.sql
@@ -15,7 +15,7 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
*/
-CREATE TABLE IF NOT EXISTS PHERF.TEST_MULTI_TENANT_TABLE (
+CREATE TABLE IF NOT EXISTS PHERF.TEST_BASE_TABLE (
TENANT_ID CHAR(15) NOT NULL,
IDENTIFIER CHAR(3) NOT NULL,
ID CHAR(15) NOT NULL,
diff --git a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view1.sql
similarity index 88%
copy from phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
copy to phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view1.sql
index ad25e9b..51080dd 100644
--- a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view1.sql
@@ -16,7 +16,7 @@
-- limitations under the License.
*/
-CREATE VIEW IF NOT EXISTS PHERF.TEST_GLOBAL_VIEW (
+CREATE VIEW IF NOT EXISTS PHERF.TEST_GLOBAL_VIEW1 (
GID CHAR(15) NOT NULL,
FIELD1 VARCHAR,
OTHER_INT INTEGER
@@ -24,4 +24,4 @@ CREATE VIEW IF NOT EXISTS PHERF.TEST_GLOBAL_VIEW (
(
GID
)
-) AS SELECT * FROM PHERF.TEST_MULTI_TENANT_TABLE WHERE IDENTIFIER = 'EV1'
+) AS SELECT * FROM PHERF.TEST_BASE_TABLE WHERE IDENTIFIER = 'EV1'
diff --git a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view2.sql
similarity index 88%
rename from phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
rename to phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view2.sql
index ad25e9b..a435eb7 100644
--- a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view.sql
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_view2.sql
@@ -16,7 +16,7 @@
-- limitations under the License.
*/
-CREATE VIEW IF NOT EXISTS PHERF.TEST_GLOBAL_VIEW (
+CREATE VIEW IF NOT EXISTS PHERF.TEST_GLOBAL_VIEW2 (
GID CHAR(15) NOT NULL,
FIELD1 VARCHAR,
OTHER_INT INTEGER
@@ -24,4 +24,4 @@ CREATE VIEW IF NOT EXISTS PHERF.TEST_GLOBAL_VIEW (
(
GID
)
-) AS SELECT * FROM PHERF.TEST_MULTI_TENANT_TABLE WHERE IDENTIFIER = 'EV1'
+) AS SELECT * FROM PHERF.TEST_BASE_TABLE WHERE IDENTIFIER = 'EV2'
diff --git
a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
b/phoenix-pherf/src/test/resources/datamodel/test_schema_tbl_simple.sql
similarity index 76%
rename from phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
rename to phoenix-pherf/src/test/resources/datamodel/test_schema_tbl_simple.sql
index b6791bf..8b76820 100644
--- a/phoenix-pherf/src/test/resources/datamodel/test_schema_mt_table.sql
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema_tbl_simple.sql
@@ -16,16 +16,18 @@
-- limitations under the License.
*/
CREATE TABLE IF NOT EXISTS PHERF.TEST_MULTI_TENANT_TABLE (
- TENANT_ID CHAR(15) NOT NULL,
- IDENTIFIER CHAR(3) NOT NULL,
- ID CHAR(15) NOT NULL,
- CREATED_DATE DATE,
- FIELD VARCHAR,
- SOME_INT INTEGER
+ HOST CHAR(2) NOT NULL,
+ DOMAIN VARCHAR NOT NULL,
+ FEATURE VARCHAR NOT NULL,
+ DATE DATE NOT NULL,
+ USAGE.CORE BIGINT,
+ USAGE.DB BIGINT,
+ STATS.ACTIVE_VISITOR INTEGER
CONSTRAINT PK PRIMARY KEY
(
- TENANT_ID,
- IDENTIFIER,
- ID
+ HOST,
+ DOMAIN,
+ FEATURE,
+ DATE
)
-) VERSIONS=1,MULTI_TENANT=true
+) VERSIONS=1, MULTI_TENANT=true
diff --git a/phoenix-pherf/src/test/resources/scenario/test_mt_workload.xml
b/phoenix-pherf/src/test/resources/scenario/test_mt_workload.xml
index d3b83a2..00d613b 100644
--- a/phoenix-pherf/src/test/resources/scenario/test_mt_workload.xml
+++ b/phoenix-pherf/src/test/resources/scenario/test_mt_workload.xml
@@ -45,6 +45,26 @@
<name>GENERAL_INTEGER</name>
</column>
<column>
+ <type>INTEGER</type>
+ <dataSequence>SEQUENTIAL</dataSequence>
+ <!-- Number [0-100] that represents the probability of creating a
null value -->
+ <!-- The higher the number, the more like the value will returned
will be null -->
+ <!-- Leaving this tag out is equivalent to having a 0 probability.
i.e. never null -->
+ <nullChance>0</nullChance>
+ <name>INT_ID</name>
+ </column>
+ <column>
+ <type>DATE</type>
+ <!--SEQUENTIAL is unsupported for DATE -->
+ <dataSequence>RANDOM</dataSequence>
+ <!-- Number [0-100] that represents the probability of creating a
null value -->
+ <!-- The higher the number, the more like the value will returned
will be null -->
+ <!-- Leaving this tag out is equivalent to having a 0 probability.
i.e. never null -->
+ <nullChance>0</nullChance>
+ <useCurrentDate>true</useCurrentDate>
+ <name>GENERAL_DATE</name>
+ </column>
+ <column>
<type>CHAR</type>
<length>3</length>
<userDefined>true</userDefined>
@@ -63,9 +83,14 @@
</datavalue>
</valuelist>
</column>
+ <column>
+ <type>CHAR</type>
+ <length>3</length>
+ <name>IDENTIFIER</name>
+ </column>
</datamapping>
<scenarios>
- <scenario tableName="PHERF.EVT_1" name="EVT_1">
+ <scenario tableName="PHERF.EVT_1" name="EVT_11">
<loadProfile>
<batchSize>1</batchSize>
<numOperations>10</numOperations>
@@ -80,7 +105,7 @@
<opDistribution id="udfOp" weight="20"></opDistribution>
</loadProfile>
<preScenarioDdls>
- <ddl statement="CREATE VIEW IF NOT EXISTS PHERF.EVT_1 (ZID
CHAR(15), TYPE VARCHAR) AS SELECT * FROM PHERF.TEST_GLOBAL_VIEW" />
+ <ddl statement="CREATE VIEW IF NOT EXISTS PHERF.EVT_1 (ZID
CHAR(15), TYPE VARCHAR) AS SELECT * FROM PHERF.TEST_GLOBAL_VIEW1" />
</preScenarioDdls>
<upserts>
@@ -131,5 +156,71 @@
</udf>
</udfs>
</scenario>
+ <scenario tableName="PHERF.EVT_2" name="EVT_21">
+ <loadProfile>
+ <batchSize>1</batchSize>
+ <numOperations>10</numOperations>
+ <!-- Case 1 : Upsert Operation test -->
+ <tenantDistribution id="tg1" weight="100"
numTenants="1"></tenantDistribution>
+ <tenantDistribution id="tg2" weight="0"
numTenants="0"></tenantDistribution>
+ <tenantDistribution id="tg3" weight="0"
numTenants="0"></tenantDistribution>
+ <opDistribution id="upsertOp" weight="20"></opDistribution>
+ <opDistribution id="queryOp1" weight="20"></opDistribution>
+ <opDistribution id="queryOp2" weight="20"></opDistribution>
+ <opDistribution id="idleOp" weight="20"></opDistribution>
+ <opDistribution id="udfOp" weight="20"></opDistribution>
+ </loadProfile>
+ <preScenarioDdls>
+ <ddl statement="CREATE VIEW IF NOT EXISTS PHERF.EVT_2 (INT_ID
INTEGER, TYPE VARCHAR) AS SELECT * FROM PHERF.TEST_GLOBAL_VIEW2" />
+ </preScenarioDdls>
+
+ <upserts>
+ <upsert id="upsertOp">
+ <column>
+ <type>CHAR</type>
+ <name>ID</name>
+ </column>
+ <column>
+ <type>INTEGER</type>
+ <name>SOME_INT</name>
+ </column>
+ <column>
+ <type>CHAR</type>
+ <name>GID</name>
+ </column>
+ <column>
+ <type>VARCHAR</type>
+ <name>FIELD1</name>
+ </column>
+ <column>
+ <type>INTEGER</type>
+ <name>OTHER_INT</name>
+ </column>
+ <column>
+ <type>INTEGER</type>
+ <name>INT_ID</name>
+ </column>
+ <column>
+ <type>CHAR</type>
+ <name>TYPE</name>
+ </column>
+ </upsert>
+ </upserts>
+
+ <querySet>
+ <query id="queryOp1" statement="select count(*) from
PHERF.EVT_2"/>
+ <query id="queryOp2" statement="select * from PHERF.EVT_2"/>
+ </querySet>
+ <idleTimes>
+ <idleTime id="idleOp" idleTime="50"/>
+ </idleTimes>
+ <udfs>
+ <udf id="udfOp" >
+
<clazzName>org.apache.phoenix.pherf.ConfigurationParserTest.TestUDF</clazzName>
+ <args>Hello</args>
+ <args>World</args>
+ </udf>
+ </udfs>
+ </scenario>
</scenarios>
</datamodel>
diff --git a/phoenix-pherf/src/test/resources/scenario/test_tbl_workload.xml
b/phoenix-pherf/src/test/resources/scenario/test_tbl_workload.xml
new file mode 100644
index 0000000..286dcf8
--- /dev/null
+++ b/phoenix-pherf/src/test/resources/scenario/test_tbl_workload.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ 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.
+ -->
+
+<datamodel name="TEST_MT_TABLE_MODEL">
+ <datamapping>
+ <column>
+ <type>CHAR</type>
+ <length>2</length>
+ <userDefined>true</userDefined>
+ <dataSequence>SEQUENTIAL</dataSequence>
+ <name>HOST</name>
+ <valuelist>
+ <!-- Distributes according to specified values. These must
total 100 -->
+ <!-- ["NA","CS","EU"] -->
+ <datavalue distribution="34">
+ <value>NA</value>
+ </datavalue>
+ <datavalue distribution="33">
+ <value>CS</value>
+ </datavalue>
+ <datavalue distribution="33">
+ <value>EU</value>
+ </datavalue>
+ </valuelist>
+ </column>
+ <column>
+ <type>VARCHAR</type>
+ <userDefined>true</userDefined>
+ <dataSequence>SEQUENTIAL</dataSequence>
+ <name>DOMAIN</name>
+ <valuelist>
+ <!-- Distributes according to specified values. These must
total 100 -->
+ <!--
["Salesforce.com","Apple.com","Google.com","Amazon.com"]-->
+ <datavalue distribution="25">
+ <value>Salesforce.com</value>
+ </datavalue>
+ <datavalue distribution="25">
+ <value>Apple.com</value>
+ </datavalue>
+ <datavalue distribution="25">
+ <value>Google.com</value>
+ </datavalue>
+ <datavalue distribution="25">
+ <value>Amazon.com</value>
+ </datavalue>
+ </valuelist>
+ </column>
+ <column>
+ <type>VARCHAR</type>
+ <userDefined>true</userDefined>
+ <dataSequence>SEQUENTIAL</dataSequence>
+ <name>FEATURE</name>
+ <valuelist>
+ <!-- Distributes according to specified values. These must
total 100 -->
+ <!-- ["Login","Report","Dashboard","Sales","UI"]-->
+ <datavalue distribution="20">
+ <value>Login</value>
+ </datavalue>
+ <datavalue distribution="20">
+ <value>Report</value>
+ </datavalue>
+ <datavalue distribution="20">
+ <value>Dashboard</value>
+ </datavalue>
+ <datavalue distribution="20">
+ <value>Sales</value>
+ </datavalue>
+ <datavalue distribution="20">
+ <value>UI</value>
+ </datavalue>
+ </valuelist>
+ </column>
+ <column>
+ <type>DATE</type>
+ <userDefined>true</userDefined>
+ <dataSequence>SEQUENTIAL</dataSequence>
+ <name>DATE</name>
+ </column>
+ <column>
+ <type>DATE</type>
+ <userDefined>true</userDefined>
+ <!--SEQUENTIAL is unsupported for DATE -->
+ <dataSequence>RANDOM</dataSequence>
+ <!-- Number [0-100] that represents the probability of creating a
null value -->
+ <!-- The higher the number, the more like the value will returned
will be null -->
+ <!-- Leaving this tag out is equivalent to having a 0 probability.
i.e. never null -->
+ <nullChance>0</nullChance>
+ <minValue>2020</minValue>
+ <maxValue>2025</maxValue>
+ <name>DATE_O</name>
+ </column>
+
+ <column>
+ <type>BIGINT</type>
+ <dataSequence>RANDOM</dataSequence>
+ <minValue>1</minValue>
+ <maxValue>100</maxValue>
+ <!-- Number [0-100] that represents the probability of creating a
null value -->
+ <!-- The higher the number, the more like the value will returned
will be null -->
+ <!-- Leaving this tag out is equivalent to having a 0 probability.
i.e. never null -->
+ <nullChance>0</nullChance>
+ <name>USAGE.CORE</name>
+ </column>
+ <column>
+ <type>BIGINT</type>
+ <dataSequence>RANDOM</dataSequence>
+ <minValue>1</minValue>
+ <maxValue>2000</maxValue>
+ <!-- Number [0-100] that represents the probability of creating a
null value -->
+ <!-- The higher the number, the more like the value will returned
will be null -->
+ <!-- Leaving this tag out is equivalent to having a 0 probability.
i.e. never null -->
+ <nullChance>0</nullChance>
+ <name>USAGE.DB</name>
+ </column>
+ <column>
+ <type>INTEGER</type>
+ <dataSequence>RANDOM</dataSequence>
+ <minValue>1</minValue>
+ <maxValue>10000</maxValue>
+ <!-- Number [0-100] that represents the probability of creating a
null value -->
+ <!-- The higher the number, the more like the value will returned
will be null -->
+ <!-- Leaving this tag out is equivalent to having a 0 probability.
i.e. never null -->
+ <nullChance>0</nullChance>
+ <name>STATS.ACTIVE_VISITOR</name>
+ </column>
+ </datamapping>
+ <scenarios>
+ <scenario tableName="PHERF.TEST_MULTI_TENANT_TABLE"
name="TEST_TABLE_WRITE">
+ <loadProfile>
+ <numOperations>1</numOperations>
+ <tenantDistribution useGlobalConnection="true"/>
+ <opDistribution id="upsertOp" weight="100"/>
+ </loadProfile>
+
+ <upserts>
+ <upsert id="upsertOp" useGlobalConnection="true"
upsertGroup="write"/>
+ </upserts>
+ </scenario>
+ <scenario tableName="PHERF.TEST_MULTI_TENANT_TABLE"
name="TEST_TABLE_READ">
+ <loadProfile>
+ <numOperations>1</numOperations>
+ <tenantDistribution useGlobalConnection="true"/>
+ <opDistribution id="queryOp1" weight="20"/>
+ <opDistribution id="queryOp2" weight="20"/>
+ </loadProfile>
+
+ <querySet>
+ <query id="queryOp1" useGlobalConnection="true"
statement="select count(*) from PHERF.TEST_MULTI_TENANT_TABLE"
queryGroup="Aggregation"/>
+ <query id="queryOp2" useGlobalConnection="true"
statement="select * from PHERF.TEST_MULTI_TENANT_TABLE LIMIT 100"
queryGroup="LIMIT"/>
+ </querySet>
+ </scenario>
+ </scenarios>
+</datamodel>