|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectorg.hd.d.pg2k.svrCore.datasource.ExhibitDataSimpleCache
public final class ExhibitDataSimpleCache
Exhibit pipeline cache stage. This performs transparent persistent cacheing of exhibit data and variables.
The presence of an instance of this stage upstream of a tunnel or other potentially slow/expensive/unreliable data source should, for normal data access (eg sequential download of exhibits) significantly reduce upstream bandwidth requirements and reduce downstream latency by answering requests from local cache.
This also attempts to shelter its downstream callers/users from I/O errors upstream, by fulfilling requests from cache, or, when synchronous calls upstream have to be made, transforming some requests and replies into async forms where possible.
When caching exhibit data this class only does so as a continuous prefix from offset zero; other (random) accesses may have to read-through the cache.
This cache is also able to precache data likely to be valuable, such as thumbnails and the initial portions of exhibits, though this will only be attempted if the cache appears to be in use. Bandwidth/resource consumption used by precacheing are regulated. This cache regards thumbnails and meta-data as precious, and tries not to let them go once collected and cached because reasonable application performance will often depend on fast access to these data.
This attempts to cache data well enough that, especially if aggressive (pre)cacheing is available and the cache area is large enough, almost no reference should be needed to the backend server in response to a data request on the pipeline except in response to the tail end of very long exhibits; all requests are answered from the local cache where possible. Ideally, it should be possible for the back-end server to go down altogether and have the front end still provide a high degree of functionality. The front-end and back-end are almost completely decoupled in this cache design.
This includes limited in-memory cacheing, in many cases using soft references to allow peaceful coexistence with other (potentially heavy) users of memory.
This class relies mainly on the asynchronous calls to poll() to fetch meta-data updates such as GenProps and AllExhibitImmutableData. These happen under a private lock and do not block cache access much or at all.
The full lock ordering (where multiple locks need to be taken at once) is:
This cache may serialise access to raw exhibit data (and may serialise accesses to back-end resources too). No two live instances of this class should refer to the same cache directory at once else madness and corruption will almost certainly break out.
On disc, the files are some prefix of the full exhibit, retrieved if possible in MAX_TRANSFER_CHUNK_SIZE chunks. They are touched every time accessed or updated and the timestamps can therefore be used as the basis of an LRU cache. We expect almost all access to be sequential, starting at the beginning.
We satisfy requests wholly within already-cached data immediately, and will extend (up to the limit) by up to one chunk each time by downloading from the server to satisfy requests just beyond the current end. Requests starting well beyond the current end of cache are punted directly to the server, which is rather ugly and slow, but there we go.
This cache only considers general precacheing until the low-water mark is reached, and by default only deletes existing entries if it has to in order to satisfy an incoming cacheable request. This means that stale entries for deleted/renamed exhibits may persist for a while, but this is mainly harmless.
This maintains a bidirectional cache of variable values and updates, and also some running parameters of the cache may be read as variables.
This cache supports a limited amount of peer-to-peer (P2P) data transfers to reduce load on the master. The general policy is that any synchronous (and thus presumably time-sensitive) data request from an end user that cannot be satisfied from local cache is satisfied upstream from the master. Asynchronous data fetches, such as read-ahead and precache activity, can be fetched P2P. Also if the master fails or is unavailable then it may be acceptable to use P2P if loops/cycles can be avoided.
TODO: re-analyse/reduce locking and possibly avoid locks on the metaData object.
| Nested Class Summary | |
|---|---|
private static class |
ExhibitDataSimpleCache.CachedFile
Object representing one (partially) cached file on disc. |
private static class |
ExhibitDataSimpleCache.MetaData
Cache meta-data class. |
| Nested classes/interfaces inherited from interface org.hd.d.pg2k.svrCore.datasource.SimpleExhibitPipelineIF |
|---|
SimpleExhibitPipelineIF.PropsKey |
| Field Summary | |
|---|---|
private AllExhibitProperties |
_AEP
Cached AllExhibitProperties; never null. |
private boolean |
_aggressive
Flag to adjust the aggressiveness of the cache; by default not aggressive. |
private java.util.Set<Name.ExhibitFull> |
_bestExhibits
Contains the full exhibit names of the "best" few exhibits for enhanced precacheing; never null. |
private long |
_checkMetaData_notBefore
Time before which next _checkMetaData() call should not be initiated. |
private java.util.concurrent.locks.ReentrantLock |
_cMD_lock_
Private lock for _checkMetaData() to avoid starting more than one thread; non-null. |
private java.util.concurrent.locks.ReentrantLock |
_gAEP_lock
Private lock for _getAllExhibitProperties()/constructor to prevent re-entry and multiple concurrent AEP fetches. |
private java.util.concurrent.locks.ReentrantLock |
_gTfirstTNBuildLock
A lock to allow only one of concurrent thumbnail builds to assume unlimited resources. |
private java.util.concurrent.locks.ReentrantLock |
_gTFP_lock
Private lock for _getThumbnailsFromPeer() to prevent concurrent P2P thumbnail fetches; never null. |
private static int |
_gXL_offset
Stack offset for _getXXXXLock() to find caller's stack frame. |
private long |
_handleSysVars_evSave
Last time we saved (any) event histories, private to _handleSysVars(), initially zero. |
private java.lang.Long |
_handleSysVars_lastFetch
Last time we flushed/fetched variables, private to _handleSysVars(). |
private java.util.Iterator<Name.ExhibitFull> |
_iCMEE_iterator
Private iterator over all cached full exhibit names for _incrCheckMRUExhibitEntries(). |
private long |
_lastPollAEP
Last time we polled for AllExhibitImmutableData; initially 'now' to postpone first poll. |
private long |
_lastPollGp
Last time we polled for genProps. |
private long |
_lastPollGSp
Last time we polled for genSecProps. |
private java.util.concurrent.locks.ReentrantLock |
_metadataSave_lock_
Lock to prevent concurrent attempts to save metadata; non-null. |
private long |
_noMorePrecacheUntil
Time before which we will not do more precacheing. |
private java.lang.Long |
_precacheExhibitHash
Indicator for which image set we are working on. |
private java.util.Iterator<Name.ExhibitFull> |
_precacheIterator
An iterator over a snapshot of all exhibit names. |
private java.util.concurrent.locks.ReentrantLock |
_preCacheLock
Precache lock to prevent multi-threaded precache runs. |
private long |
_saveMetaData_notBefore
Time before which not to to save metaData again; private to _cleanAndSaveMetaData(). |
private MemoryTools.SoftReferenceMap<Name.ExhibitFull,java.lang.Object> |
_thumbnailsInMemory
Private in-memory cache of deserialised thumbnails; never null. |
private MemoryTools.RecurrentEmergencyFreeHandle |
_timREFH
If we run very low on space then discard the thumbnails and just keep the do-not-retry Long timestamps. |
private boolean |
_userRequestedDataFromCache
Set true when a user requests data from the cache. |
private static boolean |
ALLOW_DATA_FETCH_FROM_PEERS
If true, allow us to try fetching exhibit data from peers rather than master. |
private static boolean |
ALLOW_SYNC_TN_FETCH
If true then allow missing thumbnails to be fetched synchronously at the risk of blocking for extened periods. |
private static boolean |
ALLOW_TN_FETCH_FROM_PEERS
If true, allow us to try fetching thumbnails from peers rather than only the master. |
private java.util.Map<java.lang.String,java.lang.Long> |
altDataSourceRating
Thread-safe Map from mirror ID to strictly-positive rating with "" for master; never null. |
private static boolean |
ASSUME_LOADED_METADATA_OK
If true, assume that newly-loaded meta-data at is OK at start-up until proven otherwise. |
private static java.lang.String |
CACHE_BASE_DIR
Base dir within cache dir for all our exhibit data. |
private static java.lang.String |
CACHE_EXAUX_PREFIX
The prefix for all aux files associated with an exhibit file. |
private static java.lang.String |
CACHE_EXAUX_TIMESTAMP_KW
The keyword for the file containing the (decimal) exhibit timestamp. |
private static java.lang.String |
CACHE_EXAUX_TN_KW
The keyword for the file containing the serialised thumbnails object. |
private static java.lang.String |
CACHE_EXDATA_DIR
Base dir within cache dir for all our raw exhibit content data. |
private static java.lang.String |
CACHE_EXPROPS_FILENAME
Name of file in which to persist immutable exhibit data. |
private static java.lang.String |
CACHE_METADATA_FILENAME
Name of file in which to persist cache meta data. |
private java.io.File |
cacheDir
The cache dir, else null. |
private static boolean |
CALC_MISSING_EPCM_DURING_PRECACHE
If true then try to at least partially compute EPCM while precacheing. |
private long |
consTime
Time of construction. |
private boolean |
destroyed
Set true once destroy() is called; never set false again. |
private static int |
DISC_RECHECK_INTERVAL_MS
Approximate minimum interval between rechecks of on-disc cache. |
private java.util.concurrent.ThreadPoolExecutor |
discardableReadAheadTaskThreadPool
Shared thread pool for I/O-bound activities (for thumbnail fetching). |
private static java.lang.String |
EVENT_HISTORY_DIR
Base dir within cache dir for all our event history data. |
private AllExhibitProperties.ExhibitDataSource |
exhibitDataSource
An AllExhibitProperties.ExhibitDataSource wrapping ourselves; never null. |
private static int |
FALLBACK_MIN_CACHE_SIZE
Minimum cache size to allow if GenProps is not set (bytes). |
private static boolean |
FORCE_IMMEDIATE_SAVE_ON_EXPANDED_METADATA
If true, synchronously force a save of meta-data each time we add a new entry at least. |
private GenProps |
genProps
Our record of the current GenProps; never null. |
private java.util.Properties |
genSecProps
Our record of the current GenProps; never null. |
private static java.lang.String |
KEY_debugFlag_P2P_BLOCKXFER
Key in generic props of P2P-profiling flag. |
private SimpleLoggerIF |
logger
Our local logger; never null. |
private static float |
LOW_WATER_FRACTION
Fraction of max cache size that is the low-water mark. |
private static java.lang.String |
MASTER_FAKE_TAG
Fake tag we use to indicate a fetch from the master/upstream via the pipeline. |
private static int |
MAX_BEST_EX_PRECACHED
Maximum number of "best" exhibits to get enhanced precaching; non-negative. |
private int |
MAX_dPC_BACKOFF_TIME
Max time _doPreCache() has to sleep for (ms). |
private int |
MAX_dPC_SPIN_TIME_MS
Maximum time that _doPreCache() can spend in one go (ms). |
private static int |
MAX_EXTD_TRANSFER_CHUNK_SIZE
Maximum extended exhibit data transfer chunk size (bytes); strictly positive. |
private static int |
MAX_LOCK_ATTEMPTS
Maximum number of consecutive attempts to obtain lock for read or write; strictly positive. |
private static int |
MAX_QUEUED_TN_FETCHES
Maximum number of async thumbnail fetches to queue; strictly positive. |
private static int |
MAX_REMOTE_FETCH_TO_MAKE_THUMBNAIL
The maximum number of bytes we will force a transfer of to force an immediate thumbnail generation. |
private static int |
MAX_THREADS_aTWQ
Maximum number of threads that may run in _asyncTNFetch() and other local discardable data read-ahead tasks; strictly positive. |
private static int |
MAX_TRANSFER_CHUNK_SIZE
Maximum (normal) exhibit data transfer chunk size (bytes); strictly positive. |
private static long |
MAX_WAIT_BETWEEN_THUMBNAIL_REPEAT_FETCHES_MS
Maximum wait time between attempts to fetch or generate thumbnails (ms) by long-running cache; strictly positive. |
private ExhibitDataSimpleCache.MetaData |
metaData
In-memory copy of whole-cache meta-data; never null. |
private static int |
METADATA_MIN_SAVE_INTERVAL_MS
Approximate minimum interval between saves of the metadata; strictly positive. |
private static int |
MIN_AEP_POLL_TIME_UNTIL_LOADED_MS
Minimum time before attempting to poll again for AEP while we don't have a real one loaded (ms). |
private static int |
NEARLY_TOP_FACTOR
Factor/multiplier of peers worse than top that will be considered for fetches routinely; strictly positive. |
private static long |
NORMAL_WAIT_BETWEEN_THUMBNAIL_REPEAT_FETCHES_MS
Normal wait time between attempts to fetch or generate thumbnails (ms) by long-running cache; strictly positive. |
private static boolean |
ORPHANED_EXHIBIT_EXPIRY_ALLOWED
If true then we may purge cached data for exhibits that appear to have been deleted (or renamed). |
private static long |
ORPHANED_EXHIBIT_MIN_UNUSED_TIME_MS
The minimum time before we will preemptively purge orphaned cache entries (ms); strictly positive. |
private int |
P2P_NEXT_BEST_FRAC
Fraction of the time to choose a 2nd-tier peer rather than the best peer; strictly positive. |
private int |
P2P_RND_FRAC
Fraction of the time to pick a peer completely at random; strictly positive. |
private static boolean |
PEER_SELECTION_CAUTIOUS
If true then use a cautious strategy to select a peer to talk to. |
private static int |
PEER_STATS_TC
Time-constant for updating peer fetch time value; strictly positive. |
private static int |
PEER_STATS_UNKNOWN_MS
Default rating/time (ms) for "unknown" data source/mirror/peer; strictly positive. |
private static boolean |
PREFER_PEERS_TO_MASTER_WHERE_POSSIBLE
If true, avoid use of master where peers are available. |
private java.util.concurrent.locks.ReentrantReadWriteLock |
rwl
The read/write lock for the whole cache except system variables; never null. |
static java.lang.String |
SCGNAME_CACHE_VALIDATION
General stats event name: an exhibit in the cache was fully validated against checksums, etc. |
static java.lang.String |
SCGNAME_CACHE_VALIDATION_PART
General stats event name: an exhibit in the cache was partially validated against checksums, etc. |
static java.lang.String |
SCGNAME_CACHEADD
General stats event name: an exhibit was added to the cache. |
static java.lang.String |
SCGNAME_CACHEEVICTLRU
General stats event name: an exhibit was evicted from the cache in LRU order. |
static java.lang.String |
SCGNAME_CACHERAWDATAHIT
General stats event name: cache raw data read hit. |
static java.lang.String |
SCGNAME_CACHERAWDATAMISS
General stats event name: cache raw data read miss. |
static java.lang.String |
SCGNAME_CACHEREM
General stats event name: an exhibit was removed from the cache. |
static java.lang.String |
SCGNAME_CACHEREM_CORRUPT
General stats event name: a corrupt exhibit was removed from the cache. |
static java.lang.String |
SCGNAME_CACHETNHIT
General stats event name: on-disc cache hit for thumbnail. |
static java.lang.String |
SCGNAME_CACHETNMEMHIT
General stats event name: in-memory cache hit for thumbnail. |
static java.lang.String |
SCGNAME_CACHETNMISS
General stats event name: in-memory cache hit for thumbnail. |
static java.lang.String |
SCGNAME_DATAFETCHFROMPEER_PREFIX
General stats event name: fetched a data block from a peer. |
static java.lang.String |
SCGNAME_EXDATAREQIN
General stats event name: incoming request for exhibit data. |
static java.lang.String |
SCGNAME_EXDATAREQINDC
General stats event name: incoming request for exhibit data with "dontCache" flag set. |
static java.lang.String |
SCGNAME_EXTHUCREATED
General stats event name: created thumbnails locally from cached data. |
static java.lang.String |
SCGNAME_EXTHUREQIN
General stats event name: incoming request for exhibit thumbnails. |
static java.lang.String |
SCGNAME_EXTHUREQINDC
General stats event name: incoming request for exhibit thumbnails with "dontCreate" flag set. |
static java.lang.String |
SCGNAME_MDSAVE
General stats event name: an exhibit was evicted from the cache in LRU order. |
static java.lang.String |
SCGNAME_PRECACHEERROR
General stats event name: errors encountered during precaching. |
static java.lang.String |
SCGNAME_PRECACHEEXAMINED
General stats event name: exhibits examined for precaching. |
static java.lang.String |
SCGNAME_PRECACHEEXDATABLOCK
General stats event name: exhibit data block precached. |
static java.lang.String |
SCGNAME_PRECACHERESTART
General stats event name: restarted scanning all exhibits for precaching. |
static java.lang.String |
SCGPREF_PRECACHEEXDATABLOCKFETCHTIME
General stats event name prefix: exhibit data block precache (succesful) fetch time (log2 ms). |
static java.lang.String |
SCGPREF_PRECACHEEXDATABLOCKSRC
General stats event name prefix: exhibit data block precache source (if not from master/upstream). |
static java.lang.String |
SCGPREF_PRECACHEEXDATABLOCKSRCERR
General stats event name prefix: exhibit data block precache source for error (if not from master/upstream). |
private SimpleExhibitPipelineIF |
source
The upstream data source; never null. |
private StatsLogger.StatsConfig |
statsIDSCGEN
The stats set to which we log general cache behaviour. |
private static boolean |
STORE_EXPROPS_GZIPED
If true, store exprops data (and cache metadata) GZIPed to possibly save space and I/O time. |
private static boolean |
THUMBNAIL_ACCESS_UPDATES_ACCESS_TIMESTAMP
If true then accessing a thumbnail marks its exhibit as accessed. |
private static boolean |
TRACE_P2P_ACTIVITY
If true then trace/log P2P activity; defaults to false/off. |
private static boolean |
TRACE_THUMBNAIL_ACTIVITY
If true then trace/log interesting/unusual thumbnail activity; defaults to false/off. |
private static boolean |
TRACE_THUMBNAIL_ACTIVITY_ALL
If true then trace/log all thumbnail activity; defaults to false/off. |
private Stratum |
upstreamStratum
Our stratum cached; never null though may be UNKNOWN. |
private static int |
VAR_CACHE_HOLD_TIME_MS
Variable flush/retrieval interval (ms); strictly positive. |
private PipelineVarMgr |
varMgr
Manages our local cache of variables, etc; never null. |
| Fields inherited from interface org.hd.d.pg2k.svrCore.datasource.SimpleExhibitPipelineIF |
|---|
MAX_USER_READ_SIZE |
| Constructor Summary | |
|---|---|
private |
ExhibitDataSimpleCache(SimpleExhibitPipelineIF dataSource,
java.io.File cacheDir,
SimpleLoggerIF logger)
Wrap a new cache instance around a data source. |
| Method Summary | |
|---|---|
private void |
_asyncTNFetch(Name.ExhibitFull exhibitName)
Attempt to asynchronously fetch/create thumbnail that we have failed to return to the user. |
private void |
_checkMetaData()
Initiates, in the background, a check of the in-memory cache meta data against disc. |
private void |
_cleanAndSaveMetaData(boolean force)
Saves the cache metadata if needed. |
private void |
_doCacheDataValidityTest(AllExhibitProperties aep,
ExhibitStaticAttr esa)
Partly check the cache data (including metadata, tns, etc) for validity. |
private void |
_doPreCache(GenProps gp)
Routine to do incremental pre-cacheing. |
private void |
_getAllExhibitProperties_postUpdate(AllExhibitProperties new_AEP,
boolean inCons)
Accepts a (new) AEP value posted from a background thread. |
private void |
_getAllExhibitProperties()
Attempts to get all exhibit properties if our cached copy may be stale. |
private void |
_getExhibitDataFromUpstreamToPrecache(ExhibitStaticAttr esa,
AllExhibitImmutableData aeid,
GenProps gp,
long start,
int len,
boolean forceIt)
Try to extend cached data for the specified exhibit. |
private void |
_getGenProps()
Attempts to get sysprops if our cached copy may be stale. |
private void |
_getGenSecProps()
Attempts to get gensecprops if our cached copy may be stale. |
(package private) static int |
_getMaximumCacheableBytesForOneExhibit(GenProps gp)
Computes the maximum number of bytes to cache from (the start of) any one exhibit; strictly positive. |
private static void |
_getReadLock(java.util.concurrent.locks.ReentrantReadWriteLock rwl,
java.lang.String detail,
SimpleLoggerIF logger)
Get a cache read lock, complaining/aborting if we have to wait for a long time. |
private ExhibitThumbnails |
_getThumbnails(Name.ExhibitFull name,
boolean create,
boolean allowSyncFetch)
Get the thumbnails for an exhibit; null if not available. |
private ExhibitThumbnails |
_getThumbnailsFromPeer(Name.ExhibitFull name)
Attempt to fetch the specified thumbnails from any peer; may be null if currently unavailable. |
private static void |
_getWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock rwl,
java.lang.String detail,
SimpleLoggerIF logger)
Get the cache write lock, complaining/aborting if we have to wait for a long time. |
private void |
_handleSysVars(boolean force)
Handle (update, sync, persist) system variables as required. |
private void |
_incrCheckMRUExhibitEntries(java.util.Set<Name.ExhibitFull> done)
Incrementally check cached exhibits for integrity. |
private void |
_incrPurgeOrphanedExhibits()
Do incremental purge of orphaned cache entries conditions are right. |
private long |
_instanceLifems()
How long this instance has been alive in milliseconds. |
private java.lang.String |
_pickPeer()
Pick a peer to attempt to fetch exhibit data from; never null. |
private java.lang.String |
_pickPeer(java.util.Set<java.lang.String> activeMirrors)
Pick one of the supplied peers to attempt to fetch exhibit data from; never null. |
private void |
_removeCorruptData(ExhibitDataSimpleCache.CachedFile cf)
Remove cached exhibit data identified as corrupt. |
private void |
_save_AEP()
Save AllExhibitProperties to disc. |
private boolean |
_updateOneExhibit(ExhibitStaticAttr esa,
GenProps gp,
AllExhibitProperties aep,
boolean forceDataFetch)
Update one exhibit incrementally during precaching. |
private void |
_updatePeerStats(java.lang.String peer,
boolean fetchSuccessful,
long timeTaken)
Update data-transfer stats for the given peer. |
static ExhibitDataSimpleCache |
cacheFactory(SimpleExhibitPipelineIF dataSource,
java.io.File cacheDir,
SimpleLoggerIF logger)
Get the an instance copy of this class; may be a singleton. |
void |
destroy()
Shut down the data pipeline. |
AllExhibitImmutableData |
getAllExhibitImmutableData(long oldStamp)
Gets all static exhibit data if its timestamp is not that specified. |
AllExhibitProperties |
getAllExhibitProperties(long oldHash)
Gets set of all exhibit properties if its hash is not that specified. |
EventVariableValue |
getEventValue(SimpleVariableDefinition def,
EventPeriod intervalSelector,
boolean current)
Get the current partial, or previous full, event set at the specified interval; never returns null. |
EventVariableValue[] |
getEventValues(SimpleVariableDefinition def,
EventPeriod intervalSelector,
long intervalNumber,
java.util.BitSet whichValues)
Get the specified event sets for the specified intervals; never null. |
GenProps |
getGenProps(long oldStamp)
Gets the general properties as a GenProps object if its timestamp is not that specified. |
java.util.Properties |
getGenSecProps(long oldStamp)
Gets the security properties as a Properties object if its timestamp is not that specified. |
int |
getLiveCachedExhibitCount()
Return directly the number of partly- or fully- cached exhibits; never negative. |
java.util.Properties |
getProperties(SimpleExhibitPipelineIF.PropsKey key,
long versionID)
Get requested Properties selected by key and versionID. |
void |
getRawFile(java.nio.ByteBuffer buf,
Name.ExhibitFull exhibitName,
int position,
boolean dontCache)
Get a chunk of the raw exhibit binary. |
ExhibitStaticAttr |
getStaticAttr(Name.ExhibitFull name)
Get the static attributes for a given exhibit; null if no such exhibit. |
Stratum |
getStratum()
Return cached stratum; never null. |
ExhibitThumbnails |
getThumbnails(Name.ExhibitFull name,
boolean create)
Gets the thumbnails for an exhibit. |
SimpleVariableValue |
getVariable(SimpleVariableDefinition var)
Get a single variable value; returns null if no such value or wrong type. |
SimpleVariableValue[] |
getVariables(long changedSince)
Get immutable Set of variable values altered on or after a given time, or all for -1. |
private boolean |
isPopularDownload(ExhibitStaticAttr esa)
In the top-N (global) downloads recently, with at least 2 downloads. |
void |
poll(GenProps _gp)
Poll periodically (of the order of a second) to do cache maintenance. |
static void |
rmCache(java.io.File cacheDir)
Remove a persistent cache. |
void |
setAggressive(boolean isAggressive)
Set the aggressiveness of the cache; by default not aggressive. |
void |
setVariable(SimpleVariableValue newValue)
Set variable. |
int |
setVariables(SimpleVariableValue[] newValues)
Update number of variables at once for efficiency. |
void |
syncVariables(boolean force)
Synchronise with upstream values. |
private boolean |
upstreamSourceIsLocal()
Returns true iff upstream is local disc so some operations should be cheap without cacheing. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
private static final boolean TRACE_THUMBNAIL_ACTIVITY_ALL
Can be activated from the command-line.
private static final boolean TRACE_THUMBNAIL_ACTIVITY
Generally shows rare events such as generation of thumbnails and request to save NO_THUMBNAILS values and other non-routine activity.
Forced to true if TRACE_THUMBNAIL_ACTIVITY_ALL is true.
Can be activated from the command-line.
private static final boolean TRACE_P2P_ACTIVITY
Can be activated from the command-line.
private static final boolean ORPHANED_EXHIBIT_EXPIRY_ALLOWED
We will generally only do this if:
We do not rush to delete exhibits' data in case a transient problem has made an exhibit disappear temporarily. (Data for deleted exhibits will in any case eventually be deleted LRU (Least-Recently-Used) if the cache becomes full.)
private static final long ORPHANED_EXHIBIT_MIN_UNUSED_TIME_MS
Add a random component so that all clients do not purge orphans at once!
A value of the order of a few days to a few months is probably reasonable.
private static final java.lang.String CACHE_BASE_DIR
private static final java.lang.String CACHE_EXPROPS_FILENAME
private static final java.lang.String CACHE_METADATA_FILENAME
private static final boolean STORE_EXPROPS_GZIPED
private static final java.lang.String CACHE_EXDATA_DIR
private static final java.lang.String EVENT_HISTORY_DIR
private static final java.lang.String CACHE_EXAUX_PREFIX
private static final java.lang.String CACHE_EXAUX_TIMESTAMP_KW
private static final java.lang.String CACHE_EXAUX_TN_KW
private static final int MAX_TRANSFER_CHUNK_SIZE
Should probably be of the order of a few tens of kBytes to allow efficient transfers on the wire, and a power of two to be more likely to interact efficiently with other caches (and network protocols).
If we use (a small multiple of) the bulk data transfer chunk size this will be reasonably efficient in terms of disc/network traffic, and if we can also keep it aligned to whole chunk boundaries then we may get maximally efficient accesses into disc (etc) data.
private static final int MAX_EXTD_TRANSFER_CHUNK_SIZE
So in this case we may allow the upstream request window to be moved back to patch up the hole from the end of our cached data to the start of the request, thus allowing us to capture the result.
This value should be a small multiple of the MAX_TRANSFER_CHUNK_SIZE.
private static final int MAX_REMOTE_FETCH_TO_MAKE_THUMBNAIL
private static final int FALLBACK_MIN_CACHE_SIZE
private static final boolean THUMBNAIL_ACCESS_UPDATES_ACCESS_TIMESTAMP
If false then only actually reading part of the exhibit itself helps keep the exhibit ``fresh'' in the cache.
private static final int DISC_RECHECK_INTERVAL_MS
A period of the order of at least a day is probably about right; not being exactly a multiple helps to ensure that we do not hit the same time every day, which might otherwise collide with other regular activity. Note that this recheck may take at least several minutes, so we don't want to do it too often!
The chosen interval is less than 2D (including a random component). We use less than a day-multiple to tend to be waiting for energy to become available at a similar time each day, eg from solar PV, when the system is in energy-conserving mode. This seems frequent enough in practice.
private static final int METADATA_MIN_SAVE_INTERVAL_MS
We can postpone a save for a while at the risk that if the system crashes or shuts down during that time and there was a structural change to the cache, we might have to abandon the old metadata and start again, which could be slow and a bit messy (losing some useful though not vital information).
Taking our cue from the old UNIX sync interval of 30s, a value in the range 30s to a few minutes is probably reasonable. Larger values of several minutes help reduce disc (write) activity which may be important for (say) solid-state storage such as Flash.
private final SimpleLoggerIF logger
private final StatsLogger.StatsConfig statsIDSCGEN
public static final java.lang.String SCGNAME_MDSAVE
public static final java.lang.String SCGNAME_CACHEEVICTLRU
public static final java.lang.String SCGNAME_CACHEREM
public static final java.lang.String SCGNAME_CACHEADD
public static final java.lang.String SCGNAME_CACHEREM_CORRUPT
public static final java.lang.String SCGNAME_CACHE_VALIDATION
public static final java.lang.String SCGNAME_CACHE_VALIDATION_PART
public static final java.lang.String SCGNAME_CACHERAWDATAMISS
(It is possible to have a hit and a miss on the same read if part is satisfied from cache and part not.)
public static final java.lang.String SCGNAME_CACHERAWDATAHIT
(It is possible to have a hit and a miss on the same read if part is satisfied from cache and part not.)
public static final java.lang.String SCGNAME_CACHETNHIT
public static final java.lang.String SCGNAME_CACHETNMEMHIT
public static final java.lang.String SCGNAME_CACHETNMISS
public static final java.lang.String SCGNAME_DATAFETCHFROMPEER_PREFIX
public static final java.lang.String SCGNAME_PRECACHERESTART
public static final java.lang.String SCGNAME_PRECACHEEXAMINED
public static final java.lang.String SCGNAME_PRECACHEEXDATABLOCK
public static final java.lang.String SCGPREF_PRECACHEEXDATABLOCKSRC
public static final java.lang.String SCGPREF_PRECACHEEXDATABLOCKSRCERR
public static final java.lang.String SCGPREF_PRECACHEEXDATABLOCKFETCHTIME
public static final java.lang.String SCGNAME_PRECACHEERROR
public static final java.lang.String SCGNAME_EXDATAREQIN
public static final java.lang.String SCGNAME_EXDATAREQINDC
public static final java.lang.String SCGNAME_EXTHUREQIN
public static final java.lang.String SCGNAME_EXTHUREQINDC
public static final java.lang.String SCGNAME_EXTHUCREATED
private static final boolean ASSUME_LOADED_METADATA_OK
private static final boolean FORCE_IMMEDIATE_SAVE_ON_EXPANDED_METADATA
private static final java.lang.String KEY_debugFlag_P2P_BLOCKXFER
private static final int MAX_BEST_EX_PRECACHED
private final java.util.Set<Name.ExhibitFull> _bestExhibits
This is a snapshot of what the "best" exhibits are estimated to be as each precacheing round starts, often based on "quick approximation" data.
The implementation is optimised for fast lookup with "contains()".
Thread-safe.
private final ExhibitDataSimpleCache.MetaData metaData
The instance is never replaced; the state is replaced in-situ if need be to ensure that we never have two instances of this that believe they control the disc cache.
private final SimpleExhibitPipelineIF source
private final java.io.File cacheDir
private final java.util.concurrent.locks.ReentrantReadWriteLock rwl
Any access that may just read the cache need only have a read lock.
Most accesses may have to start by taking a write lock (for example because they may have to fetch data from upstream and insert it into the cache) but can downgrade it to a read lock as soon as they know that they will not be altering the cache at all or any further.
The main exception is any state component held in volatile fields.
Note that the variable store is internally thread-safe and does not require protection by this lock.
Ideally we want performance (ie best throughput) rather than fairness, but starvation of some users is not good.
We generally do not want lock attempts to block forever, which means that we give up attempting to obtain a lock after a given number of attempts (with a maximum time per attempt). While this is intended to prevent to limit delays in the face of I/O problems, this may rescue us from logic errors in extremis.
private static final int MAX_LOCK_ATTEMPTS
private static final int _gXL_offset
private final AllExhibitProperties.ExhibitDataSource exhibitDataSource
private static final int MAX_THREADS_aTWQ
private static final int MAX_QUEUED_TN_FETCHES
private final java.util.concurrent.ThreadPoolExecutor discardableReadAheadTaskThreadPool
A limited amount of work can be queued, but excess is handled by discarding the oldest queued items silently.
The threads in the pool are daemon threads, so will not prevent the JVM from exiting.
All threads can time out (and thus release resources) when idle.
private final java.util.concurrent.locks.ReentrantLock _gAEP_lock
private static final int MIN_AEP_POLL_TIME_UNTIL_LOADED_MS
private volatile AllExhibitProperties _AEP
private transient volatile long _lastPollAEP
private transient volatile long _checkMetaData_notBefore
Volatile for thread-safe access without a lock.
Private to _checkMetaData() and _checkMetaData_postResults().
private final java.util.concurrent.locks.ReentrantLock _cMD_lock_
private transient long _saveMetaData_notBefore
private final java.util.concurrent.locks.ReentrantLock _metadataSave_lock_
private transient java.util.Iterator<Name.ExhibitFull> _iCMEE_iterator
May be null.
Marked transient to avoid being serialised.
private transient volatile long _lastPollGp
private transient volatile long _lastPollGSp
private volatile java.util.Properties genSecProps
private static final long MAX_WAIT_BETWEEN_THUMBNAIL_REPEAT_FETCHES_MS
A value of several times the allowed system latency/skew up to of the order of a day in the expectation of a daily exhibit-accession and thumbnail-build cycle on the server is probably reasonable.
We randomise the value so that different clients will not conflict with one another unduly.
We may wait longer than this when resource-constrained.
We may wait less than this when the cache is relatively young.
private static final long NORMAL_WAIT_BETWEEN_THUMBNAIL_REPEAT_FETCHES_MS
A value of a few minutes is good for this purpose.
We randomise the value so that different clients will not conflict with one another unduly.
We may wait longer than this when resource-constrained.
We may wait less than this when the cache is relatively young.
private final MemoryTools.SoftReferenceMap<Name.ExhibitFull,java.lang.Object> _thumbnailsInMemory
Holding a lock on this object will not prevent updates to it.
This is a mapping:
private final MemoryTools.RecurrentEmergencyFreeHandle _timREFH
We have to hold a reference to the handle to prevent it expiring.
private static final boolean ALLOW_SYNC_TN_FETCH
private final long consTime
private final java.util.concurrent.locks.ReentrantLock _gTfirstTNBuildLock
private final java.util.concurrent.locks.ReentrantLock _gTFP_lock
private final PipelineVarMgr varMgr
private static final int VAR_CACHE_HOLD_TIME_MS
We randomise this a little to help avoid many slaves bothering the master simultaneously.
private transient volatile java.lang.Long _handleSysVars_lastFetch
This is volatile so that we do not need to hold a lock to access it.
private transient volatile long _handleSysVars_evSave
private volatile boolean _aggressive
This can be set false when the system is overloaded to eliminate most effort not strictly necessary.
Volatile to eliminate the need for locking.
private volatile GenProps genProps
Is volatile so can be accessed without a lock.
private static final float LOW_WATER_FRACTION
We will only do precacheing when the cache size is below the low-water mark.
Don't get this too close to 1 to avoid churning the cache when loading large single blocks of data or upon other minor disturbances.
private static final boolean CALC_MISSING_EPCM_DURING_PRECACHE
private static final boolean ALLOW_DATA_FETCH_FROM_PEERS
private static final boolean ALLOW_TN_FETCH_FROM_PEERS
This may allow lateral spread of a thumbnail once any mirror has managed to create one even when the master is unable (eg due to resource restrictions) to make one.
private final java.util.Map<java.lang.String,java.lang.Long> altDataSourceRating
All values are strictly positive.
This is periodically purged of stale data (ie inactive peers) to keep it from growing without bound.
private static final boolean PEER_SELECTION_CAUTIOUS
private static final int PEER_STATS_UNKNOWN_MS
private static final int PEER_STATS_TC
A value that is a power of two may result in more efficient code.
A value from 8 to 256 is probably reasonable.
private static final java.lang.String MASTER_FAKE_TAG
private final int P2P_RND_FRAC
private final int P2P_NEXT_BEST_FRAC
private static final int NEARLY_TOP_FACTOR
private static final boolean PREFER_PEERS_TO_MASTER_WHERE_POSSIBLE
private final java.util.concurrent.locks.ReentrantLock _preCacheLock
private transient volatile long _noMorePrecacheUntil
Initial value of 0 allows precaching to start immediately.
private transient volatile boolean _userRequestedDataFromCache
Accessed without locking; read by _doPreCache() and may be set by a routine that is sure that it has received a user request to fetch exhibit/thumbnail data.
We can reset this if we believe we have finished precaching (or at least a reasonable chunk of precacheing work) for the current exhibit set.
private transient java.util.Iterator<Name.ExhibitFull> _precacheIterator
We access this only from _doPreCache() which is single-threaded, so this need not be thread safe.
We may order the iteration in some way as to try to precache as efficiently as possible, eg smallest or `best' first, or we might store the exhibits in, for example, a shuffled order.
When we get a name from this iterator we must make sure that it still represents a valid exhibit, since the exhibit might have been deleted, for example.
Accessed only by _doPreCache().
private transient java.lang.Long _precacheExhibitHash
If we come across an exhibit that we do some precaching work on, we set this to null.
When we are about to start a new round of precaching and discover this is set to the hash of the current exhibit set, we assume that there was no work to be done and we skip precaching. When the exhibit set changes we will then resume.
Accessed under the rwl by _doPreCache().
private final int MAX_dPC_SPIN_TIME_MS
Precacheing will not generally interfere with interactive operations so we try to make this time large enough to allow the fetch of a block or three of exhibit data over a slow Net link, allowing for RTT and connection setup and bandwidth, etc.
Something of the order of a few seconds may be good.
We radically reduce this for CPU-sensitive (eg cloud) environments.
private final int MAX_dPC_BACKOFF_TIME
A few minutes is probably reasonable.
private volatile Stratum upstreamStratum
Is marked volatile for thread-safe lock-free access.
Updates piggybacked on variable set/fetch work.
private volatile boolean destroyed
| Constructor Detail |
|---|
private ExhibitDataSimpleCache(SimpleExhibitPipelineIF dataSource,
java.io.File cacheDir,
SimpleLoggerIF logger)
throws java.io.IOException
We try to load the cache meta-data and exhibit properties from persisted copies. We can survive without the exhibit properties, but if we can't load our meta data the default value we use is read-only so that we don't trust it until it's been checked against disc, presumably in the background.
java.io.IOException - if cache directory does not exist
and/or cannot be created
(the containing directory passed in must always exist)| Method Detail |
|---|
public int getLiveCachedExhibitCount()
public static ExhibitDataSimpleCache cacheFactory(SimpleExhibitPipelineIF dataSource,
java.io.File cacheDir,
SimpleLoggerIF logger)
throws java.io.IOException,
java.lang.IllegalStateException
If the upstream source is an ExhibitDataFileSource then this instance may assume that data access from the ExhibitDataFileSource is only slightly more expensive than accessing its own local cache (accessing the file source may involve powering-up bulk storage). This will typically be the case on the master for example.
java.lang.IllegalStateException - if this is a singleton,
and a request to create with a different cache dir to an
extant instance is made
java.io.IOException - if cache directory does not exist
and/or cannot be created
(the containing directory passed in must always exist)
public static void rmCache(java.io.File cacheDir)
throws java.io.IOException
Will not remove entries in cacheDir unrelated to the cache.
Do not use this lightly; it may discard gigabytes of useful state.
java.io.IOException - in case of I/O error
private static void _getWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock rwl,
java.lang.String detail,
SimpleLoggerIF logger)
throws java.io.InterruptedIOException
rwl - cache lock; never null
java.io.InterruptedIOException - if the thread is interrupted or locking is aborted
private static void _getReadLock(java.util.concurrent.locks.ReentrantReadWriteLock rwl,
java.lang.String detail,
SimpleLoggerIF logger)
throws java.io.InterruptedIOException
rwl - cache lock; never null
java.io.InterruptedIOException - if the thread is interrupted or locking is aborted
public void getRawFile(java.nio.ByteBuffer buf,
Name.ExhibitFull exhibitName,
int position,
boolean dontCache)
throws java.io.IOException
The name, start byte offset/position and a buffer to fill are supplied.
getRawFile in interface SimpleExhibitPipelineIFposition - must be non-negative and less than the exhibit size in bytesdontCache - if true do not cache locally, unless we have lots of free spacebuf - the buffer into which to read the data;
must be non-null, in put()able state,
and with remaining capacity of at least the requested number of bytesexhibitName - the full name of the exhibit to read from;
never null and must be syntactically valid
java.io.IOException - for requests that cannot be fulfilled because of
I/O restrictions or problems, such as link failure or
an upper bound on the length of a requeststatic int _getMaximumCacheableBytesForOneExhibit(GenProps gp)
No one exhibit is allowed to grow to more than a few percent of the cache space, though this limit may only be checked at each point that an exhibit might be extended in cache.
public final ExhibitStaticAttr getStaticAttr(Name.ExhibitFull name)
Returns null if the named exhibit does not exist.
getStaticAttr in interface SimpleExhibitPipelineIFpublic final AllExhibitImmutableData getAllExhibitImmutableData(long oldStamp)
If no exhibits are currently installed then a default set with a zero timestamp is returned.
If the caller's copy appears to be up-to-date (eg the oldStamp matches that that would have been returned) null is returned.
We get this from our cache of the immutable data rather than going to the source directly. We don't block or hold any locks to fetch this.
getAllExhibitImmutableData in interface SimpleExhibitPipelineIFpublic AllExhibitProperties getAllExhibitProperties(long oldHash)
If no exhibits are currently installed a default set with a zero timestamp is returned.
If the caller's copy appears to be up-to-date (eg the oldHash matches that that would have been returned) null is returned.
We get this from our cache rather than going to the source directly. We don't block or hold any locks to fetch this.
getAllExhibitProperties in interface SimpleExhibitPipelineIFprivate void _getAllExhibitProperties()
We also adaptively attempt to use an AEP diff fetch if one is available (ie if the underlying connection is a tunnel).
private void _getAllExhibitProperties_postUpdate(AllExhibitProperties new_AEP,
boolean inCons)
throws java.io.IOException
Must grab a write lock to (potentially) update/change the cache.
If the static exhibit data was stale then we also clear our in-memory raw-exhibit data cache entirely, to be refilled by slower means.
inCons - if true then this was called from the constructor
so we don't save the AEP nor do some other expensive things
that may rely on external mechanisms not yet set up
java.io.IOException
private void _save_AEP()
throws java.io.IOException
In principle this needs a write lock to alter state on disc. In practice at most one thread at once will ever try to call this, and the serialiseToFile() routine attempts to atomically replace the file, and this can take a long time and thus needlessly block cache activity, so we do not take a cache lock here.
java.io.IOExceptionprivate void _checkMetaData()
Refuses to do the check if it is too soon since the last one or if the cache seems busy.
May postpone a check if the system is short of power or otherwise stressed.
private void _cleanAndSaveMetaData(boolean force)
Aims to avoid saving the metaData more than once every METADATA_MIN_SAVE_INTERVAL_MS, though if no save has taken place for a while then the next save will happen on the next call.
If saving the meta-data is taking a long time this aims to postpone the next save at least a reasonable multiple of that to avoid wasting too much system/CPU/disc bandwidth, though we do put a cap on the maximum delay in case of weirdness...
This may also incrementally purge stale meta-data and data just before the save to avoid the need for an extra meta-data save to account for the purge-induced changes themselves.
This may also pick one or more exhibits at random to spot-check for consistency with the master copy (eg looking for data corruption).
force - if true, force an immediate save to disc before return,
else run asynchronously (if possible, else discard) and never block
private void _incrCheckMRUExhibitEntries(java.util.Set<Name.ExhibitFull> done)
throws java.io.IOException
This concentrates on the most-recently-used cache entries as data corruption in these would probably be the most serious, though may also attempt to systematically scan all cache entries.
This may examine any cached entry.
This may not examine any entry at all if the cache seems to be busy.
This will stop after removing at most one corrupt entry.
done - if not null then this routine adds to this Set
the full name any exhibit that it checks (just before checking)
and avoid checking any exhibit in this Set;
this need not be thread-safe for one unshared instance
java.io.IOException
private void _incrPurgeOrphanedExhibits()
throws java.io.IOException
Doesn't attempt any purging if there is an empty exhibit set or if there is no cache size currently set since this cache may not even be properly initialised yet...
We clear at most one orphaned entry on each call.
java.io.IOExceptionpublic GenProps getGenProps(long oldStamp)
If no fresh props have yet been fetched then a default set with a zero timestamp is returned.
If the caller's copy appears to be up-to-date (eg the oldStamp matches that that we would have been returned) null is returned.
We get this from our cache of the immutable data rather than going to the source directly. So we don't block or grab any lock to fetch this value.
We do not attempt to persist this data since carrying old GenProps values across a restart may be a very poor idea.
getGenProps in interface SimpleExhibitPipelineIF
private void _getGenProps()
throws java.io.IOException
A special case here: if we have a GenProps object with a non-zero timestamp (presumably pulled over from a running master) and then we get one with a zero timestamp, we ignore the new, zero, instance since it probably means that the master has just been restarted and has not yet loaded new GenProps.
This does not need to hold any locks since all the values it touches are volatile.
java.io.IOExceptionpublic java.util.Properties getGenSecProps(long oldStamp)
If no props are currently installed/available a default set with a zero timestamp is returned.
If the caller's copy appears to be up-to-date (eg the oldStamp matches that that would have been returned) null is returned.
We get this from our cache of the immutable data rather than going to the source directly. We don't block or grab any locks to fetch this.
We do not attempt to persist this data since carrying old values across a restart may be a very poor idea.
We wrap this as the defaults to a new Properties object to protect our copy against accidental alteration.
getGenSecProps in interface SimpleExhibitPipelineIF
private void _getGenSecProps()
throws java.io.IOException
java.io.IOException
public ExhibitThumbnails getThumbnails(Name.ExhibitFull name,
boolean create)
This retains a private in-memory cache of deserialised thumbnails held by SoftReference, and it tries first to recover them from there.
This tries to retrieve thumbnails from the cache, and returns them if they are there.
Else, if create is true, this tries to create the thumbnails, cache them, and return the value. But we won't bother unless the main image is fully loaded.
Note that only the read and write of cache is done under lock; the thumbnail generation is unlocked and concurrency is restricted, if at all, by the handler routine(s).
Partly because this routine is called by our own precache routines, we do not regard reading a thumbnail as proving user access to the cache (exhibit data has to be read for that).
getThumbnails in interface SimpleExhibitPipelineIFcreate - if true, and no thumbnail yet exists, try to
create one if possible; else if create is false
only return an existing one and return null if none is to hand
(or possibly allow fetch of pre-built remote one)
private ExhibitThumbnails _getThumbnails(Name.ExhibitFull name,
boolean create,
boolean allowSyncFetch)
This retains a private in-memory cache of deserialised thumbnails held by SoftReference, and it tries first to recover them from there. This is very important to fast delivery of thumbnails for building pages referencing many thumbnails.
This tries to retrieve thumbnails from the cache, and returns them if they are there.
Else, if create is true, this tries to create the thumbnails, cache them, and return the value. But we won't bother unless the main image is fully loaded.
Note that only the read and write of our tn cache is done under lock; the thumbnail generation is unlocked and concurrency is restricted, if at all, by the handler routine(s).
Partly because this routine is called by our own precache routines, we do not regard reading a thumbnail as proving user access to the cache (exhibit data has to be read for that).
create - if true, and no thumbnail yet exists, try to
create one if possible; else if create is false
only return an existing one and return null if none is to hand
(or possibly allow fetch of pre-built remote one)allowSyncFetch - if they then allow a synchronous fetch from upstream
private long _instanceLifems()
private boolean upstreamSourceIsLocal()
private ExhibitThumbnails _getThumbnailsFromPeer(Name.ExhibitFull name)
throws java.io.IOException
This updates the P2P stats as if an exhibit-data-block transfer, which is reasonable since this only attempts a fetch of data, never a create which may take signifiant remote CPU time. Note that only an (IO)Exception (not having null returned) is 'failure'.
This may potentially 'loop' between peers consuming resources uselessly unless some other mechanism is used to prevent such behaviour. However, only one outgoing P2P thumbnail request is allowed at once here, which should limit any such problem and resources consumed by it.
name - full exhibit name; never null
java.io.IOExceptionprivate void _asyncTNFetch(Name.ExhibitFull exhibitName)
This only uses a strictly limited number of threads, but avoids a wait for general precacheing, which may never happen.
exhibitName - full exhibit name; non-null valid exhibit name
private void _handleSysVars(boolean force)
throws java.io.IOException
We recompute local variables when we would be prepared to flush/fetch system variables.
Timing is handled with volatile values, so we do not need to take out any other locks while working.
We rely on the locking within varMgr to ensure consistency, including during the save. Bad things may happen if trying to remove a cache while we are trying to save event histories!
We also use this to recompute any vote/correlation factors and update our notion of this instance's stratum.
force - if true, force an immediate complete save of state upstream,
and to disc (if upstream source not already local)
java.io.IOException
public void setVariable(SimpleVariableValue newValue)
throws java.io.IOException
setVariable in interface BasicVarMgrInterfacejava.lang.IllegalArgumentException - on attempt to:
set variable with value of wrong type or incompatible definition,
set non-existent or read-only variable (or these can be ignored)
java.io.IOException - in case of I/O difficulty
public int setVariables(SimpleVariableValue[] newValues)
throws java.io.IOException
This implementation "fails fast" on the first error.
This implementation never throws an IOException.
setVariables in interface BasicVarMgrInterfacejava.lang.IllegalArgumentException - on attempt to:
set variable with value of wrong type or incompatible definition,
set non-existent or read-only variable (or these can be ignored)
java.io.IOExceptionpublic SimpleVariableValue getVariable(SimpleVariableDefinition var)
This implementation never throws an IOException.
getVariable in interface BasicVarMgrInterfacevar - definition of variable to fetch; never nullpublic SimpleVariableValue[] getVariables(long changedSince)
This may be slow if there are many live variables.
This implementation never throws an IOException.
getVariables in interface BasicVarMgrInterface
public EventVariableValue getEventValue(SimpleVariableDefinition def,
EventPeriod intervalSelector,
boolean current)
The current set is the most timely, but may not contain enough data to be meaningful if the new interval has just started.
The previous set is complete and thus most likely to have enough samples to be useful, but is not completely current.
If the requested event set is not (immediately) available, an empty synthetic one is created and returned. Thus, with this interface, it is not possible to distinguish between there being no events in the given interval or simply no data.
TODO: This attempts to limit the amount of time that may be spent blocking, eg due to upstream I/O issues, but its ability to do so may depend on availability of threads, etc.
getEventValue in interface BasicVarMgrInterfacedef - event definition (must be for an event); never nullintervalSelector - never nullcurrent - if true the current event set is returned,
else the previous complete set is returned
java.lang.IllegalArgumentException - if the request arguments are invalid
public EventVariableValue[] getEventValues(SimpleVariableDefinition def,
EventPeriod intervalSelector,
long intervalNumber,
java.util.BitSet whichValues)
Requests for more than SystemVariables.EVENT_SAMPLES_RETAINED in the past (or for the future!) cannot be satisfied and data will not be returned for them.
Usually not more than SystemVariables.EVENT_SAMPLES_RETAINED samples will be returned in response to any one request as a safety measure.
(An implementation that is not an end-point may go upstream to fetch missing values and cache them to satisfy future requests.)
getEventValues in interface BasicVarMgrInterfacedef - event definition (must be for an event); never nullintervalSelector - never nullintervalNumber - a time (as from System.currentTimeMillis())
which identifies the first interval for which data is potentially
required; if too far in the past or future then possibly no data
will be available,
zero is used to select the "all" bucketwhichValues - each true bit represents a slot for which data is
required, bit 0 indicating data from the slot within which
firstIntervalTime is located, bit 1 the previous slot, etc
public void syncVariables(boolean force)
throws java.io.IOException
Holds no externally-visible locks, but if called by multiple threads this will serialise the calls.
syncVariables in interface SimpleVariablePipelineIFforce - if true, this will force a full sync on the read side
by using getVariables(-1) rather than attempting to choose a
nearer timestamp for efficiency;
the implementation is at liberty to use getVariables(-1)
at any time whatever the argument value,
and almost certainly should use it on the first call
java.io.IOException - if one is received from upstreampublic void setAggressive(boolean isAggressive)
public java.util.Properties getProperties(SimpleExhibitPipelineIF.PropsKey key,
long versionID)
throws java.io.IOException
getProperties in interface SimpleExhibitPipelineIFkey - selector (with possible embedded sub-key)
for desired properties set; never nullversionID - if -1 then map is always returned if available,
else must be non-negative and null is returned if the versionID
presented matches that of the current version
(ie if the caller has presumably got the up-to-date version);
may be a timestamp or a hash or other value,
and by convention is zero only for an empty properties set
java.io.IOException
public void poll(GenProps _gp)
throws java.io.IOException
This routine takes care of calling the upstream poll().
We have to be careful about not restricting servlet callers' concurrency here... We try not to do fetches from the back-end, which may be very slow, with the instance lock, which would shut out all foreground users needlessly.
We ignore the caller's GenProps and fetch and cache our own...
poll in interface SimpleExhibitPipelineIFjava.io.IOException - in case of difficulty, but even if a sub-ordinate
call throws IOException then poll() call should continue
to do as much of its remaining work as reasonably possibleprivate void _doPreCache(GenProps gp)
This relies on the following items being fetched and entirely maintained by other activity/methods, probably under poll():
This will only do any data prefetching while the cache is below the low-water mark, and will limit the amount of client and master resource used.
We won't actually start any precacheing until we see some evidence of user/upstream activity that might eventually benefit from it.
This will also only precache while the "aggressive" flag is set, and this should be set true only when the system is not busy.
This may also involve precomputation/preloading of optional data, though should not be relied in lieu of other methods to keep this fresh, so we may have work to do even if there is no space for prefetching.
This also incrementally checks the cache for consistency with the current exhibit properties, ie timestamp, size, hashes.
When running as a cloud instance, with bandwidth and CPU metered/charged, we may resist precaching exhibit data and all but the most popular thumbnails.
This does not hold a cache lock for its duration, but does hold a private lock to protect its internal state because it must not be multi-threaded; any attempt to run this in a second thread is quietly vetoed.
private final void _doCacheDataValidityTest(AllExhibitProperties aep,
ExhibitStaticAttr esa)
throws java.io.IOException
Checks include length, timestamp, and hashes dependent on the data available.
This is designed to complete reasonably quickly in most cases, to perform an incremental check, removing or in some cases repairing damaged/corrupt/invalid data.
If this finds the cache entry to be broken somehow then this routine may delete the cache entry entirely, or repair the data, or prune back to some valid prefix of the data held, or just remove the corrupt underlying data to leave the metadata to be fixed at a later date.
This will grab locks only as it needs them in order to be as unintrusive as possible.
This is not expected to be needed very often, but is mainly designed to avoid silent disc corruption, and to provide for automatic repair.
aep - the current exhibit properties; never nullesa - the exhibit whose cache data is to be verified; never null
java.io.IOException
private void _removeCorruptData(ExhibitDataSimpleCache.CachedFile cf)
throws java.io.IOException
The metadata will have to get fixed later.
Since this will have to grab a cache write lock and then the metadata lock if it is to remove the corrupt data, the caller must not have a read lock in place for example.
cf - exhibit cache metadata; never null
java.io.IOException
private boolean _updateOneExhibit(ExhibitStaticAttr esa,
GenProps gp,
AllExhibitProperties aep,
boolean forceDataFetch)
throws java.io.IOException
forceDataFetch - if true, strongly encourage data fetch,
ie extension of exhibit data if at all possible
java.io.IOException
private void _getExhibitDataFromUpstreamToPrecache(ExhibitStaticAttr esa,
AllExhibitImmutableData aeid,
GenProps gp,
long start,
int len,
boolean forceIt)
throws java.io.IOException
Also, this may be used to attempt data/error recovery if data cannot be fetched from the master for some reason.
start - byte offset in exhibit to start reading/fetching for; non-negativelen - number of bytes to read; strictly positive.forceIt - if true then we try very hard to get the data from a peer,
for example to help with master/server error recovery
java.io.IOExceptionprivate java.lang.String _pickPeer(java.util.Set<java.lang.String> activeMirrors)
Occasionally this will purge the cached peer stats of anything not in the argument set, with constant amortised cost per call.
activeMirrors - set of mirror tags
(and possible MASTER_FAKE_TAG ("") for the master);
never null, never empty
private java.lang.String _pickPeer()
Occasionally this will purge the cached peer stats of anything not in the argument set.
The master should by preference avoid fetching data from a peer to avoid contaminating the master copy with bad data from any peer. However, if it has a mirror tag, then it may fetch data P2P.
private void _updatePeerStats(java.lang.String peer,
boolean fetchSuccessful,
long timeTaken)
private boolean isPopularDownload(ExhibitStaticAttr esa)
throws java.io.IOException
This uses a combination of hits from the previous and current days.
esa - the exhibit details; never null
java.io.IOExceptionpublic Stratum getStratum()
getStratum in interface SimpleExhibitPipelineIFpublic void destroy()
destroy in interface SimpleExhibitPipelineIF
|
DHD Multimedia Gallery V1.57.21 | ||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||