@VisibleForTesting
  long openTxn(Context ctx, String user, TxnType txnType, long delay) throws LockException {
    /*Q: why don't we lock the snapshot here???  Instead of having client make an explicit call
    whenever it chooses
    A: If we want to rely on locks for transaction scheduling we must get the snapshot after lock
    acquisition.  Relying on locks is a pessimistic strategy which works better under high
    contention.*/
    init();
    getLockManager();
    if (isTxnOpen()) {
      throw new LockException("Transaction already opened. " + JavaUtils.txnIdToString(txnId));
    }
    try {
      replPolicy = ctx.getReplPolicy();
      if (replPolicy != null) {
        txnId = getMS().replOpenTxn(replPolicy, null, user, txnType).get(0);
      } else {
        txnId = getMS().openTxn(user, txnType);
      }
      stmtId = 0;
      numStatements = 0;
      tableWriteIds.clear();
      shouldReallocateWriteIds = false;
      isExplicitTransaction = false;
      startTransactionCount = 0;
      this.queryId = ctx.getConf().get(HiveConf.ConfVars.HIVE_QUERY_ID.varname);
      LOG.info("Opened " + JavaUtils.txnIdToString(txnId));
      ctx.setHeartbeater(startHeartbeat(delay));
      return txnId;
    } catch (TException e) {
      throw new LockException(e, ErrorMsg.METASTORE_COMMUNICATION_FAILED);
    }
  }
We do this on every call to make sure TM uses same MS connection as is used by the caller (Driver,
SemanticAnalyzer, etc).  {@code Hive} instances are cached using ThreadLocal and
{@link IMetaStoreClient} is cached within {@code Hive} with additional logic.  Futhermore, this
ensures that multiple threads are not sharing the same Thrift client (which could happen
if we had cached {@link IMetaStoreClient} here.

ThreadLocal gets cleaned up automatically when its thread goes away
https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html.  This is especially
important for threads created by {@link #heartbeatExecutorService} threads.

Embedded {@link DbLockManager} follows the same logic.
@return IMetaStoreClient
@throws LockException on any errors
ql/src/java/org/apache/hadoop/hive/ql/lockmgr/DbTxnManager.java