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/master 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.");