2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.model.cache;
23 import fj.data.Either;
24 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
25 import org.apache.commons.lang3.tuple.ImmutablePair;
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.ApplicationL1CacheConfig;
29 import org.openecomp.sdc.be.config.Configuration.ApplicationL1CacheInfo;
30 import org.openecomp.sdc.be.config.ConfigurationManager;
31 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
32 import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
33 import org.openecomp.sdc.be.model.DataTypeDefinition;
34 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
35 import org.openecomp.sdc.be.resources.data.DataTypeData;
36 import org.openecomp.sdc.common.log.wrappers.Logger;
37 import org.springframework.stereotype.Component;
39 import javax.annotation.PostConstruct;
40 import javax.annotation.PreDestroy;
41 import javax.annotation.Resource;
42 import java.util.HashMap;
43 import java.util.List;
45 import java.util.Map.Entry;
47 import java.util.concurrent.Executors;
48 import java.util.concurrent.ScheduledExecutorService;
49 import java.util.concurrent.ScheduledFuture;
50 import java.util.concurrent.TimeUnit;
51 import java.util.concurrent.locks.Lock;
52 import java.util.concurrent.locks.ReentrantReadWriteLock;
53 import java.util.stream.Collectors;
55 @Component("application-datatype-cache")
56 public class ApplicationDataTypeCache implements ApplicationCache<DataTypeDefinition>, Runnable {
58 private static final String APPLICATION_DATA_TYPES_CACHE = "ApplicationDataTypesCache";
59 private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
60 private final Lock r = rwl.readLock();
61 private final Lock w = rwl.writeLock();
63 private Map<String, DataTypeDefinition> data = new HashMap<>();
65 private ScheduledExecutorService scheduledPollingService = Executors.newScheduledThreadPool(1,
66 new BasicThreadFactory.Builder().namingPattern("ApplicationDataTypeCacheThread-%d").build());
67 ScheduledFuture<?> scheduledFuture = null;
69 private static final Logger log = Logger.getLogger(ApplicationDataTypeCache.class.getName());
71 private int firstRunDelayInSec = 30;
72 private int pollingIntervalInSec = 60;
75 private PropertyOperation propertyOperation;
80 ApplicationL1CacheConfig applicationL1CacheConfig = ConfigurationManager.getConfigurationManager()
81 .getConfiguration().getApplicationL1Cache();
82 if (applicationL1CacheConfig != null) {
83 if (applicationL1CacheConfig.getDatatypes() != null) {
84 ApplicationL1CacheInfo datatypesInfo = applicationL1CacheConfig.getDatatypes();
85 if (datatypesInfo.getEnabled()) {
86 Integer intervalInSec = datatypesInfo.getPollIntervalInSec();
87 if (intervalInSec != null) {
88 pollingIntervalInSec = intervalInSec;
90 Integer firstRunDelay = datatypesInfo.getFirstRunDelay();
91 if (firstRunDelay != null) {
92 firstRunDelayInSec = firstRunDelay;
94 log.trace("ApplicationDataTypesCache polling interval is {} seconds.", pollingIntervalInSec);
95 if (scheduledPollingService != null) {
96 log.debug("Start ApplicationDataTypeCache polling task. polling interval {} seconds",
97 pollingIntervalInSec);
98 scheduledFuture = scheduledPollingService.scheduleAtFixedRate(this, firstRunDelayInSec,
99 pollingIntervalInSec, TimeUnit.SECONDS);
104 BeEcompErrorManager.getInstance().logInternalFlowError(APPLICATION_DATA_TYPES_CACHE, "Cache is disabled",
108 BeEcompErrorManager.getInstance().logInternalFlowError(APPLICATION_DATA_TYPES_CACHE, "Cache is disabled",
117 if (scheduledFuture != null) {
118 boolean result = scheduledFuture.cancel(true);
119 log.debug("Stop polling task. result = {}", result);
121 scheduledFuture = null;
126 private void shutdownExecutor() {
127 if (scheduledPollingService == null)
130 scheduledPollingService.shutdown(); // Disable new tasks from being
133 // Wait a while for existing tasks to terminate
134 if (!scheduledPollingService.awaitTermination(60, TimeUnit.SECONDS)) {
135 scheduledPollingService.shutdownNow(); // Cancel currently
137 // Wait a while for tasks to respond to being cancelled
138 if (!scheduledPollingService.awaitTermination(60, TimeUnit.SECONDS))
139 log.debug("Pool did not terminate");
141 } catch (InterruptedException ie) {
142 // (Re-)Cancel if current thread also interrupted
143 scheduledPollingService.shutdownNow();
144 // Preserve interrupt status
145 Thread.currentThread().interrupt();
149 private Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> getAllDataTypesFromGraph() {
151 return propertyOperation
157 public Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> getAll() {
162 if (data == null || data.isEmpty()) {
163 return getAllDataTypesFromGraph();
166 return Either.left(data);
174 public Either<DataTypeDefinition, JanusGraphOperationStatus> get(String uniqueId) {
179 if (data == null || data.isEmpty()) {
180 return propertyOperation
181 .getDataTypeByUid(uniqueId);
183 DataTypeDefinition dataTypeDefinition = data.values().stream()
184 .filter(p -> p.getUniqueId().equals(uniqueId)).findFirst().orElse(null);
185 if (dataTypeDefinition == null) {
186 return propertyOperation
187 .getDataTypeByUid(uniqueId);
189 return Either.left(dataTypeDefinition);
199 log.trace("run() method. polling db to fetch data types");
203 Long start = System.currentTimeMillis();
204 log.trace("Start fetching all data types from db");
205 Either<List<DataTypeData>, JanusGraphOperationStatus> allDataTypeNodes = propertyOperation.getAllDataTypeNodes();
206 Long end = System.currentTimeMillis();
207 log.trace("Finish fetching all data types from db. Took {} Milliseconds", (end - start));
208 if (allDataTypeNodes.isRight()) {
209 JanusGraphOperationStatus status = allDataTypeNodes.right().value();
210 if (status != JanusGraphOperationStatus.OK) {
211 log.debug("ApplicationDataTypesCache - Failed to fetch all data types nodes");
212 BeEcompErrorManager.getInstance().logInternalConnectionError("FetchDataTypes",
213 "Failed to fetch data types from graph(cache)", ErrorSeverity.INFO);
217 List<DataTypeData> list = allDataTypeNodes.left().value();
220 Map<String, ImmutablePair<Long, Long>> dataTypeNameToModificationTime = list.stream()
221 .collect(Collectors.toMap(p -> p.getDataTypeDataDefinition().getName(),
222 p -> new ImmutablePair<>(p.getDataTypeDataDefinition().getCreationTime(),
223 p.getDataTypeDataDefinition().getModificationTime())));
225 Map<String, ImmutablePair<Long, Long>> currentDataTypeToModificationTime = new HashMap<>();
229 currentDataTypeToModificationTime = data.values().stream().collect(Collectors.toMap(
230 DataTypeDataDefinition::getName,
231 p -> new ImmutablePair<>(p.getCreationTime(), p.getModificationTime())));
238 boolean isChanged = compareDataTypes(dataTypeNameToModificationTime,
239 currentDataTypeToModificationTime);
247 } catch (Exception e) {
248 log.debug("unexpected error occured", e);
250 BeEcompErrorManager.getInstance().logInternalUnexpectedError(APPLICATION_DATA_TYPES_CACHE,
251 "Failed to run refresh data types job", ErrorSeverity.INFO);
254 propertyOperation.getJanusGraphGenericDao().commit();
255 } catch (Exception e) {
256 log.trace("Failed to commit ApplicationDataTypeCache", e);
262 private boolean compareDataTypes(Map<String, ImmutablePair<Long, Long>> dataTypeNameToModificationTime,
263 Map<String, ImmutablePair<Long, Long>> currentDataTypeToModificationTime) {
264 if (dataTypeNameToModificationTime.size() != currentDataTypeToModificationTime.size()) {
268 Set<String> currentkeySet = currentDataTypeToModificationTime.keySet();
269 Set<String> keySet = dataTypeNameToModificationTime.keySet();
271 if (currentkeySet.containsAll(keySet)) {
273 for (Entry<String, ImmutablePair<Long, Long>> entry : dataTypeNameToModificationTime.entrySet()) {
274 String dataTypeName = entry.getKey();
275 ImmutablePair<Long, Long> creationAndModificationTimes = entry.getValue();
276 long creationTime = creationAndModificationTimes.getLeft() == null ? 0
277 : creationAndModificationTimes.getLeft().longValue();
278 long modificationTime = creationAndModificationTimes.getRight() == null ? 0
279 : creationAndModificationTimes.getRight().longValue();
281 ImmutablePair<Long, Long> currentEntry = currentDataTypeToModificationTime.get(dataTypeName);
282 long currentCreationTime = currentEntry.getLeft() == null ? 0 : currentEntry.getLeft().longValue();
283 long currentModificationTime = currentEntry.getRight() == null ? 0
284 : currentEntry.getRight().longValue();
286 if (creationTime > currentCreationTime || modificationTime > currentModificationTime) {
287 log.debug("Datatype {} was updated. Creation Time {} vs {}. Modification Time {} vs {}",
288 dataTypeName, currentCreationTime, creationTime, currentModificationTime,
302 private void replaceAllData() {
304 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = propertyOperation
307 if (allDataTypes.isRight()) {
308 JanusGraphOperationStatus status = allDataTypes.right().value();
309 log.debug("Failed to fetch all data types from db. Status is {}", status);
315 data = allDataTypes.left().value();
317 BeEcompErrorManager.getInstance().logInternalFlowError("ReplaceDataTypesCache",
318 "Succeed to replace the data types cache", ErrorSeverity.INFO);