|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectorg.hd.d.pg2k.webSvr.exhibit.AbstractFilterBean
public abstract class AbstractFilterBean
JavaBean that can filter/sort and cache selections of exhibits. Designed to be used as a bean in a JSP or servlet, and can cache filter/sort results, for example, at application level or in a user's session.
This applies its filter to the input List (or entire exhibit set) that it is provided with; deriving classes may make all or part of the result directly or indirectly available.
This silently recomputes its results if they may have been affected by any update in the exhibit data (or when select() is called differently from the last call to the same instance). The cached state is not persisted if the bean is serialised, but the filter description is. This is only meant to be persisted, for example, to be passed between multiple instances of a distributable WAR and not to be stored for lengthy periods on disc, so does not use some of the fancier support for serialisation.
This uses but does not cache a DataSourceBean which can be supplied explicitly or recovered implicitly from a servlet context (at application scope), and can take the whole set of exhibits as input or can use the output of another filter. In all cases the output is only recomputed if the DataSourceBean.exhibitDataVersionHash() method result changes (so any randomised or conditional element had better be the last stage of the chain and only have (say) page or request scope), or if select() is called with different args to the last call on this instance (so, if for example, a different List argument is passed; select does a test on the hash code of the select() List arg).
This is thread-safe and as concurrent as possible, with the intention that it may be involved in many users' activity simultaneously.
The expression must be set (ideally exactly once) before any attempt is made to fetch results. For JSPs this set can be done in the body of the JSP so that it is done only on creation of the bean as a small efficiency gain.
If the expression is changed and is not equals() to the previous value, the cache is cleared.
The result returned by any select() operation is an immutable, thread-safe, RandomAccess List (eg like ArrayList). (This cannot be enforced on derived classes, but is part of the general contract.)
The expression is of the form:
expr = expr sortExpr
| expr filterExpr
| ALL
sortExpr = sort(args)
filterExpr = filter(args)
| filterExpr filterExpr &&
| filterExpr filterExpr ||
| filterExpr !
ie a filter on its own is applied to all the available exhibits,
or can be negated or combined (ANDed or ORed) with other filter
expressions to make more complex filter expressions.
A complete expression is a series of filter expressions and/or
sorts applied in a pipeline to the result of some filtering.
The expression syntax is reverse Polish amd dataflow is from left to right.
This class implements the Observer interface and when it receives a notification its immediately clears its cache by default. This is in addition to the normal automatic cache discard in select() when the imput has changed, and is an optimisation; behvaiour is correct without it. This mechanism helps discard stale data quickly and thus make better use of memory.
This can also be set to expire automatically from time to time, for example to allow for slowly mutating/changing data such as ExhibitPropsComputableMutable items. The default is not to expire periodically.
This Serializable so as to be able to be stored in a servlet session; nothing especially long-lived or sensitive.
TODO: Should do validation on deserialisation.
| Nested Class Summary | |
|---|---|
private static class |
AbstractFilterBean.ExpiryTask
Task to actively expire a filter and release its memory. |
private static class |
AbstractFilterBean.MyObserver
This object has only a WeakReference to the outer class to allow GC. |
private static class |
AbstractFilterBean.WeakenerTask
Task to weaken retained references to soft from strong. |
| Field Summary | |
|---|---|
private java.lang.Object |
_basicCache
The cached results (or null if not yet computed). |
private java.lang.Object |
_retainedCacheRefs
Collection of all references to internal cache objects requested to be retained; null when none present. |
private long |
_select_runTime
Records the time taken to complete _select() and descendants; non-negative and 0 if not yet called (or if deserialised). |
private long |
_select_startTime
Records the time at which _select() was last started; 0 if not yet called (or if deserialised). |
private java.util.TimerTask |
_ttExpiry
Timer task if any, to eagerly force expiry and release of resources, associated with this cache. |
private java.util.TimerTask |
_ttPurgeRetainedRefs
A task for clearing the _retainedCacheRefs; ephemeral and usually null. |
protected static int |
BUILD_TIME_LIVE_RATIO
Minimum multiple of build time for which we attempt to keep a memory-sensitive cache live; strictly positive. |
protected static int |
BUILD_TIME_LIVE_RATIO_MEM_STRESS
Minimum multiple of build time for which we attempt to keep a memory-sensitive cache live when memory may be short; strictly positive. |
private java.lang.Runnable |
emergencyFreeHook
Callback for 'emergency free' from MemoryTools; never null after registration. |
private int |
exhibitDataHash
The exhibit data hash when the cache was computed. |
private int |
expiryInterval
Expiry interval in ms, zero (the default) means no automatic expiry; non-negative. |
private long |
expiryTime
Expiry time of the cache (ie its content is to be considered invalid after this). |
private Expr |
expr
The (filter/sorter) expression, or null if not yet set. |
private int |
lastListArgHashCode
The hashCode of the last List arg to select or 0 if none. |
private static java.util.Timer |
lifetimeManager
Timer used to help manage the cache lifetimes for memory-sensitive caches. |
protected static int |
MAX_STRONG_RETENTION_MS
Maximum strong-ref retention time in ms; strictly positive. |
private boolean |
memorySensitiveCache
If true then led cached value go if we run short of memory, eg hold it via a SoftReference. |
private java.lang.String |
name
Name for this instance; by default null. |
private static java.lang.ref.SoftReference<java.util.Collection<java.lang.Object>> |
NO_REFS
Fixed dead SoftReference to use to clear _retainedCacheRefs without allocating. |
private static boolean |
OBSERVE_DATASOURCEBEAN
If true, become an Observer of the DataSourceBean so that we can eagerly discard a stale cache. |
private AbstractFilterBean.MyObserver |
observer
Embedded observer object. |
private static long |
serialVersionUID
Unique Serialisation class ID generated by http://random.hd.org/. |
| Constructor Summary | |
|---|---|
AbstractFilterBean()
|
|
| Method Summary | |
|---|---|
private void |
_clearRetainedRefs()
Clears retained references without taking any locks. |
private static int |
_computeListArgHashCode(java.util.List<Name.ExhibitFull> inputSet)
Compute the hash over our List argument, used by _isValid() and _select(). |
protected java.util.List<Name.ExhibitFull> |
_isValid(DataSourceBean ds,
java.util.List<Name.ExhibitFull> inputSet)
Returns cache reference if the cache still seems to be valid. |
protected void |
_retainCacheRef(java.lang.Object newRef)
Add to the retained refs an cached internal object that must be maintained to avoid the cache expiring. |
protected java.util.List<Name.ExhibitFull> |
_select(DataSourceBean ds,
java.util.List<Name.ExhibitFull> inputSet)
Internal method that computes the result of accepted exhibits. |
protected void |
clearCache()
Clears the cache of the basic set of filtered/sorted items. |
private int |
getExhibitDataHash()
Set exhibitDataHash. |
int |
getExpiryInterval()
Get expiry interval in ms, zero (the default) means no automatic expiry; non-negative. |
protected Expr |
getExpr()
Get the simple single (input) filter/sort expression directly. |
boolean |
getMemorySensitiveCache()
Get the `memory-sensitive' flag for the cache. |
java.lang.String |
getName()
Get the name for this instance; by default null. |
void |
invalidate()
Invalidate the cache. |
private void |
setExhibitDataHash(int exhibitDataHash)
Get exhibitDataHash. |
void |
setExpiryInterval(int expiryInterval)
Set expiry interval in ms, zero means no automatic expiry; non-negative. |
void |
setExpr(Expr _expr)
Set the simple single (input) filter/sort expression directly. |
void |
setExpr(java.lang.String _expr)
Set the filter/sorter expression as a textual expression. |
void |
setMemorySensitiveCache(boolean f)
Set the `memory-sensitive' flag for the cache. |
void |
setName(java.lang.String n)
Set the name for this instance; by default null. |
java.lang.String |
toString()
Get human-readable summary; never null. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Field Detail |
|---|
private static final boolean OBSERVE_DATASOURCEBEAN
private Expr expr
This is persisted if the object is serialised.
private boolean memorySensitiveCache
This can be set or reset at any time but is only effective when the cache is filled, so is probably done once, before the first set of values is retrieved.
By default this value is true and the cache is memory sensitive, ie won't cause the system to run out of memory.
Accessed under the instance lock.
This is persisted if the object is serialised.
private int expiryInterval
Is volatile so as to allow access without a lock.
private transient volatile int exhibitDataHash
Is volatile so that it can be accessed from multiple threads without taking a lock.
Should be accessed only by getExhibitDataHash() and setExhibitDataHash().
Zero when the cache is clear (the initial state).
private transient int lastListArgHashCode
Accessed under the instance lock and is private to _select() and clearCache().
Zero when the cache is clear.
private transient java.lang.Object _basicCache
If the exhibit data hash (or select()-arg hash) changes then we should regard the cache as invalid.
This is null only if not yet computed; it is zero length if the result set was empty.
Accessed under the instance lock and is private to _select() and clearCache().
Is either a List or a SoftReference wrapper around one.
private final AbstractFilterBean.MyObserver observer
This inner object has only a SoftReference to us.
private java.lang.Runnable emergencyFreeHook
When it is called it unguards any SoftReferences allowing memory to be freed rather than an OutOfMemoryException getting thrown somewhere in the application.
It is assumed that MemoryTools holds this via a WeakReference so that it will not inhibit this instance being GCed.
private java.lang.String name
private transient java.util.TimerTask _ttExpiry
Accessed under the instance lock.
private transient long expiryTime
Transient to force an immediate recomputation if deserialised.
private transient long _select_startTime
Only written to by _select(), under the instance lock.
private transient long _select_runTime
May not be maintained if the cache is not memory sensitive.
TODO: May be used to give the cached state a new lease of life on each access.
Only written to by _retainCacheRef(), under the instance lock.
private static final long serialVersionUID
private transient volatile java.lang.Object _retainedCacheRefs
Intended primarily for memory-sensitive caches though will do no harm will occur if references to internal cached state are always posted here.
Erased/dropped entirely when the cache is invalidated.
Cleared or switched to being themselves held via a soft reference whenever the initial lifetime is over, but not until _select() and its descendants have finished their computation. May then be switched back to being a strong reference for a while on each read access of not already expired, to provide another memory-insensitive period.
Created in _select() when a new value is computed. Each derived class should post its recomputed cached values (under the instance lock) after (re)computing them, to prevent them expiring too soon.
Accessed under the instance lock except marked volatile so that it may safely be cleared without a lock by _clearRetainedRefs().
private static final java.lang.ref.SoftReference<java.util.Collection<java.lang.Object>> NO_REFS
private transient java.util.TimerTask _ttPurgeRetainedRefs
Helps retain the cache for a minimum lifetime.
protected static final int BUILD_TIME_LIVE_RATIO
TODO: may replace with dynamic calculation of ratio large enough to keep amortised build time to <~100ms per _select().
A reasonable value is probably in the range 5--1000; a power of two may prove marginally more efficient.
protected static final int BUILD_TIME_LIVE_RATIO_MEM_STRESS
A reasonable value is probably in the range 2--32; a power of two may prove marginally more efficient.
protected static final int MAX_STRONG_RETENTION_MS
Should be a very long time in computing terms, eg minutes through to hours.
private static final java.util.Timer lifetimeManager
Should never be cancelled (will be GCed in due course if this class is).
It is very important that any tasks not due to run immediately should only hold onto AFB references weakly (and thus must be static classed for example) to avoid retaining garbage and compounding the problem that is intended to solve!
| Constructor Detail |
|---|
public AbstractFilterBean()
| Method Detail |
|---|
public int getExpiryInterval()
public void setExpiryInterval(int expiryInterval)
private int getExhibitDataHash()
private void setExhibitDataHash(int exhibitDataHash)
public java.lang.String getName()
public void setName(java.lang.String n)
public java.lang.String toString()
toString in class java.lang.Objectpublic void setMemorySensitiveCache(boolean f)
This can be set or reset at any time but is only effective when the cache is filled, so is probably best done once, before the first set of values is retrieved.
By default this value is true and the cache is not memory sensitive.
This is persisted if the object is serialised.
public boolean getMemorySensitiveCache()
public void setExpr(Expr _expr)
throws java.lang.IllegalArgumentException,
java.lang.IllegalStateException
java.lang.IllegalArgumentException - if the argument is null
java.lang.IllegalStateExceptionprotected Expr getExpr()
This can be overridden to provide some extra filtering or sorting, for example, in derived classes.
public void setExpr(java.lang.String _expr)
throws java.lang.IllegalArgumentException,
java.lang.IllegalStateException
java.lang.IllegalArgumentException - if the argument is null or unparseable
java.lang.IllegalStateExceptionprotected void clearCache()
A deriving class can override this to clear any extra state it maintains, but must chain to this first in order to clear the underlying caches and free other resources.
This routine is synchronized and overriding methods almost certainly should be so too.
public void invalidate()
May need to grab locks.
protected java.util.List<Name.ExhibitFull> _isValid(DataSourceBean ds,
java.util.List<Name.ExhibitFull> inputSet)
throws java.io.IOException
Parameters as for _select(), return value as for _select() or null if invalid.
Cheaper than calling _select() to force the cache to be invalidated since it does not attempt to rebuild the cache.
java.io.IOExceptionprivate static int _computeListArgHashCode(java.util.List<Name.ExhibitFull> inputSet)
protected java.util.List<Name.ExhibitFull> _select(DataSourceBean ds,
java.util.List<Name.ExhibitFull> inputSet)
throws java.io.IOException,
java.lang.IllegalStateException
The ds argument must not be null.
If the inputSet argument is null the whole set of exhibits is used, else the supplied set is used. This must be a List of String items with no nulls nor duplicates.
This will (re)compute its results if necessary, ie:
This never returns null.
Null names and names that do not represent items currently in the exhibit set are silently dropped.
This routine may register this instance with the data source as an Observer of exhibit set changes in order to be able to quickly invalidate/release our (then-stale) cache upon any changes.
inputSet - null, or a list of full exhibit names
java.lang.IllegalStateException - if the filter has not been set
java.io.IOExceptionprivate void _clearRetainedRefs()
protected void _retainCacheRef(java.lang.Object newRef)
Automatically creates/replaces the timer task to clear this.
We go through the motions even if not currently a memory-sensitive cache since that status may be changed at any time.
newRef - reference to retain, or null to revive existing references if possible
|
DHD Multimedia Gallery V1.53.0 | ||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||