KYLIN-1168 fix "Update data model is not allowed! Please create a new cube if 
needed" error


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

Branch: refs/heads/1.x-HBase1.1.3
Commit: 04c6607fee3775c7225d19ff55503e38238cecdb
Parents: 55c448b
Author: shaofengshi <shaofeng...@apache.org>
Authored: Wed Nov 25 17:25:14 2015 +0800
Committer: shaofengshi <shaofeng...@apache.org>
Committed: Wed Nov 25 17:25:44 2015 +0800

----------------------------------------------------------------------
 .../kylin/metadata/model/DataModelDesc.java     | 38 -------------------
 .../kylin/rest/controller/CubeController.java   | 39 +++++++++++++-------
 .../apache/kylin/rest/service/CacheService.java |  8 ++--
 .../apache/kylin/rest/service/CubeService.java  |  2 +-
 4 files changed, 31 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/04c6607f/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
----------------------------------------------------------------------
diff --git 
a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java 
b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
index 88fafdf..f8dc54d 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
@@ -220,44 +220,6 @@ public class DataModelDesc extends RootPersistentEntity {
         }
     }
 
-    /**
-     * Check whether two data model are compatible or not. Compatible means
-     * having the same structure. Tow models could be compatible even they
-     * have different UUID or last modified time.
-     * @param that model to compare with
-     * @return true if compatible, false otherwise.
-     */
-    public boolean compatibleWith(DataModelDesc that) {
-        if (this == that)
-            return true;
-
-        if (that == null)
-            return false;
-
-        try {
-            String thisRepr = excludeHeaderInfo(this);
-            String thatRepr = excludeHeaderInfo(that);
-            return StringUtils.equals(thisRepr, thatRepr);
-
-        } catch (IOException e) {
-            logger.error("Failed to serialize DataModelDesc to string", e);
-            return false;
-        }
-    }
-
-    private String excludeHeaderInfo(DataModelDesc modelDesc) throws 
IOException {
-        // make a copy
-        String repr = JsonUtil.writeValueAsString(modelDesc);
-        DataModelDesc copy = JsonUtil.readValue(repr, DataModelDesc.class);
-
-        copy.setUuid(null);
-        copy.setLastModified(0);
-        copy.setCapacity(RealizationCapacity.MEDIUM);
-        copy.setFilterCondition(null);
-        copy.setPartitionDesc(null);
-        return JsonUtil.writeValueAsString(copy);
-    }
-
     @Override
     public String toString() {
         return "DataModelDesc [name=" + name + "]";

http://git-wip-us.apache.org/repos/asf/kylin/blob/04c6607f/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git 
a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java 
b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index 9d1dfad..8565d5e 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -359,8 +359,8 @@ public class CubeController extends BasicController {
         }
 
         MetadataManager metadataManager = 
MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        // KYLIN-958: disallow data model structure change
         DataModelDesc modelDesc = null;
+        DataModelDesc oldModelDesc = null;
         if (StringUtils.isNotEmpty(cubeRequest.getModelDescData())) {
             modelDesc = deserializeDataModelDesc(cubeRequest);
             if (modelDesc == null) {
@@ -373,15 +373,11 @@ public class CubeController extends BasicController {
                 return errorRequest(cubeRequest, "CubeDesc.model_name " + 
desc.getModelName() + " not consistent with model " + modeName);
             }
 
-            DataModelDesc oldModelDesc = 
metadataManager.getDataModelDesc(modeName);
+            oldModelDesc = metadataManager.getDataModelDesc(modeName);
             if (oldModelDesc == null) {
                 return errorRequest(cubeRequest, "Data model " + modeName + " 
not found");
             }
 
-            if (!modelDesc.compatibleWith(oldModelDesc)) {
-                return errorRequest(cubeRequest, "Update data model is not 
allowed! Please create a new cube if needed");
-            }
-
         }
 
         // Check if the cube is editable
@@ -390,27 +386,42 @@ public class CubeController extends BasicController {
             return errorRequest(cubeRequest, error);
         }
 
+        boolean updateModelSuccess = false, updateCubeSuccess = false;
         try {
-            if (modelDesc != null)
+            if (modelDesc != null) {
                 metadataManager.updateDataModelDesc(modelDesc);
-            
+                updateModelSuccess = true;
+            }
+
             CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
             String projectName = (null == cubeRequest.getProject()) ? 
ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject();
             desc = cubeService.updateCubeAndDesc(cube, desc, projectName);
 
+
+            if (desc.getError().isEmpty()) {
+                cubeRequest.setSuccessful(true);
+                updateCubeSuccess = true;
+            } else {
+                logger.warn("Cube " + desc.getName() + " fail to create 
because " + desc.getError());
+                errorRequest(cubeRequest, omitMessage(desc.getError()));
+            }
         } catch (AccessDeniedException accessDeniedException) {
             throw new ForbiddenException("You don't have right to update this 
cube.");
         } catch (Exception e) {
             logger.error("Failed to deal with the request:" + 
e.getLocalizedMessage(), e);
             throw new InternalErrorException("Failed to deal with the request: 
" + e.getLocalizedMessage());
+        } finally {
+            if (updateModelSuccess == true && updateCubeSuccess == false ) {
+                // recover data model
+                try {
+                    metadataManager.updateDataModelDesc(oldModelDesc);
+                } catch (IOException e) {
+                    logger.error("Failed to recover data model desc:" + 
e.getLocalizedMessage(), e);
+                    throw new InternalErrorException("Failed to deal with the 
request: " + e.getLocalizedMessage());
+                }
+            }
         }
 
-        if (desc.getError().isEmpty()) {
-            cubeRequest.setSuccessful(true);
-        } else {
-            logger.warn("Cube " + desc.getName() + " fail to create because " 
+ desc.getError());
-            errorRequest(cubeRequest, omitMessage(desc.getError()));
-        }
         String descData = JsonUtil.writeValueAsIndentString(desc);
         cubeRequest.setCubeDescData(descData);
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/04c6607f/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
----------------------------------------------------------------------
diff --git 
a/server/src/main/java/org/apache/kylin/rest/service/CacheService.java 
b/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
index 6adbc15..c953b7e 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
@@ -59,7 +59,11 @@ public class CacheService extends BasicService {
                 cleanProjectCacheByRealization(RealizationType.CUBE, cacheKey);
                 break;
             case CUBE_DESC:
+                String modelName = 
getCubeDescManager().getCubeDesc(cacheKey).getModelName();
+                getMetadataManager().reloadDataModelDesc(modelName);
                 getCubeDescManager().reloadCubeDesc(cacheKey);
+                IIDescManager.clearCache();
+                CubeDescManager.clearCache();
                 break;
             case PROJECT:
                 getProjectManager().reloadProject(cacheKey);
@@ -78,9 +82,7 @@ public class CacheService extends BasicService {
                 CubeDescManager.clearCache();
                 break;
             case DATA_MODEL:
-                getMetadataManager().reloadDataModelDesc(cacheKey);
-                IIDescManager.clearCache();
-                CubeDescManager.clearCache();
+                // To avoid in an inconsistent state, model desc will be 
refreshed together with cube desc
                 break;
             case ALL:
                 MetadataManager.clearCache();

http://git-wip-us.apache.org/repos/asf/kylin/blob/04c6607f/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git 
a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java 
b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
index f115d89..612798e 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -229,7 +229,7 @@ public class CubeService extends BasicService {
     }
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 
'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String 
newProjectName) throws UnknownHostException, IOException, JobException {
+    public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String 
newProjectName) throws IOException, JobException {
         final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), 
null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
         if (!cubingJobs.isEmpty()) {
             throw new JobException("Cube schema shouldn't be changed with 
running job.");

Reply via email to