diff --git common/src/java/org/apache/hadoop/hive/conf/HiveConf.java common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 608a37745b..45a839f1f8 100644 --- common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -383,6 +383,9 @@ public void setSparkConfigUpdated(boolean isSparkConfigUpdated) { MAPREDTASKCLEANUPNEEDED(ShimLoader.getHadoopShims().getHadoopConfNames().get("MAPREDTASKCLEANUPNEEDED"), false, "", true), // Metastore stuff. Be sure to update HiveConf.metaVars when you add something here! + METASTORE_CLIENT_FACTORY_CLASS("hive.metastore.client.factory.class", + "org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClientFactory", + "The name of the factory class that produces objects implementing the IMetaStoreClient interface."), METASTOREWAREHOUSE("hive.metastore.warehouse.dir", "/user/hive/warehouse", "location of default database for the warehouse"), METASTOREURIS("hive.metastore.uris", "", diff --git ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java index bc99b225a9..f95d54a667 100644 --- ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java +++ ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java @@ -118,6 +118,7 @@ import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.mapred.InputFormat; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.StringUtils; import org.apache.thrift.TException; @@ -2969,8 +2970,7 @@ public void exchangeTablePartitions(Map partitionSpecs, } /** - * Creates a metastore client. Currently it creates only JDBC based client as - * File based store support is removed + * Creates a metastore client using a factory specified via HiveConf. * * @returns a Meta Store Client * @throws HiveMetaException @@ -3002,8 +3002,26 @@ public HiveMetaHook getHook( } } }; - return RetryingMetaStoreClient.getProxy(conf, hookLoader, metaCallTimeMap, - SessionHiveMetaStoreClient.class.getName()); + + HiveMetaStoreClientFactory factory = createMetaStoreClientFactory(); + return factory.createMetaStoreClient(conf, hookLoader); + } + + private HiveMetaStoreClientFactory createMetaStoreClientFactory() throws MetaException { + String metaStoreClientFactoryClassName = conf + .getVar(HiveConf.ConfVars.METASTORE_CLIENT_FACTORY_CLASS); + + try { + Class factoryClass = conf.getClassByName( + metaStoreClientFactoryClassName).asSubclass(HiveMetaStoreClientFactory.class); + return ReflectionUtils.newInstance(factoryClass, conf); + } catch (Exception e) { + String errorMessage = String.format( + "Unable to instantiate a metastore client factory %s due to: %s", + metaStoreClientFactoryClassName, e); + LOG.error(errorMessage, e); + throw new MetaException(errorMessage); + } } /** diff --git ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMetaStoreClientFactory.java ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMetaStoreClientFactory.java new file mode 100644 index 0000000000..28ef322535 --- /dev/null +++ ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMetaStoreClientFactory.java @@ -0,0 +1,48 @@ +/** + * 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.ql.metadata; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.metastore.HiveMetaHookLoader; +import org.apache.hadoop.hive.metastore.IMetaStoreClient; +import org.apache.hadoop.hive.metastore.api.MetaException; + +/** + * Abstract factory that defines an interface for other factories that produce concrete + * MetaStoreClient objects. + * + */ +public interface HiveMetaStoreClientFactory { + + /** + * A method for producing IMetaStoreClient objects. + * + * The implementation returned by this method must throw a MetaException if allowEmbedded = true + * and it does not support embedded mode. + * + * @param conf + * Hive Configuration. + * @param hookLoader + * Hook for handling events related to tables. + * @return IMetaStoreClient An implementation of IMetaStoreClient. + * @throws MetaException + */ + IMetaStoreClient createMetaStoreClient(HiveConf conf, HiveMetaHookLoader hookLoader) + throws MetaException; +} \ No newline at end of file diff --git ql/src/java/org/apache/hadoop/hive/ql/metadata/SessionHiveMetaStoreClientFactory.java ql/src/java/org/apache/hadoop/hive/ql/metadata/SessionHiveMetaStoreClientFactory.java new file mode 100644 index 0000000000..34aab051df --- /dev/null +++ ql/src/java/org/apache/hadoop/hive/ql/metadata/SessionHiveMetaStoreClientFactory.java @@ -0,0 +1,46 @@ +/** + * 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.ql.metadata; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.metastore.HiveMetaHookLoader; +import org.apache.hadoop.hive.metastore.IMetaStoreClient; +import org.apache.hadoop.hive.metastore.RetryingMetaStoreClient; +import org.apache.hadoop.hive.metastore.api.MetaException; + +/** + * Default MetaStoreClientFactory for Hive which produces SessionHiveMetaStoreClient objects. + * + */ +public final class SessionHiveMetaStoreClientFactory implements HiveMetaStoreClientFactory { + + @Override + public IMetaStoreClient createMetaStoreClient(HiveConf conf, HiveMetaHookLoader hookLoader) + throws MetaException { + + checkNotNull(conf, "conf cannot be null!"); + checkNotNull(hookLoader, "hookLoader cannot be null!"); + + return RetryingMetaStoreClient.getProxy(conf, hookLoader, + SessionHiveMetaStoreClient.class.getName()); + } + +} diff --git ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java index 99fbd5dd80..a66d580dd4 100755 --- ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java +++ ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java @@ -19,6 +19,8 @@ package org.apache.hadoop.hive.ql.metadata; import static org.apache.hadoop.hive.metastore.MetaStoreUtils.DEFAULT_DATABASE_NAME; +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.instanceOf; import java.io.StringWriter; import java.util.ArrayList; @@ -36,6 +38,7 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hadoop.hive.metastore.IMetaStoreClient; import org.apache.hadoop.hive.metastore.MetaStoreUtils; import org.apache.hadoop.hive.metastore.PartitionDropOptions; import org.apache.hadoop.hive.metastore.Warehouse; @@ -821,6 +824,35 @@ public void testHiveRefreshOnConfChange() throws Throwable{ newHiveObj = Hive.get(newHconf); assertTrue(prevHiveObj != newHiveObj); } + + public void testLoadingHiveMetaStoreClientFactory() throws Throwable { + String factoryClassName = SessionHiveMetaStoreClientFactory.class.getName(); + HiveConf conf = new HiveConf(); + conf.setVar(ConfVars.METASTORE_CLIENT_FACTORY_CLASS, factoryClassName); + // The current object was constructed in setUp() before we got here + // so clean that up so we can inject our own implementation of IMetaStoreClient + Hive.closeCurrent(); + Hive hive = Hive.get(conf); + IMetaStoreClient msc = hive.getMSC(); + assertNotNull("getMSC() failed.", msc); + } + + public void testLoadingInvalidHiveMetaStoreClientFactory() throws Throwable { + // Intentionally invalid class + String factoryClassName = String.class.getName(); + HiveConf conf = new HiveConf(); + conf.setVar(HiveConf.ConfVars.METASTORE_CLIENT_FACTORY_CLASS, factoryClassName); + // The current object was constructed in setUp() before we got here + // so clean that up so we can inject our own implementation of IMetaStoreClient + Hive.closeCurrent(); + Hive hive = Hive.get(conf); + try { + hive.getMSC(); + fail("getMSC() was expected to throw MetaException."); + } catch (Exception e) { + return; + } + } // shamelessly copied from Path in hadoop-2 private static final String SEPARATOR = "/";