aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java
diff options
context:
space:
mode:
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.java997
1 files changed, 997 insertions, 0 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
new file mode 100644
index 0000000000..6732adbdb1
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ComponentCache.java
@@ -0,0 +1,997 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model.cache;
+
+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.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.config.Configuration;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
+import org.openecomp.sdc.be.config.Configuration.ApplicationL1CacheCatalogInfo;
+import org.openecomp.sdc.be.config.Configuration.ApplicationL2CacheConfig;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
+import org.openecomp.sdc.be.dao.cassandra.ComponentCassandraDao;
+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.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.*;
+import org.openecomp.sdc.be.resources.data.ComponentCacheData;
+import org.openecomp.sdc.common.util.SerializationUtils;
+import org.openecomp.sdc.common.util.ZipUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import fj.data.Either;
+
+@org.springframework.stereotype.Component("component-cache")
+public class ComponentCache {
+
+ private static Logger logger = LoggerFactory.getLogger(ComponentCache.class.getName());
+
+ @javax.annotation.Resource
+ ComponentCassandraDao componentCassandraDao;
+
+ @javax.annotation.Resource
+ ResourceOperation resourceOperation;
+
+ @javax.annotation.Resource
+ ServiceOperation serviceOperation;
+
+ @javax.annotation.Resource
+ ProductOperation productOperation;
+
+ 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;
+
+ }
+
+ /**
+ * 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 (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);
+
+ Set<String> leftComponentsForSearch = new HashSet<>();
+ leftComponentsForSearch.addAll(components);
+
+ // get components from inmemory cache
+ List<Component> componentsFromMemory = null;
+ if (true == catalogInMemoryEnabled) {
+ componentsFromMemory = getDataFromInMemoryCache(components, componentTypeEnum);
+ logger.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 {
+ 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<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 (true == 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(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.setAllVersions(component.getAllVersions());
+ filteredComponent.setLifecycleState(component.getLifecycleState());
+ // filteredComponent.setHighestVersion(component.isHighestVersion());
+ 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.setAbstract(resource.isAbstract());
+ // filteredResource.setVendorName(resource.getVendorName());
+ // filteredResource.setVendorRelease(resource.getVendorRelease());
+ filteredResource.setResourceType(resource.getResourceType());
+ } else if (componentTypeEnum == ComponentTypeEnum.SERVICE) {
+ // Service service = (Service)component;
+ // Service filteredService = (Service)filteredComponent;
+ // filteredService.setDistributionStatus(service.getDistributionStatus());
+ }
+ }
+
+ 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.setAllVersions(component.getAllVersions());
+ filteredComponent.setLifecycleState(component.getLifecycleState());
+ // filteredComponent.setHighestVersion(component.isHighestVersion());
+ // filteredComponent.setInvariantUUID(component.getInvariantUUID());
+ 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.setAbstract(resource.isAbstract());
+ // filteredResource.setVendorName(resource.getVendorName());
+ // filteredResource.setVendorRelease(resource.getVendorRelease());
+ 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);
+
+ if (logger.isDebugEnabled()) {
+ 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;
+ }
+
+ ComponentOperation componentOperation = getComponentOperation(nodeTypeEnum);
+
+ if (componentOperation == null) {
+ return false;
+ }
+
+ Either<Component, StorageOperationStatus> either = componentOperation.getComponent(componentUid, false);
+ 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());
+ if (logger.isTraceEnabled()) {
+ logger.trace("Failed to prepare component " + componentUid + " of type "
+ + nodeTypeEnum.name().toLowerCase() + " for cache");
+ }
+ }
+ } 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;
+
+ }
+
+ private ComponentOperation getComponentOperation(NodeTypeEnum nodeTypeEnum) {
+ ComponentOperation componentOperation = null;
+ switch (nodeTypeEnum) {
+ case Resource:
+ componentOperation = resourceOperation;
+ break;
+ case Service:
+ componentOperation = serviceOperation;
+ break;
+ case Product:
+ componentOperation = productOperation;
+ break;
+ default:
+ break;
+ }
+ return componentOperation;
+ }
+
+ /**
+ * 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);
+
+ if (logger.isDebugEnabled()) {
+ 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 = this.componentCassandraDao.deleteComponent(id);
+ if (CassandraOperationStatus.OK.equals(status)) {
+ return ActionStatus.OK;
+ } else {
+ logger.debug("delete component failed with error {}", status);
+ return ActionStatus.GENERAL_ERROR;
+ }
+ }
+
+}