Cache invalidation patch from Zell.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@2055 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -52,16 +52,28 @@ public class PersistenceContext
|
|||||||
public HashMap<String, TableGenerator> tableGenerators = new HashMap<String, TableGenerator>();
|
public HashMap<String, TableGenerator> tableGenerators = new HashMap<String, TableGenerator>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache listener is notified when cache entries are invalited through creation, deletion,
|
* A cache listener is notified when cache entries change. Its purpose is typically to do
|
||||||
* or modification. Its purpose is typically to do further invalidation of dependent entries
|
* further invalidation of dependent entries in other caches.
|
||||||
* in other caches.
|
|
||||||
*/
|
*/
|
||||||
public static interface CacheListener<T>
|
public static interface CacheListener<T>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The given entry has just been deleted, modified or created. Do what thou wilt.
|
* The given entry (which is never null) has just been evicted from the cache slot
|
||||||
|
* indicated by the given key.
|
||||||
|
*
|
||||||
|
* This method is most commonly used to trigger custom cache invalidation of records that
|
||||||
|
* depend on the one that was just invalidated.
|
||||||
*/
|
*/
|
||||||
public void entryModified (CacheKey key, T entry);
|
public void entryInvalidated (CacheKey key, T oldEntry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The given entry, which may be an explicit null, has just been placed into the cache
|
||||||
|
* under the given key. The previous cache entry, if any, is also supplied.
|
||||||
|
*
|
||||||
|
* This method is most likely used by repositories to index entries by attribute for quick
|
||||||
|
* cache invalidation when brute force is unrealistically time consuming.
|
||||||
|
*/
|
||||||
|
public void entryCached (CacheKey key, T newEntry, T oldEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,25 +234,33 @@ public class PersistenceContext
|
|||||||
/**
|
/**
|
||||||
* Stores a new entry indexed by the given key.
|
* Stores a new entry indexed by the given key.
|
||||||
*/
|
*/
|
||||||
public <T> void cacheStore (CacheKey key, T value)
|
public <T> void cacheStore (CacheKey key, T entry)
|
||||||
{
|
{
|
||||||
Log.debug("cacheStore: entry [key=" + key + ", value=" + value + "]");
|
Log.debug("cacheStore: entry [key=" + key + ", value=" + entry + "]");
|
||||||
getCache(key.getCacheId()).put(new Element(key.getCacheKey(), value));
|
|
||||||
|
|
||||||
// first do cascading invalidations
|
// find the old entry, if any
|
||||||
|
Cache cache = getCache(key.getCacheId());
|
||||||
|
Element element = cache.get(key.getCacheKey());
|
||||||
|
@SuppressWarnings("unchecked") T oldEntry =
|
||||||
|
(element != null ? (T) element.getValue() : null);
|
||||||
|
|
||||||
|
// update the cache
|
||||||
|
cache.put(new Element(key.getCacheKey(), entry));
|
||||||
|
|
||||||
|
// then do cache invalidations
|
||||||
Set<CacheListener<?>> listeners = _listenerSets.get(key.getCacheId());
|
Set<CacheListener<?>> listeners = _listenerSets.get(key.getCacheId());
|
||||||
if (listeners != null && listeners.size() > 0) {
|
if (listeners != null && listeners.size() > 0) {
|
||||||
for (CacheListener<?> listener : listeners) {
|
for (CacheListener<?> listener : listeners) {
|
||||||
Log.debug("cacheInvalidate: cascading [listener=" + listener + "]");
|
Log.debug("cacheInvalidate: cascading [listener=" + listener + "]");
|
||||||
@SuppressWarnings("unchecked") CacheListener<T> casted = (CacheListener<T>)listener;
|
@SuppressWarnings("unchecked") CacheListener<T> casted = (CacheListener<T>)listener;
|
||||||
casted.entryModified(key, value);
|
casted.entryCached(key, entry, oldEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evicts the cache entry indexed under the given key, if there is one.
|
* Evicts the cache entry indexed under the given key, if there is one. The eviction may
|
||||||
* The eviction may trigger further cache invalidations.
|
* trigger further cache invalidations.
|
||||||
*/
|
*/
|
||||||
public void cacheInvalidate (CacheKey key)
|
public void cacheInvalidate (CacheKey key)
|
||||||
{
|
{
|
||||||
@@ -248,8 +268,8 @@ public class PersistenceContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evicts the cache entry indexed under the given class and cache key, if there is one.
|
* Evicts the cache entry indexed under the given class and cache key, if there is one. The
|
||||||
* The eviction may trigger further cache invalidations.
|
* eviction may trigger further cache invalidations.
|
||||||
*/
|
*/
|
||||||
public void cacheInvalidate (Class pClass, Serializable cacheKey)
|
public void cacheInvalidate (Class pClass, Serializable cacheKey)
|
||||||
{
|
{
|
||||||
@@ -257,33 +277,38 @@ public class PersistenceContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evicts the cache entry indexed under the given cache id and cache key, if there is one.
|
* Evicts the cache entry indexed under the given cache id and cache key, if there is one. The
|
||||||
* The eviction may trigger further cache invalidations.
|
* eviction may trigger further cache invalidations.
|
||||||
*/
|
*/
|
||||||
public <T extends Serializable> void cacheInvalidate (String cacheId, Serializable cacheKey)
|
public <T extends Serializable> void cacheInvalidate (String cacheId, Serializable cacheKey)
|
||||||
{
|
{
|
||||||
Log.debug("cacheInvalidate: entry [cacheId=" + cacheId + ", cacheKey=" + cacheKey + "]");
|
Log.debug("cacheInvalidate: entry [cacheId=" + cacheId + ", cacheKey=" + cacheKey + "]");
|
||||||
|
|
||||||
Cache cache = getCache(cacheId);
|
Cache cache = getCache(cacheId);
|
||||||
Element element = cache.get(cacheKey);
|
Element element = cache.get(cacheKey);
|
||||||
|
if (element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// first do cascading invalidations
|
// find the old entry, if any
|
||||||
Set<CacheListener<?>> listeners = _listenerSets.get(cacheId);
|
@SuppressWarnings("unchecked") T oldEntry = (T) element.getValue();
|
||||||
if (listeners != null && listeners.size() > 0) {
|
if (oldEntry != null) {
|
||||||
CacheKey key = new SimpleCacheKey(cacheId, cacheKey);
|
// if there was one, do (possibly cascading) cache invalidations
|
||||||
for (CacheListener<?> listener : listeners) {
|
Set<CacheListener<?>> listeners = _listenerSets.get(cacheId);
|
||||||
Log.debug("cacheInvalidate: cascading [listener=" + listener + "]");
|
if (listeners != null && listeners.size() > 0) {
|
||||||
@SuppressWarnings("unchecked") CacheListener<T> casted = (CacheListener<T>)listener;
|
CacheKey key = new SimpleCacheKey(cacheId, cacheKey);
|
||||||
@SuppressWarnings("unchecked") T value =
|
for (CacheListener<?> listener : listeners) {
|
||||||
(element != null ? (T) element.getValue() : null);
|
Log.debug("cacheInvalidate: cascading [listener=" + listener + "]");
|
||||||
casted.entryModified(key, value);
|
@SuppressWarnings("unchecked") CacheListener<T> casted =
|
||||||
|
(CacheListener<T>)listener;
|
||||||
|
casted.entryInvalidated(key, oldEntry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// then evict the keyed entry, if needed
|
// then evict the keyed entry, if needed
|
||||||
if (element != null) {
|
Log.debug("cacheInvalidate: evicting [cacheKey=" + cacheKey + "]");
|
||||||
Log.debug("cacheInvalidate: evicting [cacheKey=" + cacheKey + "]");
|
cache.remove(cacheKey);
|
||||||
cache.remove(cacheKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user