http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-metadata/src/main/java/org/apache/kylin/metadata/cachesync/CachedCrudAssist.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/cachesync/CachedCrudAssist.java b/core-metadata/src/main/java/org/apache/kylin/metadata/cachesync/CachedCrudAssist.java new file mode 100644 index 0000000..5c2ca17 --- /dev/null +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/cachesync/CachedCrudAssist.java @@ -0,0 +1,139 @@ +/* + * 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.metadata.cachesync; + +import java.io.IOException; +import java.util.List; + +import org.apache.kylin.common.persistence.JsonSerializer; +import org.apache.kylin.common.persistence.ResourceStore; +import org.apache.kylin.common.persistence.RootPersistentEntity; +import org.apache.kylin.common.persistence.Serializer; +import org.apache.kylin.metadata.MetadataConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; + +abstract public class CachedCrudAssist<T extends RootPersistentEntity> { + + private static final Logger logger = LoggerFactory.getLogger(CachedCrudAssist.class); + + final private ResourceStore store; + final private Class<T> entityType; + final private String resRootPath; + final private Serializer<T> serializer; + final private SingleValueCache<String, T> cache; + + private boolean checkCopyOnWrite; + + public CachedCrudAssist(ResourceStore store, String resourceRootPath, Class<T> entityType, + SingleValueCache<String, T> cache) { + this.store = store; + this.entityType = entityType; + this.resRootPath = resourceRootPath; + this.serializer = new JsonSerializer<T>(entityType); + this.cache = cache; + + this.checkCopyOnWrite = store.getConfig().isCheckCopyOnWrite(); + + Preconditions.checkArgument(resRootPath.startsWith("/")); + Preconditions.checkArgument(resRootPath.endsWith("/") == false); + } + + public void setCheckOnWrite(boolean check) { + this.checkCopyOnWrite = check; + } + + private String resourcePath(String resourceName) { + return resRootPath + "/" + resourceName + MetadataConstants.FILE_SURFIX; + } + + public void reloadAll() throws IOException { + logger.debug("Reloading " + entityType.getName() + " from " + store.getReadableResourcePath(resRootPath)); + + cache.clear(); + + List<String> paths = store.collectResourceRecursively(resRootPath, MetadataConstants.FILE_SURFIX); + for (String path : paths) { + reloadQuietlyAt(path); + } + + logger.debug("Loaded " + cache.size() + " " + entityType.getName() + "(s)"); + } + + public T reload(String resourceName) throws IOException { + return reloadAt(resourcePath(resourceName)); + } + + public T reloadQuietly(String resourceName) { + return reloadQuietlyAt(resourcePath(resourceName)); + } + + private T reloadQuietlyAt(String path) { + try { + return reloadAt(path); + } catch (Exception ex) { + logger.error("Error loading " + entityType.getName() + " at " + path, ex); + return null; + } + } + + public T reloadAt(String path) throws IOException { + T entity = store.getResource(path, entityType, serializer); + if (entity == null) { + logger.warn("No " + entityType.getName() + " found at " + path + ", returning null"); + return null; + } + + initEntityAfterReload(entity); + cache.putLocal(entity.resourceName(), entity); + return entity; + } + + abstract protected void initEntityAfterReload(T entity); + + public T save(T entity) throws IOException { + Preconditions.checkArgument(entity != null); + Preconditions.checkArgument(entityType.isInstance(entity)); + + String resName = entity.resourceName(); + if (checkCopyOnWrite) { + if (cache.get(resName) == entity) { + throw new IllegalStateException("Copy-on-write violation! The updating entity " + entity + + " is a shared object in " + entityType.getName() + " cache, which should not be."); + } + } + + store.putResource(resourcePath(resName), entity, serializer); + cache.put(resName, entity); + return entity; + } + + public void delete(T entity) throws IOException { + delete(entity.resourceName()); + } + + public void delete(String resName) throws IOException { + Preconditions.checkArgument(resName != null); + store.deleteResource(resourcePath(resName)); + cache.remove(resName); + } + +}
http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-metadata/src/main/java/org/apache/kylin/metadata/draft/DraftManager.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/draft/DraftManager.java b/core-metadata/src/main/java/org/apache/kylin/metadata/draft/DraftManager.java index e2cdfa5..103da10 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/draft/DraftManager.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/draft/DraftManager.java @@ -22,8 +22,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.NavigableSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.persistence.JsonSerializer; @@ -41,35 +39,13 @@ public class DraftManager { public static final Serializer<Draft> DRAFT_SERIALIZER = new JsonSerializer<Draft>(Draft.class); - private static final ConcurrentMap<KylinConfig, DraftManager> CACHE = new ConcurrentHashMap<KylinConfig, DraftManager>(); - public static DraftManager getInstance(KylinConfig config) { - DraftManager r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (DraftManager.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - try { - r = new DraftManager(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist"); - } - - return r; - } catch (IOException e) { - throw new IllegalStateException("Failed to init DraftManager from " + config, e); - } - } + return config.getManager(DraftManager.class); } - public static void clearCache() { - CACHE.clear(); + // called by reflection + static DraftManager newInstance(KylinConfig config) throws IOException { + return new DraftManager(config); } // ============================================================================ http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelManager.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelManager.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelManager.java index 8fbb8b1..dc1ac44 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelManager.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelManager.java @@ -22,12 +22,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import javax.annotation.Nullable; - -import org.apache.commons.lang.StringUtils; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.persistence.JsonSerializer; import org.apache.kylin.common.persistence.ResourceStore; @@ -44,8 +39,6 @@ import org.apache.kylin.metadata.project.ProjectManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Function; -import com.google.common.collect.Iterators; import com.google.common.collect.Lists; /** @@ -54,38 +47,12 @@ public class DataModelManager { private static final Logger logger = LoggerFactory.getLogger(DataModelManager.class); - // static cached instances - private static final ConcurrentMap<KylinConfig, DataModelManager> CACHE = new ConcurrentHashMap<KylinConfig, DataModelManager>(); - public static DataModelManager getInstance(KylinConfig config) { - DataModelManager r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (DataModelManager.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - r = newInstance(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist, current keys: {}", StringUtils - .join(Iterators.transform(CACHE.keySet().iterator(), new Function<KylinConfig, String>() { - @Nullable - @Override - public String apply(@Nullable KylinConfig input) { - return String.valueOf(System.identityHashCode(input)); - } - }), ",")); - } - - return r; - } + return config.getManager(DataModelManager.class); } - private static DataModelManager newInstance(KylinConfig conf) { + // called by reflection + static DataModelManager newInstance(KylinConfig conf) { try { String cls = StringUtil.noBlank(conf.getDataModelManagerImpl(), DataModelManager.class.getName()); Class<? extends DataModelManager> clz = ClassUtil.forName(cls, DataModelManager.class); @@ -95,10 +62,6 @@ public class DataModelManager { } } - public static void clearCache() { - CACHE.clear(); - } - // ============================================================================ private KylinConfig config; @@ -148,10 +111,6 @@ public class DataModelManager { } private class DataModelSyncListener extends Broadcaster.Listener { - @Override - public void onClearAll(Broadcaster broadcaster) throws IOException { - clearCache(); - } @Override public void onProjectSchemaChange(Broadcaster broadcaster, String project) throws IOException { http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/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 f25acc7..7b1f840 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 @@ -126,6 +126,11 @@ public class ProjectInstance extends RootPersistentEntity { public ProjectInstance() { } + @Override + public String resourceName() { + return this.name; + } + public String getDescription() { return description; } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/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 11d0f62..4622f35 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 @@ -26,20 +26,17 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.commons.lang3.StringUtils; import org.apache.kylin.common.KylinConfig; -import org.apache.kylin.common.persistence.JsonSerializer; import org.apache.kylin.common.persistence.ResourceStore; -import org.apache.kylin.common.persistence.Serializer; +import org.apache.kylin.common.util.AutoReadWriteLock; +import org.apache.kylin.common.util.AutoReadWriteLock.AutoLock; import org.apache.kylin.metadata.TableMetadataManager; import org.apache.kylin.metadata.badquery.BadQueryHistoryManager; import org.apache.kylin.metadata.cachesync.Broadcaster; import org.apache.kylin.metadata.cachesync.Broadcaster.Event; +import org.apache.kylin.metadata.cachesync.CachedCrudAssist; import org.apache.kylin.metadata.cachesync.CaseInsensitiveStringCache; import org.apache.kylin.metadata.model.ColumnDesc; import org.apache.kylin.metadata.model.ExternalFilterDesc; @@ -56,36 +53,14 @@ import com.google.common.collect.Sets; public class ProjectManager { private static final Logger logger = LoggerFactory.getLogger(ProjectManager.class); - private static final ConcurrentMap<KylinConfig, ProjectManager> CACHE = new ConcurrentHashMap<KylinConfig, ProjectManager>(); - public static final Serializer<ProjectInstance> PROJECT_SERIALIZER = new JsonSerializer<ProjectInstance>( - ProjectInstance.class); public static ProjectManager getInstance(KylinConfig config) { - ProjectManager r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (ProjectManager.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - try { - r = new ProjectManager(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist"); - } - return r; - } catch (IOException e) { - throw new IllegalStateException("Failed to init ProjectManager from " + config, e); - } - } + return config.getManager(ProjectManager.class); } - public static void clearCache() { - CACHE.clear(); + // called by reflection + static ProjectManager newInstance(KylinConfig config) throws IOException { + return new ProjectManager(config); } // ============================================================================ @@ -98,27 +73,31 @@ public class ProjectManager { // protects concurrent operations around the projectMap, to avoid for example // writing a project in the middle of reloading it (dirty read) - private ReadWriteLock prjMapLock = new ReentrantReadWriteLock(); + private AutoReadWriteLock prjMapLock = new AutoReadWriteLock(); + + private CachedCrudAssist<ProjectInstance> crud; private ProjectManager(KylinConfig config) throws IOException { logger.info("Initializing ProjectManager with metadata url " + config); this.config = config; this.projectMap = new CaseInsensitiveStringCache<ProjectInstance>(config, "project"); this.l2Cache = new ProjectL2Cache(this); + this.crud = new CachedCrudAssist<ProjectInstance>(getStore(), ResourceStore.PROJECT_RESOURCE_ROOT, + ProjectInstance.class, projectMap) { + @Override + protected void initEntityAfterReload(ProjectInstance prj) { + prj.init(); + } + }; - // touch lower level metadata before registering my listener - reloadAllProjects(); + crud.reloadAll(); + Broadcaster.getInstance(config).registerListener(new ProjectSyncListener(), "project"); } private class ProjectSyncListener extends Broadcaster.Listener { @Override - public void onClearAll(Broadcaster broadcaster) throws IOException { - clearCache(); - } - - @Override public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) throws IOException { String project = cacheKey; @@ -128,7 +107,7 @@ public class ProjectManager { return; } - reloadProjectLocal(project); + reloadProjectQuietly(project); broadcaster.notifyProjectSchemaUpdate(project); broadcaster.notifyProjectDataUpdate(project); } @@ -138,85 +117,39 @@ public class ProjectManager { l2Cache.clear(); } - private void reloadAllProjects() throws IOException { - prjMapLock.writeLock().lock(); - try { - ResourceStore store = getStore(); - List<String> paths = store.collectResourceRecursively(ResourceStore.PROJECT_RESOURCE_ROOT, ".json"); - - logger.debug("Loading Project from folder " - + store.getReadableResourcePath(ResourceStore.PROJECT_RESOURCE_ROOT)); - - for (String path : paths) { - reloadProjectLocalAt(path); - } - logger.debug("Loaded " + projectMap.size() + " Project(s)"); - } finally { - prjMapLock.writeLock().unlock(); - } - } - - public ProjectInstance reloadProjectLocal(String project) throws IOException { - prjMapLock.writeLock().lock(); - try { - return reloadProjectLocalAt(ProjectInstance.concatResourcePath(project)); - } finally { - prjMapLock.writeLock().unlock(); - } - } - - private ProjectInstance reloadProjectLocalAt(String path) throws IOException { - ProjectInstance projectInstance = getStore().getResource(path, ProjectInstance.class, PROJECT_SERIALIZER); - if (projectInstance == null) { - logger.warn("reload project at path:" + path + " not found, this:" + this.toString()); - return null; + public ProjectInstance reloadProjectQuietly(String project) throws IOException { + try (AutoLock lock = prjMapLock.lockForWrite()) { + ProjectInstance prj = crud.reloadQuietly(project); + clearL2Cache(); + return prj; } - - projectInstance.init(); - - projectMap.putLocal(projectInstance.getName(), projectInstance); - clearL2Cache(); - - return projectInstance; } public List<ProjectInstance> listAllProjects() { - prjMapLock.readLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForRead()) { return new ArrayList<ProjectInstance>(projectMap.values()); - } finally { - prjMapLock.readLock().unlock(); } } public ProjectInstance getProject(String projectName) { - prjMapLock.readLock().lock(); - try { - projectName = norm(projectName); + try (AutoLock lock = prjMapLock.lockForRead()) { return projectMap.get(projectName); - } finally { - prjMapLock.readLock().unlock(); } } public ProjectInstance getPrjByUuid(String uuid) { - prjMapLock.readLock().lock(); - try { - Collection<ProjectInstance> copy = new ArrayList<ProjectInstance>(projectMap.values()); - for (ProjectInstance prj : copy) { + try (AutoLock lock = prjMapLock.lockForRead()) { + for (ProjectInstance prj : projectMap.values()) { if (uuid.equals(prj.getUuid())) return prj; } return null; - } finally { - prjMapLock.readLock().unlock(); } } public ProjectInstance createProject(String projectName, String owner, String description, LinkedHashMap<String, String> overrideProps) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { logger.info("Creating project " + projectName); ProjectInstance currentProject = getProject(projectName); @@ -225,18 +158,30 @@ public class ProjectManager { } else { throw new IllegalStateException("The project named " + projectName + "already exists"); } + checkOverrideProps(currentProject); - updateProject(currentProject); + return save(currentProject); + } + } - return currentProject; - } finally { - prjMapLock.writeLock().unlock(); + private void checkOverrideProps(ProjectInstance prj) throws IOException { + LinkedHashMap<String, String> overrideProps = prj.getOverrideKylinProps(); + + if (overrideProps != null) { + Iterator<Map.Entry<String, String>> iterator = overrideProps.entrySet().iterator(); + + while (iterator.hasNext()) { + Map.Entry<String, String> entry = iterator.next(); + + if (StringUtils.isAnyBlank(entry.getKey(), entry.getValue())) { + throw new IllegalStateException("Property key/value must not be blank"); + } + } } } public ProjectInstance dropProject(String projectName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { if (projectName == null) throw new IllegalArgumentException("Project name not given"); @@ -253,45 +198,18 @@ public class ProjectManager { logger.info("Dropping project '" + projectInstance.getName() + "'"); - removeProject(projectInstance); + crud.delete(projectInstance); BadQueryHistoryManager.getInstance(config).removeBadQueryHistory(projectName); + clearL2Cache(); return projectInstance; - } finally { - prjMapLock.writeLock().unlock(); - } - } - - // rename project - public ProjectInstance renameProject(ProjectInstance project, String newName, String newDesc, - LinkedHashMap<String, String> overrideProps) throws IOException { - prjMapLock.writeLock().lock(); - try { - Preconditions.checkArgument(!project.getName().equals(newName)); - ProjectInstance newProject = this.createProject(newName, project.getOwner(), newDesc, overrideProps); - - newProject.setUuid(project.getUuid()); - newProject.setCreateTimeUTC(project.getCreateTimeUTC()); - newProject.recordUpdateTime(System.currentTimeMillis()); - newProject.setRealizationEntries(project.getRealizationEntries()); - newProject.setTables(project.getTables()); - newProject.setModels(project.getModels()); - newProject.setExtFilters(project.getExtFilters()); - - removeProject(project); - updateProject(newProject); - - return newProject; - } finally { - prjMapLock.writeLock().unlock(); } } // update project itself public ProjectInstance updateProject(ProjectInstance project, String newName, String newDesc, LinkedHashMap<String, String> overrideProps) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { Preconditions.checkArgument(project.getName().equals(newName)); project.setName(newName); project.setDescription(newDesc); @@ -300,48 +218,19 @@ public class ProjectManager { if (project.getUuid() == null) project.updateRandomUuid(); - updateProject(project); - - return project; - } finally { - prjMapLock.writeLock().unlock(); + return save(project); } } - private void updateProject(ProjectInstance prj) throws IOException { - LinkedHashMap<String, String> overrideProps = prj.getOverrideKylinProps(); - - if (overrideProps != null) { - Iterator<Map.Entry<String, String>> iterator = overrideProps.entrySet().iterator(); - - while (iterator.hasNext()) { - Map.Entry<String, String> entry = iterator.next(); - - if (StringUtils.isAnyBlank(entry.getKey(), entry.getValue())) { - throw new IllegalStateException("Property key/value must not be blank"); - } - } + public void removeProjectLocal(String proj) { + try (AutoLock lock = prjMapLock.lockForWrite()) { + projectMap.removeLocal(proj); + clearL2Cache(); } - - getStore().putResource(prj.getResourcePath(), prj, PROJECT_SERIALIZER); - projectMap.put(norm(prj.getName()), prj); // triggers update broadcast - clearL2Cache(); - } - - private void removeProject(ProjectInstance proj) throws IOException { - getStore().deleteResource(proj.getResourcePath()); - projectMap.remove(norm(proj.getName())); - clearL2Cache(); - } - - private void removeProjectLocal(String proj) { - projectMap.remove(norm(proj)); - clearL2Cache(); } public ProjectInstance addModelToProject(String modelName, String newProjectName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { removeModelFromProjects(modelName); ProjectInstance prj = getProject(newProjectName); @@ -349,71 +238,57 @@ public class ProjectManager { throw new IllegalArgumentException("Project " + newProjectName + " does not exist."); } prj.addModel(modelName); - updateProject(prj); - - return prj; - } finally { - prjMapLock.writeLock().unlock(); + + return save(prj); } } public void removeModelFromProjects(String modelName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { for (ProjectInstance projectInstance : findProjectsByModel(modelName)) { projectInstance.removeModel(modelName); - updateProject(projectInstance); + save(projectInstance); } - } finally { - prjMapLock.writeLock().unlock(); } } public ProjectInstance moveRealizationToProject(RealizationType type, String realizationName, String newProjectName, String owner) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { removeRealizationsFromProjects(type, realizationName); return addRealizationToProject(type, realizationName, newProjectName, owner); - } finally { - prjMapLock.writeLock().unlock(); } } private ProjectInstance addRealizationToProject(RealizationType type, String realizationName, String project, String user) throws IOException { - String newProjectName = norm(project); - if (StringUtils.isEmpty(newProjectName)) { + if (StringUtils.isEmpty(project)) { throw new IllegalArgumentException("Project name should not be empty."); } - ProjectInstance newProject = getProject(newProjectName); + ProjectInstance newProject = getProject(project); if (newProject == null) { - newProject = this.createProject(newProjectName, user, + newProject = this.createProject(project, user, "This is a project automatically added when adding realization " + realizationName + "(" + type + ")", null); } newProject.addRealizationEntry(type, realizationName); - updateProject(newProject); + save(newProject); return newProject; } public void removeRealizationsFromProjects(RealizationType type, String realizationName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { for (ProjectInstance projectInstance : findProjects(type, realizationName)) { projectInstance.removeRealization(type, realizationName); - updateProject(projectInstance); + save(projectInstance); } - } finally { - prjMapLock.writeLock().unlock(); } } public ProjectInstance addTableDescToProject(String[] tableIdentities, String projectName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { TableMetadataManager metaMgr = getTableManager(); ProjectInstance projectInstance = getProject(projectName); for (String tableId : tableIdentities) { @@ -424,16 +299,12 @@ public class ProjectManager { projectInstance.addTable(table.getIdentity()); } - updateProject(projectInstance); - return projectInstance; - } finally { - prjMapLock.writeLock().unlock(); + return save(projectInstance); } } public void removeTableDescFromProject(String tableIdentities, String projectName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { TableMetadataManager metaMgr = getTableManager(); ProjectInstance projectInstance = getProject(projectName); TableDesc table = metaMgr.getTableDesc(tableIdentities, projectName); @@ -442,15 +313,12 @@ public class ProjectManager { } projectInstance.removeTable(table.getIdentity()); - updateProject(projectInstance); - } finally { - prjMapLock.writeLock().unlock(); + save(projectInstance); } } public ProjectInstance addExtFilterToProject(String[] filters, String projectName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { TableMetadataManager metaMgr = getTableManager(); ProjectInstance projectInstance = getProject(projectName); for (String filterName : filters) { @@ -462,16 +330,12 @@ public class ProjectManager { projectInstance.addExtFilter(filterName); } - updateProject(projectInstance); - return projectInstance; - } finally { - prjMapLock.writeLock().unlock(); + return save(projectInstance); } } public void removeExtFilterFromProject(String filterName, String projectName) throws IOException { - prjMapLock.writeLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { TableMetadataManager metaMgr = getTableManager(); ProjectInstance projectInstance = getProject(projectName); ExternalFilterDesc filter = metaMgr.getExtFilterDesc(filterName); @@ -480,28 +344,28 @@ public class ProjectManager { } projectInstance.removeExtFilter(filterName); - updateProject(projectInstance); - } finally { - prjMapLock.writeLock().unlock(); + save(projectInstance); } } + + private ProjectInstance save(ProjectInstance prj) throws IOException { + crud.save(prj); + clearL2Cache(); + return prj; + } public ProjectInstance getProjectOfModel(String model) { - prjMapLock.readLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForRead()) { for (ProjectInstance prj : projectMap.values()) { if (prj.getModels().contains(model)) return prj; } throw new IllegalStateException("No project found for model " + model); - } finally { - prjMapLock.readLock().unlock(); } } public List<ProjectInstance> findProjects(RealizationType type, String realizationName) { - prjMapLock.readLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { List<ProjectInstance> result = Lists.newArrayList(); for (ProjectInstance prj : projectMap.values()) { for (RealizationEntry entry : prj.getRealizationEntries()) { @@ -512,14 +376,11 @@ public class ProjectManager { } } return result; - } finally { - prjMapLock.readLock().unlock(); } } public List<ProjectInstance> findProjectsByModel(String modelName) { - prjMapLock.readLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { List<ProjectInstance> projects = new ArrayList<ProjectInstance>(); for (ProjectInstance projectInstance : projectMap.values()) { if (projectInstance.containsModel(modelName)) { @@ -527,14 +388,11 @@ public class ProjectManager { } } return projects; - } finally { - prjMapLock.readLock().unlock(); } } public List<ProjectInstance> findProjectsByTable(String tableIdentity) { - prjMapLock.readLock().lock(); - try { + try (AutoLock lock = prjMapLock.lockForWrite()) { List<ProjectInstance> projects = new ArrayList<ProjectInstance>(); for (ProjectInstance projectInstance : projectMap.values()) { if (projectInstance.containsTable(tableIdentity)) { @@ -542,8 +400,6 @@ public class ProjectManager { } } return projects; - } finally { - prjMapLock.readLock().unlock(); } } @@ -552,11 +408,11 @@ public class ProjectManager { } public List<TableDesc> listDefinedTables(String project) { - return l2Cache.listDefinedTables(norm(project)); + return l2Cache.listDefinedTables(project); } private Collection<TableDesc> listExposedTablesByRealizations(String project) { - return l2Cache.listExposedTables(norm(project)); + return l2Cache.listExposedTables(project); } public Collection<TableDesc> listExposedTables(String project, boolean exposeMore) { @@ -568,7 +424,7 @@ public class ProjectManager { } public List<ColumnDesc> listExposedColumns(String project, TableDesc tableDesc, boolean exposeMore) { - Set<ColumnDesc> exposedColumns = l2Cache.listExposedColumns(norm(project), tableDesc.getIdentity()); + Set<ColumnDesc> exposedColumns = l2Cache.listExposedColumns(project, tableDesc.getIdentity()); if (exposeMore) { Set<ColumnDesc> dedup = Sets.newHashSet(tableDesc.getColumns()); @@ -580,19 +436,19 @@ public class ProjectManager { } public Set<IRealization> listAllRealizations(String project) { - return l2Cache.listAllRealizations(norm(project)); + return l2Cache.listAllRealizations(project); } public Set<IRealization> getRealizationsByTable(String project, String tableName) { - return l2Cache.getRealizationsByTable(norm(project), tableName.toUpperCase()); + return l2Cache.getRealizationsByTable(project, tableName.toUpperCase()); } public List<MeasureDesc> listEffectiveRewriteMeasures(String project, String factTable) { - return l2Cache.listEffectiveRewriteMeasures(norm(project), factTable.toUpperCase(), true); + return l2Cache.listEffectiveRewriteMeasures(project, factTable.toUpperCase(), true); } public List<MeasureDesc> listEffectiveMeasures(String project, String factTable) { - return l2Cache.listEffectiveRewriteMeasures(norm(project), factTable.toUpperCase(), false); + return l2Cache.listEffectiveRewriteMeasures(project, factTable.toUpperCase(), false); } KylinConfig getConfig() { @@ -607,8 +463,4 @@ public class ProjectManager { return TableMetadataManager.getInstance(config); } - private String norm(String project) { - return project; - } - } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java b/core-metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java index 2d1a4a5..279fe44 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java @@ -22,12 +22,9 @@ import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.util.ClassUtil; -import org.apache.kylin.metadata.cachesync.Broadcaster; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,34 +35,14 @@ import com.google.common.collect.Maps; public class RealizationRegistry { private static final Logger logger = LoggerFactory.getLogger(RealizationRegistry.class); - private static final ConcurrentMap<KylinConfig, RealizationRegistry> CACHE = new ConcurrentHashMap<KylinConfig, RealizationRegistry>(); public static RealizationRegistry getInstance(KylinConfig config) { - RealizationRegistry r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (RealizationRegistry.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - try { - r = new RealizationRegistry(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist"); - } - return r; - } catch (IOException e) { - throw new IllegalStateException("Failed to init CubeManager from " + config, e); - } - } + return config.getManager(RealizationRegistry.class); } - public static void clearCache() { - CACHE.clear(); + // called by reflection + static RealizationRegistry newInstance(KylinConfig config) throws IOException { + return new RealizationRegistry(config); } // ============================================================================ @@ -77,13 +54,6 @@ public class RealizationRegistry { logger.info("Initializing RealizationRegistry with metadata url " + config); this.config = config; init(); - - Broadcaster.getInstance(config).registerListener(new Broadcaster.Listener() { - @Override - public void onClearAll(Broadcaster broadcaster) throws IOException { - clearCache(); - } - }, ""); } private void init() { http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-metadata/src/main/java/org/apache/kylin/metadata/streaming/StreamingManager.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/streaming/StreamingManager.java b/core-metadata/src/main/java/org/apache/kylin/metadata/streaming/StreamingManager.java index 48febeb..b5d7e37 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/streaming/StreamingManager.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/streaming/StreamingManager.java @@ -21,8 +21,6 @@ package org.apache.kylin.metadata.streaming; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.apache.commons.lang3.StringUtils; import org.apache.kylin.common.KylinConfig; @@ -42,20 +40,24 @@ public class StreamingManager { private static final Logger logger = LoggerFactory.getLogger(StreamingManager.class); - // static cached instances - private static final ConcurrentMap<KylinConfig, StreamingManager> CACHE = new ConcurrentHashMap<KylinConfig, StreamingManager>(); - public static final Serializer<StreamingConfig> STREAMING_SERIALIZER = new JsonSerializer<StreamingConfig>(StreamingConfig.class); + public static StreamingManager getInstance(KylinConfig config) { + return config.getManager(StreamingManager.class); + } + + // called by reflection + static StreamingManager newInstance(KylinConfig config) throws IOException { + return new StreamingManager(config); + } + + // ============================================================================ + private KylinConfig config; // name ==> StreamingConfig private CaseInsensitiveStringCache<StreamingConfig> streamingMap; - public static void clearCache() { - CACHE.clear(); - } - private StreamingManager(KylinConfig config) throws IOException { this.config = config; this.streamingMap = new CaseInsensitiveStringCache<StreamingConfig>(config, "streaming"); @@ -66,10 +68,6 @@ public class StreamingManager { } private class StreamingSyncListener extends Broadcaster.Listener { - @Override - public void onClearAll(Broadcaster broadcaster) throws IOException { - clearCache(); - } @Override public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) throws IOException { @@ -84,42 +82,6 @@ public class StreamingManager { return ResourceStore.getStore(this.config); } - public static StreamingManager getInstance(KylinConfig config) { - StreamingManager r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (StreamingManager.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - try { - r = new StreamingManager(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist"); - } - return r; - } catch (IOException e) { - throw new IllegalStateException("Failed to init StreamingManager from " + config, e); - } - } - } - - private static String formatStreamingConfigPath(String name) { - return ResourceStore.STREAMING_RESOURCE_ROOT + "/" + name + ".json"; - } - - private static String formatStreamingOutputPath(String streaming, int partition) { - return ResourceStore.STREAMING_OUTPUT_RESOURCE_ROOT + "/" + streaming + "_" + partition + ".json"; - } - - private static String formatStreamingOutputPath(String streaming, List<Integer> partitions) { - return ResourceStore.STREAMING_OUTPUT_RESOURCE_ROOT + "/" + streaming + "_" + StringUtils.join(partitions, "_") + ".json"; - } - public StreamingConfig getStreamingConfig(String name) { return streamingMap.get(name); } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java ---------------------------------------------------------------------- diff --git a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java index 095b46f..b910ffe 100644 --- a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java +++ b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java @@ -175,7 +175,7 @@ public abstract class GTCubeStorageQueryBase implements IStorageQuery { protected abstract String getGTStorage(); protected Cuboid findCuboid(CubeInstance cubeInstance, Set<TblColRef> dimensionsD, Set<FunctionDesc> metrics) { - return Cuboid.identifyCuboid(cubeInstance, dimensionsD, metrics); + return Cuboid.findCuboid(cubeInstance.getCuboidScheduler(), dimensionsD, metrics); } protected ITupleConverter newCubeTupleConverter(CubeSegment cubeSeg, Cuboid cuboid, http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/core-storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java ---------------------------------------------------------------------- diff --git a/core-storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java b/core-storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java index 2b1c2cc..37f4aff 100644 --- a/core-storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java +++ b/core-storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java @@ -20,8 +20,6 @@ package org.apache.kylin.storage.hybrid; import java.io.IOException; import java.util.Collection; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.apache.commons.lang3.StringUtils; import org.apache.kylin.common.KylinConfig; @@ -49,35 +47,13 @@ public class HybridManager implements IRealizationProvider { private static final Logger logger = LoggerFactory.getLogger(HybridManager.class); - // static cached instances - private static final ConcurrentMap<KylinConfig, HybridManager> CACHE = new ConcurrentHashMap<KylinConfig, HybridManager>(); - public static HybridManager getInstance(KylinConfig config) { - HybridManager r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (HybridManager.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - try { - r = new HybridManager(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist"); - } - return r; - } catch (IOException e) { - throw new IllegalStateException("Failed to init Hybrid Manager from " + config, e); - } - } + return config.getManager(HybridManager.class); } - public static void clearCache() { - CACHE.clear(); + // called by reflection + static HybridManager newInstance(KylinConfig config) throws IOException { + return new HybridManager(config); } // ============================================================================ @@ -99,11 +75,6 @@ public class HybridManager implements IRealizationProvider { private class HybridSyncListener extends Broadcaster.Listener { @Override - public void onClearAll(Broadcaster broadcaster) throws IOException { - clearCache(); - } - - @Override public void onProjectSchemaChange(Broadcaster broadcaster, String project) throws IOException { for (IRealization real : ProjectManager.getInstance(config).listAllRealizations(project)) { if (real instanceof HybridInstance) { http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/engine-mr/src/test/java/org/apache/kylin/engine/mr/steps/MergeCuboidMapperTest.java ---------------------------------------------------------------------- diff --git a/engine-mr/src/test/java/org/apache/kylin/engine/mr/steps/MergeCuboidMapperTest.java b/engine-mr/src/test/java/org/apache/kylin/engine/mr/steps/MergeCuboidMapperTest.java index 4d92f8e..5ddb024 100644 --- a/engine-mr/src/test/java/org/apache/kylin/engine/mr/steps/MergeCuboidMapperTest.java +++ b/engine-mr/src/test/java/org/apache/kylin/engine/mr/steps/MergeCuboidMapperTest.java @@ -41,9 +41,7 @@ import org.apache.kylin.dict.DictionaryManager; import org.apache.kylin.dict.IterableDictionaryValueEnumerator; import org.apache.kylin.metadata.datatype.DataType; import org.apache.kylin.metadata.model.SegmentRange.TSRange; -import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.model.TblColRef; -import org.apache.kylin.metadata.project.ProjectManager; import org.apache.kylin.source.IReadableTable.TableSignature; import org.junit.After; import org.junit.Before; @@ -89,11 +87,7 @@ public class MergeCuboidMapperTest extends LocalFileMetadataTestCase { createTestMetadata(); logger.info("The metadataUrl is : " + getTestConfig()); - - DataModelManager.clearCache(); - CubeManager.clearCache(); - ProjectManager.clearCache(); - DictionaryManager.clearCache(); + getTestConfig().clearManagers(); // hack for distributed cache // CubeManager.removeInstance(KylinConfig.createInstanceFromUri("../job/meta"));//to http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/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 4bb8e82..c892ff4 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 @@ -156,7 +156,8 @@ public class ProjectController extends BasicController { if (projectDesc.getName().equals(currentProject.getName())) { updatedProj = projectService.updateProject(projectDesc, currentProject); } else { - updatedProj = projectService.renameProject(projectDesc, currentProject); + throw new IllegalStateException("Rename project is not supported yet, from " + formerProjectName + + " to " + projectDesc.getName()); } } catch (Exception e) { logger.error("Failed to deal with the request.", e); http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java b/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java index 146a0a5..2ab4c24 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java +++ b/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java @@ -249,6 +249,10 @@ public class Message { return "Cannot modify non-empty project"; } + public String getPROJECT_RENAME() { + return "Project renaming is not allowed."; + } + // Table public String getHIVE_TABLE_NOT_FOUND() { return "Cannot find Hive table '%s'."; http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/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 d9627b9..417fb10 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 @@ -27,7 +27,6 @@ import java.util.List; import javax.annotation.Nullable; import org.apache.directory.api.util.Strings; -import org.apache.kylin.metadata.draft.Draft; import org.apache.kylin.metadata.project.ProjectInstance; import org.apache.kylin.metadata.realization.RealizationType; import org.apache.kylin.rest.constant.Constant; @@ -95,9 +94,6 @@ public class ProjectService extends BasicService { @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#currentProject, 'ADMINISTRATION')") public ProjectInstance updateProject(ProjectInstance newProject, ProjectInstance currentProject) throws IOException { - if (!newProject.getName().equals(currentProject.getName())) { - return renameProject(newProject, currentProject); - } String newProjectName = newProject.getName(); String newDescription = newProject.getDescription(); @@ -110,27 +106,6 @@ public class ProjectService extends BasicService { return updatedProject; } - @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#currentProject, 'ADMINISTRATION')") - public ProjectInstance renameProject(ProjectInstance newProject, ProjectInstance currentProject) - throws IOException { - String newProjectName = newProject.getName(); - String newDescription = newProject.getDescription(); - LinkedHashMap<String, String> overrideProps = newProject.getOverrideKylinProps(); - - // rename project but keep UUID, acl keeps the same - ProjectInstance renamedProject = getProjectManager().renameProject(currentProject, newProjectName, - newDescription, overrideProps); - - // rebind draft and project - for (Draft draft : getDraftManager().list(currentProject.getName())) { - draft.setProject(newProjectName); - getDraftManager().save(draft); - } - - logger.debug("Project rename."); - return renamedProject; - } - @PostFilter(Constant.ACCESS_POST_FILTER_READ) public List<ProjectInstance> listProjects(final Integer limit, final Integer offset) { List<ProjectInstance> projects = listAllProjects(limit, offset); http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/server-base/src/test/java/org/apache/kylin/rest/service/DiagnosisServiceTest.java ---------------------------------------------------------------------- diff --git a/server-base/src/test/java/org/apache/kylin/rest/service/DiagnosisServiceTest.java b/server-base/src/test/java/org/apache/kylin/rest/service/DiagnosisServiceTest.java index e51fd31..b200980 100644 --- a/server-base/src/test/java/org/apache/kylin/rest/service/DiagnosisServiceTest.java +++ b/server-base/src/test/java/org/apache/kylin/rest/service/DiagnosisServiceTest.java @@ -26,7 +26,6 @@ import org.apache.kylin.common.util.LocalFileMetadataTestCase; import org.apache.kylin.metadata.badquery.BadQueryEntry; import org.apache.kylin.metadata.badquery.BadQueryHistory; import org.apache.kylin.metadata.badquery.BadQueryHistoryManager; -import org.apache.kylin.metadata.model.DataModelManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -37,7 +36,6 @@ public class DiagnosisServiceTest extends LocalFileMetadataTestCase { @Before public void setUp() throws Exception { this.createTestMetadata(); - DataModelManager.clearCache(); } @After http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java ---------------------------------------------------------------------- diff --git a/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java b/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java index f805095..8d08d61 100644 --- a/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java +++ b/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java @@ -31,9 +31,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.beans.factory.annotation.Qualifier; /** */ @@ -76,25 +76,15 @@ public class ProjectControllerTest extends ServiceTestBase { Assert.assertEquals(ret.getOwner(), "ADMIN"); Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(), originalProjectCount + 1); - //test update project - ProjectInstance newProject = new ProjectInstance(); - newProject.setName("new_project_2"); - projectController.updateProject(getProjectRequest(newProject, "new_project")); - - Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(), originalProjectCount + 1); - Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project"), null); - Assert.assertNotEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project_2"), null); - //test update project description only ProjectInstance newProject2 = new ProjectInstance(); - newProject2.setName("new_project_2"); + newProject2.setName("new_project"); newProject2.setDescription("hello world"); - projectController.updateProject(getProjectRequest(newProject2, "new_project_2")); + projectController.updateProject(getProjectRequest(newProject2, "new_project")); Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(), originalProjectCount + 1); - Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project"), null); - Assert.assertNotEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project_2"), null); - Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project_2").getDescription(), "hello world"); + Assert.assertNotEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project"), null); + Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project").getDescription(), "hello world"); } @Test(expected = InternalErrorException.class) http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/source-kafka/src/main/java/org/apache/kylin/source/kafka/KafkaConfigManager.java ---------------------------------------------------------------------- diff --git a/source-kafka/src/main/java/org/apache/kylin/source/kafka/KafkaConfigManager.java b/source-kafka/src/main/java/org/apache/kylin/source/kafka/KafkaConfigManager.java index 50295c3..5e451b4 100644 --- a/source-kafka/src/main/java/org/apache/kylin/source/kafka/KafkaConfigManager.java +++ b/source-kafka/src/main/java/org/apache/kylin/source/kafka/KafkaConfigManager.java @@ -21,8 +21,6 @@ package org.apache.kylin.source.kafka; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.apache.commons.lang3.StringUtils; import org.apache.kylin.common.KylinConfig; @@ -43,20 +41,24 @@ public class KafkaConfigManager { private static final Logger logger = LoggerFactory.getLogger(KafkaConfigManager.class); - // static cached instances - private static final ConcurrentMap<KylinConfig, KafkaConfigManager> CACHE = new ConcurrentHashMap<KylinConfig, KafkaConfigManager>(); - - private KylinConfig config; - - // name ==> StreamingConfig - private CaseInsensitiveStringCache<KafkaConfig> kafkaMap; - public static final Serializer<KafkaConfig> KAFKA_SERIALIZER = new JsonSerializer<KafkaConfig>(KafkaConfig.class); + + public static KafkaConfigManager getInstance(KylinConfig config) { + return config.getManager(KafkaConfigManager.class); + } - public static void clearCache() { - CACHE.clear(); + // called by reflection + static KafkaConfigManager newInstance(KylinConfig config) throws IOException { + return new KafkaConfigManager(config); } + // ============================================================================ + + private KylinConfig config; + + // name ==> StreamingConfig + private CaseInsensitiveStringCache<KafkaConfig> kafkaMap; + private KafkaConfigManager(KylinConfig config) throws IOException { this.config = config; this.kafkaMap = new CaseInsensitiveStringCache<KafkaConfig>(config, "kafka"); @@ -67,10 +69,6 @@ public class KafkaConfigManager { } private class KafkaSyncListener extends Broadcaster.Listener { - @Override - public void onClearAll(Broadcaster broadcaster) throws IOException { - clearCache(); - } @Override public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) throws IOException { @@ -85,30 +83,6 @@ public class KafkaConfigManager { return ResourceStore.getStore(this.config); } - public static KafkaConfigManager getInstance(KylinConfig config) { - KafkaConfigManager r = CACHE.get(config); - if (r != null) { - return r; - } - - synchronized (KafkaConfigManager.class) { - r = CACHE.get(config); - if (r != null) { - return r; - } - try { - r = new KafkaConfigManager(config); - CACHE.put(config, r); - if (CACHE.size() > 1) { - logger.warn("More than one singleton exist"); - } - return r; - } catch (IOException e) { - throw new IllegalStateException("Failed to init KafkaConfigManager from " + config, e); - } - } - } - public List<KafkaConfig> listAllKafkaConfigs() { return new ArrayList(kafkaMap.values()); } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/util/ExtendCubeToHybridCLI.java ---------------------------------------------------------------------- diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/util/ExtendCubeToHybridCLI.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/util/ExtendCubeToHybridCLI.java index 7f55895..092023e 100644 --- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/util/ExtendCubeToHybridCLI.java +++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/util/ExtendCubeToHybridCLI.java @@ -42,9 +42,9 @@ import org.apache.kylin.cube.CubeManager; import org.apache.kylin.cube.CubeSegment; import org.apache.kylin.cube.model.CubeDesc; import org.apache.kylin.metadata.model.DataModelDesc; +import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.model.IEngineAware; import org.apache.kylin.metadata.model.IStorageAware; -import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.model.Segments; import org.apache.kylin.metadata.project.ProjectInstance; import org.apache.kylin.metadata.project.ProjectManager; @@ -210,16 +210,11 @@ public class ExtendCubeToHybridCLI { } private void verify() { - CubeDescManager.clearCache(); + kylinConfig.clearManagers(); + CubeDescManager.getInstance(kylinConfig); - - CubeManager.clearCache(); CubeManager.getInstance(kylinConfig); - - ProjectManager.clearCache(); ProjectManager.getInstance(kylinConfig); - - HybridManager.clearCache(); HybridManager.getInstance(kylinConfig); } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/cube/MeasureTypeOnlyAggrInBaseTest.java ---------------------------------------------------------------------- diff --git a/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/cube/MeasureTypeOnlyAggrInBaseTest.java b/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/cube/MeasureTypeOnlyAggrInBaseTest.java index befe8a1..61f8386 100644 --- a/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/cube/MeasureTypeOnlyAggrInBaseTest.java +++ b/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/cube/MeasureTypeOnlyAggrInBaseTest.java @@ -37,7 +37,6 @@ import org.apache.kylin.measure.MeasureIngester; import org.apache.kylin.measure.MeasureType; import org.apache.kylin.metadata.model.FunctionDesc; import org.apache.kylin.metadata.model.MeasureDesc; -import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.model.TblColRef; import org.junit.After; import org.junit.Before; @@ -65,7 +64,6 @@ public class MeasureTypeOnlyAggrInBaseTest extends LocalFileMetadataTestCase { @Before public void setUp() throws Exception { this.createTestMetadata(); - DataModelManager.clearCache(); cube = getTestKylinCubeWithSeller(); cubeDesc = cube.getDescriptor(); @@ -91,10 +89,10 @@ public class MeasureTypeOnlyAggrInBaseTest extends LocalFileMetadataTestCase { @Test public void testIdentifyCuboidV2() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, NoSuchFieldException { CubeDesc cubeDesc = cube.getDescriptor(); - Cuboid ret = Cuboid.identifyCuboid(cube, Sets.<TblColRef> newHashSet(), Lists.<FunctionDesc> newArrayList()); + Cuboid ret = Cuboid.findCuboid(cube.getCuboidScheduler(), Sets.<TblColRef> newHashSet(), Lists.<FunctionDesc> newArrayList()); long baseCuboidId = cubeDesc.getRowkey().getFullMask(); assertNotEquals(baseCuboidId, ret.getId()); - ret = Cuboid.identifyCuboid(cube, dimensions, metrics); + ret = Cuboid.findCuboid(cube.getCuboidScheduler(), dimensions, metrics); assertEquals(baseCuboidId, ret.getId()); } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/steps/RowValueDecoderTest.java ---------------------------------------------------------------------- diff --git a/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/steps/RowValueDecoderTest.java b/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/steps/RowValueDecoderTest.java index 5bd5499..199179b 100644 --- a/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/steps/RowValueDecoderTest.java +++ b/storage-hbase/src/test/java/org/apache/kylin/storage/hbase/steps/RowValueDecoderTest.java @@ -32,7 +32,6 @@ import org.apache.kylin.cube.model.HBaseColumnDesc; import org.apache.kylin.measure.BufferedMeasureCodec; import org.apache.kylin.metadata.model.FunctionDesc; import org.apache.kylin.metadata.model.MeasureDesc; -import org.apache.kylin.metadata.model.DataModelManager; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -42,7 +41,6 @@ public class RowValueDecoderTest extends LocalFileMetadataTestCase { @Before public void setUp() throws Exception { this.createTestMetadata(); - DataModelManager.clearCache(); } @After http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/tool/src/main/java/org/apache/kylin/tool/ExtendCubeToHybridCLI.java ---------------------------------------------------------------------- diff --git a/tool/src/main/java/org/apache/kylin/tool/ExtendCubeToHybridCLI.java b/tool/src/main/java/org/apache/kylin/tool/ExtendCubeToHybridCLI.java index 7517c07..9c6cba6 100644 --- a/tool/src/main/java/org/apache/kylin/tool/ExtendCubeToHybridCLI.java +++ b/tool/src/main/java/org/apache/kylin/tool/ExtendCubeToHybridCLI.java @@ -42,9 +42,9 @@ import org.apache.kylin.cube.CubeManager; import org.apache.kylin.cube.CubeSegment; import org.apache.kylin.cube.model.CubeDesc; import org.apache.kylin.metadata.model.DataModelDesc; +import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.model.IEngineAware; import org.apache.kylin.metadata.model.IStorageAware; -import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.model.Segments; import org.apache.kylin.metadata.project.ProjectInstance; import org.apache.kylin.metadata.project.ProjectManager; @@ -206,16 +206,11 @@ public class ExtendCubeToHybridCLI { } private void verify() { - CubeDescManager.clearCache(); + kylinConfig.clearManagers(); + CubeDescManager.getInstance(kylinConfig); - - CubeManager.clearCache(); CubeManager.getInstance(kylinConfig); - - ProjectManager.clearCache(); ProjectManager.getInstance(kylinConfig); - - HybridManager.clearCache(); HybridManager.getInstance(kylinConfig); } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/tool/src/main/java/org/apache/kylin/tool/KylinLogExtractor.java ---------------------------------------------------------------------- diff --git a/tool/src/main/java/org/apache/kylin/tool/KylinLogExtractor.java b/tool/src/main/java/org/apache/kylin/tool/KylinLogExtractor.java index 1471832..cda3fec 100644 --- a/tool/src/main/java/org/apache/kylin/tool/KylinLogExtractor.java +++ b/tool/src/main/java/org/apache/kylin/tool/KylinLogExtractor.java @@ -59,14 +59,12 @@ public class KylinLogExtractor extends AbstractInfoExtractor { private void beforeExtract() { // reload metadata before extract diagnosis info logger.info("Start to reload metadata from diagnosis."); + + config.clearManagers(); - CubeManager.clearCache(); CubeManager.getInstance(config); - CubeDescManager.clearCache(); CubeDescManager.getInstance(config); - DataModelManager.clearCache(); DataModelManager.getInstance(config); - ProjectManager.clearCache(); ProjectManager.getInstance(config); } http://git-wip-us.apache.org/repos/asf/kylin/blob/b8d79870/tool/src/test/java/org/apache/kylin/tool/CubeMetaIngesterTest.java ---------------------------------------------------------------------- diff --git a/tool/src/test/java/org/apache/kylin/tool/CubeMetaIngesterTest.java b/tool/src/test/java/org/apache/kylin/tool/CubeMetaIngesterTest.java index d974009..eca82be 100644 --- a/tool/src/test/java/org/apache/kylin/tool/CubeMetaIngesterTest.java +++ b/tool/src/test/java/org/apache/kylin/tool/CubeMetaIngesterTest.java @@ -22,10 +22,8 @@ import java.util.Collections; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.util.LocalFileMetadataTestCase; -import org.apache.kylin.cube.CubeDescManager; import org.apache.kylin.cube.CubeInstance; import org.apache.kylin.cube.CubeManager; -import org.apache.kylin.metadata.model.DataModelManager; import org.apache.kylin.metadata.project.ProjectInstance; import org.apache.kylin.metadata.project.ProjectManager; import org.apache.kylin.metadata.project.RealizationEntry; @@ -66,9 +64,7 @@ public class CubeMetaIngesterTest extends LocalFileMetadataTestCase { Assert.assertTrue(project.getModels().contains("cloned_model")); Assert.assertTrue(project.getRealizationEntries().contains(RealizationEntry.create(RealizationType.CUBE, "cloned_cube"))); - DataModelManager.clearCache(); - CubeDescManager.clearCache(); - CubeManager.clearCache(); + getTestConfig().clearManagers(); CubeInstance instance = CubeManager.getInstance(KylinConfig.getInstanceFromEnv()).getCube("cloned_cube"); Assert.assertTrue(instance != null); } @@ -83,9 +79,7 @@ public class CubeMetaIngesterTest extends LocalFileMetadataTestCase { Assert.assertTrue(project.getModels().contains("benchmark_model")); Assert.assertTrue(project.getRealizationEntries().contains(RealizationEntry.create(RealizationType.CUBE, "benchmark_cube"))); - DataModelManager.clearCache(); - CubeDescManager.clearCache(); - CubeManager.clearCache(); + getTestConfig().clearManagers(); CubeInstance instance = CubeManager.getInstance(KylinConfig.getInstanceFromEnv()).getCube("benchmark_cube"); Assert.assertTrue(instance != null); }