re base code
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / cache / ComponentCache.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.model.cache;
22
23 import fj.data.Either;
24 import org.apache.commons.lang3.tuple.ImmutablePair;
25 import org.apache.commons.lang3.tuple.ImmutableTriple;
26 import org.openecomp.sdc.be.config.BeEcompErrorManager;
27 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
28 import org.openecomp.sdc.be.config.Configuration;
29 import org.openecomp.sdc.be.config.Configuration.ApplicationL1CacheCatalogInfo;
30 import org.openecomp.sdc.be.config.Configuration.ApplicationL2CacheConfig;
31 import org.openecomp.sdc.be.config.ConfigurationManager;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
34 import org.openecomp.sdc.be.dao.cassandra.ComponentCassandraDao;
35 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
36 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
37 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
38 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
39 import org.openecomp.sdc.be.model.*;
40 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
41 import org.openecomp.sdc.be.resources.data.ComponentCacheData;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43 import org.openecomp.sdc.common.util.SerializationUtils;
44 import org.openecomp.sdc.common.util.ZipUtil;
45 import org.springframework.beans.factory.annotation.Autowired;
46
47 import javax.annotation.PostConstruct;
48 import java.io.IOException;
49 import java.util.*;
50 import java.util.concurrent.locks.Lock;
51 import java.util.concurrent.locks.ReentrantReadWriteLock;
52 import java.util.function.Function;
53 import java.util.stream.Collectors;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Set;
57 import java.util.concurrent.locks.Lock;
58 import java.util.concurrent.locks.ReentrantReadWriteLock;
59 import java.util.function.Function;
60 import java.util.stream.Collectors;
61
62 @org.springframework.stereotype.Component("component-cache")
63 public class ComponentCache {
64
65     private static final String COMPONENT_CACHE_IS_DISABLED = "Component Cache is disabled";
66
67         private static final Logger log = Logger.getLogger(ComponentCache.class);
68
69     @Autowired
70     ComponentCassandraDao componentCassandraDao;
71
72     @Autowired
73     ToscaOperationFacade toscaOperationFacade;
74
75     private Map<ComponentTypeEnum, Map<String, Component>> catalogInMemoryCache = new HashMap<>();
76     private final ReentrantReadWriteLock rwCatalogLock = new ReentrantReadWriteLock();
77     private final Lock rCatalogLock = rwCatalogLock.readLock();
78     private final Lock wCatalogLock = rwCatalogLock.writeLock();
79
80     boolean enabled = true;
81     int catalogInMemorySizePerResource = 300;
82     int catalogInMemorySizePerService = 200;
83     int catalogInMemorySizePerProduct = 100;
84     boolean catalogInMemoryEnabled = true;
85     Map<ComponentTypeEnum, Integer> limitMemoryCatalogSizePerType = new HashMap<>();
86
87     @PostConstruct
88     public void init() {
89
90         Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration();
91         if (configuration != null) {
92             ApplicationL2CacheConfig applicationL2Cache = configuration.getApplicationL2Cache();
93             if (applicationL2Cache != null) {
94                 this.enabled = applicationL2Cache.isEnabled();
95
96                 ApplicationL1CacheCatalogInfo catalog = applicationL2Cache.getCatalogL1Cache();
97                 if (catalog != null) {
98                     catalogInMemoryEnabled = catalog.getEnabled();
99                     catalogInMemorySizePerResource = catalog.getResourcesSizeInCache();
100                     catalogInMemorySizePerService = catalog.getServicesSizeInCache();
101                     catalogInMemorySizePerProduct = catalog.getProductsSizeInCache();
102                 }
103             }
104         }
105
106         ComponentTypeEnum[] typesForCache = { ComponentTypeEnum.RESOURCE, ComponentTypeEnum.SERVICE,
107                 ComponentTypeEnum.PRODUCT };
108         for (ComponentTypeEnum typeEnum : typesForCache) {
109             Map<String, Component> map = new HashMap<>();
110             catalogInMemoryCache.put(typeEnum, map);
111         }
112
113         limitMemoryCatalogSizePerType.put(ComponentTypeEnum.RESOURCE, catalogInMemorySizePerResource);
114         limitMemoryCatalogSizePerType.put(ComponentTypeEnum.SERVICE, catalogInMemorySizePerService);
115         limitMemoryCatalogSizePerType.put(ComponentTypeEnum.PRODUCT, catalogInMemorySizePerProduct);
116     }
117
118     public boolean isEnabled() {
119         return enabled;
120     }
121
122     public void setEnabled(boolean enabled) {
123         this.enabled = enabled;
124     }
125
126     public Either<Component, ActionStatus> getComponent(String componentUid, Long lastModificationTime,
127             Function<Component, Component> filterFieldsFunc) {
128
129         Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> componentFromCache = getComponentFromCache(
130                 componentUid, lastModificationTime, filterFieldsFunc);
131
132         if (componentFromCache.isRight()) {
133             return Either.right(componentFromCache.right().value());
134         }
135
136         return Either.left(componentFromCache.left().value().left);
137
138     }
139
140     public Either<List<ComponentCacheData>, ActionStatus> getAllComponentIdTimeAndType() {
141         if (!isEnabled()) {
142             return Either.right(ActionStatus.NOT_ALLOWED);
143         }
144
145         return componentCassandraDao
146                 .getAllComponentIdTimeAndType();
147
148     }
149
150     /**
151      * get components for catalog
152      *
153      * @param components
154      * @param componentTypeEnum
155      * @return
156      */
157     @Deprecated
158     public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsForCatalog(
159             Set<String> components, ComponentTypeEnum componentTypeEnum) {
160
161         if (!isEnabled()) {
162             log.debug("In getComponentsForCatalog for type {}. Cache is disabled.",
163                     componentTypeEnum.name().toLowerCase());
164             return Either.right(ActionStatus.NOT_ALLOWED);
165         }
166         log.debug("In getComponentsForCatalog for type {}", componentTypeEnum.name().toLowerCase());
167
168         Function<List<Component>, List<Component>> filterFieldsFunc = this::filterForCatalog;
169
170         Set<String> leftComponentsForSearch = new HashSet<>();
171         leftComponentsForSearch.addAll(components);
172
173         // get components from inmemory cache
174         List<Component> componentsFromMemory = null;
175         if (catalogInMemoryEnabled) {
176             componentsFromMemory = getDataFromInMemoryCache(components, componentTypeEnum);
177             log.debug("The number of components of type {} fetched from memory is {}",
178                     componentTypeEnum.name().toLowerCase(),
179                     componentsFromMemory == null ? 0 : componentsFromMemory.size());
180             if (componentsFromMemory != null) {
181                 componentsFromMemory.forEach(p -> leftComponentsForSearch.remove(p.getUniqueId()));
182             }
183         } else {
184             log.debug("Catalog InMemory cache is disabled");
185         }
186
187         log.debug("Number of components from type {} needed to fetch is {}", componentTypeEnum.name().toLowerCase(),
188                 leftComponentsForSearch.size());
189
190         // get components from cassandra cache and filter each component
191         Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> result = getComponents(
192                 leftComponentsForSearch, filterFieldsFunc);
193
194         if (result.isLeft()) {
195             // add inmemory components to the valid components(not dirty)
196             List<Component> foundComponents = result.left().value().getLeft();
197             if (componentsFromMemory != null) {
198                 foundComponents.addAll(componentsFromMemory);
199             }
200             if (catalogInMemoryEnabled) {
201                 updateCatalogInMemoryCacheWithCertified(foundComponents, componentTypeEnum);
202             }
203         }
204
205         return result;
206     }
207
208     /**
209      * @param foundComponents
210      * @param componentTypeEnum
211      */
212     private void updateCatalogInMemoryCacheWithCertified(List<Component> foundComponents,
213             ComponentTypeEnum componentTypeEnum) {
214
215         try {
216             wCatalogLock.lock();
217
218             long start = System.currentTimeMillis();
219             Map<String, Component> map = catalogInMemoryCache.get(componentTypeEnum);
220             int mapSizeBefore = map.size();
221             map.clear();
222             Map<String, Component> collect = foundComponents.stream()
223                     .filter(p -> p.getLifecycleState() == LifecycleStateEnum.CERTIFIED)
224                     .limit(limitMemoryCatalogSizePerType.get(componentTypeEnum))
225                     .collect(Collectors.toMap(Component::getUniqueId, p -> p));
226             map.putAll(collect);
227             log.debug(
228                     "Size of in memory cache for catalog {}(certified only): Before {}, After {}. Replacement Time is {} ms.",
229                     componentTypeEnum.name().toLowerCase(), mapSizeBefore, map.size(),
230                     System.currentTimeMillis() - start);
231         } finally {
232             wCatalogLock.unlock();
233         }
234
235     }
236
237     private List<Component> getDataFromInMemoryCache(Set<String> components, ComponentTypeEnum componentTypeEnum) {
238         List<Component> foundComponents = new ArrayList<>();
239
240         try {
241
242             rCatalogLock.lock();
243
244             Map<String, Component> map = catalogInMemoryCache.get(componentTypeEnum);
245             for (String compUid : components) {
246                 Component component = map.get(compUid);
247                 if (component != null) {
248                     foundComponents.add(component);
249                 }
250             }
251
252         } finally {
253             rCatalogLock.unlock();
254         }
255
256         return foundComponents;
257     }
258
259     /**
260      *
261      * get full components from cassandra. On each component apply filter
262      * function in order to remove unused members
263      *
264      * @param components
265      * @param filterFieldsFunc
266      * @return <found components, found dirty components, not found components
267      *         list> or Error
268      */
269     public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponents(
270             Set<String> components, Function<List<Component>, List<Component>> filterFieldsFunc) {
271
272         if (!isEnabled()) {
273             log.debug(COMPONENT_CACHE_IS_DISABLED);
274             return Either.right(ActionStatus.NOT_ALLOWED);
275         }
276
277         Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> componentsFull = getComponentsFull(
278                 components);
279
280         if (componentsFull.isRight()) {
281             return Either.right(componentsFull.right().value());
282         }
283
284         ImmutableTriple<List<Component>, List<Component>, Set<String>> immutableTriple = componentsFull.left().value();
285         List<Component> foundResources = immutableTriple.left;
286         List<Component> foundDirtyResources = immutableTriple.middle;
287         Set<String> notFoundResources = immutableTriple.right;
288
289         List<Component> filterdFoundResources = filterFieldsFunc.apply(foundResources);
290         List<Component> filterdFoundDirtyResources = filterFieldsFunc.apply(foundDirtyResources);
291
292         ImmutableTriple<List<Component>, List<Component>, Set<String>> result = new ImmutableTriple<>(
293                 filterdFoundResources, filterdFoundDirtyResources, notFoundResources);
294
295         return Either.left(result);
296
297     }
298
299     public Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsForLeftPanel(
300             ComponentTypeEnum componentTypeEnum, String internalComponentType, Set<String> filteredResources) {
301
302         log.debug("In getComponentsForLeftPanel componentTypeEnum = {}, internalComponentType = {}",
303                 componentTypeEnum, internalComponentType);
304
305         Function<List<Component>, List<Component>> filterFieldsFunc = this::filterForLeftPanel;
306
307         return getComponents(filteredResources, filterFieldsFunc);
308
309     }
310
311     private List<Component> filterForLeftPanel(List<Component> components) {
312
313         List<Component> result = new ArrayList<>();
314         if (components != null) {
315             components.forEach(p -> result.add(filterFieldsForLeftPanel(p)));
316         }
317
318         return result;
319     }
320
321     private List<Component> filterForCatalog(List<Component> components) {
322
323         List<Component> result = new ArrayList<>();
324         if (components != null) {
325             components.forEach(p -> result.add(filterFieldsForCatalog(p)));
326         }
327
328         return result;
329     }
330
331     private Component filterFieldsForLeftPanel(Component component) {
332
333         Component result = null;
334         ComponentTypeEnum componentTypeEnum = component.getComponentType();
335         switch (componentTypeEnum) {
336         case RESOURCE:
337             result = new Resource();
338             copyFieldsForLeftPanel(component, result);
339             break;
340         case SERVICE:
341             result = new Service();
342             copyFieldsForLeftPanel(component, result);
343             break;
344         default:
345             break;
346         }
347
348         return result;
349     }
350
351     private Component filterFieldsForCatalog(Component component) {
352
353         Component result = null;
354         ComponentTypeEnum componentTypeEnum = component.getComponentType();
355         switch (componentTypeEnum) {
356         case RESOURCE:
357             result = new Resource();
358             copyFieldsForCatalog(component, result);
359             break;
360         case SERVICE:
361             result = new Service();
362             copyFieldsForCatalog(component, result);
363             break;
364         case PRODUCT:
365             result = new Product();
366             copyFieldsForCatalog(component, result);
367             break;
368         default:
369             break;
370         }
371
372         return result;
373     }
374
375     /**
376      * Copy relevant fields to the filtered component for left panel
377      *
378      * @param component
379      * @param filteredComponent
380      */
381     private void copyFieldsForLeftPanel(Component component, Component filteredComponent) {
382
383         ComponentTypeEnum componentTypeEnum = component.getComponentType();
384         filteredComponent.setCategories(component.getCategories());
385         filteredComponent.setComponentType(component.getComponentType());
386         if (ComponentTypeEnum.RESOURCE.equals(component.getComponentType())
387                 && ResourceTypeEnum.VL.equals(((ResourceMetadataDataDefinition) component
388                         .getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType())) {
389             filteredComponent.setCapabilities(component.getCapabilities());
390             filteredComponent.setRequirements(component.getRequirements());
391         }
392         filteredComponent.setVersion(component.getVersion());
393         filteredComponent.setDescription(component.getDescription());
394         filteredComponent.setUniqueId(component.getUniqueId());
395         filteredComponent.setIcon(component.getIcon());
396         filteredComponent.setTags(component.getTags());
397         filteredComponent.setLifecycleState(component.getLifecycleState());
398         filteredComponent.setInvariantUUID(component.getInvariantUUID());
399         filteredComponent.setUUID(component.getUUID());
400         filteredComponent.setSystemName(component.getSystemName());
401         filteredComponent.setName(component.getName());
402
403         if (componentTypeEnum == ComponentTypeEnum.RESOURCE) {
404             Resource resource = (Resource) component;
405             Resource filteredResource = (Resource) filteredComponent;
406             filteredResource.setToscaResourceName(resource.getToscaResourceName());
407             filteredResource.setResourceType(resource.getResourceType());
408         }
409     }
410
411     private void copyFieldsForCatalog(Component component, Component filteredComponent) {
412
413         ComponentTypeEnum componentTypeEnum = component.getComponentType();
414         filteredComponent.setCategories(component.getCategories());
415         filteredComponent.setComponentType(component.getComponentType());
416         filteredComponent.setVersion(component.getVersion());
417         filteredComponent.setDescription(component.getDescription());
418         filteredComponent.setUniqueId(component.getUniqueId());
419         filteredComponent.setIcon(component.getIcon());
420         filteredComponent.setTags(component.getTags());
421         filteredComponent.setLifecycleState(component.getLifecycleState());
422         filteredComponent.setSystemName(component.getSystemName());
423         filteredComponent.setName(component.getName());
424         filteredComponent.setLastUpdateDate(component.getLastUpdateDate());
425
426         if (componentTypeEnum == ComponentTypeEnum.RESOURCE) {
427             Resource resource = (Resource) component;
428             Resource filteredResource = (Resource) filteredComponent;
429             filteredResource.setToscaResourceName(resource.getToscaResourceName());
430             filteredResource.setResourceType(resource.getResourceType());
431         } else if (componentTypeEnum == ComponentTypeEnum.SERVICE) {
432             Service service = (Service) component;
433             Service filteredService = (Service) filteredComponent;
434             filteredService.setDistributionStatus(service.getDistributionStatus());
435         }
436     }
437
438     /**
439      * get components from cache of a given list ou unique ids.
440      *
441      * for each component data from cassandra, unzip the data if needed and
442      * deserialize the unzipped data to java object(Component).
443      *
444      * @param filteredResources
445      * @return ImmutableTripple or ActionStatus. | |-- components |-- dirty
446      *         components - components with dirty flag = true. |-- set of non
447      *         cached components
448      *
449      */
450     private Either<ImmutableTriple<List<Component>, List<Component>, Set<String>>, ActionStatus> getComponentsFull(
451             Set<String> filteredResources) {
452
453         if (!isEnabled()) {
454             log.debug(COMPONENT_CACHE_IS_DISABLED);
455             return Either.right(ActionStatus.NOT_ALLOWED);
456         }
457
458         List<Component> foundResources = new LinkedList<>();
459         List<Component> foundDirtyResources = new LinkedList<>();
460         Set<String> notFoundResources = new HashSet<>();
461         ImmutableTriple<List<Component>, List<Component>, Set<String>> result = new ImmutableTriple<>(
462                 foundResources, foundDirtyResources, notFoundResources);
463
464         long cassandraFetchStart = System.currentTimeMillis();
465         List<String> uidsList = new ArrayList<>();
466         uidsList.addAll(filteredResources);
467         Either<List<ComponentCacheData>, ActionStatus> componentsFromCache = componentCassandraDao
468                 .getComponents(uidsList);
469
470         long cassandraFetchEnd = System.currentTimeMillis();
471         log.debug("Fetch time from cassandara of all components took {} ms",
472                 (cassandraFetchEnd - cassandraFetchStart));
473         if (componentsFromCache.isRight()) {
474             BeEcompErrorManager.getInstance().logInternalFlowError("FetchFromCache",
475                     "Failed to fetch components from cache", ErrorSeverity.ERROR);
476             return Either.right(componentsFromCache.right().value());
477         }
478
479         List<ComponentCacheData> list = componentsFromCache.left().value();
480         log.debug("Number of components fetched from cassandra is {}", (list == null ? 0 : list.size()));
481         if (list != null && !list.isEmpty()) {
482
483             List<ComponentCacheData> filteredData = list.stream().filter(p -> filteredResources.contains(p.getId()))
484                     .collect(Collectors.toList());
485             log.debug("Number of components filterd is {}", filteredData == null ? 0 : filteredData.size());
486
487             if (filteredData != null) {
488                 long desStart = System.currentTimeMillis();
489
490                 for (ComponentCacheData componentCacheData : filteredData) {
491
492                     log.debug("Process uid {} from cache", componentCacheData.getId());
493
494                     String compUid = componentCacheData.getId();
495
496                     Either<? extends Component, Boolean> deserializeExt = convertComponentCacheToComponent(
497                             componentCacheData);
498
499                     if (deserializeExt.isLeft()) {
500                         Component component = deserializeExt.left().value();
501                         if (!componentCacheData.getIsDirty()) {
502                             foundResources.add(component);
503                         } else {
504                             foundDirtyResources.add(component);
505                         }
506                     } else {
507                         notFoundResources.add(compUid);
508                     }
509
510                 }
511                 long desEnd = System.currentTimeMillis();
512                 log.debug("Deserialization and unzip of {} components took {} ms", filteredData.size(),
513                         (desEnd - desStart));
514             }
515         }
516         List<String> foundResourcesUid = foundResources.stream().map(Component::getUniqueId).collect(Collectors.toList());
517         List<String> foundDirtyResourcesUid = foundDirtyResources.stream().map(Component::getUniqueId)
518                 .collect(Collectors.toList());
519         log.debug("Number of processed components from cache is {}",
520                 (foundResourcesUid.size() + foundDirtyResourcesUid.size()));
521         Set<String> notCachedResources = filteredResources.stream()
522                 .filter(p -> !foundResourcesUid.contains(p) && !foundDirtyResourcesUid.contains(p))
523                 .collect(Collectors.toSet());
524         notFoundResources.addAll(notCachedResources);
525
526         if (log.isDebugEnabled()) {
527             log.debug("Number of components fetched is {}", foundResources.size());
528             log.debug("Number of components fetched dirty is {}", foundDirtyResources.size());
529             log.debug("Number of components non cached is {}", notCachedResources.size());
530         }
531
532         return Either.left(result);
533     }
534
535     private Either<? extends Component, Boolean> convertComponentCacheToComponent(
536             ComponentCacheData componentCacheData) {
537
538         String compUid = componentCacheData.getId();
539
540         byte[] dataAsArray = componentCacheData.getDataAsArray();
541
542         if (componentCacheData.getIsZipped()) {
543             long startUnzip = System.nanoTime();
544             dataAsArray = ZipUtil.unzip(dataAsArray);
545             long endUnzip = System.nanoTime();
546             log.trace("Unzip component {} took {} microsecond", compUid, (endUnzip - startUnzip) / 1000);
547         }
548
549         long startDes = System.nanoTime();
550
551         Either<? extends Component, Boolean> deserializeExt = deserializeComponent(componentCacheData, dataAsArray);
552
553         long endDes = System.nanoTime();
554         log.trace("Deserialize component {} took {} microsecond", compUid, (endDes - startDes) / 1000);
555         return deserializeExt;
556     }
557
558     private Either<? extends Component, Boolean> deserializeComponent(ComponentCacheData componentCacheData,
559             byte[] dataAsArray) {
560         String type = componentCacheData.getType();
561         NodeTypeEnum typeEnum = NodeTypeEnum.getByNameIgnoreCase(type);
562
563         Either<? extends Component, Boolean> deserializeExt = Either.right(false);
564         switch (typeEnum) {
565         case Resource:
566             deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Resource.class, componentCacheData.getId());
567             break;
568         case Service:
569             deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Service.class, componentCacheData.getId());
570             break;
571         case Product:
572             deserializeExt = SerializationUtils.deserializeExt(dataAsArray, Product.class, componentCacheData.getId());
573             break;
574         default:
575             break;
576         }
577         return deserializeExt;
578     }
579
580     public Either<Component, ActionStatus> getComponent(String componentUid) {
581
582         return getComponent(componentUid, null, Function.identity());
583
584     }
585
586     private boolean saveComponent(String componentUid, Long lastModificationTime, NodeTypeEnum nodeTypeEnum,
587             Component component) {
588
589         log.trace("Going to save component {} of type {} in cache", componentUid, nodeTypeEnum.name().toLowerCase());
590
591         boolean result = false;
592
593         Either<byte[], Boolean> serializeExt = SerializationUtils.serializeExt(component);
594         if (serializeExt.isLeft()) {
595             byte[] serializedData = serializeExt.left().value();
596             byte[] zipBytes;
597             try {
598                 zipBytes = ZipUtil.zipBytes(serializedData);
599                 ComponentCacheData componentCacheData = new ComponentCacheData();
600                 componentCacheData.setDataAsArray(zipBytes);
601                 componentCacheData.setIsZipped(true);
602                 componentCacheData.setId(componentUid);
603                 componentCacheData.setModificationTime(new Date(lastModificationTime));
604                 componentCacheData.setType(component.getComponentType().name().toLowerCase());
605
606                 CassandraOperationStatus status = componentCassandraDao.saveComponent(componentCacheData);
607
608                 if (status == CassandraOperationStatus.OK) {
609                     result = true;
610                 }
611
612             } catch (IOException e) {
613                 log.debug("Failed to prepare component {} of type {} for cache", componentUid,
614                         nodeTypeEnum.name().toLowerCase());
615                 if (log.isTraceEnabled()) {
616                     log.trace("Failed to prepare component {} of type {} for cache",componentUid,nodeTypeEnum.name().toLowerCase());
617                 }
618             }
619         } else {
620             log.debug("Failed to serialize component {} of type {} for cache", componentUid,
621                     nodeTypeEnum.name().toLowerCase());
622         }
623         return result;
624     }
625
626     public boolean setComponent(Component component, NodeTypeEnum nodeTypeEnum) {
627
628         boolean result = false;
629
630         if (!isEnabled()) {
631             log.debug(COMPONENT_CACHE_IS_DISABLED);
632             return false;
633         }
634
635         String componentUid = component.getUniqueId();
636         Long lastUpdateDate = component.getLastUpdateDate();
637
638         result = saveComponent(componentUid, lastUpdateDate, nodeTypeEnum, component);
639
640         return result;
641
642     }
643
644     /**
645      * get components from cache of a given list ou unique ids.
646      *
647      * for each component data from cassandra, unzip the data if needed and
648      * deserialize the unzipped data to java object(Component).
649      *
650      * @param filteredResources
651      * @return ImmutableTripple or ActionStatus. | |-- components |-- set of non
652      *         cached components
653      *
654      */
655     private Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponentsFull(
656             Map<String, Long> filteredResources) {
657
658         if (!isEnabled()) {
659             log.debug(COMPONENT_CACHE_IS_DISABLED);
660             return Either.right(ActionStatus.NOT_ALLOWED);
661         }
662
663         List<Component> foundResources = new LinkedList<>();
664         Set<String> notFoundResources = new HashSet<>();
665         ImmutablePair<List<Component>, Set<String>> result = new ImmutablePair<>(
666                 foundResources, notFoundResources);
667
668         long cassandraFetchStart = System.currentTimeMillis();
669
670         Either<ImmutablePair<List<ComponentCacheData>, Set<String>>, ActionStatus> componentsFromCache = componentCassandraDao
671                 .getComponents(filteredResources);
672
673         long cassandraFetchEnd = System.currentTimeMillis();
674         log.debug("Fetch time from cassandara of all components took {} ms",
675                 (cassandraFetchEnd - cassandraFetchStart));
676         if (componentsFromCache.isRight()) {
677             BeEcompErrorManager.getInstance().logInternalFlowError("FetchFromCache",
678                     "Failed to fetch components from cache", ErrorSeverity.ERROR);
679             return Either.right(componentsFromCache.right().value());
680         }
681
682         ImmutablePair<List<ComponentCacheData>, Set<String>> immutablePair = componentsFromCache.left().value();
683         List<ComponentCacheData> list = immutablePair.getLeft();
684         log.debug("Number of components fetched from cassandra is {}", (list == null ? 0 : list.size()));
685         if (list != null && !list.isEmpty()) {
686
687             log.debug("Number of components filterd is {}", list == null ? 0 : list.size());
688
689             if (list != null) {
690                 long desStart = System.currentTimeMillis();
691
692                 for (ComponentCacheData componentCacheData : list) {
693
694                     log.debug("Process uid {} from cache", componentCacheData.getId());
695
696                     String compUid = componentCacheData.getId();
697
698                     Either<? extends Component, Boolean> deserializeExt = convertComponentCacheToComponent(
699                             componentCacheData);
700
701                     if (deserializeExt.isLeft()) {
702                         Component component = deserializeExt.left().value();
703                         foundResources.add(component);
704                     } else {
705                         notFoundResources.add(compUid);
706                     }
707
708                 }
709                 long desEnd = System.currentTimeMillis();
710                 log.debug("Deserialization and unzip of {} components took {} ms", list.size(), (desEnd - desStart));
711             }
712         }
713         log.debug("Number of processed components from cache is {}", foundResources.size());
714
715         Set<String> notFoundInCache = immutablePair.getRight();
716         notFoundResources.addAll(notFoundInCache);
717
718         if (log.isDebugEnabled()) {
719             log.debug("Number of components fetched is {}", foundResources.size());
720             log.debug("Number of components non cached is {}", notFoundResources.size());
721         }
722
723         return Either.left(result);
724     }
725
726     /**
727      * get components for catalog
728      *
729      * @param components
730      * @param componentTypeEnum
731      * @return
732      */
733     public Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponentsForCatalog(
734             Map<String, Long> components, ComponentTypeEnum componentTypeEnum) {
735
736         if (!isEnabled()) {
737             log.debug("In getComponentsForCatalog for type {}. Cache is disabled.",
738                     componentTypeEnum.name().toLowerCase());
739             return Either.right(ActionStatus.NOT_ALLOWED);
740         }
741         log.debug("In getComponentsForCatalog for type {}", componentTypeEnum.name().toLowerCase());
742
743         Function<List<Component>, List<Component>> filterFieldsFunc = this::filterForCatalog;
744
745         Map<String, Long> leftComponentsForSearch = new HashMap<>();
746         leftComponentsForSearch.putAll(components);
747
748         // get components from inmemory cache
749         List<Component> componentsFromMemory = null;
750         if (catalogInMemoryEnabled) {
751             componentsFromMemory = getDataFromInMemoryCache(components.keySet(), componentTypeEnum);
752             log.debug("The number of components of type {} fetched from memory is {}",
753                     componentTypeEnum.name().toLowerCase(),
754                     componentsFromMemory == null ? 0 : componentsFromMemory.size());
755             if (componentsFromMemory != null) {
756                 List<String> ignoredComponents = new ArrayList<>();
757                 for (Component componentFromMem : componentsFromMemory) {
758                     if (componentFromMem.getLastUpdateDate().longValue() != components
759                             .get(componentFromMem.getUniqueId()).longValue()) {
760                         // Ignore the component from memory
761                         ignoredComponents.add(componentFromMem.getUniqueId());
762                     }
763                 }
764
765                 log.debug("Number of components from type {} ignored from memory cache is {}",
766                         componentTypeEnum.name().toLowerCase(), ignoredComponents.size());
767                 // remove from memory result the components which are not valid
768                 componentsFromMemory = componentsFromMemory.stream()
769                                                            .filter(p -> !ignoredComponents.contains(p.getUniqueId())).collect(Collectors.toList());
770                 // Remove from leftComponentsForSearch the valid components from
771                 // memory
772                 componentsFromMemory.forEach(p -> leftComponentsForSearch.remove(p.getUniqueId()));
773
774             }
775         } else {
776             log.debug("Catalog InMemory cache is disabled");
777         }
778
779         log.debug("Number of components from type {} needed to fetch is {}", componentTypeEnum.name().toLowerCase(),
780                 leftComponentsForSearch.size());
781
782         // get components from cassandra cache and filter each component
783         Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> result = getComponents(
784                 leftComponentsForSearch, filterFieldsFunc);
785
786         if (result.isLeft()) {
787             // add inmemory components to the valid components(not dirty)
788             List<Component> foundComponents = result.left().value().getLeft();
789             if (componentsFromMemory != null) {
790                 foundComponents.addAll(componentsFromMemory);
791             }
792             if (catalogInMemoryEnabled) {
793                 updateCatalogInMemoryCacheWithCertified(foundComponents, componentTypeEnum);
794             }
795         }
796
797         return result;
798     }
799
800     /**
801      * @param components
802      *            - Map of <componentUniqueId, last update date>
803      * @param filterFieldsFunc
804      * @return
805      */
806     public Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> getComponents(Map<String, Long> components,
807             Function<List<Component>, List<Component>> filterFieldsFunc) {
808
809         if (!isEnabled()) {
810             log.debug(COMPONENT_CACHE_IS_DISABLED);
811             return Either.right(ActionStatus.NOT_ALLOWED);
812         }
813
814         Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> componentsFull = getComponentsFull(
815                 components);
816
817         if (componentsFull.isRight()) {
818             return Either.right(componentsFull.right().value());
819         }
820
821         ImmutablePair<List<Component>, Set<String>> immutablePair = componentsFull.left().value();
822         List<Component> foundResources = immutablePair.left;
823         Set<String> notFoundResources = immutablePair.right;
824
825         List<Component> filterdFoundResources = filterFieldsFunc.apply(foundResources);
826
827         ImmutablePair<List<Component>, Set<String>> result = new ImmutablePair<>(
828                 filterdFoundResources, notFoundResources);
829
830         return Either.left(result);
831
832     }
833
834     /**
835      * get the component and its modification time from cache
836      *
837      * @param componentUid
838      * @param filterFieldsFunc
839      * @return
840      */
841     public Either<ImmutablePair<Component, Long>, ActionStatus> getComponentAndTime(String componentUid,
842             Function<Component, Component> filterFieldsFunc) {
843
844         Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> componentFromCache = getComponentFromCache(
845                 componentUid, null, filterFieldsFunc);
846
847         if (componentFromCache.isRight()) {
848             return Either.right(componentFromCache.right().value());
849         }
850
851         ImmutablePair<Component, ComponentCacheData> immutablePair = componentFromCache.left().value();
852
853         ImmutablePair<Component, Long> result = new ImmutablePair<>(immutablePair.left,
854                 immutablePair.right.getModificationTime().getTime());
855
856         return Either.left(result);
857     }
858
859     private Either<ImmutablePair<Component, ComponentCacheData>, ActionStatus> getComponentFromCache(
860             String componentUid, Long lastModificationTime, Function<Component, Component> filterFieldsFunc) {
861         if (!isEnabled()) {
862             return Either.right(ActionStatus.NOT_ALLOWED);
863         }
864
865         Either<ComponentCacheData, ActionStatus> componentRes = componentCassandraDao.getComponent(componentUid);
866
867         if (componentRes.isRight()) {
868             return Either.right(componentRes.right().value());
869         }
870
871         ComponentCacheData componentCacheData = componentRes.left().value();
872
873         if (lastModificationTime != null) {
874             long cacheCompModificationTime = componentCacheData.getModificationTime().getTime();
875             if (lastModificationTime != cacheCompModificationTime) {
876                 log.debug(
877                         "Component {} found in cache but its modification time {} does not match to the timestamp in cache {}.",
878                         componentUid, lastModificationTime, cacheCompModificationTime);
879                 return Either.right(ActionStatus.INVALID_CONTENT);
880             }
881         }
882
883         Either<? extends Component, Boolean> convertRes = convertComponentCacheToComponent(componentCacheData);
884         if (convertRes.isRight()) {
885             return Either.right(ActionStatus.CONVERT_COMPONENT_ERROR);
886         }
887
888         Component component = convertRes.left().value();
889
890         Component filteredComponent = component;
891         if (filterFieldsFunc != null) {
892             filteredComponent = filterFieldsFunc.apply(component);
893         }
894
895         ImmutablePair<Component, ComponentCacheData> result = new ImmutablePair<>(
896                 filteredComponent, componentCacheData);
897
898         return Either.left(result);
899     }
900
901     public ActionStatus deleteComponentFromCache(String id) {
902         if (!isEnabled()) {
903             return ActionStatus.NOT_ALLOWED;
904         }
905         CassandraOperationStatus status = this.componentCassandraDao.deleteComponent(id);
906         if (CassandraOperationStatus.OK.equals(status)) {
907             return ActionStatus.OK;
908         } else {
909             log.debug("delete component failed with error {}", status);
910             return ActionStatus.GENERAL_ERROR;
911         }
912     }
913
914 }