org.hd.d.pg2k.webSvr.threeD
Class ThreeDLogic

java.lang.Object
  extended by org.hd.d.pg2k.webSvr.threeD.ThreeDLogic
All Implemented Interfaces:
LightweightMetaDataFetchInterface

final class ThreeDLogic
extends java.lang.Object
implements LightweightMetaDataFetchInterface

3D Walkthrough "business-logic" holder. Is designed to be GUI-free and just contain the logic.

Package visible since need be seen only by the main GUI class.


Nested Class Summary
 
Nested classes/interfaces inherited from interface org.hd.d.pg2k.webSvr.threeD.LightweightMetaDataFetchInterface
LightweightMetaDataFetchInterface.GalleryBasicMetaData
 
Field Summary
private  java.lang.Object _c_fT
          Private cache value for fetchTexture().
private  Name.ExhibitFull[] _cache_getExhibitName
          Cache for getExhibitName(); never null.
private  java.util.Map<Name.ExhibitFull,java.lang.ref.SoftReference<javax.media.j3d.Texture>> _cache_getThumbnailImage_sml
          Cache of small thumbnail images for getThumbnailImageAsTexture(); never null.
private  MemoryTools.SimpleLRUMap<Name.ExhibitFull,ROByteArray> _cache_getThumbnailImage_sml_binary
          LRU cache of small thumbnail images for getThumbnailImageAsTexture() in binary form; never null.
private  java.util.Map<Name.ExhibitFull,java.lang.ref.SoftReference<javax.media.j3d.Texture>> _cache_getThumbnailImage_std
          Cache of standard (larger) thumbnail images for getThumbnailImageAsTexture(); never null.
private  long _metaDataCheckTime
          Time after which we should check metadata with server.
private  java.util.BitSet _namesNeeded
          Set of requested exhibit names by ordinal; never null.
private static boolean ALLOW_FALLBACK_FS_FILE_ACCESS
          If true then we can try the local filesystem as a fallback if not in JWS.
private static boolean ALLOW_TEXTURE_FALLBACK
          If true then allow fetchTexture() to return a small thumbnail where the standard one is unavailable.
(package private)  javax.jnlp.BasicService bs
          Handle on JWS basic service; null if none.
private static boolean CACHE_JWS_TN_SML
          If true then allow local persistance of small thumbnails in their binary form using JWS.
private static boolean CACHE_MEM_TN_SML
          If true then allow local cacheing of small thumbnails in their binary form in memory.
private  LightweightMetaDataFetchInterface.GalleryBasicMetaData cachedBasicMetaData
          Cached copy of the basic Gallery meta-data; never null.
private static java.awt.image.BufferedImage defaultTNImage
          Default thumbnail place-holder image; never null.
private static int defaultTNImage_Edge
          Power-of-two edge size of default/absent thumbnail stand-in.
private static javax.media.j3d.Texture defaultTNTexture
          Default thumbnail place-holder image as a texture; never null.
private  SimpleLoggerIF logger
          Reference to central logger; never null.
private static int MAX_SML_TN_CACHE_IN_MEMORY
          Maximum number of small thumbnail binaries to cache in memory to limit resource use; strictly positive.
private static int MAX_TN_CONC_FETCHES
          Maximum number of thumbnails to fetch in parallel; strictly positive.
private static int MIN_TN_RETRY_MS
          Minimum time in milliseconds before retrying a thumbnail fetch after any previous failure to fetch it; strictly positive.
private  java.lang.Thread nameFetchWorker
          Worker thread that does nothing but get names in the background.
private static java.awt.image.BufferedImage notLoadedTNImage
          Thumbnail image for items not yet loaded, minimal power-of-two-edge size; never null.
private static javax.media.j3d.Texture notLoadedTNTexture
          Thumbnail not-loaded image as a texture; never null.
(package private)  javax.jnlp.PersistenceService ps
          Handle on JWS persistence service; null if none.
private  boolean shuttingDown
          Set true when we are shutting down (and never set false again).
(package private)  javax.jnlp.SingleInstanceService sis
          Handle on JWS singleton service; null if none.
private static int TEXTURE_LOADER_FLAGS
          Default flags for loading textures.
private  java.util.Map<Name.ExhibitFull,java.lang.Thread> thumbnailsBeingFetched
          Map of names of exhibits whose thumbnails currently being fetched to the Threads fetching them; never null.
(package private) static int TN_IMAGE_FORMAT
          Thumbnail image format (from Java3D point of view).
(package private) static int TN_SML_IMAGE_DIM
          Thumbnail (small) rendered image width and height, positive power-of-two smaller than TN_STD_IMAGE_DIM.
private static java.lang.String TN_SML_RRURL_PREFIX
          Root-relatve absolute URL prefix for small thumbnails; starts and ends with '/'.
(package private) static int TN_STD_IMAGE_DIM
          Thumbnail (standard) rendered image width and height, positive power-of-two; fixed maximum value for all thumbnails.
private static java.lang.String TN_STD_RRURL_PREFIX
          Root-relatve absolute URL prefix for standard thumbnails; starts and ends with '/'.
private  java.util.Map<Name.ExhibitFull,java.lang.Long> tnNoRetryBefore
          Map of thumbnail's full exhibit name to time before we may attempt to refetch following a failure; never null.
private  long userLastActive
          Last time the user was active in this run, eg in the UI; initially object construction time.
 
Fields inherited from interface org.hd.d.pg2k.webSvr.threeD.LightweightMetaDataFetchInterface
MAX_NAMES_REQUEST
 
Constructor Summary
ThreeDLogic(SimpleLoggerIF logger)
          Package-visible constructor since need be seen only by the main GUI class.
 
Method Summary
private static java.net.URL _adjustURLForMuffin(java.net.URL full)
          Adjust URLs to be suitable for JWS muffins.
private  void _fetchNames(long stopBy, Name.ExhibitFull[] names)
          Fetch all outstanding names that we can, up to the specified time limit.
private  void fetchTexture(Name.ExhibitFull exhibitName, java.util.Map<Name.ExhibitFull,java.lang.ref.SoftReference<javax.media.j3d.Texture>> cache, boolean std)
          Fetch the image/texture synchronously from the server.
 Name.ExhibitFull getExhibitName(int ordinal)
          Fetch the full name of the given numbered exhibit; null if no such exhibit or not currently available.
 Name.ExhibitFull[] getExhibitNames(int[] ordinals)
          Fetch the full name of the given numbered exhibits; each entry null if no such exhibit or not currently available, overall result never null.
 LightweightMetaDataFetchInterface.GalleryBasicMetaData getGalleryBasicMetaData()
          Return cached copy (or EMPTY if none); never null.
(package private)  javax.media.j3d.Texture getThumbnailImageAsTexture(int ordinal, boolean std, boolean lowPriority)
          Get thumbnail image as a power-of-two-side square Texture for given image index.
 long getUserLastActive()
          Get the last time the user was active in this run, eg in the UI; initially zero.
private  void poll()
          Called (by a daemon thread) to perform async activity.
(package private)  void setUserLastActive(java.lang.String doingWhat)
          Note user as active.
(package private)  void shutdown()
          Perform any activity required to shut down cleanly, eg save state.
(package private)  void startup()
          Load any (large) persisted data from a previous execution and start a background worker thread.
 boolean userInactive()
          Returns true iff the user is considered inactive.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

ALLOW_FALLBACK_FS_FILE_ACCESS

private static final boolean ALLOW_FALLBACK_FS_FILE_ACCESS
If true then we can try the local filesystem as a fallback if not in JWS. This can be an aid to development, especially if working off-line.

See Also:
Constant Field Values

logger

private final SimpleLoggerIF logger
Reference to central logger; never null.


bs

final javax.jnlp.BasicService bs
Handle on JWS basic service; null if none. Package-visible so as to be directly usable by GUI classes.


ps

final javax.jnlp.PersistenceService ps
Handle on JWS persistence service; null if none. Package-visible so as to be directly usable by GUI classes.


sis

final javax.jnlp.SingleInstanceService sis
Handle on JWS singleton service; null if none. Package-visible so as to be directly usable by GUI classes.


userLastActive

private volatile long userLastActive
Last time the user was active in this run, eg in the UI; initially object construction time. Volatile for thread-safe access without a lock.


cachedBasicMetaData

private volatile LightweightMetaDataFetchInterface.GalleryBasicMetaData cachedBasicMetaData
Cached copy of the basic Gallery meta-data; never null. Initially EMPTY.

Is volatile for thread-safe lock-free access.


_metaDataCheckTime

private transient volatile long _metaDataCheckTime
Time after which we should check metadata with server. Is volatile for thread-safe lock-free access.


_cache_getExhibitName

private volatile Name.ExhibitFull[] _cache_getExhibitName
Cache for getExhibitName(); never null. Mapping from index to name.

Length should be exhibit count.

This may be cleared (replaced by a new empty list of the right length) when a new exhibit set is detected by a changed hash code.

The data itself behind the reference is logically immutable.

Is volatile for safe lock-free access.


_namesNeeded

private final java.util.BitSet _namesNeeded
Set of requested exhibit names by ordinal; never null. A lock must be held on this instance during any access to it, since BitSet is not inherently thread-safe.

We use our poller thread to fetch names marked as needed.


TN_STD_IMAGE_DIM

static final int TN_STD_IMAGE_DIM
Thumbnail (standard) rendered image width and height, positive power-of-two; fixed maximum value for all thumbnails.

See Also:
Constant Field Values

TN_SML_IMAGE_DIM

static final int TN_SML_IMAGE_DIM
Thumbnail (small) rendered image width and height, positive power-of-two smaller than TN_STD_IMAGE_DIM.

See Also:
Constant Field Values

TN_IMAGE_FORMAT

static final int TN_IMAGE_FORMAT
Thumbnail image format (from Java3D point of view).

See Also:
Constant Field Values

defaultTNImage_Edge

private static final int defaultTNImage_Edge
Power-of-two edge size of default/absent thumbnail stand-in.

See Also:
Constant Field Values

defaultTNImage

private static final java.awt.image.BufferedImage defaultTNImage
Default thumbnail place-holder image; never null.


TEXTURE_LOADER_FLAGS

private static final int TEXTURE_LOADER_FLAGS
Default flags for loading textures. Using BY_REFERENCE may reduce memory usage (and make the texture cache work better) at the cost of some rendering performance.

See Also:
Constant Field Values

defaultTNTexture

private static final javax.media.j3d.Texture defaultTNTexture
Default thumbnail place-holder image as a texture; never null.


notLoadedTNImage

private static final java.awt.image.BufferedImage notLoadedTNImage
Thumbnail image for items not yet loaded, minimal power-of-two-edge size; never null.


notLoadedTNTexture

private static final javax.media.j3d.Texture notLoadedTNTexture
Thumbnail not-loaded image as a texture; never null.


MAX_SML_TN_CACHE_IN_MEMORY

private static final int MAX_SML_TN_CACHE_IN_MEMORY
Maximum number of small thumbnail binaries to cache in memory to limit resource use; strictly positive. Each small thumbnail image binary may take up to about 4kBytes.

We cap this to a fraction (~20%) of estimated total JVM memory available, though ensure that a we always set a minimum useful size. (If maxMemory() is not limited/set then we use totalMemory().)


_cache_getThumbnailImage_sml_binary

private final MemoryTools.SimpleLRUMap<Name.ExhibitFull,ROByteArray> _cache_getThumbnailImage_sml_binary
LRU cache of small thumbnail images for getThumbnailImageAsTexture() in binary form; never null. We hold the binary (compressed) format of the thumbnails, hoping that this does not exhaust memory, so that we can more-or-less guarantee to show something quickly once it has been loaded.

A zero-length entry indicates a permanent failure to load the thumbnail.


_cache_getThumbnailImage_sml

private final java.util.Map<Name.ExhibitFull,java.lang.ref.SoftReference<javax.media.j3d.Texture>> _cache_getThumbnailImage_sml
Cache of small thumbnail images for getThumbnailImageAsTexture(); never null. Mapping from full exhibit name to SoftReference to the standard (larger) thumbnail/texture.

We use a non-strong reference because the memory requirements may be large and unpredictable.

TODO: This should be purged of stale entries periodically and/or when a new exhibit set is detected by a changed hash code in case those entries refer to exhibits that no longer exist.

Thread-safe.


_cache_getThumbnailImage_std

private final java.util.Map<Name.ExhibitFull,java.lang.ref.SoftReference<javax.media.j3d.Texture>> _cache_getThumbnailImage_std
Cache of standard (larger) thumbnail images for getThumbnailImageAsTexture(); never null. Mapping from full exhibit name to SoftReference to the standard (larger) thumbnail/texture.

We use a non-strong reference because the memory requirements may be large and unpredictable.

TODO: This should be purged of stale entries periodically and/or when a new exhibit set is detected by a changed hash code in case those entries refer to exhibits that no longer exist.

Thread-safe.


MAX_TN_CONC_FETCHES

private static final int MAX_TN_CONC_FETCHES
Maximum number of thumbnails to fetch in parallel; strictly positive. Too large a number may overwhelm (or be rejected by) the server.

Set to more than the number of available processors, to help make use of available resources and overcome I/O latency, though capped to protect our resources and those of the server.


thumbnailsBeingFetched

private final java.util.Map<Name.ExhibitFull,java.lang.Thread> thumbnailsBeingFetched
Map of names of exhibits whose thumbnails currently being fetched to the Threads fetching them; never null. Thread-safe.

This may be shared with other per-exhibit threads.

The size of this should never be larger than MAX_TN_CONC_FETCHES.


MIN_TN_RETRY_MS

private static final int MIN_TN_RETRY_MS
Minimum time in milliseconds before retrying a thumbnail fetch after any previous failure to fetch it; strictly positive.

See Also:
Constant Field Values

tnNoRetryBefore

private final java.util.Map<Name.ExhibitFull,java.lang.Long> tnNoRetryBefore
Map of thumbnail's full exhibit name to time before we may attempt to refetch following a failure; never null. Thread-safe.


TN_STD_RRURL_PREFIX

private static final java.lang.String TN_STD_RRURL_PREFIX
Root-relatve absolute URL prefix for standard thumbnails; starts and ends with '/'.

See Also:
Constant Field Values

TN_SML_RRURL_PREFIX

private static final java.lang.String TN_SML_RRURL_PREFIX
Root-relatve absolute URL prefix for small thumbnails; starts and ends with '/'.

See Also:
Constant Field Values

ALLOW_TEXTURE_FALLBACK

private static final boolean ALLOW_TEXTURE_FALLBACK
If true then allow fetchTexture() to return a small thumbnail where the standard one is unavailable.

See Also:
Constant Field Values

CACHE_JWS_TN_SML

private static final boolean CACHE_JWS_TN_SML
If true then allow local persistance of small thumbnails in their binary form using JWS. As of 200603 there seems to be a problem storing more than 255 muffins total!

See Also:
Constant Field Values

CACHE_MEM_TN_SML

private static final boolean CACHE_MEM_TN_SML
If true then allow local cacheing of small thumbnails in their binary form in memory.

See Also:
Constant Field Values

_c_fT

private transient volatile java.lang.Object _c_fT
Private cache value for fetchTexture().


nameFetchWorker

private final java.lang.Thread nameFetchWorker
Worker thread that does nothing but get names in the background. Exits when this is shut down.


shuttingDown

private volatile boolean shuttingDown
Set true when we are shutting down (and never set false again).

Constructor Detail

ThreeDLogic

ThreeDLogic(SimpleLoggerIF logger)
Package-visible constructor since need be seen only by the main GUI class.

Parameters:
logger - reference to central logger; never null
Method Detail

getUserLastActive

public long getUserLastActive()
Get the last time the user was active in this run, eg in the UI; initially zero. No harm in letting everyone see this, so is public.

When the user has not been active for a long time, some activities, such as polling the server, may halt or slow down to conserve resources.


setUserLastActive

void setUserLastActive(java.lang.String doingWhat)
Note user as active. Made package-visible (ie not public) for security.

This may be triggered/called by a number of events that indicate that the user is active.

When the user has not been active for a long time, some activities, such as polling the server, may halt or slow down to conserve resources.


userInactive

public boolean userInactive()
Returns true iff the user is considered inactive. This is used to reduce load on the server (and the user's machine) if they have not used the interace for circa several minutes.


getGalleryBasicMetaData

public LightweightMetaDataFetchInterface.GalleryBasicMetaData getGalleryBasicMetaData()
Return cached copy (or EMPTY if none); never null. This value is always returned from cache, ie we never block or go over the Net to get it, so this call is always fast.

Specified by:
getGalleryBasicMetaData in interface LightweightMetaDataFetchInterface

getExhibitName

public Name.ExhibitFull getExhibitName(int ordinal)
Fetch the full name of the given numbered exhibit; null if no such exhibit or not currently available. The range is zero to numberOfExhibits-1.

This assumes that there is a sensible stable ordering of exhibits, probably in "smart-sorted" order or similar.

This ordering is fixed from one exhibit set to the next, ie is stable while the exhibit set hash remains unchanged.

This may go across the Net to fetch its values, so may block for a while. (We aim to cache responses, however, so that repeated retrieval of the same value should be quick, at least until the exhibit set changes.)

Specified by:
getExhibitName in interface LightweightMetaDataFetchInterface

getExhibitNames

public Name.ExhibitFull[] getExhibitNames(int[] ordinals)
Fetch the full name of the given numbered exhibits; each entry null if no such exhibit or not currently available, overall result never null. The range for each item is 0 to numberOfExhibits-1.

This assumes that there is a sensible stable ordering of exhibits, probably in "smart-sorted" order or similar.

This ordering is fixed from one exhibit set to the next, ie is stable while the exhibit set hash remains unchanged.

Specified by:
getExhibitNames in interface LightweightMetaDataFetchInterface

getThumbnailImageAsTexture

javax.media.j3d.Texture getThumbnailImageAsTexture(int ordinal,
                                                   boolean std,
                                                   boolean lowPriority)
Get thumbnail image as a power-of-two-side square Texture for given image index. Returns a logically-read-only RGB-format image for the given exhibit in a fixed-size (maximum dimension for a standard thumbnail) rect.

This routine assumes that the caller will never alter the result, so instances can be safely cached/shared.

If the exhibit does not exist or a thumbnail is not available then this returns a standard "grey"/not-present image.

An out-of-range request returns a different "not-loaded" image.

The underlying image is (re)fetched from the server and cached as need be which should be largely invisible to the Java3D rendering engine.

This may release image data that is not used for a long time.

This fetches low-priority requests only when not fetching any others.

Kept package-visible-only for now.

Parameters:
ordinal - index of thumbnail texture to retrieve, else -1 to get standard "not-yet-fetched" thumbnail texture
std - if true then fetch standard thumbnail, else small
lowPriority - fetch the texture only if the system is quiet
Returns:
null if currently fetching image or too busy to do so, else the thumbnail as a texture if available else a standard "no-image" texture

_adjustURLForMuffin

private static java.net.URL _adjustURLForMuffin(java.net.URL full)
                                         throws java.net.MalformedURLException
Adjust URLs to be suitable for JWS muffins. JWS does not seem to like directory components, so we flatten the URL at some slight risk of ambiguity.

Throws:
java.net.MalformedURLException

fetchTexture

private void fetchTexture(Name.ExhibitFull exhibitName,
                          java.util.Map<Name.ExhibitFull,java.lang.ref.SoftReference<javax.media.j3d.Texture>> cache,
                          boolean std)
Fetch the image/texture synchronously from the server. Caches the image if successful, else leaves the cache slot alone.

This never deletes cache entries.

This may try to fall back to the small thumbnail if the large one cannot be fetched...

Parameters:
exhibitName - the full valid name of the exhibit
cache - the cache to save the texture in
std - if true then fetch standard thumbnail, else small

startup

void startup()
Load any (large) persisted data from a previous execution and start a background worker thread. Do this as early as possible after construction, and preferably before allowing (much) user interaction.

We spin this off into a separate thread to avoid blocking startup.

This should be called at most once.

Package-visible so as to be directly usable by GUI classes.


poll

private void poll()
Called (by a daemon thread) to perform async activity. This is not Swing-safe, and does not block Swing if blocked.

This is not called until construction is complete.

Package-visible so as to be directly usable by the main GUI class.


_fetchNames

private void _fetchNames(long stopBy,
                         Name.ExhibitFull[] names)
Fetch all outstanding names that we can, up to the specified time limit. It is safe to run two or more of these concurrently, though there is a small risk of races causing duplicate fetches. Note really efficient at high levels of concurrency.


shutdown

void shutdown()
Perform any activity required to shut down cleanly, eg save state. This should try to avoid taking a long time.

Package-visible so as to be directly callable by the main GUI class.


DHD Multimedia Gallery V1.57.21

Copyright (c) 1996-2011, Damon Hart-Davis. All rights reserved.