Index: metastore/src/test/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java =================================================================== --- metastore/src/test/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java (revision 1056212) +++ metastore/src/test/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java (working copy) @@ -1009,4 +1009,16 @@ client.add_partition(part); } + + /** + * Tests {@link HiveMetaStoreClient#newSynchronizedClient}. Does not + * actually test multithreading, but does verify that the proxy + * at least works correctly. + */ + public void testSynchronized() throws Exception { + IMetaStoreClient synchronizedClient = + HiveMetaStoreClient.newSynchronizedClient(client); + List databases = synchronizedClient.getAllDatabases(); + assertEquals(1, databases.size()); + } } Index: metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java =================================================================== --- metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java (revision 1056212) +++ metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java (working copy) @@ -21,6 +21,10 @@ import static org.apache.hadoop.hive.metastore.MetaStoreUtils.DEFAULT_DATABASE_NAME; import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -922,4 +926,41 @@ return client.drop_index_by_name(dbName, tblName, name, deleteData); } + /** + * Creates a synchronized wrapper for any {@link IMetaStoreClient}. + * This may be used by multi-threaded applications until we have + * fixed all reentrancy bugs. + * + * @param client unsynchronized client + * + * @return synchronized client + */ + public static IMetaStoreClient newSynchronizedClient( + IMetaStoreClient client) { + return (IMetaStoreClient) Proxy.newProxyInstance( + HiveMetaStoreClient.class.getClassLoader(), + new Class [] { IMetaStoreClient.class }, + new SynchronizedHandler(client)); + } + + private static class SynchronizedHandler implements InvocationHandler { + private final IMetaStoreClient client; + private static final Object lock = SynchronizedHandler.class; + + SynchronizedHandler(IMetaStoreClient client) { + this.client = client; + } + + public Object invoke(Object proxy, Method method, Object [] args) + throws Throwable { + try { + synchronized (lock) { + return method.invoke(client, args); + } + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + } + }