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;
34 import java.util.logging.Level;
36 import org.onap.aaf.misc.env.Env;
37 import org.onap.aaf.misc.env.Trans;
40 * Create and maintain a Map of Maps used for Caching
47 public class Cache<TRANS extends Trans, DATA> {
48 private static Clean clean;
49 private static Timer cleanseTimer;
51 public static final String CACHE_HIGH_COUNT = "CACHE_HIGH_COUNT";
52 public static final String CACHE_CLEAN_INTERVAL = "CACHE_CLEAN_INTERVAL";
53 // public static final String CACHE_MIN_REFRESH_INTERVAL = "CACHE_MIN_REFRESH_INTERVAL";
55 private static final Map<String,Map<String,Dated>> cacheMap;
58 cacheMap = new HashMap<String,Map<String,Dated>>();
62 * Dated Class - store any Data with timestamp
67 public final static class Dated {
68 public Date timestamp;
70 private long expireIn;
72 public Dated(List<?> data, long expireIn) {
73 timestamp = new Date(System.currentTimeMillis()+expireIn);
75 this.expireIn = expireIn;
78 public <T> Dated(T t, long expireIn) {
79 timestamp = new Date(System.currentTimeMillis()+expireIn);
80 ArrayList<T> al = new ArrayList<T>(1);
83 this.expireIn = expireIn;
87 timestamp = new Date(System.currentTimeMillis()+expireIn);
91 public static Map<String,Dated> obtain(String key) {
92 Map<String, Dated> m = cacheMap.get(key);
94 m = new ConcurrentHashMap<String, Dated>();
95 synchronized(cacheMap) {
103 * Clean will examine resources, and remove those that have expired.
105 * If "highs" have been exceeded, then we'll expire 10% more the next time. This will adjust after each run
106 * without checking contents more than once, making a good average "high" in the minimum speed.
111 private final static class Clean extends TimerTask {
112 private final Env env;
113 private Set<String> set;
115 // The idea here is to not be too restrictive on a high, but to Expire more items by
116 // shortening the time to expire. This is done by judiciously incrementing "advance"
117 // when the "highs" are exceeded. This effectively reduces numbers of cached items quickly.
118 private final int high;
119 private long advance;
120 private final long timeInterval;
122 public Clean(Env env, long cleanInterval, int highCount) {
125 timeInterval = cleanInterval;
127 set = new HashSet<String>();
130 public synchronized void add(String key) {
137 // look at now. If we need to expire more by increasing "now" by "advance"
138 Date now = new Date(System.currentTimeMillis() + advance);
141 for(String name : set) {
142 Map<String,Dated> map = cacheMap.get(name);
143 if(map!=null) for(Map.Entry<String,Dated> me : map.entrySet()) {
145 if(me.getValue().timestamp.before(now)) {
146 map.remove(me.getKey());
151 // env.info().log(Level.INFO, "Cache removed",count,"expired",name,"Elements");
156 env.info().log(Level.INFO, "Cache removed",count,"expired Cached Elements out of", total);
159 // If High (total) is reached during this period, increase the number of expired services removed for next time.
160 // There's no point doing it again here, as there should have been cleaned items.
162 // advance cleanup by 10%, without getting greater than timeInterval.
163 advance = Math.min(timeInterval, advance+(timeInterval/10));
165 // reduce advance by 10%, without getting lower than 0.
166 advance = Math.max(0, advance-(timeInterval/10));
171 public static synchronized void startCleansing(Env env, String ... keys) {
172 if(cleanseTimer==null) {
173 cleanseTimer = new Timer("Cache Cleanup Timer");
174 int cleanInterval = Integer.parseInt(env.getProperty(CACHE_CLEAN_INTERVAL,"60000")); // 1 minute clean cycles
175 int highCount = Integer.parseInt(env.getProperty(CACHE_HIGH_COUNT,"5000"));
176 cleanseTimer.schedule(clean = new Clean(env, cleanInterval, highCount), cleanInterval, cleanInterval);
179 for(String key : keys) {
184 public static void stopTimer() {
185 if(cleanseTimer!=null) {
186 cleanseTimer.cancel();
191 public static void addShutdownHook() {
192 Runtime.getRuntime().addShutdownHook(new Thread() {