|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectorg.hd.d.pg2k.svrCore.datasource.simpleCache.MetaData
public final class MetaData
Cache in-memory meta-data representation. Holds information about what exhibit data is cached on disc.
Is serialisable to be able to persist to disc and allow for a fast start-up.
Can be marked read-only to hold the cache in its current state.
This object is completely thread-safe and holds its instance lock to synchronise activity.
The names of all members affecting the state of cached exhibit data and meta-data start with `exhibit'.
Note that holding the instance lock does not shut out all changes, a little like attempting to lock a WeakHashMap or ConcurrentHashMap.
Marked public only for testing, else could be package-visible only.
| Field Summary | |
|---|---|
private Tuple.Triple<java.io.File,java.lang.Long,java.lang.Long> |
_cFSBHWM_cache
Cache of estimated usable free space in the underlying cache filesystem; initially null. |
private int |
_fullyCachedCount
Cache of estimate of full-cached exhibits; non-negative. |
private java.util.Hashtable<Name.ExhibitFull,CachedFile> |
cachedExhibits
Set of cached exhibits, from full exhibit name to CachedFile entry; never null after construction/deserialisation. |
private java.util.SortedSet<CachedFile> |
exhibitsLRU
LRU ordered set of the CachedFile values in cachedExhibits; never null after construction/deserialisation. |
private static int |
MAX_FS_USABLE_SPACE_CACHE_MS
Maximum time in ms that we may retain a cached 'usable filespace' estimate; strictly positive. |
(package private) static int |
MIN_FS_PERCENT_FREE
Minimum percentage free in cache filesystem for us to expand the cache; non-negative in range ]100,0]. |
private boolean |
needsSave
If true, this needs a save to disc (ie this instance's state has changed). |
private static long |
serialVersionUID
My serial ID. |
private long |
totalBytes
Estimated total bytes of disc used by cached entries. |
private long |
totalBytesHighWaterMark
The highest value of totalBytes, ie the cache actual high-water mark; never negative. |
private static boolean |
TRY_TO_RETAIN_TN_IN_PURGE
If true then try to retain metadata and thumbnails of exhibits we purge. |
private static boolean |
USE_EXTANT_DISC_ENTRY_ON_CREATE
If true, when creating cache entry if data found on disc use it rather than refuse to build meta-data entry. |
| Constructor Summary | |
|---|---|
private |
MetaData()
Build an empty, read-only set of meta-data. |
private |
MetaData(AllExhibitProperties aepCurrent,
java.io.File cacheDir,
SimpleLoggerIF logger)
Build a new meta-data set by examining the given cache directory. |
private |
MetaData(MetaData other)
Build a lightweight copy. |
| Method Summary | |
|---|---|
private boolean |
_exhibitRemoveLRUCacheEntry(java.io.File cacheDir,
Name.ExhibitFull dontRemoveName,
boolean justData,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
Remove the least-recently-used exhibit cache item, if any. |
private void |
_recomputeDerivedValues()
This private routine updates all (transient) data derived from the primary cachedExhibits map. |
private void |
_removeCacheRecordFromMemoryCopy(Name.ExhibitFull name)
Remove cached-file details from memory record; does nothing if not present. |
private void |
_setTotalBytes(long newTB)
Set estimated total bytes of disc used by cached entries; never negative. |
(package private) void |
_updateCacheRecordInMemoryCopy(CachedFile newCf,
SimpleLoggerIF logger)
Update or add new cached-file details, adjusting cache data in situ. |
(package private) boolean |
canPrecache(java.io.File cacheDir)
If true, some precaching may be possible, going by our generally-least-strict limit. |
(package private) boolean |
canPrecacheExhibitData(java.io.File cacheDir)
If true, we can pre-cache data blocks for (new or existing) exhibits. |
(package private) boolean |
canPrecacheThumbnails(java.io.File cacheDir)
If true, we can pre-cache thumbnails for (existing) exhibits. |
(package private) long |
computeFreeSpaceBelowHighWaterMark(java.io.File cacheDir)
Compute available free space in cache (bytes); zero or negative if none. |
(package private) long |
computeFreeSpaceBelowLowWaterMark(java.io.File cacheDir)
Compute current definite free-space in cache. |
(package private) long |
computeTargetHighWaterMark()
Computes the target high-water mark (target maximum cache size); strictly positive. |
MetaData |
createLightweightCopy()
Returns fast lightweight read-only copy ready to serialise/save or check; never null. |
static MetaData |
createMetaData()
Creates empty read-only instance; never null. |
static MetaData |
createMetaData(AllExhibitProperties aepCurrent,
java.io.File cacheDir,
SimpleLoggerIF logger)
Creates new instance and populates from the filesystem; never null. |
(package private) boolean |
exhibitCreateNewCacheEntry(java.io.File cacheDir,
ExhibitStaticAttr esa,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
Create a new exhibit entry. |
(package private) CachedFile |
exhibitGetInfo(Name.ExhibitFull name)
Get cached-file details for a given exhibit; null if exhibit not cached. |
(package private) ExhibitThumbnails |
exhibitGetThumbnails(java.io.File cacheDir,
Name.ExhibitFull name,
SimpleLoggerIF logger)
Get the cached thumbnails for an exhibit, or null if none cached. |
(package private) boolean |
exhibitIsFullyLoaded(ExhibitStaticAttr esa)
Check if the exhibit is fully loaded. |
(package private) CachedFile |
exhibitMarkAsAccessed(Name.ExhibitFull name,
SimpleLoggerIF logger,
java.io.File cacheDir)
Mark exhibit as accessed (`touch' it) and returns the possibly-modified CachedFile record. |
(package private) boolean |
exhibitRemoveCacheEntry(java.io.File cacheDir,
Name.ExhibitFull name,
boolean justData,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
Remove an exhibit entry from cache, possibly including all its data and metadata. |
(package private) boolean |
exhibitSaveThumbnails(GenProps gp,
java.io.File cacheDir,
ExhibitStaticAttr esa,
ExhibitThumbnails tns,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
Saves the thumbnails for an exhibit. |
(package private) java.util.List<CachedFile> |
getExhibitsLRUList()
Get exhibit metadata in LRU order; never null but may be empty. |
(package private) int |
getFullyCachedCount(AllExhibitProperties aep,
boolean force)
Return estimated count of known-fully-cached exhibits; non-negative. |
java.util.Set<Name.ExhibitFull> |
getKnownExhibits()
Get Set of exhibits on which metadata is currently held in this cache. |
(package private) CachedFile |
getLeastRecentlyUsed()
Get most-recently-used exhibit. |
(package private) CachedFile |
getMostRecentlyUsed()
Get least-recently-used exhibit. |
(package private) boolean |
getNeedsSave()
Get the 'needs to be saved to disc' value. |
(package private) long |
getTotalBytesCurrentlyUsedByCache()
Get estimated total bytes of disc used by cached entries; never negative. |
(package private) long |
getTotalBytesHighWaterMark()
Get the highest value of totalBytes, ie the cache actual high-water mark; never negative. |
(package private) boolean |
isEmpty()
Is our meta-data store empty, ie no exhibits cached at all? |
(package private) boolean |
isEquivalent(MetaData other)
Returns true if this metadata is essentially equivalent to another one. |
(package private) boolean |
lotsFree(java.io.File cacheDir)
Returns true if we have lots of disc space free. |
(package private) void |
pruneOrAdjustBadInMemoryCacheRecords(long reloadStartTime,
MetaData newData,
SimpleLoggerIF logger)
Install info from new cache object in this one. |
(package private) void |
purge(GenProps gp,
java.io.File cacheDir,
long howMuch,
Name.ExhibitFull dontPurgeName,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
Purges the cache of old entries to make space for new, if needed. |
private void |
readObject(java.io.ObjectInputStream in)
Deserialise. |
(package private) void |
saveToDisc(java.io.File cacheDir,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
Save (serialise) to disc; throws IOException in case of difficulty. |
(package private) void |
setNeedsSave()
Set the 'needs to be saved to disc' value to be true. |
(package private) int |
size()
Get count of cached exhibits, including partially-cached ones; never negative. |
(package private) boolean |
someFree(java.io.File cacheDir)
Returns true if we have some (not lots of) disc space free. |
void |
validateObject()
Validate fields/state. |
private void |
writeObject(java.io.ObjectOutputStream oos)
Write out a less-redundant form of our internal information. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
private transient java.util.Hashtable<Name.ExhibitFull,CachedFile> cachedExhibits
This is the primary store of data; other (transient) values are derived from it; this is saved to and restored from the serialised form in an efficient and defensive way.
This is a Hashtable for thread-safety.
Compound operations may be made atomic by a lock on this object, but no other lock may be taken while this happens.
Any access that updates this table should be under the instance lock.
private transient java.util.SortedSet<CachedFile> exhibitsLRU
The least-recently-accessed items are first in this list, and are the first to be discarded if the cache becomes over-full.
This is not of itself thread-safe and all access must be under the instance lock.
private transient volatile long totalBytes
Write access restricted to _setTotalBytes(); marked volatile to allow unlocked read access.
private transient volatile long totalBytesHighWaterMark
Write access restricted to _setTotalBytes() and by _setTotalBytesHighWaterMark() and must be under the instance lock.
Marked volatile to allow lock-free read access.
private transient volatile boolean needsSave
Is volatile (so accessed with no lock) only by setNeedsSave() (to set it true) and saveToDisc() (to clear it after a successful save to disc).
private static final boolean USE_EXTANT_DISC_ENTRY_ON_CREATE
static final int MIN_FS_PERCENT_FREE
A value in the range 1-10 is probably good.
private transient volatile Tuple.Triple<java.io.File,java.lang.Long,java.lang.Long> _cFSBHWM_cache
It is in fact assumed that in general:
Marked volatile for thread-safe unlocked access.
private static final int MAX_FS_USABLE_SPACE_CACHE_MS
Pick a prime-ish value to minimise clashes with other activity...
private static final boolean TRY_TO_RETAIN_TN_IN_PURGE
private static final long serialVersionUID
private transient volatile int _fullyCachedCount
Marked volatile to allow thread-safe lock-free access.
Initially zero to force recomputation.
Not serialised.
| Constructor Detail |
|---|
private MetaData()
private MetaData(MetaData other)
other - instance to copy from; never null
private MetaData(AllExhibitProperties aepCurrent,
java.io.File cacheDir,
SimpleLoggerIF logger)
throws java.io.IOException
No locks (ie especially the rwl or cache's instance lock) should be held while this is running.
This does not modify data on disc.
The constructed object is marked as needing to be saved.
This relies in part on being able to find the data files for the cached (prefixes of) exhibits by their valid full exhibit names.
Explicitly attempts to recover any plausible entries corresponding to current AEP entries.
Thus this may miss entries which have no current data file, eg because there were zero bytes cached for that file, and may have to recover such data later as encountered.
Explicitly attempts to recover any plausible entries corresponding to current AEP entries.
aepCurrent - reasonably current AEP as a hint for entries to look for;
never nullcacheDir - the cache top-level directory; never nulllogger - to log to; never null
java.io.IOException - in case of major problems in reconstructing
the cache state (minor problems will be ignored)| Method Detail |
|---|
public static MetaData createMetaData()
public MetaData createLightweightCopy()
Can be used to free up main lock on meta-data more quickly than might otherwise be the case.
The instance returned may not be suitable for performing any operations on other than serialising/saving or verifying against another copy.
Takes lock on the core data while copying it for consistency; not other lock should be required.
Marked public to allow testing.
public static MetaData createMetaData(AllExhibitProperties aepCurrent,
java.io.File cacheDir,
SimpleLoggerIF logger)
throws java.io.IOException
aepCurrent - cacheDir - logger -
java.io.IOExceptionpublic java.util.Set<Name.ExhibitFull> getKnownExhibits()
java.util.List<CachedFile> getExhibitsLRUList()
CachedFile getLeastRecentlyUsed()
throws java.util.NoSuchElementException
java.util.NoSuchElementException
CachedFile getMostRecentlyUsed()
throws java.util.NoSuchElementException
java.util.NoSuchElementExceptionlong getTotalBytesCurrentlyUsedByCache()
private void _setTotalBytes(long newTB)
long getTotalBytesHighWaterMark()
private void _recomputeDerivedValues()
boolean getNeedsSave()
void setNeedsSave()
void saveToDisc(java.io.File cacheDir,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
throws java.io.IOException
Clears needsSave (to false) just before the save, but sets it true again if the save appeared to fail.
cacheDir - specified the top-level cache directory; never null
java.io.IOExceptionint size()
boolean isEmpty()
CachedFile exhibitGetInfo(Name.ExhibitFull name)
This is thread-safe and does not need nor grab any cache locks, but to ensure this data remains valid during any compound operation, at least a read lock should usually be obtained.
name - the exhibit whose meta-data is required; never nullboolean exhibitIsFullyLoaded(ExhibitStaticAttr esa)
This does not grab any cache locks, but to ensure this data remains valid during any compound operation, at least a read lock should generally be obtained.
esa - the exhibit whose meta-data is required; never null
private void _removeCacheRecordFromMemoryCopy(Name.ExhibitFull name)
void _updateCacheRecordInMemoryCopy(CachedFile newCf,
SimpleLoggerIF logger)
Marks the meta-data as needing to be saved.
boolean isEquivalent(MetaData other)
The result is false if the argument is null.
void pruneOrAdjustBadInMemoryCacheRecords(long reloadStartTime,
MetaData newData,
SimpleLoggerIF logger)
throws java.lang.IllegalStateException
This is conservative and removes state from memory that appears absent from disc (eg because stuff is being deleted out from under the process), and updates any record to have the least cached-length seen or current.
The newData instance is considered essentially private to this call and should be marked read-only.
The readWrite status is not altered nor updated by this operation (but will usually be read/write to avoid blocking cache activity)
The needsSave flag may be set by this call.
Only the cache-checking routines should call this at all.
TODO: Allow entries relevant to the current AEP to be added from the disc-based data
reloadStartTime - a time just before the newData was loaded from disc
java.lang.IllegalStateException
CachedFile exhibitMarkAsAccessed(Name.ExhibitFull name,
SimpleLoggerIF logger,
java.io.File cacheDir)
throws java.io.IOException
This call does not access disc (ie affects in-memory status only), and silently does nothing if there is no entry for the named exhibit.
This marks the last-accessed time in the MetaData as now, to be preserved on disc at some point in the future.
This MetaData object is marked as needing to be saved if an exhibit was `touched' successfully.
This is preferably used to:
cacheDir - if not null
then we force an update of a timestamp on disc
as a backup in case the serialised metadata is lost;
this causes extra disc traffic though not necessarily synchronous
java.io.IOException
private boolean _exhibitRemoveLRUCacheEntry(java.io.File cacheDir,
Name.ExhibitFull dontRemoveName,
boolean justData,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
throws java.io.IOException
If the named item is the oldest then we'll remove the next oldest, if there is one.
justData - if true then we try to retain metadata/thumbnails
java.io.IOException
boolean exhibitRemoveCacheEntry(java.io.File cacheDir,
Name.ExhibitFull name,
boolean justData,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
throws java.io.IOException
This will fail if the metaData is read only, or if an entry for the exhibit does not exist in the metadata and on disc.
Since these failures will be by returning false rather than by causing an exception then this can be used as a gentle unconditional way to make sure that an entry does not exist whether or not one did before.
This needs to access disc and so will need to hold the main write lock while it does so, grabbing the metaData instance lock inside the main lock where both need to be held simultaneously.
Can optionally attempt to just remove the exhibit data, leaving metadata and any thumbnails intact.
justData - if true then we try to retain metadata/thumbnails
java.io.IOException
boolean exhibitCreateNewCacheEntry(java.io.File cacheDir,
ExhibitStaticAttr esa,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
throws java.io.IOException
This will fail if the metaData is read only, or if an entry for the exhibit already exists in the metaData or on disc.
Since these failures will be by returning false rather than by causing an exception then this can be used as a gentle unconditional way to make sure that an entry does exist whether or not one did before.
This needs to access disc and so will need to grab a write lock on the main cache lock while it does so, grabbing the metaData instance lock inside the main lock where both need to be held simultaneously.
Marks the meta-data as needing to be saved if a new meta-data entry had to be created...
A write lock should be held on the cache while this is called.
esa - the basic info on the exhibit to have an entry created
java.io.IOException - in case of serious problems
accessing the on-disc cache statelong computeTargetHighWaterMark()
We may further restict cache size to leave a given percentage free in the underlying filesystem.
long computeFreeSpaceBelowLowWaterMark(java.io.File cacheDir)
If we don't trust the GenProps value then the low-water mark is the current actual high-water mark for the cache, ie we try to maintain its size approximately.
Is synchronized to maintain consistency while working.
boolean lotsFree(java.io.File cacheDir)
If we don't trust GenProps this always returns false.
boolean someFree(java.io.File cacheDir)
If we don't trust GenProps this always returns false.
long computeFreeSpaceBelowHighWaterMark(java.io.File cacheDir)
This is thread-safe though may be expensive.
boolean canPrecacheExhibitData(java.io.File cacheDir)
boolean canPrecacheThumbnails(java.io.File cacheDir)
Basically we're prepared to go right up to the wire to generate thumbnails because they are so useful to the user.
We leave a little bit of wiggle room on space.
boolean canPrecache(java.io.File cacheDir)
void purge(GenProps gp,
java.io.File cacheDir,
long howMuch,
Name.ExhibitFull dontPurgeName,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
throws java.io.IOException
This will avoid purging the cache of the item passed to it by name in case it was a candidate for removal.
If the argument is zero this tries to ensure that space for at least one new (empty) exhibit cache entry to be created.
If greater than zero this tries to ensure that an existing cache entry can be extended by at least the given number of bytes (either for the exhibit data or for thumbnail data).
This grabs the instance lock for most of its work.
This will fail if the cache is marked read-only.
howMuch - howMuch space we need to ensure is free; positive
java.io.IOException
ExhibitThumbnails exhibitGetThumbnails(java.io.File cacheDir,
Name.ExhibitFull name,
SimpleLoggerIF logger)
throws java.io.IOException
If a problem is encountered deserialising thumbnails, the cache is not-read-only, and AUTO_REPAIR_DURING_IO is true, we may zap the offending serialised file to try to recreate it later.
Should nominally be in the scope of an appropriate main read lock, but as no metadata change is made then the only risk is a race from the disc cache entry being removed during this call, resulting in an IOException.
java.io.IOException - in case of serious problems
accessing the on-disc cache state,
eg the entry was missing or removed during this call
boolean exhibitSaveThumbnails(GenProps gp,
java.io.File cacheDir,
ExhibitStaticAttr esa,
ExhibitThumbnails tns,
SimpleLoggerIF logger,
StatsLogger.StatsConfig statsIDSCGEN)
throws java.io.IOException
This will fail if the metaData is read only.
If the thumbnails argument is null, this will purge any extant thumbnails for this exhibit.
This will create a new zero-length exhibit entry if necessary.
Since these failures will be by returning false rather than by causing an exception then this can be used as a gentle unconditional way to make sure that an entry does exist whether or not one did before.
A cache write lock will need to be held while this is running.
esa - the basic info on the exhibit to have an entry created
java.io.IOException - in case of serious problems
accessing the on-disc cache state
private void writeObject(java.io.ObjectOutputStream oos)
throws java.io.IOException
The more-efficient on-the-wire format also makes defensive reading easier.
java.io.IOException
private void readObject(java.io.ObjectInputStream in)
throws java.io.IOException,
java.lang.ClassNotFoundException
java.io.IOException
java.lang.ClassNotFoundException
public void validateObject()
throws java.io.InvalidObjectException
Barf if something bad is found. (Maybe allow some extra info in debug version.)
Assumes _recomputeDerivedValues() has been called before this is called since deserialisation or construction.
validateObject in interface java.io.ObjectInputValidationjava.io.InvalidObjectException
int getFullyCachedCount(AllExhibitProperties aep,
boolean force)
Note that since the cached count is not serialised with the metadata then it will need to be recomputed when metadata is loaded/deserialised.
Even without a recomputation being forced, we may decide to do one if it seems that the value might be stale.
This will take time O(n) for an n-exhibit AEP to (re)compute its result, but does minimal or no locking, and none for the duration of the method, so is safe to launch in a background thread for example.
May be expensive (continually recomputing) if/while no exhibit is fully locally cached, but this is assumed to be unlikely in practice.
aep - if non-null, allow recomputation against this AEPforce - if true, force immediate recomputation against this AEP if non-null
|
DHD Multimedia Gallery V1.60.69 | ||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||