You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ma...@apache.org on 2015/05/26 17:21:16 UTC

[30/32] incubator-kylin git commit: KYLIN-697 totally avoid ZK in localmeta test cases

KYLIN-697 totally avoid ZK in localmeta test cases


Project: http://git-wip-us.apache.org/repos/asf/incubator-kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kylin/commit/5b6960ee
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kylin/tree/5b6960ee
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kylin/diff/5b6960ee

Branch: refs/heads/0.8.0
Commit: 5b6960eed1105750de3c751dfb1e78b428a7a3d0
Parents: 0c5d549
Author: honma <ho...@ebay.com>
Authored: Tue May 26 20:00:19 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Tue May 26 23:21:28 2015 +0800

----------------------------------------------------------------------
 .../org/apache/kylin/common/lock/JobLock.java   |  10 +
 .../apache/kylin/common/lock/MockJobLock.java   |  16 ++
 .../kylin/common/lock/ZookeeperJobLock.java     |  81 ++++++
 .../common/util/AbstractKylinTestCase.java      |  11 +-
 .../common/util/HBaseMetadataTestCase.java      |  10 +
 .../common/util/LocalFileMetadataTestCase.java  |  11 +-
 .../kylin/metadata/MetadataUpgradeTest.java     |  17 +-
 .../java/org/apache/kylin/job/Scheduler.java    |   3 +-
 .../job/impl/threadpool/DefaultScheduler.java   |  76 +-----
 .../kylin/job/BuildCubeWithEngineTest.java      |  33 ++-
 .../apache/kylin/job/BuildIIWithEngineTest.java |   3 +-
 .../job/impl/threadpool/BaseSchedulerTest.java  |   3 +-
 .../kylin/rest/controller/JobController.java    |   6 +-
 .../kylin/rest/security/AclHBaseStorage.java    |  25 ++
 .../rest/security/MockAclHBaseStorage.java      |  45 ++++
 .../rest/security/RealAclHBaseStorage.java      |  51 ++++
 .../apache/kylin/rest/service/AclService.java   |   2 +-
 .../apache/kylin/rest/service/UserService.java  |   2 +-
 .../apache/kylin/rest/util/AclHBaseStorage.java |  25 --
 .../kylin/rest/util/MockAclHBaseStorage.java    |  45 ----
 .../kylin/rest/util/RealAclHBaseStorage.java    |  51 ----
 .../src/main/resources/applicationContext.xml   | 244 ++++++++++---------
 .../kylin/rest/service/CacheServiceTest.java    |   2 +-
 23 files changed, 413 insertions(+), 359 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/common/src/main/java/org/apache/kylin/common/lock/JobLock.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/lock/JobLock.java b/common/src/main/java/org/apache/kylin/common/lock/JobLock.java
new file mode 100644
index 0000000..5293385
--- /dev/null
+++ b/common/src/main/java/org/apache/kylin/common/lock/JobLock.java
@@ -0,0 +1,10 @@
+package org.apache.kylin.common.lock;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/26/15.
+ */
+public interface JobLock {
+    boolean lock();
+
+    void unlock();
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/common/src/main/java/org/apache/kylin/common/lock/MockJobLock.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/lock/MockJobLock.java b/common/src/main/java/org/apache/kylin/common/lock/MockJobLock.java
new file mode 100644
index 0000000..9285fd2
--- /dev/null
+++ b/common/src/main/java/org/apache/kylin/common/lock/MockJobLock.java
@@ -0,0 +1,16 @@
+package org.apache.kylin.common.lock;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/26/15.
+ */
+public class MockJobLock implements JobLock {
+    @Override
+    public boolean lock() {
+        return true;
+    }
+
+    @Override
+    public void unlock() {
+        return;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/common/src/main/java/org/apache/kylin/common/lock/ZookeeperJobLock.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/lock/ZookeeperJobLock.java b/common/src/main/java/org/apache/kylin/common/lock/ZookeeperJobLock.java
new file mode 100644
index 0000000..7a755a3
--- /dev/null
+++ b/common/src/main/java/org/apache/kylin/common/lock/ZookeeperJobLock.java
@@ -0,0 +1,81 @@
+package org.apache.kylin.common.lock;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.CuratorFrameworkState;
+import org.apache.curator.framework.recipes.locks.InterProcessMutex;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.HadoopUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/26/15.
+ */
+public class ZookeeperJobLock implements JobLock {
+    private Logger logger = LoggerFactory.getLogger(ZookeeperJobLock.class);
+
+    private static final String ZOOKEEPER_LOCK_PATH = "/kylin/job_engine/lock";
+    private InterProcessMutex sharedLock;
+    private CuratorFramework zkClient;
+
+    @Override
+    public boolean lock() {
+        String ZKConnectString = getZKConnectString();
+        if (StringUtils.isEmpty(ZKConnectString)) {
+            throw new IllegalArgumentException("ZOOKEEPER_QUORUM is empty!");
+        }
+
+        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
+        this.zkClient = CuratorFrameworkFactory.newClient(ZKConnectString, retryPolicy);
+        this.zkClient.start();
+        this.sharedLock = new InterProcessMutex(zkClient, schedulerId());
+        boolean hasLock = false;
+        try {
+            hasLock = sharedLock.acquire(3, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            logger.warn("error acquire lock", e);
+        }
+        if (!hasLock) {
+            logger.warn("fail to acquire lock, scheduler has not been started");
+            zkClient.close();
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void unlock() {
+        releaseLock();
+    }
+
+    private String getZKConnectString() {
+        Configuration conf = HadoopUtil.newHBaseConfiguration(KylinConfig.getInstanceFromEnv().getStorageUrl());
+        return conf.get(HConstants.ZOOKEEPER_QUORUM) + ":" + conf.get(HConstants.ZOOKEEPER_CLIENT_PORT);
+    }
+
+    private void releaseLock() {
+        try {
+            if (zkClient.getState().equals(CuratorFrameworkState.STARTED)) {
+                // client.setData().forPath(ZOOKEEPER_LOCK_PATH, null);
+                if (zkClient.checkExists().forPath(schedulerId()) != null) {
+                    zkClient.delete().guaranteed().deletingChildrenIfNeeded().forPath(schedulerId());
+                }
+            }
+        } catch (Exception e) {
+            logger.error("error release lock:" + schedulerId());
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String schedulerId() {
+        return ZOOKEEPER_LOCK_PATH + "/" + KylinConfig.getInstanceFromEnv().getMetadataUrlPrefix();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/common/src/test/java/org/apache/kylin/common/util/AbstractKylinTestCase.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/AbstractKylinTestCase.java b/common/src/test/java/org/apache/kylin/common/util/AbstractKylinTestCase.java
index 36a9287..3fd82b3 100644
--- a/common/src/test/java/org/apache/kylin/common/util/AbstractKylinTestCase.java
+++ b/common/src/test/java/org/apache/kylin/common/util/AbstractKylinTestCase.java
@@ -18,10 +18,10 @@
 
 package org.apache.kylin.common.util;
 
-import java.lang.reflect.Method;
-
 import org.apache.kylin.common.KylinConfig;
 
+import java.lang.reflect.Method;
+
 /**
  * @author ysong1
  *
@@ -46,14 +46,7 @@ public abstract class AbstractKylinTestCase {
         return KylinConfig.getInstanceFromEnv();
     }
 
-    public static void staticCreateTestMetadata(String kylinConfigFolder) {
 
-        KylinConfig.destoryInstance();
-
-        if (System.getProperty(KylinConfig.KYLIN_CONF) == null && System.getenv(KylinConfig.KYLIN_CONF) == null)
-            System.setProperty(KylinConfig.KYLIN_CONF, kylinConfigFolder);
-
-    }
 
     public static void staticCleanupTestMetadata() {
         cleanupCache();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/common/src/test/java/org/apache/kylin/common/util/HBaseMetadataTestCase.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/HBaseMetadataTestCase.java b/common/src/test/java/org/apache/kylin/common/util/HBaseMetadataTestCase.java
index 90970e5..6473b3d 100644
--- a/common/src/test/java/org/apache/kylin/common/util/HBaseMetadataTestCase.java
+++ b/common/src/test/java/org/apache/kylin/common/util/HBaseMetadataTestCase.java
@@ -18,6 +18,8 @@
 
 package org.apache.kylin.common.util;
 
+import org.apache.kylin.common.KylinConfig;
+
 import java.io.File;
 
 /**
@@ -54,6 +56,14 @@ public class HBaseMetadataTestCase extends AbstractKylinTestCase {
         }
 
     }
+    public static void staticCreateTestMetadata(String kylinConfigFolder) {
+
+        KylinConfig.destoryInstance();
+
+        if (System.getProperty(KylinConfig.KYLIN_CONF) == null && System.getenv(KylinConfig.KYLIN_CONF) == null)
+            System.setProperty(KylinConfig.KYLIN_CONF, kylinConfigFolder);
+
+    }
 
     public static boolean useSandbox() {
         String useSandbox = System.getProperty("useSandbox");

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/common/src/test/java/org/apache/kylin/common/util/LocalFileMetadataTestCase.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/LocalFileMetadataTestCase.java b/common/src/test/java/org/apache/kylin/common/util/LocalFileMetadataTestCase.java
index 60db6eb..1bd218e 100644
--- a/common/src/test/java/org/apache/kylin/common/util/LocalFileMetadataTestCase.java
+++ b/common/src/test/java/org/apache/kylin/common/util/LocalFileMetadataTestCase.java
@@ -18,14 +18,13 @@
 
 package org.apache.kylin.common.util;
 
-import java.io.File;
-import java.io.IOException;
-
 import org.apache.commons.io.FileUtils;
-
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.ResourceStore;
 
+import java.io.File;
+import java.io.IOException;
+
 /**
  * @author ysong1
  */
@@ -33,10 +32,10 @@ public class LocalFileMetadataTestCase extends AbstractKylinTestCase {
 
     @Override
     public void createTestMetadata() {
-        createTestMetadata(LOCALMETA_TEST_DATA);
+        staticCreateTestMetadata(LOCALMETA_TEST_DATA);
     }
     
-    public static void createTestMetadata(String testDataFolder) {
+    public static void staticCreateTestMetadata(String testDataFolder) {
         KylinConfig.destoryInstance();
 
         String tempTestMetadataUrl = "../examples/test_metadata";

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
----------------------------------------------------------------------
diff --git a/cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java b/cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
index 4b1459c..17db72c 100644
--- a/cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
+++ b/cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
@@ -18,16 +18,6 @@
 
 package org.apache.kylin.metadata;
 
-import java.util.List;
-
-import org.apache.kylin.metadata.model.DataModelDesc;
-import org.apache.kylin.metadata.model.TableDesc;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.ResourceStore;
 import org.apache.kylin.common.util.LocalFileMetadataTestCase;
@@ -36,6 +26,11 @@ import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
 import org.apache.kylin.cube.model.CubeDesc;
 import org.apache.kylin.cube.model.DimensionDesc;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.model.TableDesc;
+import org.junit.*;
+
+import java.util.List;
 
 /**
  * Test the data model upgrade
@@ -47,7 +42,7 @@ public class MetadataUpgradeTest extends LocalFileMetadataTestCase {
 
     @Before
     public void setUp() throws Exception {
-        createTestMetadata(LOCALMETA_TEST_DATA_V1);
+        staticCreateTestMetadata(LOCALMETA_TEST_DATA_V1);
     }
 
     @After

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/job/src/main/java/org/apache/kylin/job/Scheduler.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/Scheduler.java b/job/src/main/java/org/apache/kylin/job/Scheduler.java
index 592b274..fe6fe95 100644
--- a/job/src/main/java/org/apache/kylin/job/Scheduler.java
+++ b/job/src/main/java/org/apache/kylin/job/Scheduler.java
@@ -18,6 +18,7 @@
 
 package org.apache.kylin.job;
 
+import org.apache.kylin.common.lock.JobLock;
 import org.apache.kylin.job.engine.JobEngineConfig;
 import org.apache.kylin.job.exception.SchedulerException;
 import org.apache.kylin.job.execution.Executable;
@@ -26,7 +27,7 @@ import org.apache.kylin.job.execution.Executable;
  */
 public interface Scheduler<T extends Executable> {
 
-    void init(JobEngineConfig jobEngineConfig) throws SchedulerException;
+    void init(JobEngineConfig jobEngineConfig, JobLock jobLock) throws SchedulerException;
 
     void shutdown() throws SchedulerException;
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java b/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
index 2acba4e..bac4227 100644
--- a/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
+++ b/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
@@ -18,31 +18,17 @@
 
 package org.apache.kylin.job.impl.threadpool;
 
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.kylin.job.execution.AbstractExecutable;
-import org.apache.commons.lang.StringUtils;
-import org.apache.curator.RetryPolicy;
+import com.google.common.collect.Maps;
 import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.imps.CuratorFrameworkState;
-import org.apache.curator.framework.recipes.locks.InterProcessMutex;
 import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HConstants;
+import org.apache.kylin.common.lock.JobLock;
 import org.apache.kylin.job.Scheduler;
 import org.apache.kylin.job.constant.ExecutableConstants;
 import org.apache.kylin.job.engine.JobEngineConfig;
 import org.apache.kylin.job.exception.ExecuteException;
 import org.apache.kylin.job.exception.SchedulerException;
+import org.apache.kylin.job.execution.AbstractExecutable;
 import org.apache.kylin.job.execution.Executable;
 import org.apache.kylin.job.execution.ExecutableState;
 import org.apache.kylin.job.execution.Output;
@@ -50,14 +36,13 @@ import org.apache.kylin.job.manager.ExecutableManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Maps;
-import org.apache.kylin.common.util.HadoopUtil;
+import java.util.Map;
+import java.util.concurrent.*;
 
 /**
  */
 public class DefaultScheduler implements Scheduler<AbstractExecutable>, ConnectionStateListener {
 
-    private static final String ZOOKEEPER_LOCK_PATH = "/kylin/job_engine/lock";
 
     private ExecutableManager executableManager;
     private ScheduledExecutorService fetcherPool;
@@ -67,9 +52,7 @@ public class DefaultScheduler implements Scheduler<AbstractExecutable>, Connecti
     private Logger logger = LoggerFactory.getLogger(DefaultScheduler.class);
     private volatile boolean initialized = false;
     private volatile boolean hasStarted = false;
-    private CuratorFramework zkClient;
     private JobEngineConfig jobEngineConfig;
-    private InterProcessMutex sharedLock;
 
     private static final DefaultScheduler INSTANCE = new DefaultScheduler();
 
@@ -139,29 +122,6 @@ public class DefaultScheduler implements Scheduler<AbstractExecutable>, Connecti
         }
     }
 
-    private void releaseLock() {
-        try {
-            if (zkClient.getState().equals(CuratorFrameworkState.STARTED)) {
-                // client.setData().forPath(ZOOKEEPER_LOCK_PATH, null);
-                if (zkClient.checkExists().forPath(schedulerId()) != null) {
-                    zkClient.delete().guaranteed().deletingChildrenIfNeeded().forPath(schedulerId());
-                }
-            }
-        } catch (Exception e) {
-            logger.error("error release lock:" + schedulerId());
-            throw new RuntimeException(e);
-        }
-    }
-
-    private String schedulerId() {
-        return ZOOKEEPER_LOCK_PATH + "/" + jobEngineConfig.getConfig().getMetadataUrlPrefix();
-    }
-
-    private String getZKConnectString(JobEngineConfig context) {
-        Configuration conf = HadoopUtil.newHBaseConfiguration(context.getConfig().getStorageUrl());
-        return conf.get(HConstants.ZOOKEEPER_QUORUM) + ":" + conf.get(HConstants.ZOOKEEPER_CLIENT_PORT);
-    }
-
     public static DefaultScheduler getInstance() {
         return INSTANCE;
     }
@@ -178,33 +138,17 @@ public class DefaultScheduler implements Scheduler<AbstractExecutable>, Connecti
     }
 
     @Override
-    public synchronized void init(JobEngineConfig jobEngineConfig) throws SchedulerException {
+    public synchronized void init(JobEngineConfig jobEngineConfig, final JobLock jobLock) throws SchedulerException {
         if (!initialized) {
             initialized = true;
         } else {
             return;
         }
-        String ZKConnectString = getZKConnectString(jobEngineConfig);
-        if (StringUtils.isEmpty(ZKConnectString)) {
-            throw new IllegalArgumentException("ZOOKEEPER_QUORUM is empty!");
-        }
 
         this.jobEngineConfig = jobEngineConfig;
-        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
-        this.zkClient = CuratorFrameworkFactory.newClient(ZKConnectString, retryPolicy);
-        this.zkClient.start();
-        this.sharedLock = new InterProcessMutex(zkClient, schedulerId());
-        boolean hasLock = false;
-        try {
-            hasLock = sharedLock.acquire(3, TimeUnit.SECONDS);
-        } catch (Exception e) {
-            logger.warn("error acquire lock", e);
-        }
-        if (!hasLock) {
-            logger.warn("fail to acquire lock, scheduler has not been started");
-            zkClient.close();
-            return;
-        }
+
+        jobLock.lock();
+
         executableManager = ExecutableManager.getInstance(jobEngineConfig.getConfig());
         //load all executable, set them to a consistent status
         fetcherPool = Executors.newScheduledThreadPool(1);
@@ -224,6 +168,7 @@ public class DefaultScheduler implements Scheduler<AbstractExecutable>, Connecti
                 logger.debug("Closing zk connection");
                 try {
                     shutdown();
+                    jobLock.unlock();
                 } catch (SchedulerException e) {
                     logger.error("error shutdown scheduler", e);
                 }
@@ -238,7 +183,6 @@ public class DefaultScheduler implements Scheduler<AbstractExecutable>, Connecti
     public void shutdown() throws SchedulerException {
         fetcherPool.shutdown();
         jobPool.shutdown();
-        releaseLock();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/job/src/test/java/org/apache/kylin/job/BuildCubeWithEngineTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/BuildCubeWithEngineTest.java b/job/src/test/java/org/apache/kylin/job/BuildCubeWithEngineTest.java
index d3c3669..74c824c 100644
--- a/job/src/test/java/org/apache/kylin/job/BuildCubeWithEngineTest.java
+++ b/job/src/test/java/org/apache/kylin/job/BuildCubeWithEngineTest.java
@@ -22,6 +22,7 @@ import com.google.common.collect.Lists;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.lock.ZookeeperJobLock;
 import org.apache.kylin.common.util.AbstractKylinTestCase;
 import org.apache.kylin.common.util.ClassUtil;
 import org.apache.kylin.common.util.HBaseMetadataTestCase;
@@ -92,18 +93,17 @@ public class BuildCubeWithEngineTest {
         DeployUtil.deployMetadata();
         DeployUtil.overrideJobJarLocations();
 
-
         final KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
         jobService = ExecutableManager.getInstance(kylinConfig);
         scheduler = DefaultScheduler.getInstance();
-        scheduler.init(new JobEngineConfig(kylinConfig));
+        scheduler.init(new JobEngineConfig(kylinConfig), new ZookeeperJobLock());
         if (!scheduler.hasStarted()) {
             throw new RuntimeException("scheduler has not been started");
         }
         cubeManager = CubeManager.getInstance(kylinConfig);
         jobEngineConfig = new JobEngineConfig(kylinConfig);
         for (String jobId : jobService.getAllJobIds()) {
-            if(jobService.getJob(jobId) instanceof CubingJob){
+            if (jobService.getJob(jobId) instanceof CubingJob) {
                 jobService.deleteJob(jobId);
             }
         }
@@ -123,18 +123,12 @@ public class BuildCubeWithEngineTest {
     }
 
     private void testInner() throws Exception {
-        String[] testCase = new String[]{
-                "testInnerJoinCube",
-                "testInnerJoinCube2",
-        };
+        String[] testCase = new String[] { "testInnerJoinCube", "testInnerJoinCube2", };
         runTestAndAssertSucceed(testCase);
     }
 
     private void testLeft() throws Exception {
-        String[] testCase = new String[]{
-                "testLeftJoinCube",
-                "testLeftJoinCube2",
-        };
+        String[] testCase = new String[] { "testLeftJoinCube", "testLeftJoinCube2", };
         runTestAndAssertSucceed(testCase);
     }
 
@@ -187,7 +181,8 @@ public class BuildCubeWithEngineTest {
         }
     }
 
-    @SuppressWarnings("unused") // called by reflection
+    @SuppressWarnings("unused")
+    // called by reflection
     private List<String> testInnerJoinCube2() throws Exception {
         clearSegment("test_kylin_cube_with_slr_empty");
         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
@@ -201,11 +196,11 @@ public class BuildCubeWithEngineTest {
         return result;
     }
 
-    @SuppressWarnings("unused") // called by reflection
+    @SuppressWarnings("unused")
+    // called by reflection
     private List<String> testInnerJoinCube() throws Exception {
         clearSegment("test_kylin_cube_without_slr_empty");
 
-
         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
         f.setTimeZone(TimeZone.getTimeZone("GMT"));
 
@@ -213,7 +208,6 @@ public class BuildCubeWithEngineTest {
         long date1 = 0;
         long date2 = f.parse("2013-01-01").getTime();
 
-
         // this cube doesn't support incremental build, always do full build
 
         List<String> result = Lists.newArrayList();
@@ -221,7 +215,8 @@ public class BuildCubeWithEngineTest {
         return result;
     }
 
-    @SuppressWarnings("unused") // called by reflection
+    @SuppressWarnings("unused")
+    // called by reflection
     private List<String> testLeftJoinCube2() throws Exception {
         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
         f.setTimeZone(TimeZone.getTimeZone("GMT"));
@@ -243,7 +238,8 @@ public class BuildCubeWithEngineTest {
 
     }
 
-    @SuppressWarnings("unused") // called by reflection
+    @SuppressWarnings("unused")
+    // called by reflection
     private List<String> testLeftJoinCube() throws Exception {
         String cubeName = "test_kylin_cube_with_slr_left_join_empty";
         clearSegment(cubeName);
@@ -263,10 +259,9 @@ public class BuildCubeWithEngineTest {
     private void clearSegment(String cubeName) throws Exception {
         CubeInstance cube = cubeManager.getCube(cubeName);
         cube.getSegments().clear();
-        cubeManager.updateCube(cube,true);
+        cubeManager.updateCube(cube, true);
     }
 
-
     private String buildSegment(String cubeName, long startDate, long endDate) throws Exception {
         CubeSegment segment = cubeManager.appendSegments(cubeManager.getCube(cubeName), endDate);
         CubingJobBuilder cubingJobBuilder = new CubingJobBuilder(jobEngineConfig);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/job/src/test/java/org/apache/kylin/job/BuildIIWithEngineTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/BuildIIWithEngineTest.java b/job/src/test/java/org/apache/kylin/job/BuildIIWithEngineTest.java
index 612ba6c..1094caa 100644
--- a/job/src/test/java/org/apache/kylin/job/BuildIIWithEngineTest.java
+++ b/job/src/test/java/org/apache/kylin/job/BuildIIWithEngineTest.java
@@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.util.ToolRunner;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.lock.ZookeeperJobLock;
 import org.apache.kylin.common.util.AbstractKylinTestCase;
 import org.apache.kylin.common.util.ClassUtil;
 import org.apache.kylin.common.util.HBaseMetadataTestCase;
@@ -98,7 +99,7 @@ public class BuildIIWithEngineTest {
         final KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
         jobService = ExecutableManager.getInstance(kylinConfig);
         scheduler = DefaultScheduler.getInstance();
-        scheduler.init(new JobEngineConfig(kylinConfig));
+        scheduler.init(new JobEngineConfig(kylinConfig),new ZookeeperJobLock());
         if (!scheduler.hasStarted()) {
             throw new RuntimeException("scheduler has not been started");
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java b/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
index f47e152..913f707 100644
--- a/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
+++ b/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
@@ -19,6 +19,7 @@
 package org.apache.kylin.job.impl.threadpool;
 
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.lock.ZookeeperJobLock;
 import org.apache.kylin.common.util.HBaseMetadataTestCase;
 import org.apache.kylin.job.constant.ExecutableConstants;
 import org.apache.kylin.job.engine.JobEngineConfig;
@@ -86,7 +87,7 @@ public abstract class BaseSchedulerTest extends HBaseMetadataTestCase {
         setFinalStatic(ExecutableConstants.class.getField("DEFAULT_SCHEDULER_INTERVAL_SECONDS"), 10);
         jobService = ExecutableManager.getInstance(KylinConfig.getInstanceFromEnv());
         scheduler = DefaultScheduler.getInstance();
-        scheduler.init(new JobEngineConfig(KylinConfig.getInstanceFromEnv()));
+        scheduler.init(new JobEngineConfig(KylinConfig.getInstanceFromEnv()), new ZookeeperJobLock());
         if (!scheduler.hasStarted()) {
             throw new RuntimeException("scheduler has not been started");
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/JobController.java b/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
index fca7e72..ed0901e 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
@@ -19,6 +19,7 @@
 package org.apache.kylin.rest.controller;
 
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.lock.JobLock;
 import org.apache.kylin.job.JobInstance;
 import org.apache.kylin.job.constant.JobStatusEnum;
 import org.apache.kylin.job.engine.JobEngineConfig;
@@ -53,6 +54,9 @@ public class JobController extends BasicController implements InitializingBean {
     @Autowired
     private JobService jobService;
 
+    @Autowired
+    private JobLock jobLock;
+
     /*
      * (non-Javadoc)
      * 
@@ -77,7 +81,7 @@ public class JobController extends BasicController implements InitializingBean {
                 public void run() {
                     try {
                         DefaultScheduler scheduler = DefaultScheduler.getInstance();
-                        scheduler.init(new JobEngineConfig(kylinConfig));
+                        scheduler.init(new JobEngineConfig(kylinConfig), jobLock);
                         while (!scheduler.hasStarted()) {
                             logger.error("scheduler has not been started");
                             Thread.sleep(1000);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
new file mode 100644
index 0000000..12cfc68
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
@@ -0,0 +1,25 @@
+package org.apache.kylin.rest.security;
+
+import org.apache.hadoop.hbase.client.HTableInterface;
+
+import java.io.IOException;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/19/15.
+ */
+public interface AclHBaseStorage {
+    String DEFAULT_TABLE_PREFIX = "kylin_metadata";
+
+    String ACL_INFO_FAMILY = "i";
+    String ACL_ACES_FAMILY = "a";
+    String ACL_TABLE_NAME = "_acl";
+
+    String USER_AUTHORITY_FAMILY = "a";
+    String USER_TABLE_NAME = "_user";
+    String USER_AUTHORITY_COLUMN = "c";
+
+    String prepareHBaseTable(Class clazz) throws IOException;
+
+    HTableInterface getTable(String tableName) throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
new file mode 100644
index 0000000..f9c9e0c
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
@@ -0,0 +1,45 @@
+package org.apache.kylin.rest.security;
+
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.kylin.common.util.MockHTable;
+import org.apache.kylin.rest.service.AclService;
+import org.apache.kylin.rest.service.UserService;
+import org.h2.util.StringUtils;
+
+import java.io.IOException;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/19/15.
+ */
+public class MockAclHBaseStorage implements AclHBaseStorage {
+
+    private HTableInterface mockedAclTable;
+    private HTableInterface mockedUserTable;
+    private static final String aclTableName = "MOCK-ACL-TABLE";
+    private static final String userTableName = "MOCK-USER-TABLE";
+
+    @Override
+    public String prepareHBaseTable(Class clazz) throws IOException {
+
+        if (clazz == AclService.class) {
+            mockedAclTable = new MockHTable(aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
+            return aclTableName;
+        } else if (clazz == UserService.class) {
+            mockedUserTable = new MockHTable(userTableName, USER_AUTHORITY_FAMILY);
+            return userTableName;
+        } else {
+            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
+        }
+    }
+
+    @Override
+    public HTableInterface getTable(String tableName) throws IOException {
+        if (StringUtils.equals(tableName, aclTableName)) {
+            return mockedAclTable;
+        } else if (StringUtils.equals(tableName, userTableName)) {
+            return mockedUserTable;
+        } else {
+            throw new IllegalStateException("getTable failed" + tableName);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
new file mode 100644
index 0000000..44e6f8f
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
@@ -0,0 +1,51 @@
+package org.apache.kylin.rest.security;
+
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.persistence.HBaseConnection;
+import org.apache.kylin.rest.service.AclService;
+import org.apache.kylin.rest.service.UserService;
+import org.h2.util.StringUtils;
+
+import java.io.IOException;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/19/15.
+ */
+public class RealAclHBaseStorage implements AclHBaseStorage {
+
+    private String hbaseUrl;
+    private String aclTableName;
+    private String userTableName;
+
+    @Override
+    public String prepareHBaseTable(Class clazz) throws IOException {
+        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
+        int cut = metadataUrl.indexOf('@');
+        String tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
+        hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
+
+        if (clazz == AclService.class) {
+            aclTableName = tableNameBase + ACL_TABLE_NAME;
+            HBaseConnection.createHTableIfNeeded(hbaseUrl, aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
+            return aclTableName;
+        } else if (clazz == UserService.class) {
+            userTableName = tableNameBase + USER_TABLE_NAME;
+            HBaseConnection.createHTableIfNeeded(hbaseUrl, userTableName, USER_AUTHORITY_FAMILY);
+            return userTableName;
+        } else {
+            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
+        }
+    }
+
+    @Override
+    public HTableInterface getTable(String tableName) throws IOException {
+        if (StringUtils.equals(tableName, aclTableName)) {
+            return HBaseConnection.get(hbaseUrl).getTable(aclTableName);
+        } else if (StringUtils.equals(tableName, userTableName)) {
+            return HBaseConnection.get(hbaseUrl).getTable(userTableName);
+        } else {
+            throw new IllegalStateException("getTable failed" + tableName);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/service/AclService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/AclService.java b/server/src/main/java/org/apache/kylin/rest/service/AclService.java
index 842233f..981205c 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/AclService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/AclService.java
@@ -25,7 +25,7 @@ import org.apache.hadoop.hbase.client.*;
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
 import org.apache.kylin.common.util.Bytes;
-import org.apache.kylin.rest.util.AclHBaseStorage;
+import org.apache.kylin.rest.security.AclHBaseStorage;
 import org.apache.kylin.rest.util.Serializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/service/UserService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/UserService.java b/server/src/main/java/org/apache/kylin/rest/service/UserService.java
index bc838b6..cf6d03c 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/UserService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/UserService.java
@@ -24,7 +24,7 @@ import org.apache.hadoop.hbase.client.*;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.JsonUtil;
 import org.apache.kylin.rest.security.UserManager;
-import org.apache.kylin.rest.util.AclHBaseStorage;
+import org.apache.kylin.rest.security.AclHBaseStorage;
 import org.apache.kylin.rest.util.Serializer;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.GrantedAuthority;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/util/AclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/AclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/util/AclHBaseStorage.java
deleted file mode 100644
index 7d495eb..0000000
--- a/server/src/main/java/org/apache/kylin/rest/util/AclHBaseStorage.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.apache.kylin.rest.util;
-
-import org.apache.hadoop.hbase.client.HTableInterface;
-
-import java.io.IOException;
-
-/**
- * Created by Hongbin Ma(Binmahone) on 5/19/15.
- */
-public interface AclHBaseStorage {
-    String DEFAULT_TABLE_PREFIX = "kylin_metadata";
-
-    String ACL_INFO_FAMILY = "i";
-    String ACL_ACES_FAMILY = "a";
-    String ACL_TABLE_NAME = "_acl";
-
-    String USER_AUTHORITY_FAMILY = "a";
-    String USER_TABLE_NAME = "_user";
-    String USER_AUTHORITY_COLUMN = "c";
-
-    String prepareHBaseTable(Class clazz) throws IOException;
-
-    HTableInterface getTable(String tableName) throws IOException;
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/util/MockAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/MockAclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/util/MockAclHBaseStorage.java
deleted file mode 100644
index ce9ef1d..0000000
--- a/server/src/main/java/org/apache/kylin/rest/util/MockAclHBaseStorage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.apache.kylin.rest.util;
-
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.kylin.common.util.MockHTable;
-import org.apache.kylin.rest.service.AclService;
-import org.apache.kylin.rest.service.UserService;
-import org.h2.util.StringUtils;
-
-import java.io.IOException;
-
-/**
- * Created by Hongbin Ma(Binmahone) on 5/19/15.
- */
-public class MockAclHBaseStorage implements AclHBaseStorage {
-
-    private HTableInterface mockedAclTable;
-    private HTableInterface mockedUserTable;
-    private static final String aclTableName = "MOCK-ACL-TABLE";
-    private static final String userTableName = "MOCK-USER-TABLE";
-
-    @Override
-    public String prepareHBaseTable(Class clazz) throws IOException {
-
-        if (clazz == AclService.class) {
-            mockedAclTable = new MockHTable(aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
-            return aclTableName;
-        } else if (clazz == UserService.class) {
-            mockedUserTable = new MockHTable(userTableName, USER_AUTHORITY_FAMILY);
-            return userTableName;
-        } else {
-            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
-        }
-    }
-
-    @Override
-    public HTableInterface getTable(String tableName) throws IOException {
-        if (StringUtils.equals(tableName, aclTableName)) {
-            return mockedAclTable;
-        } else if (StringUtils.equals(tableName, userTableName)) {
-            return mockedUserTable;
-        } else {
-            throw new IllegalStateException("getTable failed" + tableName);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/java/org/apache/kylin/rest/util/RealAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/RealAclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/util/RealAclHBaseStorage.java
deleted file mode 100644
index 4d4865e..0000000
--- a/server/src/main/java/org/apache/kylin/rest/util/RealAclHBaseStorage.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.apache.kylin.rest.util;
-
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.persistence.HBaseConnection;
-import org.apache.kylin.rest.service.AclService;
-import org.apache.kylin.rest.service.UserService;
-import org.h2.util.StringUtils;
-
-import java.io.IOException;
-
-/**
- * Created by Hongbin Ma(Binmahone) on 5/19/15.
- */
-public class RealAclHBaseStorage implements AclHBaseStorage {
-
-    private String hbaseUrl;
-    private String aclTableName;
-    private String userTableName;
-
-    @Override
-    public String prepareHBaseTable(Class clazz) throws IOException {
-        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
-        int cut = metadataUrl.indexOf('@');
-        String tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
-        hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
-
-        if (clazz == AclService.class) {
-            aclTableName = tableNameBase + ACL_TABLE_NAME;
-            HBaseConnection.createHTableIfNeeded(hbaseUrl, aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
-            return aclTableName;
-        } else if (clazz == UserService.class) {
-            userTableName = tableNameBase + USER_TABLE_NAME;
-            HBaseConnection.createHTableIfNeeded(hbaseUrl, userTableName, USER_AUTHORITY_FAMILY);
-            return userTableName;
-        } else {
-            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
-        }
-    }
-
-    @Override
-    public HTableInterface getTable(String tableName) throws IOException {
-        if (StringUtils.equals(tableName, aclTableName)) {
-            return HBaseConnection.get(hbaseUrl).getTable(aclTableName);
-        } else if (StringUtils.equals(tableName, userTableName)) {
-            return HBaseConnection.get(hbaseUrl).getTable(userTableName);
-        } else {
-            throw new IllegalStateException("getTable failed" + tableName);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/main/resources/applicationContext.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/applicationContext.xml b/server/src/main/resources/applicationContext.xml
index 619151d..aef311e 100644
--- a/server/src/main/resources/applicationContext.xml
+++ b/server/src/main/resources/applicationContext.xml
@@ -1,14 +1,13 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-	xmlns:context="http://www.springframework.org/schema/context"
-	xmlns:mvc="http://www.springframework.org/schema/mvc" 
-	xmlns:task="http://www.springframework.org/schema/task"
-	xmlns:metrics="http://www.ryantenney.com/schema/metrics" 
-	xmlns:aop="http://www.springframework.org/schema/aop"
-	xmlns:cache="http://www.springframework.org/schema/cache" 
-	xmlns:p="http://www.springframework.org/schema/p"
-	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:mvc="http://www.springframework.org/schema/mvc"
+       xmlns:task="http://www.springframework.org/schema/task"
+       xmlns:metrics="http://www.ryantenney.com/schema/metrics"
+       xmlns:aop="http://www.springframework.org/schema/aop"
+       xmlns:cache="http://www.springframework.org/schema/cache"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.1.xsd
@@ -21,114 +20,119 @@
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
     http://www.springframework.org/schema/cache
-    http://www.springframework.org/schema/cache/spring-cache.xsd
-    http://www.springframework.org/schema/jdbc  
-    http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
-
-	<description>Kylin Rest Service</description>
-	<context:annotation-config />
-	<mvc:annotation-driven />
-	<aop:aspectj-autoproxy />
-
-	<context:component-scan base-package="org.apache.kylin.rest" />
-
-	<!-- Matric Spring -->
-	<!-- Registry should be defined in only one context XML file -->
-	<metrics:metric-registry id="metrics" />
-
-	<!-- annotation-driven must be included in all context files -->
-	<metrics:annotation-driven metric-registry="metrics" />
-
-	<!--&lt;!&ndash; (Optional) Registry should be defined in only one context XML file &ndash;&gt;-->
-	<!--<metrics:reporter type="ganglia" metric-registry="metrics"-->
-		<!--group="${ganglia.group}" port="${ganglia.port}" udp-mode="MULTICAST"-->
-		<!--ttl="100" period="1m" />-->
-
-	<!-- (Optional) The metrics in this example require the metrics-jvm jar -->
-	<metrics:register metric-registry="metrics">
-		<bean metrics:name="jvm.gc"
-			class="com.codahale.metrics.jvm.GarbageCollectorMetricSet" />
-		<bean metrics:name="jvm.memory" class="com.codahale.metrics.jvm.MemoryUsageGaugeSet" />
-		<bean metrics:name="jvm.thread-states"
-			class="com.codahale.metrics.jvm.ThreadStatesGaugeSet" />
-		<!--<bean metrics:name="jvm.fd.usage" class="com.codahale.metrics.jvm.FileDescriptorRatioGauge" 
-			/> -->
-	</metrics:register>
-	<!-- Matric Spring -->
-
-	<bean class="org.apache.kylin.rest.security.PasswordPlaceholderConfigurer">
-		<property name="ignoreResourceNotFound" value="true" />
-	</bean>
-
-	<bean id="aclHBaseStorage" class="org.apache.kylin.rest.util.MockAclHBaseStorage"/>
-
-	<!-- Rest service binding -->
-	<bean
-		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
-
-	<bean id="mappingJacksonHttpMessageConverter"
-		class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
-	<bean id="stringHttpMessageConverter"
-		class="org.springframework.http.converter.StringHttpMessageConverter" />
-	<bean id="formHttpMessageConverter"
-		class="org.springframework.http.converter.FormHttpMessageConverter" />
-
-	<bean
-		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
-		<property name="messageConverters">
-			<list>
-				<ref bean="mappingJacksonHttpMessageConverter" />
-				<ref bean="stringHttpMessageConverter" />
-				<ref bean="formHttpMessageConverter" />
-			</list>
-		</property>
-	</bean>
-
-	<bean
-		class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
-		<property name="mediaTypes">
-			<map>
-				<entry key="html" value="text/html" />
-				<entry key="json" value="application/json" />
-			</map>
-		</property>
-		<property name="viewResolvers">
-			<list>
-				<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
-				<bean
-					class="org.springframework.web.servlet.view.InternalResourceViewResolver">
-					<!-- <property name="prefix" value="/WEB-INF/jsp/"/> -->
-					<property name="suffix" value=".jsp" />
-				</bean>
-			</list>
-		</property>
-		<property name="defaultViews">
-			<list>
-				<bean
-					class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
-			</list>
-		</property>
-	</bean>
-	<!-- Rest service binding -->
-
-	<task:annotation-driven />
-	<bean id="performanceMonitorTask" class="org.apache.kylin.rest.util.PerformanceMonitorTask"></bean>
-
-	<!-- Cache Config -->
-	<cache:annotation-driven />
-	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
-		p:cacheManager-ref="ehcache" />
-	<!-- Cache Config -->
-
-	<beans profile="default">
-		<bean id="ehcache"
-			class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
-			p:configLocation="classpath:ehcache.xml" p:shared="true" />
-	</beans>
-
-	<beans profile="sandbox,testing">
-		<bean id="ehcache"
-			class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
-			p:configLocation="classpath:ehcache-test.xml" p:shared="true" />
-	</beans>
+    http://www.springframework.org/schema/cache/spring-cache.xsd">
+
+    <description>Kylin Rest Service</description>
+    <context:annotation-config/>
+    <mvc:annotation-driven/>
+    <aop:aspectj-autoproxy/>
+
+    <context:component-scan base-package="org.apache.kylin.rest"/>
+
+    <!-- Matric Spring -->
+    <!-- Registry should be defined in only one context XML file -->
+    <metrics:metric-registry id="metrics"/>
+
+    <!-- annotation-driven must be included in all context files -->
+    <metrics:annotation-driven metric-registry="metrics"/>
+
+    <!--&lt;!&ndash; (Optional) Registry should be defined in only one context XML file &ndash;&gt;-->
+    <!--<metrics:reporter type="ganglia" metric-registry="metrics"-->
+    <!--group="${ganglia.group}" port="${ganglia.port}" udp-mode="MULTICAST"-->
+    <!--ttl="100" period="1m" />-->
+
+    <!-- (Optional) The metrics in this example require the metrics-jvm jar -->
+    <metrics:register metric-registry="metrics">
+        <bean metrics:name="jvm.gc"
+              class="com.codahale.metrics.jvm.GarbageCollectorMetricSet"/>
+        <bean metrics:name="jvm.memory" class="com.codahale.metrics.jvm.MemoryUsageGaugeSet"/>
+        <bean metrics:name="jvm.thread-states"
+              class="com.codahale.metrics.jvm.ThreadStatesGaugeSet"/>
+        <!--<bean metrics:name="jvm.fd.usage" class="com.codahale.metrics.jvm.FileDescriptorRatioGauge"
+            /> -->
+    </metrics:register>
+    <!-- Matric Spring -->
+
+    <bean class="org.apache.kylin.rest.security.PasswordPlaceholderConfigurer">
+        <property name="ignoreResourceNotFound" value="true"/>
+    </bean>
+
+
+    <!-- Rest service binding -->
+    <bean
+            class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
+
+    <bean id="mappingJacksonHttpMessageConverter"
+          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
+    <bean id="stringHttpMessageConverter"
+          class="org.springframework.http.converter.StringHttpMessageConverter"/>
+    <bean id="formHttpMessageConverter"
+          class="org.springframework.http.converter.FormHttpMessageConverter"/>
+
+    <bean
+            class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+        <property name="messageConverters">
+            <list>
+                <ref bean="mappingJacksonHttpMessageConverter"/>
+                <ref bean="stringHttpMessageConverter"/>
+                <ref bean="formHttpMessageConverter"/>
+            </list>
+        </property>
+    </bean>
+
+    <bean
+            class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
+        <property name="mediaTypes">
+            <map>
+                <entry key="html" value="text/html"/>
+                <entry key="json" value="application/json"/>
+            </map>
+        </property>
+        <property name="viewResolvers">
+            <list>
+                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
+                <bean
+                        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
+                    <!-- <property name="prefix" value="/WEB-INF/jsp/"/> -->
+                    <property name="suffix" value=".jsp"/>
+                </bean>
+            </list>
+        </property>
+        <property name="defaultViews">
+            <list>
+                <bean
+                        class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
+            </list>
+        </property>
+    </bean>
+    <!-- Rest service binding -->
+    <task:annotation-driven/>
+    <bean id="performanceMonitorTask" class="org.apache.kylin.rest.util.PerformanceMonitorTask"></bean>
+
+    <!-- Cache Config -->
+    <cache:annotation-driven/>
+
+    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
+          p:cacheManager-ref="ehcache"/>
+    <beans profile="default">
+        <bean id="ehcache"
+              class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
+              p:configLocation="classpath:ehcache.xml" p:shared="true"/>
+    </beans>
+    <beans profile="sandbox,testing">
+        <bean id="ehcache"
+              class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
+              p:configLocation="classpath:ehcache-test.xml" p:shared="true"/>
+    </beans>
+
+    <!-- hbase storage/global lock Config -->
+    <beans profile="default,sandbox">
+        <bean id="aclHBaseStorage" class="org.apache.kylin.rest.security.RealAclHBaseStorage"/>
+        <bean id="jobLock" class="org.apache.kylin.common.lock.ZookeeperJobLock"/>
+    </beans>
+    <beans profile="testing">
+        <bean id="aclHBaseStorage" class="org.apache.kylin.rest.security.MockAclHBaseStorage"/>
+        <bean id="jobLock" class="org.apache.kylin.common.lock.MockJobLock"/>
+    </beans>
+
 </beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5b6960ee/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java b/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
index 795afaf..ef834c0 100644
--- a/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
@@ -64,7 +64,7 @@ public class CacheServiceTest extends LocalFileMetadataTestCase {
 
     @BeforeClass
     public static void beforeClass() throws Exception {
-        createTestMetadata(LOCALMETA_TEST_DATA);
+        staticCreateTestMetadata(LOCALMETA_TEST_DATA);
         configA = KylinConfig.getInstanceFromEnv();
         configB = KylinConfig.getKylinConfigFromInputStream(KylinConfig.getKylinPropertiesAsInputSteam());
         configB.setMetadataUrl("../examples/test_metadata");