/* * Copyright (c) 2011,2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html * * 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. * * This file incorporates work covered by the following copyright and * permission notice: * * Originally created by David Erickson, Stanford University * * 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. */ package org.sdnplatform.util; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import java.util.concurrent.ConcurrentMap; /** * The key is any object/hash-code * The value is time-stamp in milliseconds * The time interval denotes the interval for which the entry should remain in the hashmap. * If an entry is present in the Linkedhashmap, it does not mean that it's valid (recently seen) * * @param <K> Type of the values in this cache */ public class TimedCache<K> { private final long timeoutInterval; //specified in milliseconds. private ConcurrentMap<K, Long> cache; /** * * @param capacity the maximum number of entries in the cache before the * oldest entry is evicted. * @param timeToLive specified in milliseconds */ public TimedCache(int capacity, int timeToLive) { cache = new ConcurrentLinkedHashMap.Builder<K, Long>() .maximumWeightedCapacity(capacity) .build(); this.timeoutInterval = timeToLive; } public long getTimeoutInterval() { return this.timeoutInterval; } /** * Always try to update the cache and set the last-seen value for this key. * * Return true, if a valid existing field was updated, else return false. * (note: if multiple threads update simultaneously, one of them will succeed, * other wills return false) * * @param key * @return boolean */ public boolean update(K key) { Long curr = new Long(System.currentTimeMillis()); Long prev = cache.putIfAbsent(key, curr); if (prev == null) { return false; } if (curr - prev > this.timeoutInterval) { if (cache.replace(key, prev, curr)) { return false; } } return true; } }