You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by dk...@apache.org on 2020/07/20 08:04:40 UTC

[hive] branch master updated: HIVE-22869: Add locking benchmark to metastore-tools/metastore-benchmarks (Zoltan Chovan, reviewed by Denys Kuzmenko)

This is an automated email from the ASF dual-hosted git repository.

dkuzmenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 764e5ed  HIVE-22869: Add locking benchmark to metastore-tools/metastore-benchmarks (Zoltan Chovan, reviewed by Denys Kuzmenko)
764e5ed is described below

commit 764e5ed20ab9a5a8bc5b8bd5947b231c14703eaa
Author: Zoltan Chovan <ne...@gmail.com>
AuthorDate: Mon Jul 20 10:04:22 2020 +0200

    HIVE-22869: Add locking benchmark to metastore-tools/metastore-benchmarks (Zoltan Chovan, reviewed by Denys Kuzmenko)
    
    Closes (#1073)
---
 .../metastore-tools/findbugs/findbugs-exclude.xml  |  21 ++
 .../metastore-tools/metastore-benchmarks/pom.xml   |  11 +
 .../hive/metastore/tools/ACIDBenchmarks.java       | 247 +++++++++++++++++++++
 .../hadoop/hive/metastore/tools/BenchmarkTool.java | 116 +++++++++-
 .../hive/metastore/tools/BenchmarkUtils.java       |  62 ++++++
 .../hadoop/hive/metastore/tools/HMSBenchmarks.java |  93 ++++----
 .../hadoop/hive/metastore/tools/HMSConfig.java     |  29 +++
 .../hive/metastore/tools/BenchmarkSuite.java       |   4 +-
 .../hadoop/hive/metastore/tools/HMSClient.java     |  61 ++++-
 .../apache/hadoop/hive/metastore/tools/Util.java   |  98 ++++++++
 10 files changed, 669 insertions(+), 73 deletions(-)

diff --git a/standalone-metastore/metastore-tools/findbugs/findbugs-exclude.xml b/standalone-metastore/metastore-tools/findbugs/findbugs-exclude.xml
new file mode 100644
index 0000000..bde8c62
--- /dev/null
+++ b/standalone-metastore/metastore-tools/findbugs/findbugs-exclude.xml
@@ -0,0 +1,21 @@
+<!--
+   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.
+-->
+<FindBugsFilter>
+    <Match>
+        <Class name="~org.apache.hadoop.hive.metastore.tools.*" />
+    </Match>
+</FindBugsFilter>
diff --git a/standalone-metastore/metastore-tools/metastore-benchmarks/pom.xml b/standalone-metastore/metastore-tools/metastore-benchmarks/pom.xml
index 754fd0e..896bfc5 100644
--- a/standalone-metastore/metastore-tools/metastore-benchmarks/pom.xml
+++ b/standalone-metastore/metastore-tools/metastore-benchmarks/pom.xml
@@ -29,6 +29,7 @@
 
   <properties>
     <standalone.metastore.path.to.root>../..</standalone.metastore.path.to.root>
+    <jmh.version>1.23</jmh.version>
   </properties>
 
   <dependencies>
@@ -74,6 +75,16 @@
         </exclusion>
       </exclusions>
     </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-core</artifactId>
+      <version>${jmh.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-generator-annprocess</artifactId>
+      <version>${jmh.version}</version>
+    </dependency>
     <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
     <dependency>
       <groupId>org.slf4j</groupId>
diff --git a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/ACIDBenchmarks.java b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/ACIDBenchmarks.java
new file mode 100644
index 0000000..50d0ff4
--- /dev/null
+++ b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/ACIDBenchmarks.java
@@ -0,0 +1,247 @@
+package org.apache.hadoop.hive.metastore.tools;
+
+import org.apache.hadoop.hive.metastore.api.DataOperationType;
+import org.apache.hadoop.hive.metastore.api.LockComponent;
+import org.apache.hadoop.hive.metastore.api.LockRequest;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.thrift.TException;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.hadoop.hive.metastore.tools.BenchmarkUtils.createManyTables;
+import static org.apache.hadoop.hive.metastore.tools.BenchmarkUtils.dropManyTables;
+import static org.apache.hadoop.hive.metastore.tools.Util.throwingSupplierWrapper;
+
+public class ACIDBenchmarks {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CoreContext.class);
+
+  @State(Scope.Benchmark)
+  public static class CoreContext {
+    @Param("1")
+    protected int howMany;
+
+    @State(Scope.Thread)
+    public static class ThreadState {
+      HMSClient client;
+
+      @Setup
+      public void doSetup() throws Exception {
+        LOG.debug("Creating client");
+        client = HMSConfig.getInstance().newClient();
+      }
+
+      @TearDown
+      public void doTearDown() throws Exception {
+        client.close();
+        LOG.debug("Closed a connection to metastore.");
+      }
+    }
+
+    @Setup
+    public void setup() {
+      LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+      Configuration ctxConfig = ctx.getConfiguration();
+      ctxConfig.getLoggerConfig(CoreContext.class.getName()).setLevel(Level.INFO);
+      ctx.updateLoggers(ctxConfig);
+    }
+  }
+
+  @State(Scope.Benchmark)
+  public static class TestOpenTxn extends CoreContext {
+
+    @State(Scope.Thread)
+    public static class ThreadState extends CoreContext.ThreadState {
+      List<Long> openTxns = new ArrayList<>();
+
+      @TearDown
+      public void doTearDown() throws Exception {
+        client.abortTxns(openTxns);
+        LOG.debug("aborted all opened txns");
+      }
+
+      void addTxn(List<Long> openTxn) {
+        openTxns.addAll(openTxn);
+      }
+    }
+
+    @Benchmark
+    public void openTxn(TestOpenTxn.ThreadState state) throws TException {
+      state.addTxn(state.client.openTxn(howMany));
+      LOG.debug("opened txns, count=", howMany);
+    }
+  }
+
+  @State(Scope.Benchmark)
+  public static class TestLocking extends CoreContext {
+    private int nTables;
+
+    @Param("0")
+    private int nPartitions;
+
+    private List<LockComponent> lockComponents;
+
+    @Setup
+    public void setup() {
+      this.nTables = (nPartitions != 0) ? howMany / nPartitions : howMany;
+      createLockComponents();
+    }
+
+    @State(Scope.Thread)
+    public static class ThreadState extends CoreContext.ThreadState {
+      List<Long> openTxns = new ArrayList<>();
+      long txnId;
+
+      @Setup(org.openjdk.jmh.annotations.Level.Invocation)
+      public void iterSetup() {
+        txnId = executeOpenTxnAndGetTxnId(client);
+        LOG.debug("opened txn, id={}", txnId);
+        openTxns.add(txnId);
+      }
+
+      @TearDown
+      public void doTearDown() throws Exception {
+        client.abortTxns(openTxns);
+        if (BenchmarkUtils.checkTxnsCleaned(client, openTxns) == false) {
+          LOG.error("Something went wrong with the cleanup of txns");
+        }
+        LOG.debug("aborted all opened txns");
+      }
+    }
+
+    @Benchmark
+    public void lock(TestLocking.ThreadState state) {
+      LOG.debug("sending lock request");
+      executeLock(state.client, state.txnId, lockComponents);
+    }
+
+    private void createLockComponents() {
+      lockComponents = new ArrayList<>();
+
+      for (int i = 0; i < nTables; i++) {
+        for (int j = 0; j < nPartitions - (nPartitions > 1 ? 1 : 0); j++) {
+          lockComponents.add(
+            new Util.LockComponentBuilder()
+              .setDbName("default")
+              .setTableName(String.format("tmp_table_%d", i))
+              .setPartitionName("p_" + j)
+              .setShared()
+              .setOperationType(DataOperationType.SELECT)
+              .build());
+        }
+        if (nPartitions != 1) {
+          lockComponents.add(
+            new Util.LockComponentBuilder()
+              .setDbName("default")
+              .setTableName(String.format("tmp_table_%d", i))
+              .setShared()
+              .setOperationType(DataOperationType.SELECT)
+              .build());
+        }
+      }
+    }
+
+    private static long executeOpenTxnAndGetTxnId(HMSClient client) {
+      return throwingSupplierWrapper(() -> client.openTxn(1).get(0));
+    }
+
+    private void executeLock(HMSClient client, long txnId, List<LockComponent> lockComponents) {
+      LockRequest req = new LockRequest(lockComponents, "hclient", "localhost");
+      req.setTxnid(txnId);
+      throwingSupplierWrapper(() -> client.lock(req));
+    }
+  }
+
+  @State(Scope.Benchmark)
+  public static class TestAllocateTableWriteIds extends CoreContext {
+    String dbName = "test_db";
+    String tblName = "tmp_table";
+
+    @State(Scope.Thread)
+    public static class ThreadState extends CoreContext.ThreadState {
+      List<Long> openTxns = new ArrayList<>();
+      long txnId;
+
+      @Setup
+      public void iterSetup() {
+        txnId = executeOpenTxnAndGetTxnId(client);
+        LOG.info("opened txn, id={}", txnId);
+        openTxns.add(txnId);
+      }
+
+      @TearDown
+      public void doTearDown() throws Exception {
+        client.abortTxns(openTxns);
+        if (BenchmarkUtils.checkTxnsCleaned(client, openTxns) == false) {
+          LOG.error("Something went wrong with the cleanup of txns");
+        }
+        LOG.info("aborted all opened txns");
+      }
+    }
+
+    @Benchmark
+    public void allocateTableWriteIds(TestAllocateTableWriteIds.ThreadState state) throws TException {
+      state.client.allocateTableWriteIds(dbName, tblName, state.openTxns);
+    }
+
+    private static long executeOpenTxnAndGetTxnId(HMSClient client) {
+      return throwingSupplierWrapper(() -> client.openTxn(1).get(0));
+    }
+  }
+
+  @State(Scope.Benchmark)
+  public static class TestGetValidWriteIds extends CoreContext {
+    String dbName = "test_db";
+    String tblName = "table_%d";
+    List<String> fullTableNames = new ArrayList<>();
+    HMSClient client;
+
+    @Setup
+    public void doSetup() {
+      try {
+        client = HMSConfig.getInstance().newClient();
+      } catch (Exception e) {
+        LOG.error(e.getMessage());
+      }
+
+      try {
+        if (!client.dbExists(dbName)) {
+          client.createDatabase(dbName);
+        }
+      } catch (TException e) {
+        LOG.error(e.getMessage());
+      }
+
+      LOG.info("creating {} tables", this.howMany);
+      createManyTables(client, this.howMany, dbName, tblName);
+      for (int i = 0; i < this.howMany; i++) {
+        fullTableNames.add(dbName + ".table_" + i);
+      }
+    }
+
+    @TearDown
+    public void doTearDown() throws Exception {
+      LOG.debug("dropping {} tables", howMany);
+      dropManyTables(client, howMany, dbName, tblName);
+    }
+
+    @Benchmark
+    public void getValidWriteIds(TestGetValidWriteIds.ThreadState state) throws TException {
+      LOG.debug("executing getValidWriteIds");
+      state.client.getValidWriteIds(this.fullTableNames);
+    }
+  }
+}
+
diff --git a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkTool.java b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkTool.java
index 2ab9388..e973db7 100644
--- a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkTool.java
+++ b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkTool.java
@@ -19,6 +19,12 @@
 package org.apache.hadoop.hive.metastore.tools;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import picocli.CommandLine;
@@ -31,12 +37,32 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Formatter;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 
 import static org.apache.hadoop.hive.metastore.tools.Constants.HMS_DEFAULT_PORT;
-import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.*;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkCreatePartition;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkCreatePartitions;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkDeleteCreate;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkDeleteWithPartitions;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkDropDatabase;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkDropPartition;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkDropPartitions;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkGetNotificationId;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkGetPartitionNames;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkGetPartitions;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkGetPartitionsByName;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkGetTable;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkListAllTables;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkListDatabases;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkListManyPartitions;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkListPartition;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkListTables;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkOpenTxns;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkRenameTable;
+import static org.apache.hadoop.hive.metastore.tools.HMSBenchmarks.benchmarkTableCreate;
 import static org.apache.hadoop.hive.metastore.tools.Util.getServerUri;
 import static picocli.CommandLine.Command;
 import static picocli.CommandLine.Option;
@@ -54,6 +80,11 @@ public class BenchmarkTool implements Runnable {
   private static final TimeUnit scale = TimeUnit.MILLISECONDS;
   private static final String CSV_SEPARATOR = "\t";
   private static final String TEST_TABLE = "bench_table";
+  private enum RunModes {
+    ACID,
+    NONACID,
+    ALL
+  }
 
 
   @Option(names = {"-H", "--host"}, description = "HMS Host", paramLabel = "URI")
@@ -68,7 +99,6 @@ public class BenchmarkTool implements Runnable {
   @Option(names = {"-t", "--table"}, description = "table name")
   private String tableName = TEST_TABLE + "_" + System.getProperty("user.name");
 
-
   @Option(names = {"-N", "--number"}, description = "number of object instances")
   private int[] instances = {100};
 
@@ -84,7 +114,7 @@ public class BenchmarkTool implements Runnable {
   @Option(names = {"-o", "--output"}, description = "output file")
   private String outputFile;
 
-  @Option(names = {"-T", "--threads"}, description = "number of concurrent threads")
+  @Option(names = {"-T", "--threads"}, description = "number of concurrent threads/clients")
   private int nThreads = 2;
 
   @Option(names = {"--confdir"}, description = "configuration directory")
@@ -97,7 +127,7 @@ public class BenchmarkTool implements Runnable {
   private boolean doCSV = false;
 
   @Option(names = {"--params"}, description = "number of table/partition parameters")
-  private int nParameters = 0;
+  private int[] nParameters = {0};
 
   @Option(names = {"--savedata"}, description = "save raw data in specified dir")
   private String dataSaveDir;
@@ -111,6 +141,10 @@ public class BenchmarkTool implements Runnable {
   @Option(names = {"-E", "--exclude"}, description = "test name patterns to exclude")
   private Pattern[] exclude;
 
+  @Option(names = {"--runMode"},
+      description = "flag for setting the mode for the benchmark, acceptable values are: ACID, NONACID, ALL")
+  private RunModes runMode = RunModes.ALL;
+
   public static void main(String[] args) {
     CommandLine.run(new BenchmarkTool(), args);
   }
@@ -141,12 +175,67 @@ public class BenchmarkTool implements Runnable {
     }
   }
 
-
   @Override
   public void run() {
-    LOG.info("Using warmup " + warmup +
-        " spin " + spinCount + " nparams " + nParameters + " threads " + nThreads);
+    LOG.info("Using warmup " + warmup + " spin " + spinCount + " nparams " + Arrays.toString(nParameters) + " threads "
+        + nThreads);
+    HMSConfig.getInstance().init(host, port, confDir);
+
+    switch (runMode) {
+      case ACID:
+        runAcidBenchmarks();
+        break;
+      case NONACID:
+        runNonAcidBenchmarks();
+        break;
+      case ALL:
+      default:
+        runNonAcidBenchmarks();
+        runAcidBenchmarks();
+        break;
+    }
+  }
 
+  private void runAcidBenchmarks() {
+    ChainedOptionsBuilder optsBuilder =
+        new OptionsBuilder()
+            .warmupIterations(warmup)
+            .measurementIterations(spinCount)
+            .operationsPerInvocation(1)
+            .mode(Mode.SingleShotTime)
+            .timeUnit(TimeUnit.MILLISECONDS)
+            .forks(0)
+            .threads(nThreads)
+            .syncIterations(true);
+
+    String[] candidates = new String[] {
+        ACIDBenchmarks.TestOpenTxn.class.getSimpleName(),
+        ACIDBenchmarks.TestLocking.class.getSimpleName(),
+        ACIDBenchmarks.TestGetValidWriteIds.class.getSimpleName(),
+        ACIDBenchmarks.TestAllocateTableWriteIds.class.getSimpleName()
+    };
+
+    for (String pattern : Util.filterMatches(Arrays.asList(candidates), matches, exclude)) {
+      optsBuilder = optsBuilder.include(pattern);
+    }
+
+    Options opts =
+        optsBuilder
+            .param("howMany", Arrays.stream(instances)
+            .mapToObj(String::valueOf)
+                .toArray(String[]::new))
+            .param("nPartitions", Arrays.stream(nParameters)
+                .mapToObj(String::valueOf).toArray(String[]::new))
+            .build();
+
+    try {
+      new Runner(opts).run();
+    } catch (RunnerException e) {
+      LOG.error(e.getMessage(), e);
+    }
+  }
+
+  private void runNonAcidBenchmarks() {
     StringBuilder sb = new StringBuilder();
     BenchData bData = new BenchData(dbName, tableName);
 
@@ -163,7 +252,7 @@ public class BenchmarkTool implements Runnable {
         .add("createTable", () -> benchmarkTableCreate(bench, bData))
         .add("dropTable", () -> benchmarkDeleteCreate(bench, bData))
         .add("dropTableWithPartitions",
-            () -> benchmarkDeleteWithPartitions(bench, bData, 1, nParameters))
+            () -> benchmarkDeleteWithPartitions(bench, bData, 1, nParameters[0]))
         .add("addPartition", () -> benchmarkCreatePartition(bench, bData))
         .add("dropPartition", () -> benchmarkDropPartition(bench, bData))
         .add("listPartition", () -> benchmarkListPartition(bench, bData))
@@ -184,7 +273,7 @@ public class BenchmarkTool implements Runnable {
       suite.add("listTables" + '.' + howMany,
           () -> benchmarkListTables(bench, bData, howMany))
           .add("dropTableWithPartitions" + '.' + howMany,
-              () -> benchmarkDeleteWithPartitions(bench, bData, howMany, nParameters))
+              () -> benchmarkDeleteWithPartitions(bench, bData, howMany, nParameters[0]))
           .add("listPartitions" + '.' + howMany,
               () -> benchmarkListManyPartitions(bench, bData, howMany))
           .add("getPartitions" + '.' + howMany,
@@ -205,8 +294,12 @@ public class BenchmarkTool implements Runnable {
               () -> benchmarkOpenTxns(bench, bData, howMany));
     }
 
+    List<String> toRun = suite.listMatching(matches, exclude);
+    if (toRun.isEmpty()) {
+      return;
+    }
     if (doList) {
-      suite.listMatching(matches, exclude).forEach(System.out::println);
+      toRun.forEach(System.out::println);
       return;
     }
 
@@ -248,12 +341,13 @@ public class BenchmarkTool implements Runnable {
 
       output.print(sb.toString());
       fmt.close();
+      output.close();
 
       if (dataSaveDir != null) {
         saveData(result.getResult(), dataSaveDir, scale);
       }
     } catch (Exception e) {
-      e.printStackTrace();
+      LOG.error(e.getMessage(), e);
     }
   }
 }
diff --git a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkUtils.java b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkUtils.java
new file mode 100644
index 0000000..36ff8e7
--- /dev/null
+++ b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkUtils.java
@@ -0,0 +1,62 @@
+package org.apache.hadoop.hive.metastore.tools;
+
+import org.apache.hadoop.hive.metastore.TableType;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.metastore.api.TxnInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import static org.apache.hadoop.hive.metastore.tools.Util.createSchema;
+import static org.apache.hadoop.hive.metastore.tools.Util.throwingSupplierWrapper;
+
+public class BenchmarkUtils {
+  private static final Logger LOG = LoggerFactory.getLogger(BenchmarkUtils.class);
+
+
+  static void createManyTables(HMSClient client, int howMany, String dbName, String format) {
+    List<FieldSchema> columns = createSchema(Arrays.asList("name", "string"));
+    List<FieldSchema> partitions = createSchema(Arrays.asList("date", "string"));
+    IntStream.range(0, howMany)
+        .forEach(i ->
+            throwingSupplierWrapper(() -> client.createTable(
+                new Util.TableBuilder(dbName, String.format(format, i))
+                    .withType(TableType.MANAGED_TABLE)
+                    .withColumns(columns)
+                    .withPartitionKeys(partitions)
+                    .build())));
+  }
+
+  static void dropManyTables(HMSClient client, int howMany, String dbName, String format) {
+    IntStream.range(0, howMany)
+        .forEach(i ->
+            throwingSupplierWrapper(() -> client.dropTable(dbName, String.format(format, i))));
+  }
+
+  // Create a simple table with a single column and single partition
+  static void createPartitionedTable(HMSClient client, String dbName, String tableName) {
+    throwingSupplierWrapper(() -> client.createTable(
+        new Util.TableBuilder(dbName, tableName)
+            .withType(TableType.MANAGED_TABLE)
+            .withColumns(createSchema(Collections.singletonList("name:string")))
+            .withPartitionKeys(createSchema(Collections.singletonList("date")))
+            .build()));
+  }
+
+  static boolean checkTxnsCleaned(HMSClient client, List<Long> txnsOpenedByBenchmark) throws InterruptedException {
+    // let's wait the default cleaner run period
+    Thread.sleep(100000);
+    List<Long> notCleanedTxns = new ArrayList<>();
+    throwingSupplierWrapper(() -> {
+      List<TxnInfo> txnInfos = client.getOpenTxnsInfo();
+      return txnInfos.stream().anyMatch(txnsOpenedByBenchmark::contains);
+    });
+
+    return false;
+  }
+}
diff --git a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSBenchmarks.java b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSBenchmarks.java
index d80c290..7c6f343 100644
--- a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSBenchmarks.java
+++ b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSBenchmarks.java
@@ -19,8 +19,6 @@
 package org.apache.hadoop.hive.metastore.tools;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
-import org.apache.hadoop.hive.metastore.TableType;
-import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.metastore.api.Partition;
 import org.apache.hadoop.hive.metastore.api.Table;
 import org.apache.thrift.TException;
@@ -28,22 +26,14 @@ import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.net.URI;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.stream.IntStream;
 
 import static org.apache.hadoop.hive.metastore.tools.Util.addManyPartitions;
 import static org.apache.hadoop.hive.metastore.tools.Util.addManyPartitionsNoException;
-import static org.apache.hadoop.hive.metastore.tools.Util.createSchema;
-import static org.apache.hadoop.hive.metastore.tools.Util.generatePartitionNames;
-import static java.util.concurrent.Executors.newFixedThreadPool;
 import static org.apache.hadoop.hive.metastore.tools.Util.throwingSupplierWrapper;
 
 /**
@@ -113,7 +103,7 @@ final class HMSBenchmarks {
 
     return bench.measure(
         () -> throwingSupplierWrapper(() -> {
-          createPartitionedTable(client, dbName, tableName);
+          BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
           addManyPartitions(client, dbName, tableName, parameters,
               Collections.singletonList("d"), howMany);
           return true;
@@ -128,7 +118,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       return bench.measure(() ->
           throwingSupplierWrapper(() -> client.getTable(dbName, tableName)));
@@ -146,11 +136,11 @@ final class HMSBenchmarks {
     // Create a bunch of tables
     String format = "tmp_table_%d";
     try {
-      createManyTables(client, count, dbName, format);
+      BenchmarkUtils.createManyTables(client, count, dbName, format);
       return bench.measure(() ->
           throwingSupplierWrapper(() -> client.getAllTables(dbName, null)));
     } finally {
-      dropManyTables(client, count, dbName, format);
+      BenchmarkUtils.dropManyTables(client, count, dbName, format);
     }
   }
 
@@ -160,7 +150,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     final List<String> values = Collections.singletonList("d1");
     try {
       Table t = client.getTable(dbName, tableName);
@@ -185,7 +175,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       addManyPartitions(client, dbName, tableName, null,
           Collections.singletonList("d"), 1);
@@ -207,7 +197,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       addManyPartitions(client, dbName, tableName, null, Collections.singletonList("d"), howMany);
       LOG.debug("Created {} partitions", howMany);
@@ -229,7 +219,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       addManyPartitions(client, dbName, tableName, null, Collections.singletonList("d"), howMany);
       LOG.debug("Created {} partitions", howMany);
@@ -250,7 +240,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     final List<String> values = Collections.singletonList("d1");
     try {
       Table t = client.getTable(dbName, tableName);
@@ -277,7 +267,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       return bench.measure(
           null,
@@ -298,7 +288,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       return bench.measure(
           () -> addManyPartitionsNoException(client, dbName, tableName, null,
@@ -319,7 +309,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       addManyPartitionsNoException(client, dbName, tableName, null,
           Collections.singletonList("d"), count);
@@ -338,7 +328,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       addManyPartitionsNoException(client, dbName, tableName, null,
           Collections.singletonList("d"), count);
@@ -361,7 +351,7 @@ final class HMSBenchmarks {
     String dbName = data.dbName;
     String tableName = data.tableName;
 
-    createPartitionedTable(client, dbName, tableName);
+    BenchmarkUtils.createPartitionedTable(client, dbName, tableName);
     try {
       addManyPartitionsNoException(client, dbName, tableName, null,
           Collections.singletonList("d"), count);
@@ -398,7 +388,7 @@ final class HMSBenchmarks {
       return bench.measure(
           () -> {
             throwingSupplierWrapper(() -> client.createDatabase(dbName));
-            createManyTables(client, count, dbName, "tmp_table_%d");
+            BenchmarkUtils.createManyTables(client, count, dbName, "tmp_table_%d");
           },
           () -> throwingSupplierWrapper(() -> client.dropDatabase(dbName)),
           null
@@ -417,33 +407,37 @@ final class HMSBenchmarks {
         () -> throwingSupplierWrapper(() -> client.abortTxns(client.getOpenTxns())));
   }
 
-  private static void createManyTables(HMSClient client, int howMany, String dbName, String format) {
-    List<FieldSchema> columns = createSchema(new ArrayList<>(Arrays.asList("name", "string")));
-    List<FieldSchema> partitions = createSchema(new ArrayList<>(Arrays.asList("date", "string")));
-    IntStream.range(0, howMany)
-        .forEach(i ->
-            throwingSupplierWrapper(() -> client.createTable(
-                new Util.TableBuilder(dbName, String.format(format, i))
-                    .withType(TableType.MANAGED_TABLE)
-                    .withColumns(columns)
-                    .withPartitionKeys(partitions)
-                    .build())));
-  }
+  static DescriptiveStatistics benchmarkAllocateTableWriteIds(@NotNull MicroBenchmark bench,
+                                                              @NotNull BenchData data,
+                                                              int howMany) {
+    final HMSClient client = data.getClient();
 
-  private static void dropManyTables(HMSClient client, int howMany, String dbName, String format) {
-    IntStream.range(0, howMany)
-        .forEach(i ->
-            throwingSupplierWrapper(() -> client.dropTable(dbName, String.format(format, i))));
+    return  bench.measure(
+        () -> throwingSupplierWrapper(() -> client.openTxn(howMany)),
+        () -> throwingSupplierWrapper(() -> client.allocateTableWriteIds("test_db", "test_tbl", client.getOpenTxns())),
+        () -> throwingSupplierWrapper(() -> client.abortTxns(client.getOpenTxns()))
+    );
   }
 
-  // Create a simple table with a single column and single partition
-  private static void createPartitionedTable(HMSClient client, String dbName, String tableName) {
-    throwingSupplierWrapper(() -> client.createTable(
-        new Util.TableBuilder(dbName, tableName)
-            .withType(TableType.MANAGED_TABLE)
-            .withColumns(createSchema(Collections.singletonList("name:string")))
-            .withPartitionKeys(createSchema(Collections.singletonList("date")))
-            .build()));
+  static DescriptiveStatistics benchmarkGetValidWriteIds(@NotNull MicroBenchmark bench,
+                                                         @NotNull BenchData data,
+                                                         int howMany) {
+    final HMSClient client = data.getClient();
+    String dbName = data.dbName;
+    List<String> tableNames = new ArrayList<>();
+
+    return bench.measure(
+        () -> {
+          BenchmarkUtils.createManyTables(client, howMany, dbName, "tmp_table_%d");
+          for (int i = 0; i < howMany; i++) {
+            tableNames.add(dbName + ".tmp_table_" + i);
+          }
+        },
+        () -> throwingSupplierWrapper(() -> client.getValidWriteIds(tableNames)),
+        () -> {
+          BenchmarkUtils.dropManyTables(client, howMany, dbName, "tmp_table_%d");
+        }
+    );
   }
 
   static DescriptiveStatistics benchmarkGetNotificationId(@NotNull MicroBenchmark benchmark,
@@ -453,5 +447,4 @@ final class HMSBenchmarks {
         throwingSupplierWrapper(client::getCurrentNotificationId));
   }
 
-
 }
diff --git a/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSConfig.java b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSConfig.java
new file mode 100644
index 0000000..86b666c
--- /dev/null
+++ b/standalone-metastore/metastore-tools/metastore-benchmarks/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSConfig.java
@@ -0,0 +1,29 @@
+package org.apache.hadoop.hive.metastore.tools;
+
+import static org.apache.hadoop.hive.metastore.tools.Util.getServerUri;
+
+public class HMSConfig {
+
+  private static final HMSConfig instance = new HMSConfig();
+
+  private String host;
+  private Integer port;
+  private String confDir;
+
+  private HMSConfig(){}
+
+  public static HMSConfig getInstance(){
+    return instance;
+  }
+
+  public void init(String host, Integer port, String confDir){
+    this.host = host;
+    this.port = port;
+    this.confDir = confDir;
+  }
+
+  public HMSClient newClient() throws Exception {
+    return new HMSClient(getServerUri(host, String.valueOf(port)), confDir);
+  }
+
+}
diff --git a/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkSuite.java b/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkSuite.java
index 5211082..d32e971 100644
--- a/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkSuite.java
+++ b/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/BenchmarkSuite.java
@@ -75,7 +75,7 @@ public final class BenchmarkSuite {
   // List of benchmarks. All benchmarks are executed in the order
   // they are inserted
   private final List<String> benchmarks = new ArrayList<>();
-  // Once benchmarks are executed, results are stored in TreeMap to prserve the order.
+  // Once benchmarks are executed, results are stored in TreeMap to preserve the order.
   private final Map<String, DescriptiveStatistics> result = new TreeMap<>();
   // Whether sanitizing of results is requested
   private boolean doSanitize = false;
@@ -115,7 +115,7 @@ public final class BenchmarkSuite {
   }
 
   /**
-   * Run all benchmarks in the 'names' list.
+     * Run all benchmarks in the 'names' list.
    * @param names list of benchmarks to run
    * @return this to allow chaining
    */
diff --git a/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSClient.java b/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSClient.java
index 4e75ede..8913cb2 100644
--- a/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSClient.java
+++ b/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/HMSClient.java
@@ -20,19 +20,25 @@ package org.apache.hadoop.hive.metastore.tools;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.conf.HiveConf;
-import org.apache.hadoop.hive.metastore.api.AbortTxnRequest;
 import org.apache.hadoop.hive.metastore.api.AbortTxnsRequest;
+import org.apache.hadoop.hive.metastore.api.AllocateTableWriteIdsRequest;
 import org.apache.hadoop.hive.metastore.api.CommitTxnRequest;
 import org.apache.hadoop.hive.metastore.api.Database;
 import org.apache.hadoop.hive.metastore.api.DropPartitionsRequest;
 import org.apache.hadoop.hive.metastore.api.DropPartitionsResult;
 import org.apache.hadoop.hive.metastore.api.GetOpenTxnsResponse;
+import org.apache.hadoop.hive.metastore.api.GetValidWriteIdsRequest;
+import org.apache.hadoop.hive.metastore.api.LockRequest;
+import org.apache.hadoop.hive.metastore.api.LockResponse;
 import org.apache.hadoop.hive.metastore.api.MetaException;
 import org.apache.hadoop.hive.metastore.api.OpenTxnRequest;
+import org.apache.hadoop.hive.metastore.api.OpenTxnsResponse;
 import org.apache.hadoop.hive.metastore.api.Partition;
 import org.apache.hadoop.hive.metastore.api.RequestPartsSpec;
 import org.apache.hadoop.hive.metastore.api.Table;
 import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore;
+import org.apache.hadoop.hive.metastore.api.TxnInfo;
+import org.apache.hadoop.hive.metastore.api.TxnType;
 import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
 import org.apache.hadoop.hive.metastore.security.HadoopThriftAuthBridge;
 import org.apache.hadoop.hive.metastore.utils.MetaStoreUtils;
@@ -53,9 +59,11 @@ import org.slf4j.LoggerFactory;
 import javax.security.auth.login.LoginException;
 import java.io.File;
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.UnknownHostException;
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -326,11 +334,6 @@ final class HMSClient implements AutoCloseable {
     client.append_partition_with_environment_context(dbName, tableName, partitionValues, null);
   }
 
-  boolean openTxn(int numTxns) throws TException {
-    client.open_txns(new OpenTxnRequest(numTxns, "Test", "Host"));
-    return true;
-  }
-
   List<Long> getOpenTxns() throws TException {
     GetOpenTxnsResponse txns = client.get_open_txns();
     List<Long> openTxns = new ArrayList<>();
@@ -345,21 +348,44 @@ final class HMSClient implements AutoCloseable {
     return openTxns;
   }
 
+  List<TxnInfo> getOpenTxnsInfo() throws TException {
+    return client.get_open_txns_info().getOpen_txns();
+  }
+
   boolean commitTxn(long txnId) throws TException {
     client.commit_txn(new CommitTxnRequest(txnId));
     return true;
   }
 
-  boolean abortTxn(long txnId) throws TException {
-    client.abort_txn(new AbortTxnRequest(txnId));
+  boolean abortTxns(List<Long> txnIds) throws TException {
+    client.abort_txns(new AbortTxnsRequest(txnIds));
     return true;
   }
 
-  boolean abortTxns(List<Long> txnIds) throws TException {
-    client.abort_txns(new AbortTxnsRequest(txnIds));
+  boolean allocateTableWriteIds(String dbName, String tableName, List<Long> openTxns) throws TException {
+    AllocateTableWriteIdsRequest awiRqst = new AllocateTableWriteIdsRequest(dbName, tableName);
+    openTxns.forEach(t -> {
+      awiRqst.addToTxnIds(t);
+    });
+
+    client.allocate_table_write_ids(awiRqst);
     return true;
   }
 
+  boolean getValidWriteIds(List<String> fullTableNames) throws TException {
+    client.get_valid_write_ids(new GetValidWriteIdsRequest(fullTableNames));
+    return true;
+  }
+
+  LockResponse lock(@NotNull LockRequest rqst) throws TException {
+    return client.lock(rqst);
+  }
+
+  List<Long> openTxn(int howMany) throws TException {
+    OpenTxnsResponse txns = openTxnsIntr("", howMany, null);
+    return txns.getTxn_ids();
+  }
+
   private TTransport open(Configuration conf, @NotNull URI uri) throws
       TException, IOException, LoginException {
     boolean useSSL = MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.USE_SSL);
@@ -459,6 +485,21 @@ final class HMSClient implements AutoCloseable {
     return transport;
   }
 
+  private OpenTxnsResponse openTxnsIntr(String user, int numTxns, TxnType txnType) throws TException {
+    String hostname;
+    try {
+      hostname = InetAddress.getLocalHost().getHostName();
+    } catch (UnknownHostException e) {
+      LOG.error("Unable to resolve my host name " + e.getMessage());
+      throw new RuntimeException(e);
+    }
+    OpenTxnRequest rqst = new OpenTxnRequest(numTxns, user, hostname);
+    if (txnType != null) {
+      rqst.setTxn_type(txnType);
+    }
+    return client.open_txns(rqst);
+  }
+
   @Override
   public void close() throws Exception {
     if (transport != null && transport.isOpen()) {
diff --git a/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/Util.java b/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/Util.java
index 101d675..fd06db6 100644
--- a/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/Util.java
+++ b/standalone-metastore/metastore-tools/tools-common/src/main/java/org/apache/hadoop/hive/metastore/tools/Util.java
@@ -21,8 +21,12 @@ package org.apache.hadoop.hive.metastore.tools;
 import com.google.common.base.Joiner;
 import com.google.common.net.HostAndPort;
 import org.apache.hadoop.hive.metastore.TableType;
+import org.apache.hadoop.hive.metastore.api.DataOperationType;
 import org.apache.hadoop.hive.metastore.api.Database;
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.metastore.api.LockComponent;
+import org.apache.hadoop.hive.metastore.api.LockLevel;
+import org.apache.hadoop.hive.metastore.api.LockType;
 import org.apache.hadoop.hive.metastore.api.Partition;
 import org.apache.hadoop.hive.metastore.api.PrincipalType;
 import org.apache.hadoop.hive.metastore.api.SerDeInfo;
@@ -232,6 +236,7 @@ public final class Util {
     private TableBuilder() {
       dbName = null;
       tableName = null;
+      parameters.putIfAbsent("transactional", "true");
     }
 
     TableBuilder(String dbName, String tableName) {
@@ -383,6 +388,99 @@ public final class Util {
     }
   }
 
+  public static class LockComponentBuilder {
+    private LockComponent component;
+    private boolean tableNameSet;
+    private boolean partNameSet;
+
+    public LockComponentBuilder() {
+      component = new LockComponent();
+      tableNameSet = partNameSet = false;
+    }
+
+    /**
+     * Set the lock to be exclusive.
+     * @return reference to this builder
+     */
+    public LockComponentBuilder setExclusive() {
+      component.setType(LockType.EXCLUSIVE);
+      return this;
+    }
+
+    /**
+     * Set the lock to be semi-shared.
+     * @return reference to this builder
+     */
+    public LockComponentBuilder setSemiShared() {
+      component.setType(LockType.SHARED_WRITE);
+      return this;
+    }
+
+    /**
+     * Set the lock to be shared.
+     * @return reference to this builder
+     */
+    public LockComponentBuilder setShared() {
+      component.setType(LockType.SHARED_READ);
+      return this;
+    }
+
+    /**
+     * Set the database name.
+     * @param dbName database name
+     * @return reference to this builder
+     */
+    public LockComponentBuilder setDbName(String dbName) {
+      component.setDbname(dbName);
+      return this;
+    }
+
+    public LockComponentBuilder setIsTransactional(boolean t) {
+      component.setIsTransactional(t);
+      return this;
+    }
+
+    public LockComponentBuilder setOperationType(DataOperationType dop) {
+      component.setOperationType(dop);
+      return this;
+    }
+
+    /**
+     * Set the table name.
+     * @param tableName table name
+     * @return reference to this builder
+     */
+    public LockComponentBuilder setTableName(String tableName) {
+      component.setTablename(tableName);
+      tableNameSet = true;
+      return this;
+    }
+
+    /**
+     * Set the partition name.
+     * @param partitionName partition name
+     * @return reference to this builder
+     */
+    public LockComponentBuilder setPartitionName(String partitionName) {
+      component.setPartitionname(partitionName);
+      partNameSet = true;
+      return this;
+    }
+
+    public LockComponent build() {
+      LockLevel level = LockLevel.DB;
+      if (tableNameSet) level = LockLevel.TABLE;
+      if (partNameSet) level = LockLevel.PARTITION;
+      component.setLevel(level);
+      return component;
+    }
+
+    public LockComponent setLock(LockType type) {
+      component.setType(type);
+      return component;
+    }
+  }
+
   /**
    * Create table schema from parameters.
    *