2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 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====================================================
22 package org.onap.aaf.auth.cache;
24 import java.util.ArrayList;
25 import java.util.Date;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
31 import java.util.Timer;
32 import java.util.TimerTask;
33 import java.util.concurrent.ConcurrentHashMap;
35 import org.onap.aaf.misc.env.Env;
36 import org.onap.aaf.misc.env.Trans;
39 * Create and maintain a Map of Maps used for Caching
46 public class Cache<TRANS extends Trans, DATA> {
47 private static Clean clean;
48 private static Timer cleanseTimer;
50 public static final String CACHE_HIGH_COUNT = "CACHE_HIGH_COUNT";
51 public static final String CACHE_CLEAN_INTERVAL = "CACHE_CLEAN_INTERVAL";
53 private static final Map<String,Map<String,Dated>> cacheMap;
56 cacheMap = new HashMap<>();
60 * Dated Class - store any Data with timestamp
65 public static final class Dated {
66 public Date timestamp;
68 private long expireIn;
70 public Dated(List<?> data, long expireIn) {
71 timestamp = new Date(System.currentTimeMillis()+expireIn);
73 this.expireIn = expireIn;
76 public <T> Dated(T t, long expireIn) {
77 timestamp = new Date(System.currentTimeMillis()+expireIn);
78 ArrayList<T> al = new ArrayList<>(1);
81 this.expireIn = expireIn;
85 timestamp = new Date(System.currentTimeMillis()+expireIn);
89 public static Map<String,Dated> obtain(String key) {
90 Map<String, Dated> m = cacheMap.get(key);
92 m = new ConcurrentHashMap<>();
93 synchronized(cacheMap) {
101 * Clean will examine resources, and remove those that have expired.
103 * If "highs" have been exceeded, then we'll expire 10% more the next time. This will adjust after each run
104 * without checking contents more than once, making a good average "high" in the minimum speed.
109 private static final class Clean extends TimerTask {
110 private final Env env;
111 private Set<String> set;
113 // The idea here is to not be too restrictive on a high, but to Expire more items by
114 // shortening the time to expire. This is done by judiciously incrementing "advance"
115 // when the "highs" are exceeded. This effectively reduces numbers of cached items quickly.
116 private final int high;
117 private long advance;
118 private final long timeInterval;
120 public Clean(Env env, long cleanInterval, int highCount) {
123 timeInterval = cleanInterval;
125 set = new HashSet<>();
128 public synchronized void add(String key) {
135 // look at now. If we need to expire more by increasing "now" by "advance"
136 Date now = new Date(System.currentTimeMillis() + advance);
139 for (String name : set) {
140 Map<String,Dated> map = cacheMap.get(name);
145 for (Map.Entry<String,Dated> me : map.entrySet()) {
147 if (me.getValue().timestamp.before(now)) {
148 map.remove(me.getKey());
155 env.debug().log("Cache removed",count,"expired Cached Elements out of", total);
158 // If High (total) is reached during this period, increase the number of expired services removed for next time.
159 // There's no point doing it again here, as there should have been cleaned items.
161 // advance cleanup by 10%, without getting greater than timeInterval.
162 advance = Math.min(timeInterval, advance+(timeInterval/10));
164 // reduce advance by 10%, without getting lower than 0.
165 advance = Math.max(0, advance-(timeInterval/10));
170 public static synchronized void startCleansing(Env env, String ... keys) {
171 if (cleanseTimer==null) {
172 cleanseTimer = new Timer("Cache Cleanup Timer");
173 int cleanInterval = Integer.parseInt(env.getProperty(CACHE_CLEAN_INTERVAL,"60000")); // 1 minute clean cycles
174 int highCount = Integer.parseInt(env.getProperty(CACHE_HIGH_COUNT,"5000"));
175 cleanseTimer.schedule(clean = new Clean(env, cleanInterval, highCount), cleanInterval, cleanInterval);
178 for (String key : keys) {
183 public static void stopTimer() {
184 if (cleanseTimer!=null) {
185 cleanseTimer.cancel();
190 public static void addShutdownHook() {
191 Runtime.getRuntime().addShutdownHook(new Thread() {