diff options
Diffstat (limited to 'catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java')
-rw-r--r-- | catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java | 1680 |
1 files changed, 855 insertions, 825 deletions
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java index 4fa41e5bee..b17a66434a 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java @@ -36,27 +36,21 @@ import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.Product; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; -import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.resources.data.ComponentCacheData; +import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.SerializationUtils; import org.openecomp.sdc.common.util.ZipUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; +import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Function; +import java.util.stream.Collectors; import java.util.List; import java.util.Map; import java.util.Set; @@ -68,817 +62,853 @@ import java.util.stream.Collectors; @org.springframework.stereotype.Component("component-cache") public class ComponentCache { - private static Logger logger = LoggerFactory.getLogger(ComponentCache.class.getName()); - - @Autowired - ComponentCassandraDao componentCassandraDao; - - @Autowired - ToscaOperationFacade toscaOperationFacade; - - private Map<ComponentTypeEnum, Map<String, Component>> catalogInMemoryCache = new HashMap<>(); - private final ReentrantReadWriteLock rwCatalogLock = new ReentrantReadWriteLock(); - private final Lock rCatalogLock = rwCatalogLock.readLock(); - private final Lock wCatalogLock = rwCatalogLock.writeLock(); - - boolean enabled = true; - int catalogInMemorySizePerResource = 300; - int catalogInMemorySizePerService = 200; - int catalogInMemorySizePerProduct = 100; - boolean catalogInMemoryEnabled = true; - Map<ComponentTypeEnum, Integer> limitMemoryCatalogSizePerType = new HashMap<>(); - - @PostConstruct - public void init() { - - Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration(); - if (configuration != null) { - ApplicationL2CacheConfig applicationL2Cache = configuration.getApplicationL2Cache(); - if (applicationL2Cache != null) { - boolean isEnabled = applicationL2Cache.isEnabled(); - this.enabled = isEnabled; - - ApplicationL1CacheCatalogInfo catalog = applicationL2Cache.getCatalogL1Cache(); - if (catalog != null) { - catalogInMemoryEnabled = catalog.getEnabled(); - catalogInMemorySizePerResource = catalog.getResourcesSizeInCache(); - catalogInMemorySizePerService = catalog.getServicesSizeInCache(); - catalogInMemorySizePerProduct = catalog.getProductsSizeInCache(); - } - } - } - - ComponentTypeEnum[] typesForCache = { ComponentTypeEnum.RESOURCE, ComponentTypeEnum.SERVICE, - ComponentTypeEnum.PRODUCT }; - for (ComponentTypeEnum typeEnum : typesForCache) { - Map<String, Component> map = new HashMap<>(); - catalogInMemoryCache.put(typeEnum, map); - } - - limitMemoryCatalogSizePerType.put(ComponentTypeEnum.RESOURCE, catalogInMemorySizePerResource); - limitMemoryCatalogSizePerType.put(ComponentTypeEnum.SERVICE, catalogInMemorySizePerService); - limitMemoryCatalogSizePerType.put(ComponentTypeEnum.PRODUCT, catalogInMemorySizePerProduct); - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public Either<Component, ActionStatus> getComponent(String componentUid, Long lastModificationTime, - Function<Component, Component> filterFieldsFunc) { - - Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> componentFromCache = getComponentFromCache( - componentUid, lastModificationTime, filterFieldsFunc); - - if (componentFromCache.isRight()) { - return Either.right(componentFromCache.right().value()); - } - - return Either.left(componentFromCache.left().value().left); - - } - - public Either<List<ComponentCacheData>, ActionStatus> getAllComponentIdTimeAndType() { - if (false == isEnabled()) { - return Either.right(ActionStatus.NOT_ALLOWED); - } - - Either<List<ComponentCacheData>, ActionStatus> componentRes = componentCassandraDao - .getAllComponentIdTimeAndType(); - - return componentRes; - - } - - /** - * @param foundComponents - * @param componentTypeEnum - */ - private void updateCatalogInMemoryCacheWithCertified(List<Component> foundComponents, - ComponentTypeEnum componentTypeEnum) { - - try { - wCatalogLock.lock(); - - long start = System.currentTimeMillis(); - Map<String, Component> map = catalogInMemoryCache.get(componentTypeEnum); - int mapSizeBefore = map.size(); - map.clear(); - Map<String, Component> collect = foundComponents.stream() - .filter(p -> p.getLifecycleState() == LifecycleStateEnum.CERTIFIED) - .limit(limitMemoryCatalogSizePerType.get(componentTypeEnum)) - .collect(Collectors.toMap(p -> p.getUniqueId(), p -> p)); - map.putAll(collect); - logger.debug( - "Size of in memory cache for catalog {}(certified only): Before {}, After {}. Replacement Time is {} ms.", - componentTypeEnum.name().toLowerCase(), mapSizeBefore, map.size(), - System.currentTimeMillis() - start); - } finally { - wCatalogLock.unlock(); - } - - } - - private List<Component> getDataFromInMemoryCache(Set<String> components, ComponentTypeEnum componentTypeEnum) { - List<Component> foundComponents = new ArrayList<>(); - - try { - - rCatalogLock.lock(); - - Map<String, Component> map = catalogInMemoryCache.get(componentTypeEnum); - for (String compUid : components) { - Component component = map.get(compUid); - if (component != null) { - foundComponents.add(component); - } - } - - } finally { - rCatalogLock.unlock(); - } - - return foundComponents; - } - - /** - * - * get full components from cassandra. On each component apply filter function - * in order to remove unused members - * - * @param components - * @param filterFieldsFunc - * @return <found components, found dirty components, not found components list> - * or Error - */ - public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponents( - Set<String> components, Function<List<Component>, List<Component>> filterFieldsFunc) { - - if (false == isEnabled()) { - logger.debug("Component Cache is disabled"); - return Either.right(ActionStatus.NOT_ALLOWED); - } - - Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> componentsFull = getComponentsFull( - components); - - if (componentsFull.isRight()) { - return Either.right(componentsFull.right().value()); - } - - ImmutableTriple<List<Component>, List<Component>, Set<String>> immutableTriple = componentsFull.left().value(); - List<Component> foundResources = immutableTriple.left; - List<Component> foundDirtyResources = immutableTriple.middle; - Set<String> notFoundResources = immutableTriple.right; - - List<Component> filterdFoundResources = filterFieldsFunc.apply(foundResources); - List<Component> filterdFoundDirtyResources = filterFieldsFunc.apply(foundDirtyResources); - - ImmutableTriple<List<Component>, List<Component>, Set<String>> result = new ImmutableTriple<List<Component>, List<Component>, Set<String>>( - filterdFoundResources, filterdFoundDirtyResources, notFoundResources); - - return Either.left(result); - - } - - public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsForLeftPanel( - ComponentTypeEnum componentTypeEnum, String internalComponentType, Set<String> filteredResources) { - - logger.debug("In getComponentsForLeftPanel componentTypeEnum = {}, internalComponentType = {}", - componentTypeEnum, internalComponentType); - - Function<List<Component>, List<Component>> filterFieldsFunc = x -> filterForLeftPanel(x); - - return getComponents(filteredResources, filterFieldsFunc); - - } - - private List<Component> filterForLeftPanel(List<Component> components) { - - List<Component> result = new ArrayList<>(); - if (components != null) { - components.forEach(p -> result.add(filterFieldsForLeftPanel(p))); - } - - return result; - } - - private List<Component> filterForCatalog(List<Component> components) { - - List<Component> result = new ArrayList<>(); - if (components != null) { - components.forEach(p -> result.add(filterFieldsForCatalog(p))); - } - - return result; - } - - private Component filterFieldsForLeftPanel(Component component) { - - Component result = null; - ComponentTypeEnum componentTypeEnum = component.getComponentType(); - switch (componentTypeEnum) { - case RESOURCE: - result = new Resource(); - copyFieldsForLeftPanel(component, result); - break; - case SERVICE: - result = new Service(); - copyFieldsForLeftPanel(component, result); - break; - default: - break; - } - - return result; - } - - private Component filterFieldsForCatalog(Component component) { - - Component result = null; - ComponentTypeEnum componentTypeEnum = component.getComponentType(); - switch (componentTypeEnum) { - case RESOURCE: - result = new Resource(); - copyFieldsForCatalog(component, result); - break; - case SERVICE: - result = new Service(); - copyFieldsForCatalog(component, result); - break; - case PRODUCT: - result = new Product(); - copyFieldsForCatalog(component, result); - default: - break; - } - - return result; - } - - /** - * Copy relevant fields to the filtered component for left panel - * - * @param component - * @param filteredComponent - */ - private void copyFieldsForLeftPanel(Component component, Component filteredComponent) { - - ComponentTypeEnum componentTypeEnum = component.getComponentType(); - filteredComponent.setCategories(component.getCategories()); - filteredComponent.setComponentType(component.getComponentType()); - if (ComponentTypeEnum.RESOURCE.equals(component.getComponentType()) - && ResourceTypeEnum.VL.equals(((ResourceMetadataDataDefinition) component - .getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType())) { - filteredComponent.setCapabilities(component.getCapabilities()); - filteredComponent.setRequirements(component.getRequirements()); - } - filteredComponent.setVersion(component.getVersion()); - filteredComponent.setDescription(component.getDescription()); - filteredComponent.setUniqueId(component.getUniqueId()); - filteredComponent.setIcon(component.getIcon()); - filteredComponent.setTags(component.getTags()); - filteredComponent.setLifecycleState(component.getLifecycleState()); - filteredComponent.setInvariantUUID(component.getInvariantUUID()); - filteredComponent.setUUID(component.getUUID()); - filteredComponent.setSystemName(component.getSystemName()); - filteredComponent.setName(component.getName()); - - if (componentTypeEnum == ComponentTypeEnum.RESOURCE) { - Resource resource = (Resource) component; - Resource filteredResource = (Resource) filteredComponent; - filteredResource.setToscaResourceName(resource.getToscaResourceName()); - filteredResource.setResourceType(resource.getResourceType()); - } - } - - private void copyFieldsForCatalog(Component component, Component filteredComponent) { - - ComponentTypeEnum componentTypeEnum = component.getComponentType(); - filteredComponent.setCategories(component.getCategories()); - filteredComponent.setComponentType(component.getComponentType()); - filteredComponent.setVersion(component.getVersion()); - filteredComponent.setDescription(component.getDescription()); - filteredComponent.setUniqueId(component.getUniqueId()); - filteredComponent.setIcon(component.getIcon()); - filteredComponent.setTags(component.getTags()); - filteredComponent.setLifecycleState(component.getLifecycleState()); - filteredComponent.setSystemName(component.getSystemName()); - filteredComponent.setName(component.getName()); - filteredComponent.setLastUpdateDate(component.getLastUpdateDate()); - - if (componentTypeEnum == ComponentTypeEnum.RESOURCE) { - Resource resource = (Resource) component; - Resource filteredResource = (Resource) filteredComponent; - filteredResource.setToscaResourceName(resource.getToscaResourceName()); - filteredResource.setResourceType(resource.getResourceType()); - } else if (componentTypeEnum == ComponentTypeEnum.SERVICE) { - Service service = (Service) component; - Service filteredService = (Service) filteredComponent; - filteredService.setDistributionStatus(service.getDistributionStatus()); - } - } - - /** - * get components from cache of a given list ou unique ids. - * - * for each component data from cassandra, unzip the data if needed and - * deserialize the unzipped data to java object(Component). - * - * @param filteredResources - * @return ImmutableTripple or ActionStatus. | |-- components |-- dirty - * components - components with dirty flag = true. |-- set of non cached - * components - * - */ - private Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsFull( - Set<String> filteredResources) { - - if (false == isEnabled()) { - logger.debug("Component Cache is disabled"); - return Either.right(ActionStatus.NOT_ALLOWED); - } - - List<Component> foundResources = new LinkedList<>(); - List<Component> foundDirtyResources = new LinkedList<>(); - Set<String> notFoundResources = new HashSet<>(); - ImmutableTriple<List<Component>, List<Component>, Set<String>> result = new ImmutableTriple<List<Component>, List<Component>, Set<String>>( - foundResources, foundDirtyResources, notFoundResources); - - long cassandraFetchStart = System.currentTimeMillis(); - List<String> uidsList = new ArrayList<>(); - uidsList.addAll(filteredResources); - Either<List<ComponentCacheData>, ActionStatus> componentsFromCache = componentCassandraDao - .getComponents(uidsList); - - long cassandraFetchEnd = System.currentTimeMillis(); - logger.debug("Fetch time from cassandara of all components took {} ms", - (cassandraFetchEnd - cassandraFetchStart)); - if (componentsFromCache.isRight()) { - BeEcompErrorManager.getInstance().logInternalFlowError("FetchFromCache", - "Failed to fetch components from cache", ErrorSeverity.ERROR); - return Either.right(componentsFromCache.right().value()); - } - - List<ComponentCacheData> list = componentsFromCache.left().value(); - logger.debug("Number of components fetched from cassandra is {}", (list == null ? 0 : list.size())); - if (list != null && false == list.isEmpty()) { - - List<ComponentCacheData> filteredData = list.stream().filter(p -> filteredResources.contains(p.getId())) - .collect(Collectors.toList()); - logger.debug("Number of components filterd is {}", filteredData == null ? 0 : filteredData.size()); - - if (filteredData != null) { - long desStart = System.currentTimeMillis(); - - for (ComponentCacheData componentCacheData : filteredData) { - - logger.debug("Process uid {} from cache", componentCacheData.getId()); - - String compUid = componentCacheData.getId(); - - Either<? extends Component, Boolean> deserializeExt = convertComponentCacheToComponent( - componentCacheData); - - if (deserializeExt.isLeft()) { - Component component = deserializeExt.left().value(); - if (false == componentCacheData.getIsDirty()) { - foundResources.add(component); - } else { - foundDirtyResources.add(component); - } - } else { - notFoundResources.add(compUid); - } - - } - long desEnd = System.currentTimeMillis(); - logger.debug("Deserialization and unzip of {} components took {} ms", filteredData.size(), - (desEnd - desStart)); - } - } - List<String> foundResourcesUid = foundResources.stream().map(p -> p.getUniqueId()).collect(Collectors.toList()); - List<String> foundDirtyResourcesUid = foundDirtyResources.stream().map(p -> p.getUniqueId()) - .collect(Collectors.toList()); - logger.debug("Number of processed components from cache is {}", - (foundResourcesUid.size() + foundDirtyResourcesUid.size())); - Set<String> notCachedResources = filteredResources.stream() - .filter(p -> false == foundResourcesUid.contains(p) && false == foundDirtyResourcesUid.contains(p)) - .collect(Collectors.toSet()); - notFoundResources.addAll(notCachedResources); - - logger.debug("Number of components fetched is {}", foundResources.size()); - logger.debug("Number of components fetched dirty is {}", foundDirtyResources.size()); - logger.debug("Number of components non cached is {}", notCachedResources.size()); - - return Either.left(result); - } - - private Either<? extends Component, Boolean> convertComponentCacheToComponent( - ComponentCacheData componentCacheData) { - - String compUid = componentCacheData.getId(); - - byte[] dataAsArray = componentCacheData.getDataAsArray(); - - if (true == componentCacheData.getIsZipped()) { - long startUnzip = System.nanoTime(); - dataAsArray = ZipUtil.unzip(dataAsArray); - long endUnzip = System.nanoTime(); - logger.trace("Unzip component {} took {} microsecond", compUid, (endUnzip - startUnzip) / 1000); - } - - long startDes = System.nanoTime(); - - Either<? extends Component, Boolean> deserializeExt = deserializeComponent(componentCacheData, dataAsArray); - - long endDes = System.nanoTime(); - logger.trace("Deserialize component {} took {} microsecond", compUid, (endDes - startDes) / 1000); - return deserializeExt; - } - - private Either<? extends Component, Boolean> deserializeComponent(ComponentCacheData componentCacheData, - byte[] dataAsArray) { - String type = componentCacheData.getType(); - NodeTypeEnum typeEnum = NodeTypeEnum.getByNameIgnoreCase(type); - - Either<? extends Component, Boolean> deserializeExt = Either.right(false); - switch (typeEnum) { - case Resource: - deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Resource.class, componentCacheData.getId()); - break; - case Service: - deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Service.class, componentCacheData.getId()); - break; - case Product: - deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Product.class, componentCacheData.getId()); - break; - default: - break; - } - return deserializeExt; - } - - public Either<Component, ActionStatus> getComponent(String componentUid) { - - return getComponent(componentUid, null, Function.identity()); - } - - public Either<Component, ActionStatus> getComponent(String componentUid, Long lastModificationTime) { - - return getComponent(componentUid, lastModificationTime, Function.identity()); - - } - - public boolean setComponent(String componentUid, Long lastModificationTime, NodeTypeEnum nodeTypeEnum) { - - boolean result = false; - - if (false == isEnabled()) { - logger.debug("Component Cache is disabled"); - return false; - } - - Either<Component, StorageOperationStatus> either = toscaOperationFacade.getToscaElement(componentUid); - if (either.isLeft()) { - Component component = either.left().value(); - result = saveComponent(componentUid, lastModificationTime, nodeTypeEnum, component); - } else { - logger.debug("Failed to get component {} of type {} from graph. Status is {}", componentUid, - nodeTypeEnum.name().toLowerCase(), either.right().value()); - } - - return result; - - } - - private boolean saveComponent(String componentUid, Long lastModificationTime, NodeTypeEnum nodeTypeEnum, - Component component) { - - logger.trace("Going to save component {} of type {} in cache", componentUid, nodeTypeEnum.name().toLowerCase()); - - boolean result = false; - - Either<byte[], Boolean> serializeExt = SerializationUtils.serializeExt(component); - if (serializeExt.isLeft()) { - byte[] serializedData = serializeExt.left().value(); - byte[] zipBytes; - try { - zipBytes = ZipUtil.zipBytes(serializedData); - ComponentCacheData componentCacheData = new ComponentCacheData(); - componentCacheData.setDataAsArray(zipBytes); - componentCacheData.setIsZipped(true); - componentCacheData.setId(componentUid); - componentCacheData.setModificationTime(new Date(lastModificationTime)); - componentCacheData.setType(component.getComponentType().name().toLowerCase()); - - CassandraOperationStatus status = componentCassandraDao.saveComponent(componentCacheData); - - if (status == CassandraOperationStatus.OK) { - result = true; - } - - } catch (IOException e) { - logger.debug("Failed to prepare component {} of type {} for cache", componentUid, - nodeTypeEnum.name().toLowerCase()); - } - } else { - logger.debug("Failed to serialize component {} of type {} for cache", componentUid, - nodeTypeEnum.name().toLowerCase()); - } - return result; - } - - public boolean setComponent(Component component, NodeTypeEnum nodeTypeEnum) { - - boolean result = false; - - if (false == isEnabled()) { - logger.debug("Component Cache is disabled"); - return false; - } - - String componentUid = component.getUniqueId(); - Long lastUpdateDate = component.getLastUpdateDate(); - - result = saveComponent(componentUid, lastUpdateDate, nodeTypeEnum, component); - - return result; - - } - - /** - * get components from cache of a given list ou unique ids. - * - * for each component data from cassandra, unzip the data if needed and - * deserialize the unzipped data to java object(Component). - * - * @param filteredResources - * @return ImmutableTripple or ActionStatus. | |-- components |-- set of non - * cached components - * - */ - private Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponentsFull( - Map<String, Long> filteredResources) { - - if (false == isEnabled()) { - logger.debug("Component Cache is disabled"); - return Either.right(ActionStatus.NOT_ALLOWED); - } - - List<Component> foundResources = new LinkedList<>(); - Set<String> notFoundResources = new HashSet<>(); - ImmutablePair<List<Component>, Set<String>> result = new ImmutablePair<List<Component>, Set<String>>( - foundResources, notFoundResources); - - long cassandraFetchStart = System.currentTimeMillis(); - - Either<ImmutablePair<List<ComponentCacheData>, Set<String>>, ActionStatus> componentsFromCache = componentCassandraDao - .getComponents(filteredResources); - - long cassandraFetchEnd = System.currentTimeMillis(); - logger.debug("Fetch time from cassandara of all components took {} ms", - (cassandraFetchEnd - cassandraFetchStart)); - if (componentsFromCache.isRight()) { - BeEcompErrorManager.getInstance().logInternalFlowError("FetchFromCache", - "Failed to fetch components from cache", ErrorSeverity.ERROR); - return Either.right(componentsFromCache.right().value()); - } - - ImmutablePair<List<ComponentCacheData>, Set<String>> immutablePair = componentsFromCache.left().value(); - List<ComponentCacheData> list = immutablePair.getLeft(); - logger.debug("Number of components fetched from cassandra is {}", (list == null ? 0 : list.size())); - if (list != null && false == list.isEmpty()) { - - // List<ComponentCacheData> filteredData = list.stream().filter(p -> - // filteredResources.contains(p.getId())).collect(Collectors.toList()); - logger.debug("Number of components filterd is {}", list == null ? 0 : list.size()); - - if (list != null) { - long desStart = System.currentTimeMillis(); - - for (ComponentCacheData componentCacheData : list) { - - logger.debug("Process uid {} from cache", componentCacheData.getId()); - - String compUid = componentCacheData.getId(); - - Either<? extends Component, Boolean> deserializeExt = convertComponentCacheToComponent( - componentCacheData); - - if (deserializeExt.isLeft()) { - Component component = deserializeExt.left().value(); - foundResources.add(component); - } else { - notFoundResources.add(compUid); - } - - } - long desEnd = System.currentTimeMillis(); - logger.debug("Deserialization and unzip of {} components took {} ms", list.size(), (desEnd - desStart)); - } - } - logger.debug("Number of processed components from cache is {}", foundResources.size()); - - Set<String> notFoundInCache = immutablePair.getRight(); - notFoundResources.addAll(notFoundInCache); - - logger.debug("Number of components fetched is {}", foundResources.size()); - logger.debug("Number of components non cached is {}", notFoundResources.size()); - - return Either.left(result); - } - - /** - * get components for catalog - * - * @param components - * @param componentTypeEnum - * @return - */ - public Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponentsForCatalog( - Map<String, Long> components, ComponentTypeEnum componentTypeEnum) { - - if (false == isEnabled()) { - logger.debug("In getComponentsForCatalog for type {}. Cache is disabled.", - componentTypeEnum.name().toLowerCase()); - return Either.right(ActionStatus.NOT_ALLOWED); - } - logger.debug("In getComponentsForCatalog for type {}", componentTypeEnum.name().toLowerCase()); - - Function<List<Component>, List<Component>> filterFieldsFunc = x -> filterForCatalog(x); - - Map<String, Long> leftComponentsForSearch = new HashMap<>(); - leftComponentsForSearch.putAll(components); - - // get components from inmemory cache - List<Component> componentsFromMemory = null; - if (true == catalogInMemoryEnabled) { - componentsFromMemory = getDataFromInMemoryCache(components.keySet(), componentTypeEnum); - logger.debug("The number of components of type {} fetched from memory is {}", - componentTypeEnum.name().toLowerCase(), - componentsFromMemory == null ? 0 : componentsFromMemory.size()); - if (componentsFromMemory != null) { - List<String> ignoredComponents = new ArrayList<>(); - for (Component componentFromMem : componentsFromMemory) { - if (componentFromMem.getLastUpdateDate().longValue() != components - .get(componentFromMem.getUniqueId()).longValue()) { - // Ignore the component from memory - ignoredComponents.add(componentFromMem.getUniqueId()); - } - } - - logger.debug("Number of components from type {} ignored from memory cache is {}", - componentTypeEnum.name().toLowerCase(), ignoredComponents.size()); - // remove from memory result the components which are not valid - componentsFromMemory = componentsFromMemory.stream() - .filter(p -> false == ignoredComponents.contains(p.getUniqueId())).collect(Collectors.toList()); - // Remove from leftComponentsForSearch the valid components from - // memory - componentsFromMemory.forEach(p -> leftComponentsForSearch.remove(p.getUniqueId())); - - } - } else { - logger.debug("Catalog InMemory cache is disabled"); - } - - logger.debug("Number of components from type {} needed to fetch is {}", componentTypeEnum.name().toLowerCase(), - leftComponentsForSearch.size()); - - // get components from cassandra cache and filter each component - Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> result = getComponents( - leftComponentsForSearch, filterFieldsFunc); - - if (result.isLeft()) { - // add inmemory components to the valid components(not dirty) - List<Component> foundComponents = result.left().value().getLeft(); - if (componentsFromMemory != null) { - foundComponents.addAll(componentsFromMemory); - } - if (true == catalogInMemoryEnabled) { - updateCatalogInMemoryCacheWithCertified(foundComponents, componentTypeEnum); - } - } - - return result; - } - - /** - * @param components - * - Map of <componentUniqueId, last update date> - * @param filterFieldsFunc - * @return - */ - public Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponents(Map<String, Long> components, - Function<List<Component>, List<Component>> filterFieldsFunc) { - - if (false == isEnabled()) { - logger.debug("Component Cache is disabled"); - return Either.right(ActionStatus.NOT_ALLOWED); - } - - Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> componentsFull = getComponentsFull( - components); - - if (componentsFull.isRight()) { - return Either.right(componentsFull.right().value()); - } - - ImmutablePair<List<Component>, Set<String>> immutablePair = componentsFull.left().value(); - List<Component> foundResources = immutablePair.left; - Set<String> notFoundResources = immutablePair.right; - - List<Component> filterdFoundResources = filterFieldsFunc.apply(foundResources); - - ImmutablePair<List<Component>, Set<String>> result = new ImmutablePair<List<Component>, Set<String>>( - filterdFoundResources, notFoundResources); - - return Either.left(result); - - } - - /** - * get the component and its modification time from cache - * - * @param componentUid - * @param filterFieldsFunc - * @return - */ - public Either<ImmutablePair<Component, Long>, ActionStatus> getComponentAndTime(String componentUid, - Function<Component, Component> filterFieldsFunc) { - - Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> componentFromCache = getComponentFromCache( - componentUid, null, filterFieldsFunc); - - if (componentFromCache.isRight()) { - return Either.right(componentFromCache.right().value()); - } - - ImmutablePair<Component, ComponentCacheData> immutablePair = componentFromCache.left().value(); - - ImmutablePair<Component, Long> result = new ImmutablePair<Component, Long>(immutablePair.left, - immutablePair.right.getModificationTime().getTime()); - - return Either.left(result); - } - - private Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> getComponentFromCache( - String componentUid, Long lastModificationTime, Function<Component, Component> filterFieldsFunc) { - if (false == isEnabled()) { - return Either.right(ActionStatus.NOT_ALLOWED); - } - - Either<ComponentCacheData, ActionStatus> componentRes = componentCassandraDao.getComponent(componentUid); - - if (componentRes.isRight()) { - return Either.right(componentRes.right().value()); - } - - ComponentCacheData componentCacheData = componentRes.left().value(); - - if (lastModificationTime != null) { - long cacheCompModificationTime = componentCacheData.getModificationTime().getTime(); - if (lastModificationTime != cacheCompModificationTime) { - logger.debug( - "Component {} found in cache but its modification time {} does not match to the timestamp in cache {}.", - componentUid, lastModificationTime, cacheCompModificationTime); - return Either.right(ActionStatus.INVALID_CONTENT); - } - } - - Either<? extends Component, Boolean> convertRes = convertComponentCacheToComponent(componentCacheData); - if (convertRes.isRight()) { - return Either.right(ActionStatus.CONVERT_COMPONENT_ERROR); - } - - Component component = convertRes.left().value(); - - Component filteredComponent = component; - if (filterFieldsFunc != null) { - filteredComponent = filterFieldsFunc.apply(component); - } - - ImmutablePair<Component, ComponentCacheData> result = new ImmutablePair<Component, ComponentCacheData>( - filteredComponent, componentCacheData); - - return Either.left(result); - } - - public ActionStatus deleteComponentFromCache(String id) { - if (false == isEnabled()) { - return ActionStatus.NOT_ALLOWED; - } - CassandraOperationStatus status = componentCassandraDao.deleteComponent(id); - if (CassandraOperationStatus.OK.equals(status)) { - return ActionStatus.OK; - } else { - logger.debug("delete component failed with error {}", status); - return ActionStatus.GENERAL_ERROR; - } - } + private static final String COMPONENT_CACHE_IS_DISABLED = "Component Cache is disabled"; + + private static final Logger log = Logger.getLogger(ComponentCache.class); + + @Autowired + ComponentCassandraDao componentCassandraDao; + + @Autowired + ToscaOperationFacade toscaOperationFacade; + + private Map<ComponentTypeEnum, Map<String, Component>> catalogInMemoryCache = new HashMap<>(); + private final ReentrantReadWriteLock rwCatalogLock = new ReentrantReadWriteLock(); + private final Lock rCatalogLock = rwCatalogLock.readLock(); + private final Lock wCatalogLock = rwCatalogLock.writeLock(); + + boolean enabled = true; + int catalogInMemorySizePerResource = 300; + int catalogInMemorySizePerService = 200; + int catalogInMemorySizePerProduct = 100; + boolean catalogInMemoryEnabled = true; + Map<ComponentTypeEnum, Integer> limitMemoryCatalogSizePerType = new HashMap<>(); + + @PostConstruct + public void init() { + + Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration(); + if (configuration != null) { + ApplicationL2CacheConfig applicationL2Cache = configuration.getApplicationL2Cache(); + if (applicationL2Cache != null) { + this.enabled = applicationL2Cache.isEnabled(); + + ApplicationL1CacheCatalogInfo catalog = applicationL2Cache.getCatalogL1Cache(); + if (catalog != null) { + catalogInMemoryEnabled = catalog.getEnabled(); + catalogInMemorySizePerResource = catalog.getResourcesSizeInCache(); + catalogInMemorySizePerService = catalog.getServicesSizeInCache(); + catalogInMemorySizePerProduct = catalog.getProductsSizeInCache(); + } + } + } + + ComponentTypeEnum[] typesForCache = { ComponentTypeEnum.RESOURCE, ComponentTypeEnum.SERVICE, + ComponentTypeEnum.PRODUCT }; + for (ComponentTypeEnum typeEnum : typesForCache) { + Map<String, Component> map = new HashMap<>(); + catalogInMemoryCache.put(typeEnum, map); + } + + limitMemoryCatalogSizePerType.put(ComponentTypeEnum.RESOURCE, catalogInMemorySizePerResource); + limitMemoryCatalogSizePerType.put(ComponentTypeEnum.SERVICE, catalogInMemorySizePerService); + limitMemoryCatalogSizePerType.put(ComponentTypeEnum.PRODUCT, catalogInMemorySizePerProduct); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Either<Component, ActionStatus> getComponent(String componentUid, Long lastModificationTime, + Function<Component, Component> filterFieldsFunc) { + + Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> componentFromCache = getComponentFromCache( + componentUid, lastModificationTime, filterFieldsFunc); + + if (componentFromCache.isRight()) { + return Either.right(componentFromCache.right().value()); + } + + return Either.left(componentFromCache.left().value().left); + + } + + public Either<List<ComponentCacheData>, ActionStatus> getAllComponentIdTimeAndType() { + if (!isEnabled()) { + return Either.right(ActionStatus.NOT_ALLOWED); + } + + return componentCassandraDao + .getAllComponentIdTimeAndType(); + + } + + /** + * get components for catalog + * + * @param components + * @param componentTypeEnum + * @return + */ + @Deprecated + public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsForCatalog( + Set<String> components, ComponentTypeEnum componentTypeEnum) { + + if (!isEnabled()) { + log.debug("In getComponentsForCatalog for type {}. Cache is disabled.", + componentTypeEnum.name().toLowerCase()); + return Either.right(ActionStatus.NOT_ALLOWED); + } + log.debug("In getComponentsForCatalog for type {}", componentTypeEnum.name().toLowerCase()); + + Function<List<Component>, List<Component>> filterFieldsFunc = this::filterForCatalog; + + Set<String> leftComponentsForSearch = new HashSet<>(); + leftComponentsForSearch.addAll(components); + + // get components from inmemory cache + List<Component> componentsFromMemory = null; + if (catalogInMemoryEnabled) { + componentsFromMemory = getDataFromInMemoryCache(components, componentTypeEnum); + log.debug("The number of components of type {} fetched from memory is {}", + componentTypeEnum.name().toLowerCase(), + componentsFromMemory == null ? 0 : componentsFromMemory.size()); + if (componentsFromMemory != null) { + componentsFromMemory.forEach(p -> leftComponentsForSearch.remove(p.getUniqueId())); + } + } else { + log.debug("Catalog InMemory cache is disabled"); + } + + log.debug("Number of components from type {} needed to fetch is {}", componentTypeEnum.name().toLowerCase(), + leftComponentsForSearch.size()); + + // get components from cassandra cache and filter each component + Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> result = getComponents( + leftComponentsForSearch, filterFieldsFunc); + + if (result.isLeft()) { + // add inmemory components to the valid components(not dirty) + List<Component> foundComponents = result.left().value().getLeft(); + if (componentsFromMemory != null) { + foundComponents.addAll(componentsFromMemory); + } + if (catalogInMemoryEnabled) { + updateCatalogInMemoryCacheWithCertified(foundComponents, componentTypeEnum); + } + } + + return result; + } + + /** + * @param foundComponents + * @param componentTypeEnum + */ + private void updateCatalogInMemoryCacheWithCertified(List<Component> foundComponents, + ComponentTypeEnum componentTypeEnum) { + + try { + wCatalogLock.lock(); + + long start = System.currentTimeMillis(); + Map<String, Component> map = catalogInMemoryCache.get(componentTypeEnum); + int mapSizeBefore = map.size(); + map.clear(); + Map<String, Component> collect = foundComponents.stream() + .filter(p -> p.getLifecycleState() == LifecycleStateEnum.CERTIFIED) + .limit(limitMemoryCatalogSizePerType.get(componentTypeEnum)) + .collect(Collectors.toMap(Component::getUniqueId, p -> p)); + map.putAll(collect); + log.debug( + "Size of in memory cache for catalog {}(certified only): Before {}, After {}. Replacement Time is {} ms.", + componentTypeEnum.name().toLowerCase(), mapSizeBefore, map.size(), + System.currentTimeMillis() - start); + } finally { + wCatalogLock.unlock(); + } + + } + + private List<Component> getDataFromInMemoryCache(Set<String> components, ComponentTypeEnum componentTypeEnum) { + List<Component> foundComponents = new ArrayList<>(); + + try { + + rCatalogLock.lock(); + + Map<String, Component> map = catalogInMemoryCache.get(componentTypeEnum); + for (String compUid : components) { + Component component = map.get(compUid); + if (component != null) { + foundComponents.add(component); + } + } + + } finally { + rCatalogLock.unlock(); + } + + return foundComponents; + } + + /** + * + * get full components from cassandra. On each component apply filter + * function in order to remove unused members + * + * @param components + * @param filterFieldsFunc + * @return <found components, found dirty components, not found components + * list> or Error + */ + public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponents( + Set<String> components, Function<List<Component>, List<Component>> filterFieldsFunc) { + + if (!isEnabled()) { + log.debug(COMPONENT_CACHE_IS_DISABLED); + return Either.right(ActionStatus.NOT_ALLOWED); + } + + Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> componentsFull = getComponentsFull( + components); + + if (componentsFull.isRight()) { + return Either.right(componentsFull.right().value()); + } + + ImmutableTriple<List<Component>, List<Component>, Set<String>> immutableTriple = componentsFull.left().value(); + List<Component> foundResources = immutableTriple.left; + List<Component> foundDirtyResources = immutableTriple.middle; + Set<String> notFoundResources = immutableTriple.right; + + List<Component> filterdFoundResources = filterFieldsFunc.apply(foundResources); + List<Component> filterdFoundDirtyResources = filterFieldsFunc.apply(foundDirtyResources); + + ImmutableTriple<List<Component>, List<Component>, Set<String>> result = new ImmutableTriple<>( + filterdFoundResources, filterdFoundDirtyResources, notFoundResources); + + return Either.left(result); + + } + + public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsForLeftPanel( + ComponentTypeEnum componentTypeEnum, String internalComponentType, Set<String> filteredResources) { + + log.debug("In getComponentsForLeftPanel componentTypeEnum = {}, internalComponentType = {}", + componentTypeEnum, internalComponentType); + + Function<List<Component>, List<Component>> filterFieldsFunc = this::filterForLeftPanel; + + return getComponents(filteredResources, filterFieldsFunc); + + } + + private List<Component> filterForLeftPanel(List<Component> components) { + + List<Component> result = new ArrayList<>(); + if (components != null) { + components.forEach(p -> result.add(filterFieldsForLeftPanel(p))); + } + + return result; + } + + private List<Component> filterForCatalog(List<Component> components) { + + List<Component> result = new ArrayList<>(); + if (components != null) { + components.forEach(p -> result.add(filterFieldsForCatalog(p))); + } + + return result; + } + + private Component filterFieldsForLeftPanel(Component component) { + + Component result = null; + ComponentTypeEnum componentTypeEnum = component.getComponentType(); + switch (componentTypeEnum) { + case RESOURCE: + result = new Resource(); + copyFieldsForLeftPanel(component, result); + break; + case SERVICE: + result = new Service(); + copyFieldsForLeftPanel(component, result); + break; + default: + break; + } + + return result; + } + + private Component filterFieldsForCatalog(Component component) { + + Component result = null; + ComponentTypeEnum componentTypeEnum = component.getComponentType(); + switch (componentTypeEnum) { + case RESOURCE: + result = new Resource(); + copyFieldsForCatalog(component, result); + break; + case SERVICE: + result = new Service(); + copyFieldsForCatalog(component, result); + break; + case PRODUCT: + result = new Product(); + copyFieldsForCatalog(component, result); + break; + default: + break; + } + + return result; + } + + /** + * Copy relevant fields to the filtered component for left panel + * + * @param component + * @param filteredComponent + */ + private void copyFieldsForLeftPanel(Component component, Component filteredComponent) { + + ComponentTypeEnum componentTypeEnum = component.getComponentType(); + filteredComponent.setCategories(component.getCategories()); + filteredComponent.setComponentType(component.getComponentType()); + if (ComponentTypeEnum.RESOURCE.equals(component.getComponentType()) + && ResourceTypeEnum.VL.equals(((ResourceMetadataDataDefinition) component + .getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType())) { + filteredComponent.setCapabilities(component.getCapabilities()); + filteredComponent.setRequirements(component.getRequirements()); + } + filteredComponent.setVersion(component.getVersion()); + filteredComponent.setDescription(component.getDescription()); + filteredComponent.setUniqueId(component.getUniqueId()); + filteredComponent.setIcon(component.getIcon()); + filteredComponent.setTags(component.getTags()); + filteredComponent.setLifecycleState(component.getLifecycleState()); + filteredComponent.setInvariantUUID(component.getInvariantUUID()); + filteredComponent.setUUID(component.getUUID()); + filteredComponent.setSystemName(component.getSystemName()); + filteredComponent.setName(component.getName()); + + if (componentTypeEnum == ComponentTypeEnum.RESOURCE) { + Resource resource = (Resource) component; + Resource filteredResource = (Resource) filteredComponent; + filteredResource.setToscaResourceName(resource.getToscaResourceName()); + filteredResource.setResourceType(resource.getResourceType()); + } + } + + private void copyFieldsForCatalog(Component component, Component filteredComponent) { + + ComponentTypeEnum componentTypeEnum = component.getComponentType(); + filteredComponent.setCategories(component.getCategories()); + filteredComponent.setComponentType(component.getComponentType()); + filteredComponent.setVersion(component.getVersion()); + filteredComponent.setDescription(component.getDescription()); + filteredComponent.setUniqueId(component.getUniqueId()); + filteredComponent.setIcon(component.getIcon()); + filteredComponent.setTags(component.getTags()); + filteredComponent.setLifecycleState(component.getLifecycleState()); + filteredComponent.setSystemName(component.getSystemName()); + filteredComponent.setName(component.getName()); + filteredComponent.setLastUpdateDate(component.getLastUpdateDate()); + + if (componentTypeEnum == ComponentTypeEnum.RESOURCE) { + Resource resource = (Resource) component; + Resource filteredResource = (Resource) filteredComponent; + filteredResource.setToscaResourceName(resource.getToscaResourceName()); + filteredResource.setResourceType(resource.getResourceType()); + } else if (componentTypeEnum == ComponentTypeEnum.SERVICE) { + Service service = (Service) component; + Service filteredService = (Service) filteredComponent; + filteredService.setDistributionStatus(service.getDistributionStatus()); + } + } + + /** + * get components from cache of a given list ou unique ids. + * + * for each component data from cassandra, unzip the data if needed and + * deserialize the unzipped data to java object(Component). + * + * @param filteredResources + * @return ImmutableTripple or ActionStatus. | |-- components |-- dirty + * components - components with dirty flag = true. |-- set of non + * cached components + * + */ + private Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsFull( + Set<String> filteredResources) { + + if (!isEnabled()) { + log.debug(COMPONENT_CACHE_IS_DISABLED); + return Either.right(ActionStatus.NOT_ALLOWED); + } + + List<Component> foundResources = new LinkedList<>(); + List<Component> foundDirtyResources = new LinkedList<>(); + Set<String> notFoundResources = new HashSet<>(); + ImmutableTriple<List<Component>, List<Component>, Set<String>> result = new ImmutableTriple<>( + foundResources, foundDirtyResources, notFoundResources); + + long cassandraFetchStart = System.currentTimeMillis(); + List<String> uidsList = new ArrayList<>(); + uidsList.addAll(filteredResources); + Either<List<ComponentCacheData>, ActionStatus> componentsFromCache = componentCassandraDao + .getComponents(uidsList); + + long cassandraFetchEnd = System.currentTimeMillis(); + log.debug("Fetch time from cassandara of all components took {} ms", + (cassandraFetchEnd - cassandraFetchStart)); + if (componentsFromCache.isRight()) { + BeEcompErrorManager.getInstance().logInternalFlowError("FetchFromCache", + "Failed to fetch components from cache", ErrorSeverity.ERROR); + return Either.right(componentsFromCache.right().value()); + } + + List<ComponentCacheData> list = componentsFromCache.left().value(); + log.debug("Number of components fetched from cassandra is {}", (list == null ? 0 : list.size())); + if (list != null && !list.isEmpty()) { + + List<ComponentCacheData> filteredData = list.stream().filter(p -> filteredResources.contains(p.getId())) + .collect(Collectors.toList()); + log.debug("Number of components filterd is {}", filteredData == null ? 0 : filteredData.size()); + + if (filteredData != null) { + long desStart = System.currentTimeMillis(); + + for (ComponentCacheData componentCacheData : filteredData) { + + log.debug("Process uid {} from cache", componentCacheData.getId()); + + String compUid = componentCacheData.getId(); + + Either<? extends Component, Boolean> deserializeExt = convertComponentCacheToComponent( + componentCacheData); + + if (deserializeExt.isLeft()) { + Component component = deserializeExt.left().value(); + if (!componentCacheData.getIsDirty()) { + foundResources.add(component); + } else { + foundDirtyResources.add(component); + } + } else { + notFoundResources.add(compUid); + } + + } + long desEnd = System.currentTimeMillis(); + log.debug("Deserialization and unzip of {} components took {} ms", filteredData.size(), + (desEnd - desStart)); + } + } + List<String> foundResourcesUid = foundResources.stream().map(Component::getUniqueId).collect(Collectors.toList()); + List<String> foundDirtyResourcesUid = foundDirtyResources.stream().map(Component::getUniqueId) + .collect(Collectors.toList()); + log.debug("Number of processed components from cache is {}", + (foundResourcesUid.size() + foundDirtyResourcesUid.size())); + Set<String> notCachedResources = filteredResources.stream() + .filter(p -> !foundResourcesUid.contains(p) && !foundDirtyResourcesUid.contains(p)) + .collect(Collectors.toSet()); + notFoundResources.addAll(notCachedResources); + + if (log.isDebugEnabled()) { + log.debug("Number of components fetched is {}", foundResources.size()); + log.debug("Number of components fetched dirty is {}", foundDirtyResources.size()); + log.debug("Number of components non cached is {}", notCachedResources.size()); + } + + return Either.left(result); + } + + private Either<? extends Component, Boolean> convertComponentCacheToComponent( + ComponentCacheData componentCacheData) { + + String compUid = componentCacheData.getId(); + + byte[] dataAsArray = componentCacheData.getDataAsArray(); + + if (componentCacheData.getIsZipped()) { + long startUnzip = System.nanoTime(); + dataAsArray = ZipUtil.unzip(dataAsArray); + long endUnzip = System.nanoTime(); + log.trace("Unzip component {} took {} microsecond", compUid, (endUnzip - startUnzip) / 1000); + } + + long startDes = System.nanoTime(); + + Either<? extends Component, Boolean> deserializeExt = deserializeComponent(componentCacheData, dataAsArray); + + long endDes = System.nanoTime(); + log.trace("Deserialize component {} took {} microsecond", compUid, (endDes - startDes) / 1000); + return deserializeExt; + } + + private Either<? extends Component, Boolean> deserializeComponent(ComponentCacheData componentCacheData, + byte[] dataAsArray) { + String type = componentCacheData.getType(); + NodeTypeEnum typeEnum = NodeTypeEnum.getByNameIgnoreCase(type); + + Either<? extends Component, Boolean> deserializeExt = Either.right(false); + switch (typeEnum) { + case Resource: + deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Resource.class, componentCacheData.getId()); + break; + case Service: + deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Service.class, componentCacheData.getId()); + break; + case Product: + deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Product.class, componentCacheData.getId()); + break; + default: + break; + } + return deserializeExt; + } + + public Either<Component, ActionStatus> getComponent(String componentUid) { + + return getComponent(componentUid, null, Function.identity()); + + } + + private boolean saveComponent(String componentUid, Long lastModificationTime, NodeTypeEnum nodeTypeEnum, + Component component) { + + log.trace("Going to save component {} of type {} in cache", componentUid, nodeTypeEnum.name().toLowerCase()); + + boolean result = false; + + Either<byte[], Boolean> serializeExt = SerializationUtils.serializeExt(component); + if (serializeExt.isLeft()) { + byte[] serializedData = serializeExt.left().value(); + byte[] zipBytes; + try { + zipBytes = ZipUtil.zipBytes(serializedData); + ComponentCacheData componentCacheData = new ComponentCacheData(); + componentCacheData.setDataAsArray(zipBytes); + componentCacheData.setIsZipped(true); + componentCacheData.setId(componentUid); + componentCacheData.setModificationTime(new Date(lastModificationTime)); + componentCacheData.setType(component.getComponentType().name().toLowerCase()); + + CassandraOperationStatus status = componentCassandraDao.saveComponent(componentCacheData); + + if (status == CassandraOperationStatus.OK) { + result = true; + } + + } catch (IOException e) { + log.debug("Failed to prepare component {} of type {} for cache", componentUid, + nodeTypeEnum.name().toLowerCase()); + if (log.isTraceEnabled()) { + log.trace("Failed to prepare component {} of type {} for cache",componentUid,nodeTypeEnum.name().toLowerCase()); + } + } + } else { + log.debug("Failed to serialize component {} of type {} for cache", componentUid, + nodeTypeEnum.name().toLowerCase()); + } + return result; + } + + public boolean setComponent(Component component, NodeTypeEnum nodeTypeEnum) { + + boolean result = false; + + if (!isEnabled()) { + log.debug(COMPONENT_CACHE_IS_DISABLED); + return false; + } + + String componentUid = component.getUniqueId(); + Long lastUpdateDate = component.getLastUpdateDate(); + + result = saveComponent(componentUid, lastUpdateDate, nodeTypeEnum, component); + + return result; + + } + + /** + * get components from cache of a given list ou unique ids. + * + * for each component data from cassandra, unzip the data if needed and + * deserialize the unzipped data to java object(Component). + * + * @param filteredResources + * @return ImmutableTripple or ActionStatus. | |-- components |-- set of non + * cached components + * + */ + private Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponentsFull( + Map<String, Long> filteredResources) { + + if (!isEnabled()) { + log.debug(COMPONENT_CACHE_IS_DISABLED); + return Either.right(ActionStatus.NOT_ALLOWED); + } + + List<Component> foundResources = new LinkedList<>(); + Set<String> notFoundResources = new HashSet<>(); + ImmutablePair<List<Component>, Set<String>> result = new ImmutablePair<>( + foundResources, notFoundResources); + + long cassandraFetchStart = System.currentTimeMillis(); + + Either<ImmutablePair<List<ComponentCacheData>, Set<String>>, ActionStatus> componentsFromCache = componentCassandraDao + .getComponents(filteredResources); + + long cassandraFetchEnd = System.currentTimeMillis(); + log.debug("Fetch time from cassandara of all components took {} ms", + (cassandraFetchEnd - cassandraFetchStart)); + if (componentsFromCache.isRight()) { + BeEcompErrorManager.getInstance().logInternalFlowError("FetchFromCache", + "Failed to fetch components from cache", ErrorSeverity.ERROR); + return Either.right(componentsFromCache.right().value()); + } + + ImmutablePair<List<ComponentCacheData>, Set<String>> immutablePair = componentsFromCache.left().value(); + List<ComponentCacheData> list = immutablePair.getLeft(); + log.debug("Number of components fetched from cassandra is {}", (list == null ? 0 : list.size())); + if (list != null && !list.isEmpty()) { + + log.debug("Number of components filterd is {}", list == null ? 0 : list.size()); + + if (list != null) { + long desStart = System.currentTimeMillis(); + + for (ComponentCacheData componentCacheData : list) { + + log.debug("Process uid {} from cache", componentCacheData.getId()); + + String compUid = componentCacheData.getId(); + + Either<? extends Component, Boolean> deserializeExt = convertComponentCacheToComponent( + componentCacheData); + + if (deserializeExt.isLeft()) { + Component component = deserializeExt.left().value(); + foundResources.add(component); + } else { + notFoundResources.add(compUid); + } + + } + long desEnd = System.currentTimeMillis(); + log.debug("Deserialization and unzip of {} components took {} ms", list.size(), (desEnd - desStart)); + } + } + log.debug("Number of processed components from cache is {}", foundResources.size()); + + Set<String> notFoundInCache = immutablePair.getRight(); + notFoundResources.addAll(notFoundInCache); + + if (log.isDebugEnabled()) { + log.debug("Number of components fetched is {}", foundResources.size()); + log.debug("Number of components non cached is {}", notFoundResources.size()); + } + + return Either.left(result); + } + + /** + * get components for catalog + * + * @param components + * @param componentTypeEnum + * @return + */ + public Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponentsForCatalog( + Map<String, Long> components, ComponentTypeEnum componentTypeEnum) { + + if (!isEnabled()) { + log.debug("In getComponentsForCatalog for type {}. Cache is disabled.", + componentTypeEnum.name().toLowerCase()); + return Either.right(ActionStatus.NOT_ALLOWED); + } + log.debug("In getComponentsForCatalog for type {}", componentTypeEnum.name().toLowerCase()); + + Function<List<Component>, List<Component>> filterFieldsFunc = this::filterForCatalog; + + Map<String, Long> leftComponentsForSearch = new HashMap<>(); + leftComponentsForSearch.putAll(components); + + // get components from inmemory cache + List<Component> componentsFromMemory = null; + if (catalogInMemoryEnabled) { + componentsFromMemory = getDataFromInMemoryCache(components.keySet(), componentTypeEnum); + log.debug("The number of components of type {} fetched from memory is {}", + componentTypeEnum.name().toLowerCase(), + componentsFromMemory == null ? 0 : componentsFromMemory.size()); + if (componentsFromMemory != null) { + List<String> ignoredComponents = new ArrayList<>(); + for (Component componentFromMem : componentsFromMemory) { + if (componentFromMem.getLastUpdateDate().longValue() != components + .get(componentFromMem.getUniqueId()).longValue()) { + // Ignore the component from memory + ignoredComponents.add(componentFromMem.getUniqueId()); + } + } + + log.debug("Number of components from type {} ignored from memory cache is {}", + componentTypeEnum.name().toLowerCase(), ignoredComponents.size()); + // remove from memory result the components which are not valid + componentsFromMemory = componentsFromMemory.stream() + .filter(p -> !ignoredComponents.contains(p.getUniqueId())).collect(Collectors.toList()); + // Remove from leftComponentsForSearch the valid components from + // memory + componentsFromMemory.forEach(p -> leftComponentsForSearch.remove(p.getUniqueId())); + + } + } else { + log.debug("Catalog InMemory cache is disabled"); + } + + log.debug("Number of components from type {} needed to fetch is {}", componentTypeEnum.name().toLowerCase(), + leftComponentsForSearch.size()); + + // get components from cassandra cache and filter each component + Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> result = getComponents( + leftComponentsForSearch, filterFieldsFunc); + + if (result.isLeft()) { + // add inmemory components to the valid components(not dirty) + List<Component> foundComponents = result.left().value().getLeft(); + if (componentsFromMemory != null) { + foundComponents.addAll(componentsFromMemory); + } + if (catalogInMemoryEnabled) { + updateCatalogInMemoryCacheWithCertified(foundComponents, componentTypeEnum); + } + } + + return result; + } + + /** + * @param components + * - Map of <componentUniqueId, last update date> + * @param filterFieldsFunc + * @return + */ + public Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponents(Map<String, Long> components, + Function<List<Component>, List<Component>> filterFieldsFunc) { + + if (!isEnabled()) { + log.debug(COMPONENT_CACHE_IS_DISABLED); + return Either.right(ActionStatus.NOT_ALLOWED); + } + + Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> componentsFull = getComponentsFull( + components); + + if (componentsFull.isRight()) { + return Either.right(componentsFull.right().value()); + } + + ImmutablePair<List<Component>, Set<String>> immutablePair = componentsFull.left().value(); + List<Component> foundResources = immutablePair.left; + Set<String> notFoundResources = immutablePair.right; + + List<Component> filterdFoundResources = filterFieldsFunc.apply(foundResources); + + ImmutablePair<List<Component>, Set<String>> result = new ImmutablePair<>( + filterdFoundResources, notFoundResources); + + return Either.left(result); + + } + + /** + * get the component and its modification time from cache + * + * @param componentUid + * @param filterFieldsFunc + * @return + */ + public Either<ImmutablePair<Component, Long>, ActionStatus> getComponentAndTime(String componentUid, + Function<Component, Component> filterFieldsFunc) { + + Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> componentFromCache = getComponentFromCache( + componentUid, null, filterFieldsFunc); + + if (componentFromCache.isRight()) { + return Either.right(componentFromCache.right().value()); + } + + ImmutablePair<Component, ComponentCacheData> immutablePair = componentFromCache.left().value(); + + ImmutablePair<Component, Long> result = new ImmutablePair<>(immutablePair.left, + immutablePair.right.getModificationTime().getTime()); + + return Either.left(result); + } + + private Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> getComponentFromCache( + String componentUid, Long lastModificationTime, Function<Component, Component> filterFieldsFunc) { + if (!isEnabled()) { + return Either.right(ActionStatus.NOT_ALLOWED); + } + + Either<ComponentCacheData, ActionStatus> componentRes = componentCassandraDao.getComponent(componentUid); + + if (componentRes.isRight()) { + return Either.right(componentRes.right().value()); + } + + ComponentCacheData componentCacheData = componentRes.left().value(); + + if (lastModificationTime != null) { + long cacheCompModificationTime = componentCacheData.getModificationTime().getTime(); + if (lastModificationTime != cacheCompModificationTime) { + log.debug( + "Component {} found in cache but its modification time {} does not match to the timestamp in cache {}.", + componentUid, lastModificationTime, cacheCompModificationTime); + return Either.right(ActionStatus.INVALID_CONTENT); + } + } + + Either<? extends Component, Boolean> convertRes = convertComponentCacheToComponent(componentCacheData); + if (convertRes.isRight()) { + return Either.right(ActionStatus.CONVERT_COMPONENT_ERROR); + } + + Component component = convertRes.left().value(); + + Component filteredComponent = component; + if (filterFieldsFunc != null) { + filteredComponent = filterFieldsFunc.apply(component); + } + + ImmutablePair<Component, ComponentCacheData> result = new ImmutablePair<>( + filteredComponent, componentCacheData); + + return Either.left(result); + } + + public ActionStatus deleteComponentFromCache(String id) { + if (!isEnabled()) { + return ActionStatus.NOT_ALLOWED; + } + CassandraOperationStatus status = this.componentCassandraDao.deleteComponent(id); + if (CassandraOperationStatus.OK.equals(status)) { + return ActionStatus.OK; + } else { + log.debug("delete component failed with error {}", status); + return ActionStatus.GENERAL_ERROR; + } + } } |