Index: shims/src/common/java/org/apache/hadoop/hive/thrift/TUGIContainingTransport.java =================================================================== --- shims/src/common/java/org/apache/hadoop/hive/thrift/TUGIContainingTransport.java (revision 1303878) +++ shims/src/common/java/org/apache/hadoop/hive/thrift/TUGIContainingTransport.java (working copy) @@ -18,9 +18,11 @@ package org.apache.hadoop.hive.thrift; +import java.net.Socket; import java.util.concurrent.ConcurrentMap; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportFactory; @@ -46,6 +48,18 @@ this.ugi = ugi; } + /** + * If the underlying TTransport is an instance of TSocket, it returns the Socket object + * which it contains. Otherwise it returns null. + */ + public Socket getSocket() { + if (wrapped instanceof TSocket) { + return (((TSocket)wrapped).getSocket()); + } + + return null; + } + /** Factory to create TUGIContainingTransport. */ Index: metastore/src/test/org/apache/hadoop/hive/metastore/TestRemoteUGIHiveMetaStoreIpAddress.java =================================================================== --- metastore/src/test/org/apache/hadoop/hive/metastore/TestRemoteUGIHiveMetaStoreIpAddress.java (revision 0) +++ metastore/src/test/org/apache/hadoop/hive/metastore/TestRemoteUGIHiveMetaStoreIpAddress.java (revision 0) @@ -0,0 +1,11 @@ +package org.apache.hadoop.hive.metastore; + +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; + +public class TestRemoteUGIHiveMetaStoreIpAddress extends TestRemoteHiveMetaStoreIpAddress { + public TestRemoteUGIHiveMetaStoreIpAddress() { + super(); + System.setProperty(ConfVars.METASTORE_EXECUTE_SET_UGI.varname, "true"); + } + +} Index: metastore/src/test/org/apache/hadoop/hive/metastore/IpAddressListener.java =================================================================== --- metastore/src/test/org/apache/hadoop/hive/metastore/IpAddressListener.java (revision 0) +++ metastore/src/test/org/apache/hadoop/hive/metastore/IpAddressListener.java (revision 0) @@ -0,0 +1,108 @@ +/** + * 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 java.net.InetAddress; +import java.net.UnknownHostException; + +import junit.framework.Assert; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hive.metastore.HiveMetaStore.HMSHandler; +import org.apache.hadoop.hive.metastore.api.MetaException; +import org.apache.hadoop.hive.metastore.events.AddPartitionEvent; +import org.apache.hadoop.hive.metastore.events.AlterPartitionEvent; +import org.apache.hadoop.hive.metastore.events.AlterTableEvent; +import org.apache.hadoop.hive.metastore.events.CreateDatabaseEvent; +import org.apache.hadoop.hive.metastore.events.CreateTableEvent; +import org.apache.hadoop.hive.metastore.events.DropDatabaseEvent; +import org.apache.hadoop.hive.metastore.events.DropPartitionEvent; +import org.apache.hadoop.hive.metastore.events.DropTableEvent; +import org.apache.hadoop.hive.metastore.events.LoadPartitionDoneEvent; + +/** An implementation for MetaStoreEventListener which checks that the IP Address stored in + * HMSHandler matches that of local host, for testing purposes. + */ +public class IpAddressListener extends MetaStoreEventListener{ + + private static final String LOCAL_HOST = "localhost"; + + public IpAddressListener(Configuration config) { + super(config); + } + + private String getIpFromInetAddress(String addr) { + return addr.substring(addr.indexOf('/') + 1); + } + + private void checkIpAddress() { + try { + String localhostIp = InetAddress.getByName(LOCAL_HOST).toString(); + Assert.assertEquals(getIpFromInetAddress(localhostIp), + getIpFromInetAddress(HMSHandler.getIpAddress())); + } catch (UnknownHostException e) { + Assert.assertTrue("InetAddress.getLocalHost threw an exception: " + e.getMessage(), false); + } + } + + @Override + public void onAddPartition(AddPartitionEvent partition) throws MetaException { + checkIpAddress(); + } + + @Override + public void onCreateDatabase(CreateDatabaseEvent db) throws MetaException { + checkIpAddress(); + } + + @Override + public void onCreateTable(CreateTableEvent table) throws MetaException { + checkIpAddress(); + } + + @Override + public void onDropDatabase(DropDatabaseEvent db) throws MetaException { + checkIpAddress(); + } + + @Override + public void onDropPartition(DropPartitionEvent partition) throws MetaException { + checkIpAddress(); + } + + @Override + public void onDropTable(DropTableEvent table) throws MetaException { + checkIpAddress(); + } + + @Override + public void onAlterTable(AlterTableEvent event) throws MetaException { + checkIpAddress(); + } + + @Override + public void onAlterPartition(AlterPartitionEvent event) throws MetaException { + checkIpAddress(); + } + + @Override + public void onLoadPartitionDone(LoadPartitionDoneEvent partEvent) throws MetaException { + checkIpAddress(); + } +} Index: metastore/src/test/org/apache/hadoop/hive/metastore/TestRemoteHiveMetaStoreIpAddress.java =================================================================== --- metastore/src/test/org/apache/hadoop/hive/metastore/TestRemoteHiveMetaStoreIpAddress.java (revision 0) +++ metastore/src/test/org/apache/hadoop/hive/metastore/TestRemoteHiveMetaStoreIpAddress.java (revision 0) @@ -0,0 +1,98 @@ +/** + * 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 junit.framework.TestCase; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hadoop.hive.metastore.api.Database; +import org.apache.hadoop.util.StringUtils; + +/** + * + * TestRemoteHiveMetaStoreIpAddress. + * + * Test which checks that the remote Hive metastore stores the proper IP address using + * IpAddressListener + */ +public class TestRemoteHiveMetaStoreIpAddress extends TestCase { + protected static final String METASTORE_PORT = "39083"; + private static boolean isServerStarted = false; + private static HiveConf hiveConf; + private static HiveMetaStoreClient msc; + + private static class RunMS implements Runnable { + + @Override + public void run() { + try { + System.setProperty(ConfVars.METASTORE_EVENT_LISTENERS.varname, + IpAddressListener.class.getName()); + HiveMetaStore.main(new String[] { METASTORE_PORT }); + } catch (Throwable e) { + e.printStackTrace(System.err); + assert false; + } + } + + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + hiveConf = new HiveConf(this.getClass()); + + if (isServerStarted) { + assertNotNull("Unable to connect to the MetaStore server", msc); + return; + } + + System.out.println("Starting MetaStore Server on port " + METASTORE_PORT); + Thread t = new Thread(new RunMS()); + t.start(); + isServerStarted = true; + + // Wait a little bit for the metastore to start. Should probably have + // a better way of detecting if the metastore has started? + Thread.sleep(5000); + // This is default case with setugi off for both client and server + createClient(); + } + + public void testIpAddress() throws Exception { + try { + + Database db = new Database(); + db.setName("testIpAddressIp"); + msc.createDatabase(db); + msc.dropDatabase(db.getName()); + } catch (Exception e) { + System.err.println(StringUtils.stringifyException(e)); + System.err.println("testIpAddress() failed."); + throw e; + } + } + + protected void createClient() throws Exception { + hiveConf.setBoolVar(ConfVars.METASTORE_MODE, false); + hiveConf.setVar(HiveConf.ConfVars.METASTOREURIS, "thrift://localhost:" + METASTORE_PORT); + msc = new HiveMetaStoreClient(hiveConf); + } +} Index: metastore/src/java/org/apache/hadoop/hive/metastore/TUGIBasedProcessor.java =================================================================== --- metastore/src/java/org/apache/hadoop/hive/metastore/TUGIBasedProcessor.java (revision 1303878) +++ metastore/src/java/org/apache/hadoop/hive/metastore/TUGIBasedProcessor.java (working copy) @@ -21,12 +21,12 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.Socket; import java.security.PrivilegedExceptionAction; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore; import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Iface; import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Processor; import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.set_ugi_args; @@ -53,7 +53,7 @@ * Note that old clients will never call set_ugi() and thus ugi will never be received on server * side, in which case server exhibits previous behavior and continues as usual. */ -public class TUGIBasedProcessor extends ThriftHiveMetastore.Processor { +public class TUGIBasedProcessor extends TSetIpAddressProcessor { private final I iface; private final Map>> @@ -76,6 +76,7 @@ @Override public boolean process(final TProtocol in, final TProtocol out) throws TException { + setIpAddress(in); final TMessage msg = in.readMessageBegin(); final ProcessFunction> fn = functions.get(msg.name); @@ -175,4 +176,13 @@ oprot.writeMessageEnd(); oprot.getTransport().flush(); } + + @Override + protected void setIpAddress(final TProtocol in) { + TUGIContainingTransport ugiTrans = (TUGIContainingTransport)in.getTransport(); + Socket socket = ugiTrans.getSocket(); + if (socket != null) { + setIpAddress(socket); + } + } } Index: metastore/src/java/org/apache/hadoop/hive/metastore/TSetIpAddressProcessor.java =================================================================== --- metastore/src/java/org/apache/hadoop/hive/metastore/TSetIpAddressProcessor.java (revision 0) +++ metastore/src/java/org/apache/hadoop/hive/metastore/TSetIpAddressProcessor.java (revision 0) @@ -0,0 +1,62 @@ +/** + * 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 java.lang.reflect.InvocationTargetException; +import java.net.Socket; + +import org.apache.hadoop.hive.metastore.HiveMetaStore.HMSHandler; +import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore; +import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore.Iface; +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; + +/** + * TSetIpAddressProcessor passes the IP address of the Thrift client to the HMSHandler. + */ +public class TSetIpAddressProcessor extends ThriftHiveMetastore.Processor { + + @SuppressWarnings("unchecked") + public TSetIpAddressProcessor(I iface) throws SecurityException, NoSuchFieldException, + IllegalArgumentException, IllegalAccessException, NoSuchMethodException, + InvocationTargetException { + super(iface); + } + + @Override + public boolean process(final TProtocol in, final TProtocol out) throws TException { + setIpAddress(in); + + return super.process(in, out); + } + + protected void setIpAddress(final TProtocol in) { + TTransport transport = in.getTransport(); + if (!(transport instanceof TSocket)) { + return; + } + setIpAddress(((TSocket)transport).getSocket()); + } + + protected void setIpAddress(final Socket inSocket) { + HMSHandler.setIpAddress(inSocket.getInetAddress().toString()); + } +} Index: metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java =================================================================== --- metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java (revision 1303878) +++ metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java (working copy) @@ -203,6 +203,26 @@ } }; + // This will only be set if the metastore is being accessed from a metastore Thrift server, + // not if it is from the CLI. Also, only if the TTransport being used to connect is an + // instance of TSocket. + private static ThreadLocal threadLocalIpAddress = new ThreadLocal() { + @Override + protected synchronized String initialValue() { + return null; + } + }; + + public static void setIpAddress(String ipAddress) { + threadLocalIpAddress.set(ipAddress); + } + + // This will return null if the metastore is not being accessed from a metastore Thrift server, + // or if the TTransport being used to connect is not an instance of TSocket. + public static String getIpAddress() { + return threadLocalIpAddress.get(); + } + public static Integer get() { return threadLocalId.get(); } @@ -2914,7 +2934,7 @@ LOG.info("Starting DB backed MetaStore Server with SetUGI enabled"); } else { transFactory = new TTransportFactory(); - processor = new ThriftHiveMetastore.Processor(handler); + processor = new TSetIpAddressProcessor(handler); LOG.info("Starting DB backed MetaStore Server"); } }