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 609b7a4b993 HIVE-27284: Make HMSHandler proxy pluggable (Wechar Yu, 
reviewed by Denys Kuzmenko, Zhihua Deng)
609b7a4b993 is described below

commit 609b7a4b993570189385a74b1c6c77264e0883a7
Author: Wechar Yu <[email protected]>
AuthorDate: Sun Jun 25 01:30:52 2023 +0800

    HIVE-27284: Make HMSHandler proxy pluggable (Wechar Yu, reviewed by Denys 
Kuzmenko, Zhihua Deng)
    
    Closes #4257
---
 .../org/apache/iceberg/hive/TestHiveMetastore.java |  6 +-
 .../hadoop/hive/metastore/HiveMetaStoreClient.java |  8 +-
 .../hadoop/hive/metastore/conf/MetastoreConf.java  |  5 ++
 .../hadoop/hive/metastore/utils/JavaUtils.java     |  4 +-
 .../hive/metastore/AbstractHMSHandlerProxy.java    | 96 ++++++++++++++++++++++
 .../apache/hadoop/hive/metastore/HMSHandler.java   | 22 -----
 .../hive/metastore/HMSHandlerProxyFactory.java     | 59 +++++++++++++
 .../hadoop/hive/metastore/HiveMetaStore.java       | 20 ++---
 .../hadoop/hive/metastore/RetryingHMSHandler.java  | 90 ++++----------------
 .../hive/metastore/TestHiveMetaStoreTimeout.java   | 56 +++++++++++--
 .../metastore/TestRetriesInRetryingHMSHandler.java | 28 ++++---
 .../hive/metastore/conf/TestMetastoreConf.java     |  5 +-
 12 files changed, 258 insertions(+), 141 deletions(-)

diff --git 
a/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveMetastore.java
 
b/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveMetastore.java
index 76eb87b21b5..6af2e050755 100644
--- 
a/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveMetastore.java
+++ 
b/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveMetastore.java
@@ -29,9 +29,9 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.metastore.HMSHandler;
+import org.apache.hadoop.hive.metastore.HMSHandlerProxyFactory;
 import org.apache.hadoop.hive.metastore.IHMSHandler;
 import org.apache.hadoop.hive.metastore.IMetaStoreClient;
-import org.apache.hadoop.hive.metastore.RetryingHMSHandler;
 import org.apache.hadoop.hive.metastore.TSetIpAddressProcessor;
 import org.apache.hadoop.hive.metastore.api.GetTableRequest;
 import org.apache.hadoop.hive.metastore.api.Table;
@@ -67,8 +67,8 @@ public class TestHiveMetastore {
           .build();
 
   private static final DynMethods.StaticMethod GET_BASE_HMS_HANDLER = 
DynMethods.builder("getProxy")
-          .impl(RetryingHMSHandler.class, Configuration.class, 
IHMSHandler.class, boolean.class)
-          .impl(RetryingHMSHandler.class, HiveConf.class, IHMSHandler.class, 
boolean.class)
+          .impl(HMSHandlerProxyFactory.class, Configuration.class, 
IHMSHandler.class, boolean.class)
+          .impl(HMSHandlerProxyFactory.class, HiveConf.class, 
IHMSHandler.class, boolean.class)
           .buildStatic();
 
   // Hive3 introduces background metastore tasks (MetastoreTaskThread) for 
performing various cleanup duties. These
diff --git 
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java
 
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java
index d3e3479899a..503183b4532 100644
--- 
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java
+++ 
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java
@@ -138,8 +138,8 @@ public class HiveMetaStoreClient implements 
IMetaStoreClient, AutoCloseable {
       "org.apache.hadoop.hive.metastore.HiveMetaStore";
 
   // Method used to create Hive Metastore client. It is called as
-  // HiveMetaStore.newRetryingHMSHandler("hive client", this.conf, true);
-  private static final String HIVE_METASTORE_CREATE_HANDLER_METHOD = 
"newRetryingHMSHandler";
+  // HiveMetaStore.newHMSHandler("hive client", this.conf, true);
+  private static final String HIVE_METASTORE_CREATE_HANDLER_METHOD = 
"newHMSHandler";
 
   ThriftHiveMetastore.Iface client = null;
   private TTransport transport = null;
@@ -292,10 +292,10 @@ public class HiveMetaStoreClient implements 
IMetaStoreClient, AutoCloseable {
     //
     // The code below simulates the following code
     //
-    // client = HiveMetaStore.newRetryingHMSHandler(this.conf);
+    // client = HiveMetaStore.newHMSHandler(this.conf);
     //
     // using reflection API. This is done to avoid dependency of 
MetastoreClient on Hive Metastore.
-    // Note that newRetryingHMSHandler is static method, so we pass null as 
the object reference.
+    // Note that newHMSHandler is static method, so we pass null as the object 
reference.
     //
     try {
       Class<?> clazz = Class.forName(HIVE_METASTORE_CLASS);
diff --git 
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
 
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
index 62ea1a63eae..c1354341c34 100644
--- 
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
+++ 
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
@@ -105,6 +105,8 @@ public class MetastoreConf {
 
   public static final String 
METASTORE_AUTHENTICATION_LDAP_USERMEMBERSHIPKEY_NAME =
           "metastore.authentication.ldap.userMembershipKey";
+  public static final String METASTORE_RETRYING_HANDLER_CLASS =
+          "org.apache.hadoop.hive.metastore.RetryingHMSHandler";
 
   private static final Map<String, ConfVars> metaConfs = new HashMap<>();
   private static volatile URL hiveSiteURL = null;
@@ -874,6 +876,9 @@ public class MetastoreConf {
             "testing only."),
     HMS_HANDLER_INTERVAL("metastore.hmshandler.retry.interval", 
"hive.hmshandler.retry.interval",
         2000, TimeUnit.MILLISECONDS, "The time between HMSHandler retry 
attempts on failure."),
+    HMS_HANDLER_PROXY_CLASS("metastore.hmshandler.proxy", 
"hive.metastore.hmshandler.proxy",
+        METASTORE_RETRYING_HANDLER_CLASS,
+        "The proxy class name of HMSHandler, default is RetryingHMSHandler."),
     IDENTIFIER_FACTORY("datanucleus.identifierFactory",
         "datanucleus.identifierFactory", "datanucleus1",
         "Name of the identifier factory to use when generating table/column 
names etc. \n" +
diff --git 
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/utils/JavaUtils.java
 
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/utils/JavaUtils.java
index b08d9fd71f6..503345d043d 100644
--- 
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/utils/JavaUtils.java
+++ 
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/utils/JavaUtils.java
@@ -17,6 +17,7 @@
  */
 package org.apache.hadoop.hive.metastore.utils;
 
+import org.apache.commons.lang3.ClassUtils;
 import org.apache.hadoop.hive.metastore.api.MetaException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,7 +72,8 @@ public class JavaUtils {
           "Number of constructor parameter types doesn't match number of 
arguments");
     }
     for (int i = 0; i < parameterTypes.length; i++) {
-      Class<?> clazz = parameterTypes[i];
+      // initargs are boxed to Object, so we need to wrapper primitive types 
here.
+      Class<?> clazz = ClassUtils.primitiveToWrapper(parameterTypes[i]);
       if (initargs[i] != null && !(clazz.isInstance(initargs[i]))) {
         throw new IllegalArgumentException("Object : " + initargs[i]
             + " is not an instance of " + clazz);
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/AbstractHMSHandlerProxy.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/AbstractHMSHandlerProxy.java
new file mode 100644
index 00000000000..539765c1514
--- /dev/null
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/AbstractHMSHandlerProxy.java
@@ -0,0 +1,96 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.MetaStoreInit.MetaStoreInitData;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars;
+import org.apache.hadoop.hive.metastore.metrics.PerfLogger;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AbstractHMSHandlerProxy implements InvocationHandler {
+  protected final MetaStoreInitData metaStoreInitData = new 
MetaStoreInitData();
+  protected final IHMSHandler baseHandler;
+  protected final Configuration origConf;    // base configuration
+  protected final Configuration activeConf;  // active configuration
+  protected final boolean reloadConf;
+  protected final long timeout;
+
+  public AbstractHMSHandlerProxy(Configuration conf, IHMSHandler baseHandler, 
boolean local)
+      throws MetaException {
+    this.origConf = conf;
+    this.baseHandler = baseHandler;
+    if (local) {
+      baseHandler.setConf(origConf); // tests expect configuration changes 
applied directly to metastore
+    }
+    activeConf = baseHandler.getConf();
+    reloadConf = MetastoreConf.getBoolVar(origConf, 
ConfVars.HMS_HANDLER_FORCE_RELOAD_CONF);
+    timeout = MetastoreConf.getTimeVar(origConf,
+            ConfVars.CLIENT_SOCKET_TIMEOUT, TimeUnit.MILLISECONDS);
+
+    // This has to be called before initializing the instance of HMSHandler
+    // Using the hook on startup ensures that the hook always has priority
+    // over settings in *.xml.  The thread local conf needs to be used because 
at this point
+    // it has already been initialized using hiveConf.
+    MetaStoreInit.updateConnectionURL(origConf, getActiveConf(), null, 
metaStoreInitData);
+    initBaseHandler();
+  }
+
+  static final class Result {
+    static final Result ERROR_RESULT = new Result(null, "error=true");
+    private final Object result;
+    private final String additionalInfo;
+
+    public Result(Object result, String additionalInfo) {
+      this.result = result;
+      this.additionalInfo = additionalInfo;
+    }
+  }
+
+  protected void initBaseHandler() throws MetaException {
+    baseHandler.init();
+  }
+
+  @Override
+  public Object invoke(Object proxy, Method method, Object[] objects) throws 
Throwable {
+    PerfLogger perfLogger = PerfLogger.getPerfLogger(false);
+    perfLogger.perfLogBegin(this.getClass().getName(), method.getName());
+    Result result = Result.ERROR_RESULT;
+    Deadline.registerIfNot(timeout);
+    try {
+      result = invokeInternal(proxy, method, objects);
+      return result == null ? null : result.result;
+    } finally {
+      String info = result == null ? "" : result.additionalInfo;
+      perfLogger.perfLogEnd(this.getClass().getName(), method.getName(), info);
+    }
+  }
+
+  protected abstract Result invokeInternal(Object proxy, Method method, 
Object[] args)
+      throws Throwable;
+
+  public Configuration getActiveConf() {
+    return activeConf;
+  }
+}
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
index 4f38f986b81..e0cc6486676 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
@@ -143,12 +143,6 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
   public static final String PARTITION_NUMBER_EXCEED_LIMIT_MSG =
       "Number of partitions scanned (=%d) on table '%s' exceeds limit (=%d). 
This is controlled on the metastore server by %s.";
 
-  // Used for testing to simulate method timeout.
-  @VisibleForTesting
-  static boolean testTimeoutEnabled = false;
-  @VisibleForTesting
-  static long testTimeoutValue = -1;
-
   public static final String ADMIN = "admin";
   public static final String PUBLIC = "public";
 
@@ -1345,14 +1339,6 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
         // expected
       }
 
-      if (testTimeoutEnabled) {
-        try {
-          Thread.sleep(testTimeoutValue);
-        } catch (InterruptedException e) {
-          // do nothing
-        }
-        Deadline.checkTimeout();
-      }
       create_database_core(getMS(), db);
       success = true;
     } catch (Exception e) {
@@ -1892,14 +1878,6 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
       } catch (NoSuchObjectException e) {
         // expected
       }
-      if (testTimeoutEnabled) {
-        try {
-          Thread.sleep(testTimeoutValue);
-        } catch (InterruptedException e) {
-          // do nothing
-        }
-        Deadline.checkTimeout();
-      }
       create_dataconnector_core(getMS(), connector);
       success = true;
     } catch (Exception e) {
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandlerProxyFactory.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandlerProxyFactory.java
new file mode 100644
index 00000000000..b0a16ba71d2
--- /dev/null
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandlerProxyFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hive.metastore;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars;
+import org.apache.hadoop.hive.metastore.utils.JavaUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Proxy;
+
+public class HMSHandlerProxyFactory {
+  private static final Logger LOG = 
LoggerFactory.getLogger(HMSHandlerProxyFactory.class);
+
+  public static IHMSHandler getProxy(Configuration conf, IHMSHandler handler, 
boolean local)
+      throws MetaException {
+    String hmsHandlerProxyName = MetastoreConf.getVar(conf, 
ConfVars.HMS_HANDLER_PROXY_CLASS);
+    LOG.info("Creating HMSHandler proxy by class: {}", hmsHandlerProxyName);
+    Class<? extends AbstractHMSHandlerProxy> proxyClass =
+            JavaUtils.getClass(hmsHandlerProxyName, 
AbstractHMSHandlerProxy.class);
+    AbstractHMSHandlerProxy invocationHandler = null;
+    try {
+      invocationHandler = JavaUtils.newInstance(proxyClass,
+          new Class[]{Configuration.class, IHMSHandler.class, boolean.class},
+          new Object[]{conf, handler, local});
+    } catch (Throwable t) {
+      // Reflection by JavaUtils will throw RuntimeException, try to get real 
MetaException here.
+      Throwable rootCause = ExceptionUtils.getRootCause(t);
+      if (rootCause instanceof Exception) {
+        throw ExceptionHandler.newMetaException((Exception) rootCause);
+      }
+      throw t;
+    }
+
+    return (IHMSHandler) Proxy.newProxyInstance(
+            HMSHandlerProxyFactory.class.getClassLoader(),
+            new Class[]{ IHMSHandler.class }, invocationHandler);
+  }
+}
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java
index 40f5fe37991..4e49b76f6f9 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java
@@ -136,18 +136,8 @@ public class HiveMetaStore extends ThriftHiveMetastore {
     return true;
   }
 
-  private static IHMSHandler newRetryingHMSHandler(IHMSHandler baseHandler, 
Configuration conf)
-      throws MetaException {
-    return newRetryingHMSHandler(baseHandler, conf, false);
-  }
-
-  private static IHMSHandler newRetryingHMSHandler(IHMSHandler baseHandler, 
Configuration conf,
-      boolean local) throws MetaException {
-    return RetryingHMSHandler.getProxy(conf, baseHandler, local);
-  }
-
   /**
-   * Create retrying HMS handler for embedded metastore.
+   * Create HMS handler for embedded metastore.
    *
    * <h1>IMPORTANT</h1>
    *
@@ -158,10 +148,10 @@ public class HiveMetaStore extends ThriftHiveMetastore {
    * @param conf configuration to use
    * @throws MetaException
    */
-  static Iface newRetryingHMSHandler(Configuration conf)
+  static Iface newHMSHandler(Configuration conf)
       throws MetaException {
     HMSHandler baseHandler = new HMSHandler("hive client", conf);
-    return RetryingHMSHandler.getProxy(conf, baseHandler, true);
+    return HMSHandlerProxyFactory.getProxy(conf, baseHandler, true);
   }
 
   /**
@@ -453,7 +443,7 @@ public class HiveMetaStore extends ThriftHiveMetastore {
     }
 
     HMSHandler baseHandler = new HMSHandler("new db based metaserver", conf);
-    IHMSHandler handler = newRetryingHMSHandler(baseHandler, conf);
+    IHMSHandler handler = HMSHandlerProxyFactory.getProxy(conf, baseHandler, 
false);
     processor = new ThriftHiveMetastore.Processor<>(handler);
     LOG.info("Starting DB backed MetaStore Server with generic processor");
     TServlet thriftHttpServlet = new HmsThriftHttpServlet(processor, 
protocolFactory, conf);
@@ -564,7 +554,7 @@ public class HiveMetaStore extends ThriftHiveMetastore {
       LOG.info("Binding host " + msHost + " for metastore server");
     }
     
-    IHMSHandler handler = newRetryingHMSHandler(baseHandler, conf);
+    IHMSHandler handler = HMSHandlerProxyFactory.getProxy(conf, baseHandler, 
false);
     TServerSocket serverSocket;
     if (useSasl) {
       processor = saslServer.wrapProcessor(
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/RetryingHMSHandler.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/RetryingHMSHandler.java
index 7774dfe5d46..ce7656fdb0c 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/RetryingHMSHandler.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/RetryingHMSHandler.java
@@ -18,10 +18,8 @@
 
 package org.apache.hadoop.hive.metastore;
 
-import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 import java.lang.reflect.UndeclaredThrowableException;
 import java.sql.SQLException;
 import java.sql.SQLIntegrityConstraintViolationException;
@@ -35,7 +33,6 @@ import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
 import org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars;
-import org.apache.hadoop.hive.metastore.metrics.PerfLogger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.hadoop.conf.Configuration;
@@ -45,45 +42,23 @@ import org.datanucleus.exceptions.NucleusException;
 
 @InterfaceAudience.Private
 @InterfaceStability.Evolving
-public class RetryingHMSHandler implements InvocationHandler {
-
+public class RetryingHMSHandler extends AbstractHMSHandlerProxy {
   private static final Logger LOG = 
LoggerFactory.getLogger(RetryingHMSHandler.class);
-  private static final String CLASS_NAME = RetryingHMSHandler.class.getName();
   private static final Class<SQLException>[] unrecoverableSqlExceptions = new 
Class[]{
       // TODO: collect more unrecoverable SQLExceptions
       SQLIntegrityConstraintViolationException.class
   };
 
+  private final long retryInterval;
+  private final int retryLimit;
 
-  private static class Result {
-    private final Object result;
-    private final int numRetries;
-
-    public Result(Object result, int numRetries) {
-      this.result = result;
-      this.numRetries = numRetries;
-    }
-  }
-
-  private final IHMSHandler baseHandler;
-  private final MetaStoreInit.MetaStoreInitData metaStoreInitData =
-    new MetaStoreInit.MetaStoreInitData();
-
-  private final Configuration origConf;            // base configuration
-  private final Configuration activeConf;  // active configuration
+  public RetryingHMSHandler(Configuration conf, IHMSHandler baseHandler, 
boolean local)
+      throws MetaException {
+    super(conf, baseHandler, local);
+    retryInterval = MetastoreConf.getTimeVar(origConf,
+        ConfVars.HMS_HANDLER_INTERVAL, TimeUnit.MILLISECONDS);
+    retryLimit = MetastoreConf.getIntVar(origConf, 
ConfVars.HMS_HANDLER_ATTEMPTS);
 
-  private RetryingHMSHandler(Configuration origConf, IHMSHandler baseHandler, 
boolean local) throws MetaException {
-    this.origConf = origConf;
-    this.baseHandler = baseHandler;
-    if (local) {
-      baseHandler.setConf(origConf); // tests expect configuration changes 
applied directly to metastore
-    }
-    activeConf = baseHandler.getConf();
-    // This has to be called before initializing the instance of HMSHandler
-    // Using the hook on startup ensures that the hook always has priority
-    // over settings in *.xml.  The thread local conf needs to be used because 
at this point
-    // it has already been initialized using hiveConf.
-    MetaStoreInit.updateConnectionURL(origConf, getActiveConf(), null, 
metaStoreInitData);
     try {
       //invoking init method of baseHandler this way since it adds the retry 
logic
       //in case of transient failures in init method
@@ -97,46 +72,13 @@ public class RetryingHMSHandler implements 
InvocationHandler {
     }
   }
 
-  public static IHMSHandler getProxy(Configuration conf, IHMSHandler 
baseHandler, boolean local)
-      throws MetaException {
-
-    RetryingHMSHandler handler = new RetryingHMSHandler(conf, baseHandler, 
local);
-
-    return (IHMSHandler) Proxy.newProxyInstance(
-      RetryingHMSHandler.class.getClassLoader(),
-      new Class[] { IHMSHandler.class }, handler);
-  }
-
   @Override
-  public Object invoke(final Object proxy, final Method method, final Object[] 
args) throws Throwable {
-    int retryCount = -1;
-    boolean error = true;
-    PerfLogger perfLogger = PerfLogger.getPerfLogger(false);
-    perfLogger.perfLogBegin(CLASS_NAME, method.getName());
-    try {
-      Result result = invokeInternal(proxy, method, args);
-      retryCount = result.numRetries;
-      error = false;
-      return result.result;
-    } finally {
-      StringBuilder additionalInfo = new StringBuilder();
-      additionalInfo.append("retryCount=").append(retryCount)
-        .append(" error=").append(error);
-      perfLogger.perfLogEnd(CLASS_NAME, method.getName(), 
additionalInfo.toString());
-    }
+  protected void initBaseHandler() throws MetaException {
+    // init operation has finished in constructor. noop here.
   }
 
   public Result invokeInternal(final Object proxy, final Method method, final 
Object[] args) throws Throwable {
-
     boolean gotNewConnectUrl = false;
-    boolean reloadConf = MetastoreConf.getBoolVar(origConf, 
ConfVars.HMS_HANDLER_FORCE_RELOAD_CONF);
-    long retryInterval = MetastoreConf.getTimeVar(origConf,
-        ConfVars.HMS_HANDLER_INTERVAL, TimeUnit.MILLISECONDS);
-    int retryLimit = MetastoreConf.getIntVar(origConf, 
ConfVars.HMS_HANDLER_ATTEMPTS);
-    long timeout = MetastoreConf.getTimeVar(origConf,
-        ConfVars.CLIENT_SOCKET_TIMEOUT, TimeUnit.MILLISECONDS);
-
-    Deadline.registerIfNot(timeout);
 
     if (reloadConf) {
       MetaStoreInit.updateConnectionURL(origConf, getActiveConf(),
@@ -159,8 +101,10 @@ public class RetryingHMSHandler implements 
InvocationHandler {
             Deadline.stopTimer();
           }
         }
-        return new Result(object, retryCount);
-
+        StringBuilder additionalInfo = new StringBuilder();
+        additionalInfo.append("retryCount=").append(retryCount)
+            .append(" error=").append(false);
+        return new Result(object, additionalInfo.toString());
       } catch (UndeclaredThrowableException e) {
         if (e.getCause() != null) {
           if (e.getCause() instanceof javax.jdo.JDOException) {
@@ -245,8 +189,4 @@ public class RetryingHMSHandler implements 
InvocationHandler {
     return Stream.of(unrecoverableSqlExceptions)
                  .allMatch(ex -> ExceptionUtils.indexOfType(t, ex) < 0);
   }
-
-  public Configuration getActiveConf() {
-    return activeConf;
-  }
 }
diff --git 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTimeout.java
 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTimeout.java
index 7588f0d9941..66331ddcbfb 100644
--- 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTimeout.java
+++ 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTimeout.java
@@ -18,8 +18,11 @@
 
 package org.apache.hadoop.hive.metastore;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.lang.reflect.Method;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hadoop.conf.Configuration;
@@ -32,7 +35,6 @@ import 
org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars;
 import org.apache.thrift.TException;
 import org.apache.thrift.transport.TTransportException;
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -40,8 +42,7 @@ import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 /**
- * Test long running request timeout functionality in MetaStore Server
- * HMSHandler.create_database() is used to simulate a long running method.
+ * Test long running request timeout functionality in MetaStore Server.
  */
 @Category(MetastoreCheckinTest.class)
 public class TestHiveMetaStoreTimeout {
@@ -52,6 +53,42 @@ public class TestHiveMetaStoreTimeout {
 
   private final String dbName = "db";
   
+  /** Test handler proxy used to simulate a long-running create_database() 
method */
+  static class DelayedHMSHandler extends AbstractHMSHandlerProxy {
+    static long testTimeoutValue = -1;
+    public DelayedHMSHandler(Configuration conf, IHMSHandler baseHandler, 
boolean local)
+        throws MetaException {
+      super(conf, baseHandler, local);
+    }
+
+    @Override
+    protected Result invokeInternal(Object proxy, Method method, Object[] args)
+        throws Throwable {
+      try {
+        boolean isStarted = Deadline.startTimer(method.getName());
+        Object object;
+        try {
+          if (testTimeoutValue > 0 && 
method.getName().equals("create_database")) {
+            try {
+              Thread.sleep(testTimeoutValue);
+            } catch (InterruptedException e) {
+              // do nothing.
+            }
+            Deadline.checkTimeout();
+          }
+          object = method.invoke(baseHandler, args);
+        } finally {
+          if (isStarted) {
+            Deadline.stopTimer();
+          }
+        }
+        return new Result(object, "error=false");
+      } catch (UndeclaredThrowableException | InvocationTargetException e) {
+        throw e.getCause();
+      }
+    }
+  }
+
   @BeforeClass
   public static void startMetaStoreServer() throws Exception {
     conf = MetastoreConf.newMetastoreConf();
@@ -59,6 +96,7 @@ public class TestHiveMetaStoreTimeout {
         MockPartitionExpressionForMetastore.class, 
PartitionExpressionProxy.class);
     MetastoreConf.setTimeVar(conf, ConfVars.CLIENT_SOCKET_TIMEOUT, 2000,
         TimeUnit.MILLISECONDS);
+    MetastoreConf.setVar(conf, ConfVars.HMS_HANDLER_PROXY_CLASS, 
DelayedHMSHandler.class.getName());
     MetaStoreTestUtils.setConfForStandloneMode(conf);
     warehouse = new Warehouse(conf);
     port = MetaStoreTestUtils.startMetaStoreWithRetry(conf);
@@ -68,8 +106,7 @@ public class TestHiveMetaStoreTimeout {
 
   @Before
   public void setup() throws MetaException {
-    HMSHandler.testTimeoutEnabled = false;
-    HMSHandler.testTimeoutValue = -1;
+    DelayedHMSHandler.testTimeoutValue = -1;
     client = new HiveMetaStoreClient(conf);
   }
 
@@ -90,8 +127,7 @@ public class TestHiveMetaStoreTimeout {
 
   @Test
   public void testTimeout() throws Exception {
-    HMSHandler.testTimeoutEnabled = true;
-    HMSHandler.testTimeoutValue = 4000;
+    DelayedHMSHandler.testTimeoutValue = 4000;
 
     Database db = new DatabaseBuilder()
         .setName(dbName)
@@ -102,6 +138,9 @@ public class TestHiveMetaStoreTimeout {
     } catch (TTransportException e) {
       Assert.assertTrue("unexpected Exception", e.getMessage().contains("Read 
timed out"));
     }
+
+    // restore
+    DelayedHMSHandler.testTimeoutValue = -1;
   }
 
   @Test
@@ -117,8 +156,7 @@ public class TestHiveMetaStoreTimeout {
     client.dropDatabase(dbName, true, true);
 
     // reset
-    HMSHandler.testTimeoutEnabled = true;
-    HMSHandler.testTimeoutValue = 4000;
+    DelayedHMSHandler.testTimeoutValue = 4000;
 
     // timeout after reset
     try {
diff --git 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestRetriesInRetryingHMSHandler.java
 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestRetriesInRetryingHMSHandler.java
index b970c54006f..4c4905deb0a 100644
--- 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestRetriesInRetryingHMSHandler.java
+++ 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestRetriesInRetryingHMSHandler.java
@@ -48,6 +48,8 @@ public class TestRetriesInRetryingHMSHandler {
   @BeforeClass
   public static void setup() throws IOException {
     conf = MetastoreConf.newMetastoreConf();
+    MetastoreConf.setVar(conf, ConfVars.HMS_HANDLER_PROXY_CLASS,
+        MetastoreConf.METASTORE_RETRYING_HANDLER_CLASS);
     MetastoreConf.setLongVar(conf, ConfVars.HMS_HANDLER_ATTEMPTS, 
RETRY_ATTEMPTS);
     MetastoreConf.setTimeVar(conf, ConfVars.HMS_HANDLER_INTERVAL, 10, 
TimeUnit.MILLISECONDS);
     MetastoreConf.setBoolVar(conf, ConfVars.HMS_HANDLER_FORCE_RELOAD_CONF, 
false);
@@ -65,7 +67,7 @@ public class TestRetriesInRetryingHMSHandler {
     .doThrow(JDOException.class)
     .doNothing()
     .when(mockBaseHandler).init();
-    RetryingHMSHandler.getProxy(conf, mockBaseHandler, false);
+    HMSHandlerProxyFactory.getProxy(conf, mockBaseHandler, false);
     Mockito.verify(mockBaseHandler, Mockito.times(2)).init();
   }
 
@@ -77,7 +79,7 @@ public class TestRetriesInRetryingHMSHandler {
     IHMSHandler mockBaseHandler = Mockito.mock(IHMSHandler.class);
     Mockito.when(mockBaseHandler.getConf()).thenReturn(conf);
     Mockito.doNothing().when(mockBaseHandler).init();
-    RetryingHMSHandler.getProxy(conf, mockBaseHandler, false);
+    HMSHandlerProxyFactory.getProxy(conf, mockBaseHandler, false);
     Mockito.verify(mockBaseHandler, Mockito.times(1)).init();
   }
 
@@ -85,13 +87,18 @@ public class TestRetriesInRetryingHMSHandler {
    * If the init method in HMSHandler throws exception all the times it should 
be retried until
    * HiveConf.ConfVars.HMSHANDLERATTEMPTS is reached before giving up
    */
-  @Test(expected = MetaException.class)
+  @Test
   public void testRetriesLimit() throws MetaException {
     IHMSHandler mockBaseHandler = Mockito.mock(IHMSHandler.class);
     Mockito.when(mockBaseHandler.getConf()).thenReturn(conf);
     Mockito.doThrow(JDOException.class).when(mockBaseHandler).init();
-    RetryingHMSHandler.getProxy(conf, mockBaseHandler, false);
-    Mockito.verify(mockBaseHandler, Mockito.times(RETRY_ATTEMPTS)).init();
+    try {
+      HMSHandlerProxyFactory.getProxy(conf, mockBaseHandler, false);
+      Assert.fail("should fail for mockBaseHandler init.");
+    } catch (MetaException e) {
+      // expected
+    }
+    Mockito.verify(mockBaseHandler, Mockito.times(RETRY_ATTEMPTS + 1)).init();
   }
 
   /*
@@ -110,7 +117,7 @@ public class TestRetriesInRetryingHMSHandler {
     .doThrow(me)
     .doNothing()
     .when(mockBaseHandler).init();
-    RetryingHMSHandler.getProxy(conf, mockBaseHandler, false);
+    HMSHandlerProxyFactory.getProxy(conf, mockBaseHandler, false);
     Mockito.verify(mockBaseHandler, Mockito.times(2)).init();
   }
 
@@ -132,7 +139,7 @@ public class TestRetriesInRetryingHMSHandler {
     InvocationTargetException ex = new InvocationTargetException(me);
     Mockito.doThrow(me).when(mockBaseHandler).getMS();
 
-    IHMSHandler retryingHandler = RetryingHMSHandler.getProxy(conf, 
mockBaseHandler, false);
+    IHMSHandler retryingHandler = HMSHandlerProxyFactory.getProxy(conf, 
mockBaseHandler, false);
     try {
       retryingHandler.getMS();
       Assert.fail("should throw the mocked MetaException");
@@ -159,7 +166,7 @@ public class TestRetriesInRetryingHMSHandler {
     InvocationTargetException ex = new InvocationTargetException(me);
     Mockito.doThrow(me).when(mockBaseHandler).getMS();
 
-    IHMSHandler retryingHandler = RetryingHMSHandler.getProxy(conf, 
mockBaseHandler, false);
+    IHMSHandler retryingHandler = HMSHandlerProxyFactory.getProxy(conf, 
mockBaseHandler, false);
     try {
       retryingHandler.getMS();
       Assert.fail("should throw the mocked MetaException");
@@ -185,14 +192,13 @@ public class TestRetriesInRetryingHMSHandler {
     InvocationTargetException ex = new InvocationTargetException(me);
     Mockito.doThrow(me).when(mockBaseHandler).getMS();
 
-    IHMSHandler retryingHandler = RetryingHMSHandler.getProxy(conf, 
mockBaseHandler, false);
+    IHMSHandler retryingHandler = HMSHandlerProxyFactory.getProxy(conf, 
mockBaseHandler, false);
     try {
       retryingHandler.getMS();
       Assert.fail("should throw the mocked MetaException");
     } catch (MetaException e) {
       // expected
     }
-    int retryTimes = MetastoreConf.getIntVar(conf, 
ConfVars.HMS_HANDLER_ATTEMPTS);
-    Mockito.verify(mockBaseHandler, Mockito.times(retryTimes + 1)).getMS();
+    Mockito.verify(mockBaseHandler, Mockito.times(RETRY_ATTEMPTS + 1)).getMS();
   }
 }
diff --git 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/conf/TestMetastoreConf.java
 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/conf/TestMetastoreConf.java
index 92ab7f9eeed..a5a8145ccbd 100644
--- 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/conf/TestMetastoreConf.java
+++ 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/conf/TestMetastoreConf.java
@@ -42,11 +42,12 @@ import java.util.Random;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader;
-import org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader;
 import org.apache.hadoop.hive.metastore.HiveAlterHandler;
 import org.apache.hadoop.hive.metastore.MaterializationsRebuildLockCleanerTask;
 import org.apache.hadoop.hive.metastore.MetastoreTaskThread;
+import org.apache.hadoop.hive.metastore.RetryingHMSHandler;
 import org.apache.hadoop.hive.metastore.RuntimeStatsCleanerTask;
+import org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader;
 import org.apache.hadoop.hive.metastore.events.EventCleanerTask;
 import 
org.apache.hadoop.hive.metastore.security.MetastoreDelegationTokenManager;
 import org.apache.hadoop.hive.metastore.txn.AcidHouseKeeperService;
@@ -491,6 +492,8 @@ public class TestMetastoreConf {
         MaterializationsRebuildLockCleanerTask.class.getName());
     Assert.assertEquals(MetastoreConf.METASTORE_TASK_THREAD_CLASS,
         MetastoreTaskThread.class.getName());
+    Assert.assertEquals(MetastoreConf.METASTORE_RETRYING_HANDLER_CLASS,
+        RetryingHMSHandler.class.getName());
     Assert.assertEquals(MetastoreConf.RUNTIME_STATS_CLEANER_TASK_CLASS,
         RuntimeStatsCleanerTask.class.getName());
     Assert.assertEquals(MetastoreConf.EVENT_CLEANER_TASK_CLASS,


Reply via email to