|
|||||||||
| 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 pre-cache 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 pre-cacheing 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 backend 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 statisfy requests wholy 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 statisfy 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 precaching until the low-water mark is reached, and by default only deletes existing entries if it has to in order to statisfy 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 bi-directional 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 pre-cache 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. |
private static class |
ExhibitDataSimpleCache.TIMSoftReference
Enqueueable SoftReference for cached-in-memory thumbnails. |
| 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 java.util.concurrent.Future<?> |
_AEPPoller
Future for task fetching _AEP in the background; never null after construction. |
private boolean |
_aggressive
Flag to adjust the aggressiveness of the cache; by default not aggressive. |
private java.util.Set<java.lang.String> |
_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. |
private java.util.concurrent.locks.ReentrantLock |
_gAEP_lock
Private lock for _getAllExhibitProperties()/constructor to prevent re-entry and multiple concurrent AEP fetches. |
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<java.lang.String> |
_iCMEE_iterator
Private iterator over all cached full exhibit names for _incrCheckMRUExhibitEntries(). |
private long |
_lastPollAEP
Last time we polled for AllExhibitImmutableData; initially zero. |
private long |
_lastPollGp
Last time we polled for genProps. |
private long |
_lastPollGSp
Last time we polled for genSecProps. |
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<java.lang.String> |
_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 java.util.concurrent.ConcurrentMap<java.lang.String,java.lang.Object> |
_thumbnailsInMemory
Private in-memory cache of deserialised thumbnails; never null. |
private java.lang.ref.ReferenceQueue<ExhibitThumbnails> |
_tIM_deadRefQueue
Queue of zapped thumbnail SoftReference entries. |
private java.util.concurrent.locks.ReentrantLock |
_tIMT_lock
Lock to avoid more than one active thread in _thumbnailsInMemoryTidy(). |
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 some 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 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 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.ExecutorService |
discardableReadAheadTaskThreadPool
Shared thread pool for I/O-bound activities for Web-driven requests. |
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 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 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 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 minimim time before we will pre-emptively 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_FOR_DATA_PREFETCH
If true, deter 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 |
UPDATE_EPCM_DURING_PRECACHE
Deprecated. Use CALC_MISSING_EPCM_DURING_PRECACHE instead |
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. |
private static long |
WAIT_BETWEEN_THUMBNAIL_REPEAT_FETCHES_MS
Wait time between attempts to fetch or generate thumbnails (ms). |
| 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(java.lang.String 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 the value posted from the 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 given 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. |
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(java.lang.String name,
boolean create,
boolean allowSyncFetch)
Get the thumbnails for an exhibit. |
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<java.lang.String> done)
Incrementally check cached exhibits for integrity. |
private void |
_incrPurgeOrphanedExhibits()
Do incremental purge of orphaned cache entries conditions are right. |
private java.lang.String |
_pickPeer(java.util.Set<java.lang.String> activeMirrors)
Pick one of the supplied peers to attempt to fetch the 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 void |
_thumbnailsInMemoryTidy()
Incrementally purge stale entries from the in-memory thumbnail cache. |
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,
java.lang.String exhibitName,
int position,
boolean dontCache)
Get a chunk of the raw exhibit binary. |
ExhibitStaticAttr |
getStaticAttr(java.lang.String name)
Get the static attributes for a given exhibit. |
ExhibitThumbnails |
getThumbnails(java.lang.String 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. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
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.
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<java.lang.String> _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.
We want performance (ie best throughput) rather than fairness.
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.ExecutorService discardableReadAheadTaskThreadPool
A limited amount of work can be queued, but excess is handled by discarding the oldest queued it