KYLIN-2529 Allow thread-local override of KylinConfig
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/1e8b6a5e Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/1e8b6a5e Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/1e8b6a5e Branch: refs/heads/master-hbase0.98 Commit: 1e8b6a5e7b1350930c68e750fb1ce75c27428082 Parents: 782a974 Author: lidongsjtu <lid...@apache.org> Authored: Thu Mar 30 19:54:34 2017 +0800 Committer: lidongsjtu <lid...@apache.org> Committed: Fri Mar 31 19:03:54 2017 +0800 ---------------------------------------------------------------------- .../org/apache/kylin/common/KylinConfig.java | 37 ++++++++++++++------ .../apache/kylin/common/KylinConfigTest.java | 31 +++++++++++++++- 2 files changed, 56 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/1e8b6a5e/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java ---------------------------------------------------------------------- diff --git a/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java b/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java index c6b1511..a9a0c45 100644 --- a/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java +++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java @@ -50,30 +50,41 @@ public class KylinConfig extends KylinConfigBase { public static final String KYLIN_CONF = "KYLIN_CONF"; // static cached instances - private static KylinConfig ENV_INSTANCE = null; + private static KylinConfig SYS_ENV_INSTANCE = null; + + // thread-local instances, will override SYS_ENV_INSTANCE + private static final transient ThreadLocal<KylinConfig> THREAD_ENV_INSTANCE = new ThreadLocal<>(); public static KylinConfig getInstanceFromEnv() { synchronized (KylinConfig.class) { - if (ENV_INSTANCE == null) { + KylinConfig config = THREAD_ENV_INSTANCE.get(); + if (config != null) { + return config; + } + + if (SYS_ENV_INSTANCE == null) { try { - KylinConfig config = new KylinConfig(); + config = new KylinConfig(); config.reloadKylinConfig(getKylinProperties()); logger.info("Initialized a new KylinConfig from getInstanceFromEnv : " + System.identityHashCode(config)); - ENV_INSTANCE = config; + SYS_ENV_INSTANCE = config; } catch (IllegalArgumentException e) { throw new IllegalStateException("Failed to find KylinConfig ", e); } } - return ENV_INSTANCE; + return SYS_ENV_INSTANCE; } } //Only used in test cases!!! public static void destroyInstance() { - logger.info("Destory KylinConfig"); - dumpStackTrace(); - ENV_INSTANCE = null; + synchronized (KylinConfig.class) { + logger.info("Destroy KylinConfig"); + dumpStackTrace(); + SYS_ENV_INSTANCE = null; + THREAD_ENV_INSTANCE.remove(); + } } public enum UriType { @@ -158,12 +169,12 @@ public class KylinConfig extends KylinConfigBase { public static void setKylinConfigInEnvIfMissing(Properties prop) { synchronized (KylinConfig.class) { - if (ENV_INSTANCE == null) { + if (SYS_ENV_INSTANCE == null) { try { KylinConfig config = new KylinConfig(); config.reloadKylinConfig(prop); - logger.info("Resetting ENV_INSTANCE by a input stream: " + System.identityHashCode(config)); - ENV_INSTANCE = config; + logger.info("Resetting SYS_ENV_INSTANCE by a input stream: " + System.identityHashCode(config)); + SYS_ENV_INSTANCE = config; } catch (IllegalArgumentException e) { throw new IllegalStateException("Failed to find KylinConfig ", e); } @@ -177,6 +188,10 @@ public class KylinConfig extends KylinConfigBase { setKylinConfigInEnvIfMissing(props); } + public static void setKylinConfigThreadLocal(KylinConfig config) { + THREAD_ENV_INSTANCE.set(config); + } + public static KylinConfig createKylinConfig(String propsInStr) throws IOException { Properties props = new Properties(); props.load(new StringReader(propsInStr)); http://git-wip-us.apache.org/repos/asf/kylin/blob/1e8b6a5e/core-common/src/test/java/org/apache/kylin/common/KylinConfigTest.java ---------------------------------------------------------------------- diff --git a/core-common/src/test/java/org/apache/kylin/common/KylinConfigTest.java b/core-common/src/test/java/org/apache/kylin/common/KylinConfigTest.java index 7e4b444..3976c6c 100644 --- a/core-common/src/test/java/org/apache/kylin/common/KylinConfigTest.java +++ b/core-common/src/test/java/org/apache/kylin/common/KylinConfigTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Map; +import java.util.Properties; import org.apache.kylin.common.util.HotLoadKylinPropertiesTestCase; import org.junit.Test; @@ -86,7 +87,7 @@ public class KylinConfigTest extends HotLoadKylinPropertiesTestCase { public void testGetMetadataUrlPrefix() { KylinConfig config = KylinConfig.getInstanceFromEnv(); final String default_metadata_prefix = "kylin_metadata"; - + config.setMetadataUrl("testMetaPrefix@hbase"); assertEquals("testMetaPrefix", config.getMetadataUrlPrefix()); @@ -96,4 +97,32 @@ public class KylinConfigTest extends HotLoadKylinPropertiesTestCase { config.setMetadataUrl("/kylin/temp"); assertEquals(default_metadata_prefix, config.getMetadataUrlPrefix()); } + + @Test + public void testThreadLocalOverride() { + final String metadata1 = "meta1"; + final String metadata2 = "meta2"; + + // set system KylinConfig + KylinConfig sysConfig = KylinConfig.getInstanceFromEnv(); + sysConfig.setMetadataUrl(metadata1); + + assertEquals(metadata1, KylinConfig.getInstanceFromEnv().getMetadataUrl()); + + // test thread-local override + KylinConfig threadConfig = KylinConfig.createKylinConfig(new Properties()); + threadConfig.setMetadataUrl(metadata2); + KylinConfig.setKylinConfigThreadLocal(threadConfig); + + assertEquals(metadata2, KylinConfig.getInstanceFromEnv().getMetadataUrl()); + + // other threads still use system KylinConfig + new Thread(new Runnable() { + @Override + public void run() { + System.out.println("Started new thread."); + assertEquals(metadata1, KylinConfig.getInstanceFromEnv().getMetadataUrl()); + } + }).start(); + } }