Repository: kylin
Updated Branches:
  refs/heads/KYLIN-1826 [created] 4b4e0b8ee


KYLIN-1826, add external hive interface, project, table..

Signed-off-by: terry-chelsea <hzfen...@corp.netease.com>
Signed-off-by: shaofengshi <shaofeng...@apache.org>


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

Branch: refs/heads/KYLIN-1826
Commit: be7128bff25448202bf888f808fda1e95d6cec2b
Parents: b08871e
Author: terry-chelsea <hzfen...@corp.netease.com>
Authored: Fri Oct 28 20:38:35 2016 +0800
Committer: shaofengshi <shaofeng...@apache.org>
Committed: Fri Oct 28 22:34:34 2016 +0800

----------------------------------------------------------------------
 .../apache/kylin/common/KylinConfigBase.java    |   4 +
 .../apache/kylin/metadata/model/TableDesc.java  |  11 +
 .../kylin/metadata/project/ProjectInstance.java |  11 +
 .../kylin/metadata/project/ProjectManager.java  |  22 +-
 .../hive/ITHiveSourceTableLoaderTest.java       |   3 +-
 .../kylin/rest/controller/CubeController.java   |  17 ++
 .../rest/controller/ProjectController.java      |  28 ++-
 .../rest/controller/StreamingController.java    |   4 +
 .../kylin/rest/controller/TableController.java  |  24 ++-
 .../rest/request/CreateProjectRequest.java      |   9 +
 .../rest/request/UpdateProjectRequest.java      |  10 +
 .../apache/kylin/rest/service/BasicService.java |  14 +-
 .../apache/kylin/rest/service/CacheService.java |   4 +-
 .../apache/kylin/rest/service/CubeService.java  |  10 +-
 .../kylin/rest/service/ProjectService.java      |   6 +-
 .../apache/kylin/source/hive/HiveClient.java    |   2 +-
 .../source/hive/HiveSourceTableLoader.java      |  22 +-
 .../hive/external/ExternalHiveClient.java       |  80 +++++++
 .../kylin/source/hive/external/HiveManager.java | 206 +++++++++++++++++++
 webapp/app/js/controllers/page.js               |   1 +
 webapp/app/js/controllers/sourceMeta.js         |   4 +-
 webapp/app/js/model/projectConfig.js            |   1 +
 .../app/partials/projects/project_create.html   |   9 +
 webapp/app/partials/projects/projects.html      |   1 +
 24 files changed, 476 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
----------------------------------------------------------------------
diff --git 
a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java 
b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
index 79ee084..5063110 100644
--- a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
+++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
@@ -365,6 +365,10 @@ abstract public class KylinConfigBase implements 
Serializable {
     public String getCliWorkingDir() {
         return getOptional("kylin.job.remote.cli.working.dir");
     }
+    
+    public String getExternalHiveRootDirectory() {
+        return getOptional("kylin.external.hive.root.directory", null);
+    }
 
     public boolean isEmptySegmentAllowed() {
         return 
Boolean.parseBoolean(getOptional("kylin.job.allow.empty.segment", "true"));

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
----------------------------------------------------------------------
diff --git 
a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java 
b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
index e163d1d..abd348d 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
@@ -45,6 +45,8 @@ public class TableDesc extends RootPersistentEntity 
implements ISourceAware {
     private int sourceType = ISourceAware.ID_HIVE;
     @JsonProperty("table_type")
     private String tableType;
+    @JsonProperty("hive")
+    private String hive;
 
     private static final String materializedTableNamePrefix = 
"kylin_intermediate_";
 
@@ -60,6 +62,7 @@ public class TableDesc extends RootPersistentEntity 
implements ISourceAware {
         this.columns = other.getColumns();
         this.database.setName(other.getDatabase());
         this.tableType = other.getTableType();
+        this.hive = other.getHive();
     }
 
     public ColumnDesc findColumnByName(String name) {
@@ -250,4 +253,12 @@ public class TableDesc extends RootPersistentEntity 
implements ISourceAware {
         this.tableType = tableType;
     }
 
+    public String getHive() {
+        return hive;
+    }
+
+    public void setHive(String hive) {
+        this.hive = hive;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
----------------------------------------------------------------------
diff --git 
a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
 
b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
index 1afc603..b0ce889 100644
--- 
a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
+++ 
b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
@@ -49,6 +49,9 @@ public class ProjectInstance extends RootPersistentEntity {
 
     @JsonProperty("name")
     private String name;
+    
+    @JsonProperty("hive")
+    private String hive;
 
     @JsonProperty("tables")
     private Set<String> tables = new TreeSet<String>();
@@ -153,6 +156,14 @@ public class ProjectInstance extends RootPersistentEntity {
     public void setName(String name) {
         this.name = name;
     }
+    
+    public String getHive() {
+        return hive;
+    }
+
+    public void setHive(String hive) {
+        this.hive = hive;
+    }
 
     public boolean containsRealization(final RealizationType type, final 
String realization) {
         return Iterables.any(this.realizationEntries, new 
Predicate<RealizationEntry>() {

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
----------------------------------------------------------------------
diff --git 
a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
 
b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
index 1bf9804..e86c1a2 100644
--- 
a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
+++ 
b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
@@ -152,6 +152,15 @@ public class ProjectManager {
 
         return currentProject;
     }
+    
+    public ProjectInstance createProject(String projectName, String owner, 
String description, String hiveName) throws IOException {
+        logger.info("Creating project " + projectName + ", hive name " + 
hiveName);
+        ProjectInstance currentProject = this.createProject(projectName, 
owner, description);
+        currentProject.setHive(hiveName);
+        updateProject(currentProject);
+        
+        return currentProject;
+    }
 
     public ProjectInstance dropProject(String projectName) throws IOException {
         if (projectName == null)
@@ -183,9 +192,9 @@ public class ProjectManager {
     }
 
     //update project itself
-    public ProjectInstance updateProject(ProjectInstance project, String 
newName, String newDesc) throws IOException {
+    public ProjectInstance updateProject(ProjectInstance project, String 
newName, String newDesc, String hiveName) throws IOException {
         if (!project.getName().equals(newName)) {
-            ProjectInstance newProject = this.createProject(newName, 
project.getOwner(), newDesc);
+            ProjectInstance newProject = this.createProject(newName, 
project.getOwner(), newDesc, hiveName);
 
             newProject.setCreateTimeUTC(project.getCreateTimeUTC());
             newProject.recordUpdateTime(System.currentTimeMillis());
@@ -200,8 +209,13 @@ public class ProjectManager {
             return newProject;
         } else {
             project.setName(newName);
-            project.setDescription(newDesc);
-
+            if(newDesc != null) {
+                project.setDescription(newDesc);
+            }
+            if(hiveName != null) {
+                project.setHive(hiveName);
+            }
+            
             if (project.getUuid() == null)
                 project.updateRandomUuid();
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/kylin-it/src/test/java/org/apache/kylin/source/hive/ITHiveSourceTableLoaderTest.java
----------------------------------------------------------------------
diff --git 
a/kylin-it/src/test/java/org/apache/kylin/source/hive/ITHiveSourceTableLoaderTest.java
 
b/kylin-it/src/test/java/org/apache/kylin/source/hive/ITHiveSourceTableLoaderTest.java
index c4f0777..c33840c 100644
--- 
a/kylin-it/src/test/java/org/apache/kylin/source/hive/ITHiveSourceTableLoaderTest.java
+++ 
b/kylin-it/src/test/java/org/apache/kylin/source/hive/ITHiveSourceTableLoaderTest.java
@@ -45,7 +45,8 @@ public class ITHiveSourceTableLoaderTest extends 
HBaseMetadataTestCase {
     public void test() throws IOException {
         KylinConfig config = getTestConfig();
         String[] toLoad = new String[] { "DEFAULT.TEST_KYLIN_FACT", 
"EDW.TEST_CAL_DT" };
-        Set<String> loaded = HiveSourceTableLoader.reloadHiveTables(toLoad, 
config);
+        String project = "learn_kylin";
+        Set<String> loaded = HiveSourceTableLoader.reloadHiveTables(toLoad, 
project, config);
 
         assertTrue(loaded.size() == toLoad.length);
         for (String str : toLoad)

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
 
b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index 5397df7..d371230 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -56,6 +56,7 @@ import org.apache.kylin.rest.service.CubeService;
 import org.apache.kylin.rest.service.JobService;
 import org.apache.kylin.rest.service.KafkaConfigService;
 import org.apache.kylin.rest.service.StreamingService;
+import org.apache.kylin.source.hive.external.HiveManager;
 import org.apache.kylin.source.kafka.config.KafkaConfig;
 import 
org.apache.kylin.storage.hbase.cube.v1.coprocessor.observer.ObserverEnabler;
 import org.slf4j.Logger;
@@ -343,6 +344,9 @@ public class CubeController extends BasicController {
         String newCubeName = cubeRequest.getCubeName();
         String project = cubeRequest.getProject();
 
+        if(!this.isBasedSameSource(cubeName, project)) {
+            throw new InternalErrorException("Can not move cube to project 
with different hive source!");
+        }
         CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
         if (cube == null) {
             throw new InternalErrorException("Cannot find cube " + cubeName);
@@ -364,6 +368,19 @@ public class CubeController extends BasicController {
         return newCube;
 
     }
+    
+    private boolean isBasedSameSource(String cubeName, String projectName) {
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+        if(cube == null)
+            return true;
+        
+        ProjectInstance project = 
cubeService.getProjectManager().getProject(projectName);
+        if(project == null) {
+            return true;
+        }
+        ProjectInstance cubeProject = cubeService.getProjectByCube(cubeName);
+        return HiveManager.isSameHiveSource(project.getHive(), 
cubeProject.getHive());
+    }
 
     @RequestMapping(value = "/{cubeName}/enable", method = { RequestMethod.PUT 
})
     @ResponseBody

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
 
b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
index 496e44a..bee4a63 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
@@ -33,6 +33,7 @@ import org.apache.kylin.rest.request.UpdateProjectRequest;
 import org.apache.kylin.rest.service.AccessService;
 import org.apache.kylin.rest.service.CubeService;
 import org.apache.kylin.rest.service.ProjectService;
+import org.apache.kylin.source.hive.external.HiveManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -199,7 +200,9 @@ public class ProjectController extends BasicController {
         if (StringUtils.isEmpty(projectRequest.getName())) {
             throw new InternalErrorException("A project name must be given to 
create a project");
         }
-
+        
+        String hiveName = projectRequest.getHive();
+        checkHiveIsValid(hiveName);
         ProjectInstance createdProj = null;
         try {
             createdProj = projectService.createProject(projectRequest);
@@ -217,7 +220,7 @@ public class ProjectController extends BasicController {
         if (StringUtils.isEmpty(projectRequest.getFormerProjectName())) {
             throw new InternalErrorException("A project name must be given to 
update a project");
         }
-
+        checkHiveIsValid(projectRequest.getNewHiveName());
         ProjectInstance updatedProj = null;
         try {
             ProjectInstance currentProject = 
projectService.getProjectManager().getProject(projectRequest.getFormerProjectName());
@@ -254,4 +257,25 @@ public class ProjectController extends BasicController {
     public void setCubeService(CubeService cubeService) {
         this.cubeService = cubeService;
     }
+    
+    /**
+     * Check input hive name is valid
+     * @param hiveName
+     */
+    private void checkHiveIsValid(String hiveName) {
+        try {
+            if(HiveManager.getInstance().isSupportExternalHives()) {
+                HiveManager.getInstance().getHiveCommand(hiveName);
+                HiveManager.getInstance().getHiveConfigFile(hiveName);
+                return;
+            }
+        } catch (Exception e) {
+            logger.error("Can not find hive " + hiveName + ", support hives : 
" + 
+                    HiveManager.getInstance().getExternalHiveName());
+            throw new InternalErrorException("Can not find hive " + hiveName + 
" by current external hives configuration");
+        }
+        if(hiveName != null) {
+            throw new 
InternalErrorException(HiveManager.NOT_SUPPORT_ERROR_MESSAGE);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
 
b/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
index f3374c3..addf544 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
@@ -29,6 +29,7 @@ import org.apache.kylin.engine.mr.HadoopUtil;
 import org.apache.kylin.engine.streaming.StreamingConfig;
 import org.apache.kylin.metadata.MetadataManager;
 import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.rest.exception.BadRequestException;
 import org.apache.kylin.rest.exception.ForbiddenException;
 import org.apache.kylin.rest.exception.InternalErrorException;
@@ -103,6 +104,8 @@ public class StreamingController extends BasicController {
     public StreamingRequest saveStreamingConfig(@RequestBody StreamingRequest 
streamingRequest) {
 
         String project = streamingRequest.getProject();
+        ProjectManager projectMgr = 
ProjectManager.getInstance(KylinConfig.getInstanceFromEnv());
+        String hive = projectMgr.getProject(project).getHive();
         TableDesc tableDesc = deserializeTableDesc(streamingRequest);
         StreamingConfig streamingConfig = 
deserializeSchemalDesc(streamingRequest);
         KafkaConfig kafkaConfig = 
deserializeKafkaSchemalDesc(streamingRequest);
@@ -110,6 +113,7 @@ public class StreamingController extends BasicController {
 
         try {
             tableDesc.setUuid(UUID.randomUUID().toString());
+            tableDesc.setHive(hive);
             MetadataManager metaMgr = 
MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
             metaMgr.saveSourceTable(tableDesc);
             cubeMgmtService.syncTableToProject(new String[] { 
tableDesc.getIdentity() }, project);

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
 
b/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
index eefeba8..81ccb4b 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
@@ -37,6 +37,7 @@ import org.apache.kylin.metadata.MetadataConstants;
 import org.apache.kylin.metadata.MetadataManager;
 import org.apache.kylin.metadata.model.ColumnDesc;
 import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.rest.exception.InternalErrorException;
 import org.apache.kylin.rest.request.CardinalityRequest;
 import org.apache.kylin.rest.request.HiveTableRequest;
@@ -48,6 +49,7 @@ import org.apache.kylin.rest.service.ModelService;
 import org.apache.kylin.rest.service.ProjectService;
 import org.apache.kylin.rest.service.StreamingService;
 import org.apache.kylin.source.hive.HiveClient;
+import org.apache.kylin.source.hive.external.HiveManager;
 import org.apache.kylin.source.kafka.config.KafkaConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -145,7 +147,7 @@ public class TableController extends BasicController {
     @ResponseBody
     public Map<String, String[]> loadHiveTable(@PathVariable String tables, 
@PathVariable String project, @RequestBody HiveTableRequest request) throws 
IOException {
         String submitter = 
SecurityContextHolder.getContext().getAuthentication().getName();
-        String[] loaded = cubeMgmtService.reloadHiveTable(tables);
+        String[] loaded = cubeMgmtService.reloadHiveTable(tables, project);
         if (request.isCalculate()) {
             cubeMgmtService.calculateCardinalityIfNotPresent(loaded, 
submitter);
         }
@@ -233,8 +235,11 @@ public class TableController extends BasicController {
     public Map<String, String> addStreamingTable(@RequestBody StreamingRequest 
request) throws IOException {
         Map<String, String> result = new HashMap<String, String>();
         String project = request.getProject();
+        String hiveName = getHiveNameByProject(project);
+        
         TableDesc desc = JsonUtil.readValue(request.getTableData(), 
TableDesc.class);
         desc.setUuid(UUID.randomUUID().toString());
+        desc.setHive(hiveName);
         MetadataManager metaMgr = 
MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
         metaMgr.saveSourceTable(desc);
         cubeMgmtService.syncTableToProject(new String[] { desc.getName() }, 
project);
@@ -311,11 +316,13 @@ public class TableController extends BasicController {
      */
     @RequestMapping(value = "/hive", method = { RequestMethod.GET })
     @ResponseBody
-    private static List<String> showHiveDatabases() throws IOException {
-        HiveClient hiveClient = new HiveClient();
+    private static List<String> showHiveDatabases(@RequestParam(value = 
"project", required = true) String project) 
+            throws IOException {
         List<String> results = null;
 
         try {
+            String hiveName = getHiveNameByProject(project);
+            HiveClient hiveClient = 
HiveManager.getInstance().createHiveClient(hiveName);
             results = hiveClient.getHiveDbNames();
         } catch (Exception e) {
             e.printStackTrace();
@@ -332,11 +339,13 @@ public class TableController extends BasicController {
      */
     @RequestMapping(value = "/hive/{database}", method = { RequestMethod.GET })
     @ResponseBody
-    private static List<String> showHiveTables(@PathVariable String database) 
throws IOException {
-        HiveClient hiveClient = new HiveClient();
+    private static List<String> showHiveTables(@RequestParam(value = 
"project", required = true) String project, 
+            @PathVariable String database) throws IOException {
         List<String> results = null;
 
         try {
+            String hiveName = getHiveNameByProject(project);
+            HiveClient hiveClient = 
HiveManager.getInstance().createHiveClient(hiveName);
             results = hiveClient.getHiveTableNames(database);
         } catch (Exception e) {
             e.printStackTrace();
@@ -344,6 +353,11 @@ public class TableController extends BasicController {
         }
         return results;
     }
+    
+    private static String getHiveNameByProject(String project) {
+        ProjectManager projectMgr = 
ProjectManager.getInstance(KylinConfig.getInstanceFromEnv());
+        return projectMgr.getProject(project).getHive();
+    }
 
     public void setCubeService(CubeService cubeService) {
         this.cubeMgmtService = cubeService;

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
 
b/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
index 71cd1c4..745172f 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
@@ -22,6 +22,7 @@ package org.apache.kylin.rest.request;
  */
 public class CreateProjectRequest {
     private String name;
+    private String hive;
     private String description;
 
     public CreateProjectRequest() {
@@ -43,4 +44,12 @@ public class CreateProjectRequest {
         this.description = description;
     }
 
+    public String getHive() {
+        return hive;
+    }
+
+    public void setHive(String hive) {
+        this.hive = hive;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
 
b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
index 29ba162..8dca4d9 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
@@ -23,6 +23,7 @@ package org.apache.kylin.rest.request;
 public class UpdateProjectRequest {
     private String formerProjectName;
     private String newProjectName;
+    private String newHiveName;
     private String newDescription;
 
     public UpdateProjectRequest() {
@@ -52,4 +53,13 @@ public class UpdateProjectRequest {
     public void setNewProjectName(String newProjectName) {
         this.newProjectName = newProjectName;
     }
+
+    public String getNewHiveName() {
+        return newHiveName;
+    }
+
+    public void setNewHiveName(String newHiveName) {
+        this.newHiveName = newHiveName;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java 
b/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
index abf0638..e96bddf 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
@@ -26,6 +26,7 @@ import java.util.Set;
 
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
 import org.apache.kylin.engine.mr.CubingJob;
 import org.apache.kylin.engine.mr.steps.CubingExecutableUtil;
@@ -143,7 +144,18 @@ public abstract class BasicService {
         })));
         return results;
     }
-
+    
+    public ProjectInstance getProjectByCube(String cubeName) {
+        CubeInstance cube = getCubeManager().getCube(cubeName);
+        List<ProjectInstance> projList = 
this.getProjectManager().findProjects(cube.getType(), cube.getName());
+        if (projList == null || projList.size() == 0) {
+            throw new RuntimeException("Cannot find the project containing the 
cube " + cube.getName());
+        } else if (projList.size() >= 2) {
+            throw new RuntimeException("Find more than one project containing 
the cube " + cube.getName() + ". It does't meet the uniqueness requirement");
+        }
+        return projList.get(0);
+    }
+    
     protected List<CubingJob> listAllCubingJobs(final String cubeName, final 
String projectName, final Set<ExecutableState> statusList) {
         return listAllCubingJobs(cubeName, projectName, statusList, 
getExecutableManager().getAllOutputs());
     }

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java 
b/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
index 2160e3d..6e091d8 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
@@ -48,6 +48,7 @@ import org.apache.kylin.metadata.realization.RealizationType;
 import org.apache.kylin.query.enumerator.OLAPQuery;
 import org.apache.kylin.query.schema.OLAPSchemaFactory;
 import org.apache.kylin.rest.controller.QueryController;
+import org.apache.kylin.source.hive.external.HiveManager;
 import org.apache.kylin.source.kafka.KafkaConfigManager;
 import org.apache.kylin.storage.hbase.HBaseConnection;
 import org.apache.kylin.storage.hybrid.HybridManager;
@@ -210,7 +211,8 @@ public class CacheService extends BasicService {
                 KafkaConfigManager.clearCache();
                 StreamingManager.clearCache();
                 HBaseConnection.clearConnCache();
-
+                HiveManager.clearCache();
+                
                 cleanAllDataCache();
                 removeAllOLAPDataSources();
                 break;

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java 
b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
index 4cd527c..e6db717 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -482,7 +482,11 @@ public class CubeService extends BasicService {
 
         String outPath = HiveColumnCardinalityJob.OUTPUT_PATH + "/" + 
tableName;
         String param = "-table " + tableName + " -output " + outPath;
-
+        if(table.getHive() != null) {
+            logger.warn("Can not calculate cardinality for tables which loaded 
from external hive source !");
+            return;
+        }
+        
         MapReduceExecutable step1 = new MapReduceExecutable();
 
         step1.setMapReduceJobClass(HiveColumnCardinalityJob.class);
@@ -561,8 +565,8 @@ public class CubeService extends BasicService {
     }
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_MODELER + " or " + 
Constant.ACCESS_HAS_ROLE_ADMIN)
-    public String[] reloadHiveTable(String tables) throws IOException {
-        Set<String> loaded = 
HiveSourceTableLoader.reloadHiveTables(tables.split(","), getConfig());
+    public String[] reloadHiveTable(String tables, String project) throws 
IOException {
+        Set<String> loaded = 
HiveSourceTableLoader.reloadHiveTables(tables.split(","), project, getConfig());
         return (String[]) loaded.toArray(new String[loaded.size()]);
     }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
----------------------------------------------------------------------
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java 
b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
index b4cceb2..00e4da6 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
@@ -53,13 +53,14 @@ public class ProjectService extends BasicService {
     public ProjectInstance createProject(CreateProjectRequest projectRequest) 
throws IOException {
         String projectName = projectRequest.getName();
         String description = projectRequest.getDescription();
+        String hiveName = projectRequest.getHive();
         ProjectInstance currentProject = 
getProjectManager().getProject(projectName);
 
         if (currentProject != null) {
             throw new InternalErrorException("The project named " + 
projectName + " already exists");
         }
         String owner = 
SecurityContextHolder.getContext().getAuthentication().getName();
-        ProjectInstance createdProject = 
getProjectManager().createProject(projectName, owner, description);
+        ProjectInstance createdProject = 
getProjectManager().createProject(projectName, owner, description, hiveName);
         accessService.init(createdProject, AclPermission.ADMINISTRATION);
         logger.debug("New project created.");
 
@@ -71,12 +72,13 @@ public class ProjectService extends BasicService {
         String formerProjectName = projectRequest.getFormerProjectName();
         String newProjectName = projectRequest.getNewProjectName();
         String newDescription = projectRequest.getNewDescription();
+        String newHiveName = projectRequest.getNewHiveName();
 
         if (currentProject == null) {
             throw new InternalErrorException("The project named " + 
formerProjectName + " does not exists");
         }
 
-        ProjectInstance updatedProject = 
getProjectManager().updateProject(currentProject, newProjectName, 
newDescription);
+        ProjectInstance updatedProject = 
getProjectManager().updateProject(currentProject, newProjectName, 
newDescription, newHiveName);
 
         logger.debug("Project updated.");
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/source-hive/src/main/java/org/apache/kylin/source/hive/HiveClient.java
----------------------------------------------------------------------
diff --git 
a/source-hive/src/main/java/org/apache/kylin/source/hive/HiveClient.java 
b/source-hive/src/main/java/org/apache/kylin/source/hive/HiveClient.java
index a99b304..891c635 100644
--- a/source-hive/src/main/java/org/apache/kylin/source/hive/HiveClient.java
+++ b/source-hive/src/main/java/org/apache/kylin/source/hive/HiveClient.java
@@ -104,7 +104,7 @@ public class HiveClient {
             executeHQL(sql);
     }
 
-    private HiveMetaStoreClient getMetaStoreClient() throws Exception {
+    protected HiveMetaStoreClient getMetaStoreClient() throws Exception {
         if (metaStoreClient == null) {
             metaStoreClient = new HiveMetaStoreClient(hiveConf);
         }

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/source-hive/src/main/java/org/apache/kylin/source/hive/HiveSourceTableLoader.java
----------------------------------------------------------------------
diff --git 
a/source-hive/src/main/java/org/apache/kylin/source/hive/HiveSourceTableLoader.java
 
b/source-hive/src/main/java/org/apache/kylin/source/hive/HiveSourceTableLoader.java
index 70b097c..aceb791 100644
--- 
a/source-hive/src/main/java/org/apache/kylin/source/hive/HiveSourceTableLoader.java
+++ 
b/source-hive/src/main/java/org/apache/kylin/source/hive/HiveSourceTableLoader.java
@@ -33,6 +33,8 @@ import org.apache.kylin.metadata.MetadataConstants;
 import org.apache.kylin.metadata.MetadataManager;
 import org.apache.kylin.metadata.model.ColumnDesc;
 import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.source.hive.external.HiveManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,7 +57,7 @@ public class HiveSourceTableLoader {
     public static final String TABLE_FOLDER_NAME = "table";
     public static final String TABLE_EXD_FOLDER_NAME = "table_exd";
 
-    public static Set<String> reloadHiveTables(String[] hiveTables, 
KylinConfig config) throws IOException {
+    public static Set<String> reloadHiveTables(String[] hiveTables, String 
project, KylinConfig config) throws IOException {
 
         Map<String, Set<String>> db2tables = Maps.newHashMap();
         for (String table : hiveTables) {
@@ -71,7 +73,7 @@ public class HiveSourceTableLoader {
         // extract from hive
         Set<String> loadedTables = Sets.newHashSet();
         for (String database : db2tables.keySet()) {
-            List<String> loaded = extractHiveTables(database, 
db2tables.get(database), config);
+            List<String> loaded = extractHiveTables(database, 
db2tables.get(database), project, config);
             loadedTables.addAll(loaded);
         }
 
@@ -84,13 +86,23 @@ public class HiveSourceTableLoader {
         metaMgr.removeTableExd(hiveTable);
     }
 
-    private static List<String> extractHiveTables(String database, Set<String> 
tables, KylinConfig config) throws IOException {
+    private static List<String> extractHiveTables(String database, Set<String> 
tables, String project, KylinConfig config) throws IOException {
 
         List<String> loadedTables = Lists.newArrayList();
         MetadataManager metaMgr = 
MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+        ProjectManager projectMgr = 
ProjectManager.getInstance(KylinConfig.getInstanceFromEnv());
+        String hiveName = projectMgr.getProject(project).getHive();
         for (String tableName : tables) {
             Table table = null;
-            HiveClient hiveClient = new HiveClient();
+            HiveClient hiveClient = 
HiveManager.getInstance().createHiveClient(hiveName);
+            String tableIdentity = database + "." + tableName;
+            TableDesc tableDesc = metaMgr.getTableDesc(tableIdentity);
+            if(tableDesc != null && 
!HiveManager.isSameHiveSource(tableDesc.getHive(), hiveName)) {
+                throw new IllegalArgumentException("Table " + tableIdentity + 
" that in hive " + 
+                        hiveName + " has been loaded in hive " + 
tableDesc.getHive() + 
+                        ", please rename the table or unload the old one.");
+            }
+
             List<FieldSchema> partitionFields = null;
             List<FieldSchema> fields = null;
             try {
@@ -108,13 +120,13 @@ public class HiveSourceTableLoader {
 
             long tableSize = hiveClient.getFileSizeForTable(table);
             long tableFileNum = hiveClient.getFileNumberForTable(table);
-            TableDesc tableDesc = metaMgr.getTableDesc(database + "." + 
tableName);
             if (tableDesc == null) {
                 tableDesc = new TableDesc();
                 tableDesc.setDatabase(database.toUpperCase());
                 tableDesc.setName(tableName.toUpperCase());
                 tableDesc.setUuid(UUID.randomUUID().toString());
                 tableDesc.setLastModified(0);
+                tableDesc.setHive(hiveName);
             }
             if (table.getTableType() != null) {
                 tableDesc.setTableType(table.getTableType());

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/source-hive/src/main/java/org/apache/kylin/source/hive/external/ExternalHiveClient.java
----------------------------------------------------------------------
diff --git 
a/source-hive/src/main/java/org/apache/kylin/source/hive/external/ExternalHiveClient.java
 
b/source-hive/src/main/java/org/apache/kylin/source/hive/external/ExternalHiveClient.java
new file mode 100644
index 0000000..b7d1559
--- /dev/null
+++ 
b/source-hive/src/main/java/org/apache/kylin/source/hive/external/ExternalHiveClient.java
@@ -0,0 +1,80 @@
+/*
+ * 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.kylin.source.hive.external;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.metastore.HiveMetaStore;
+import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
+import org.apache.kylin.source.hive.HiveClient;
+
+/**
+ * Hive meta API client for external hive
+ * @author hzfengyu
+ */
+public class ExternalHiveClient extends HiveClient {
+    private final static String LOCAL_FS_SCHEMA = "file://";
+    
+    public ExternalHiveClient(String location) {
+        URL uri = null;
+        if(location != null) {
+            try {
+                uri = new URL(LOCAL_FS_SCHEMA + location);
+            } catch (MalformedURLException e) {
+                throw new IllegalArgumentException("Can not find hive config 
file " + location);
+            }
+        } else {
+            uri = 
Thread.currentThread().getContextClassLoader().getResource("hive-site.xml");
+        }
+        
+        /**
+         * In HiveConf, hiveSiteURL is a static variable, so we should use a 
global lock.
+         * If uri is null, HiveConf will use the file from java classpath.
+         */
+        synchronized(ExternalHiveClient.class) {
+            hiveConf.setHiveSiteLocation(uri);
+            hiveConf = new HiveConf(HiveClient.class);
+        }
+    }
+    
+    public ExternalHiveClient(Map<String, String> configMap, String location) {
+        this(location);
+        appendConfiguration(configMap);
+    }
+    
+    @Override
+    protected HiveMetaStoreClient getMetaStoreClient() throws Exception {
+        /**
+         * HMSHandler is a LocalThread variable, in tomcat we should check it.
+         * When to remove hive meta store client in thread local variable:
+         * 1: when create new hive client. but HMSHandler exist in current 
thread.
+         * 2: when change hive client in current thread
+         */
+        if (metaStoreClient == null) {
+            HiveMetaStore.HMSHandler.removeRawStore();
+            metaStoreClient = new HiveMetaStoreClient(hiveConf);
+        } else if(HiveMetaStore.HMSHandler.getRawStore() != null && 
HiveMetaStore.HMSHandler.getRawStore().getConf() != this.hiveConf) {
+            HiveMetaStore.HMSHandler.getRawStore().shutdown();
+            HiveMetaStore.HMSHandler.getRawStore().setConf(this.hiveConf);
+        }
+        return metaStoreClient;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/source-hive/src/main/java/org/apache/kylin/source/hive/external/HiveManager.java
----------------------------------------------------------------------
diff --git 
a/source-hive/src/main/java/org/apache/kylin/source/hive/external/HiveManager.java
 
b/source-hive/src/main/java/org/apache/kylin/source/hive/external/HiveManager.java
new file mode 100644
index 0000000..5fbf111
--- /dev/null
+++ 
b/source-hive/src/main/java/org/apache/kylin/source/hive/external/HiveManager.java
@@ -0,0 +1,206 @@
+/*
+ * 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.kylin.source.hive.external;
+
+import java.io.File;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.engine.mr.HadoopUtil;
+import org.apache.kylin.source.hive.HiveClient;
+import org.apache.log4j.Logger;
+
+
+/** 
+ * Manager all hive client, default client and external clients.
+ * This is a Singleton object.
+ * @author hzfengyu
+ */
+public class HiveManager {
+    private volatile static HiveManager HIVE_MANAGER_CACHE = null;
+    private static final Logger logger = Logger.getLogger(HiveManager.class);
+    private static final String DEFAULT_HIVE_NAME = "default(null)";
+    private static final String HIVE_CONFIG_FILE_LOCATION = 
"conf/hive-site.xml";
+    private static final String HIVE_COMMAND_LOCATION = "bin/hive";
+    public static final String NOT_SUPPORT_ERROR_MESSAGE = 
+            "Do not support external hive, set 
kylin.external.hive.root.directory to support it";
+    
+    //hive root directory, if this equals to null or empty meaning just use 
default hive
+    private File externalHiveRootDir = null;
+    private ConcurrentHashMap<String, HiveClient> externalHiveMap = null;
+    private HiveClient defaultHiveClient = null;
+    
+    public static HiveManager getInstance() {
+        //using default kylin config
+        if(HIVE_MANAGER_CACHE == null) {
+            KylinConfig config = KylinConfig.getInstanceFromEnv();
+            synchronized(HiveManager.class) {
+                if(HIVE_MANAGER_CACHE == null) {
+                    HIVE_MANAGER_CACHE = new HiveManager(config);
+                }
+            }
+        }
+        return HIVE_MANAGER_CACHE;
+    }
+    
+    private HiveManager(KylinConfig config) {
+        String externalRootDir = config.getExternalHiveRootDirectory();
+        if(externalRootDir != null && !externalRootDir.isEmpty()) {
+            File file = new File(externalRootDir);
+            //check to ensure hive root file exist
+            this.externalHiveRootDir = file;
+            if(!(file.exists() && file.isDirectory())) {
+                logger.warn("Hive root directory " + file.getAbsolutePath() + 
" do not exist !");
+                this.externalHiveRootDir = null;
+            }
+        } else {
+            this.externalHiveRootDir = null;
+        }
+        this.externalHiveMap = new ConcurrentHashMap<String, HiveClient>();
+    }
+    
+    public List<String> getExternalHiveName() {
+        List<String> hiveNames = new LinkedList<String>();
+        hiveNames.add(DEFAULT_HIVE_NAME);
+        if(this.externalHiveRootDir == null)
+            return hiveNames;
+        
+        //take every diectory in hive root dir is a hive source. take 
directory name as hive name
+        for(File file : this.externalHiveRootDir.listFiles()) {
+            if(!file.isDirectory()) {
+                logger.warn("File " + file.getAbsolutePath() + " in hive root 
directory is normal file.");
+                continue;
+            }
+            hiveNames.add(file.getName());
+        }
+        return hiveNames;
+    }
+    
+    private void checkIsSupportExternalHive() {
+        if(this.externalHiveRootDir == null) {
+            throw new IllegalArgumentException(NOT_SUPPORT_ERROR_MESSAGE);
+        }
+    }
+    
+    public String getHiveConfigFile(String hiveName) {
+        if(hiveName == null) {
+            return null;
+        }
+        checkIsSupportExternalHive();
+     
+        File hiveRootFile = new File(this.externalHiveRootDir, hiveName);
+        if(!(hiveRootFile.exists() && hiveRootFile.isDirectory())) {
+            throw new IllegalArgumentException("Hive " + hiveName + " root 
directory " + hiveRootFile.getAbsolutePath() + " do not exist.");
+        }
+        
+        File hiveConfigFile = new File(hiveRootFile, 
HIVE_CONFIG_FILE_LOCATION);
+        if(!(hiveConfigFile.exists() && hiveConfigFile.isFile())) {
+            throw new IllegalArgumentException("Hive " + hiveName + " config 
file " + hiveConfigFile.getAbsolutePath() + " do not exist.");
+        }
+        return hiveConfigFile.getAbsolutePath();
+    }
+    
+    public HiveClient createHiveClient(String hiveName) {
+        //use internal hive client while do not appoint a hive
+        if(hiveName == null) { 
+            if(defaultHiveClient == null)
+                defaultHiveClient = new ExternalHiveClient(null);
+            return this.defaultHiveClient;
+        }
+        checkIsSupportExternalHive();
+        
+        HiveClient client = this.externalHiveMap.get(hiveName);
+        if(client != null)
+            return client;
+        String configFileLocation = getHiveConfigFile(hiveName);
+        if(configFileLocation == null) {
+            throw new IllegalArgumentException("Can not find hive " + hiveName 
+ " config file in local hive root directory " +
+                    this.externalHiveRootDir.getAbsolutePath());
+        }
+        
+        try {
+            client = new ExternalHiveClient(configFileLocation);
+            this.externalHiveMap.put(hiveName, client);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Can not create hive client for 
" + hiveName + ", config file " + configFileLocation);
+        }
+        return client;
+    }
+    
+    public HiveClient createHiveClientWithConfig(Map<String, String> 
configMap, String hiveName) {
+        HiveClient client = this.createHiveClient(hiveName);
+        client.appendConfiguration(configMap);
+        return client;
+    }
+    
+    public String getHiveCommand(String hiveName) {
+        if(hiveName == null) {
+            return "hive";
+        }
+        checkIsSupportExternalHive();
+        
+        File hiveRootFile = new File(this.externalHiveRootDir, hiveName);
+        if(!(hiveRootFile.exists() && hiveRootFile.isDirectory())) {
+            throw new IllegalArgumentException("Hive " + hiveName + " root 
directory " + hiveRootFile.getAbsolutePath() + " do not exist.");
+        }
+        
+        File hiveCmdFile = new File(hiveRootFile, HIVE_COMMAND_LOCATION);
+        if(!(hiveCmdFile.exists() && hiveCmdFile.isFile())) {
+            throw new IllegalArgumentException("Hive " + hiveName + " bin file 
" + hiveCmdFile.getAbsolutePath() + " do not exist.");
+        }
+        return hiveCmdFile.getAbsolutePath();
+    }
+    
+    public String getHiveTableLocation(String database, String tableName, 
String hiveName) throws Exception {
+        HiveClient hiveClient = this.createHiveClient(hiveName);
+        try {
+            String tableLocation = hiveClient.getHiveTableLocation(database, 
tableName);
+            return tableLocation;
+        } catch (Exception e) {
+           logger.error("Get hive " + hiveName + " table " + tableName + " 
location error !");
+           throw e;
+        }
+    }
+    
+    public String getHiveTableLocation(String fullTableName, String hiveName) 
throws Exception {
+        String[] tables = HadoopUtil.parseHiveTableName(fullTableName);
+        String database = tables[0];
+        String tableName = tables[1];
+        return getHiveTableLocation(database, tableName, hiveName);
+    }
+    
+    public static void clearCache() {
+        HIVE_MANAGER_CACHE = null;
+        getInstance();
+    }
+    
+    public boolean isSupportExternalHives() {
+        return this.externalHiveRootDir != null;
+    }
+    
+    public static boolean isSameHiveSource(String first, String second) {
+        if(first == null) {
+            return second == null;
+        } else {
+            return first.equalsIgnoreCase(second);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/webapp/app/js/controllers/page.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/page.js 
b/webapp/app/js/controllers/page.js
index c65a264..c07cf70 100644
--- a/webapp/app/js/controllers/page.js
+++ b/webapp/app/js/controllers/page.js
@@ -215,6 +215,7 @@ var projCtrl = function ($scope, $location, $modalInstance, 
ProjectService, Mess
       var requestBody = {
         formerProjectName: $scope.state.oldProjName,
         newProjectName: $scope.proj.name,
+        newHiveName: $scope.proj.hive,
         newDescription: $scope.proj.description
       };
       ProjectService.update({}, requestBody, function (newProj) {

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/webapp/app/js/controllers/sourceMeta.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/sourceMeta.js 
b/webapp/app/js/controllers/sourceMeta.js
index e3ab0ac..1c08aa0 100755
--- a/webapp/app/js/controllers/sourceMeta.js
+++ b/webapp/app/js/controllers/sourceMeta.js
@@ -177,7 +177,7 @@ KylinApp
       $scope.loadHive = function () {
         if($scope.hiveLoaded)
           return;
-        TableService.showHiveDatabases({}, function (databases) {
+        TableService.showHiveDatabases({project:$scope.projectName}, function 
(databases) {
           $scope.dbNum = databases.length;
           if (databases.length > 0) {
             $scope.hiveMap = {};
@@ -293,7 +293,7 @@ KylinApp
 
       $scope.showToggle = function(node) {
         if(node.expanded == false){
-          TableService.showHiveTables({"database": node.label},function 
(hive_tables){
+               TableService.showHiveTables({"database": node.label, 
project:$scope.projectName},function (hive_tables){
             var tables = [];
             for (var i = 0; i < hive_tables.length; i++) {
               tables.push(hive_tables[i]);

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/webapp/app/js/model/projectConfig.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/projectConfig.js 
b/webapp/app/js/model/projectConfig.js
index 270eb7a..2a84b47 100644
--- a/webapp/app/js/model/projectConfig.js
+++ b/webapp/app/js/model/projectConfig.js
@@ -20,6 +20,7 @@ KylinApp.constant('projectConfig', {
   theaditems: [
     {attr: 'name', name: 'Name'},
     {attr: 'owner', name: 'Owner'},
+    {attr: 'hive', name: 'Hive Name'},
     {attr: 'description', name: 'Description'},
     {attr: 'create_time', name: 'Create Time'}
   ]

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/webapp/app/partials/projects/project_create.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/projects/project_create.html 
b/webapp/app/partials/projects/project_create.html
index 36cbaf5..f9e33ea 100644
--- a/webapp/app/partials/projects/project_create.html
+++ b/webapp/app/partials/projects/project_create.html
@@ -36,6 +36,15 @@
                 </div>
             </div>
             <div class="form-group">
+                <label><b>Project External Hive</b></label>
+ 
+                <div class="clearfix">
+                     <input name="description_input" type="text" 
class="form-control"
+                               placeholder="External hive that the project 
take as input source, ignore it if you are using default hive."
+                               ng-model="proj.hive"></textarea>
+                </div>
+            </div>
+            <div class="form-group">
                 <label><b>Project Description</b></label>
 
                 <div class="clearfix">

http://git-wip-us.apache.org/repos/asf/kylin/blob/be7128bf/webapp/app/partials/projects/projects.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/projects/projects.html 
b/webapp/app/partials/projects/projects.html
index 96e4a91..10b4dba 100644
--- a/webapp/app/partials/projects/projects.html
+++ b/webapp/app/partials/projects/projects.html
@@ -54,6 +54,7 @@
                     {{ project.name}}
                 </td>
                 <td>{{ project.owner}}</td>
+                <td>{{ project.hive}}</td>
                 <td>{{ project.description}}</td>
                 <td>{{ project.create_time_utc | utcToConfigTimeZone}}</td>
                 <td>

Reply via email to