org.apache.shindig.common.cache.SoftExpiringCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shindig-common Show documentation
Show all versions of shindig-common Show documentation
Common java code for Shindig
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.shindig.common.cache;
import org.apache.shindig.common.util.TimeSource;
import com.google.common.collect.MapMaker;
import java.util.concurrent.ConcurrentMap;
/**
* A cache that uses a soft expiration policy. Entries will be kept around for potentially as long
* as the underlying cache permits, but we keep a timestamp around to retain a notion of the actual
* age. This provides users of this class with the option of keeping an "expired" entry beyond the
* normal lifetime.
*
* As soon as an entry expires from the underlying cache, it disappears from here as well.
*
* Note that this isn't actually a cache itself, but rather a wrapper for one. It differs in the
* getElement method substantially, since the returned objects are not the same as the V parameter.
*/
public class SoftExpiringCache {
private final Cache cache;
// We keep a weak reference to the value stored in the cache so that when the value in the actual
// cache is removed, we should lose it here as well.
private final ConcurrentMap expirationTimes;
private TimeSource timeSource;
/**
* Create a new TtlCache with the given capacity and TTL values.
* The cache provider provides an implementation of the actual storage.
*
* @param cache The underlying cache that will store actual data.
*/
public SoftExpiringCache(Cache cache) {
this.cache = cache;
expirationTimes = new MapMaker().weakKeys().makeMap();
timeSource = new TimeSource();
}
/**
* Retrieve an element from the cache by key. If there is no such element
* for that key in the cache, or if the element has timed out, null is returned.
* @param key Key whose element to look up.
* @return Element in the cache, if present and not timed out.
*/
public CachedObject getElement(K key) {
V value = cache.getElement(key);
if (value == null) {
return null;
}
Long expiration = expirationTimes.get(value);
if (expiration == null) {
return null;
}
return new CachedObject(value, expiration < timeSource.currentTimeMillis());
}
/**
* Add an element to the cache, with the intended max age for its cache entry provided in
* milliseconds.
*
* @param key The key to store the entry for.
* @param value The value to store.
* @param maxAge The maximum age for this entry before it is deemed expired.
*/
public void addElement(K key, V value, long maxAge) {
long now = timeSource.currentTimeMillis();
cache.addElement(key, value);
expirationTimes.put(value, now + maxAge);
}
/**
* Set a new time source. For use in testing.
*
* @param timeSource New time source to use.
*/
public void setTimeSource(TimeSource timeSource) {
this.timeSource = timeSource;
}
public static class CachedObject {
public final V obj;
public final boolean isExpired;
protected CachedObject(V obj, boolean isExpired) {
this.obj = obj;
this.isExpired = isExpired;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy