org.hd.d.pg2k.clApp.uploader
Class UploaderLogic

java.lang.Object
  extended by org.hd.d.pg2k.clApp.uploader.UploaderLogic

final class UploaderLogic
extends java.lang.Object

Uploader "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
private  class UploaderLogic.UploaderWorkerThread
          Uploader worker thread.
(package private) static class UploaderLogic.UploadStatus
          Details of one selected file being uploaded; immutable except for progress value.
 
Field Summary
private  AllExhibitProperties aep
          Exhibit properties; never null.
private static int AEP_EXPANSION_BYTES
          Number of bytes of expansion room we allow for one growth in the AEP; non-negative.
(package private)  javax.jnlp.BasicService bs
          Handle on JWS basic service; null if none.
private  java.lang.Boolean connectionGood
          Note of polled connection state; TRUE is good, FALSE is bad, null is unknown.
(package private)  java.lang.String DEFAULT_EXHIBIT_NAME
          Default exhibit name when there is an empty AEP.
(package private)  javax.jnlp.ExtendedService exs
          Handle on JWS extended service; null if none.
private static java.lang.String FNAME_AEP
          Name under the codebase where we persist the AEP.
private static java.lang.String FNAME_MAIN_PROPS
          Name under the codebase where we persist the properties/preferences.
(package private)  javax.jnlp.FileOpenService fos
          Handle on JWS file-open service; null if none.
private  GenProps gp
          Generic properties; never null.
private  UploaderLogic.UploadStatus[] inProgressSlots
          Our current uploads-in-progress; never null and always MAX_CONC_UPLOADS long.
private  long lastAEPUpdatePoll
          Time we last polled for GP/AEP updates.
(package private)  SimpleLoggerIF logger
          Reference to central logger; never null.
private static int MAX_AEP_POLL_MS
          Maximum interval between polls for new values of AEP (and GP); strictly positive.
(package private) static int MAX_CONC_UPLOADS
          Maximum simultaneous uploads (to overcome network latency, etc); strictly positive.
private  java.lang.String passwd
          Our private note of the password supplied.
(package private)  UploaderProps props
          Persistence properties; never null.
(package private)  javax.jnlp.PersistenceService ps
          Handle on JWS persistence service; null if none.
(package private)  SelectedFilesDB selectedFiles
          Database of selected files; never null.
(package private)  javax.jnlp.SingleInstanceService sis
          Handle on JWS singleton service; null if none.
private  java.util.concurrent.atomic.AtomicLong smoothedUploadSpeedBps
          Current smoothed upload performance in bytes-per-second, initially -1; never null.
private static int TC_SUSB
          Time-constant for updating smoothedUploadSpeedBps; strictly positive.
(package private)  ExhibitDataHTTPTunnelSource tunnel
          Our end of main tunnel to server; null if no tunnel possible.
private  java.util.Set<ROByteArray> uploadedHashesMD5
          Set of MD5 hashes of exhibits already uploaded (or rejected as duplicate content); never null.
private  java.util.List<java.lang.Thread> uploaderWorkerThreads
          Our (daemon) uploader worker threads started by startup(); never null.
(package private)  SelectedFilesDB uploadingFiles
          Database of files queued for upload; never null.
private  java.lang.String userID
          Our private copy of the (less sensitive) valid user ID, or null if none or invalid ID/pass presented.
private  boolean userIDChanged
          Set whenever the userID changes; cleared when we have attempted to test the connection.
private  long userLastActive
          Last time the user was active in this run, eg in the UI; initially zero.
 
Constructor Summary
UploaderLogic(SimpleLoggerIF logger)
          Package-visible constructor since need be seen only by the main GUI class.
 
Method Summary
(package private)  java.lang.String addSelectedFiles(boolean autoGuessFormat, javax.jnlp.FileContents[] files, UploadInfoBean uib)
          Propose/select/add selected files for upload.
private  void cacheAEP(AllExhibitProperties aepToSave)
          Save/cache local copy of AEP in persistent store.
(package private)  boolean checkIfAlreadyUploadedByHashMD5(ROByteArray hashMD5)
          Check (using the content MD5 hash) if a putative exhibit has already been uploaded (or rejected as duplicate content).
(package private)  AllExhibitProperties getAep()
          Get the current AEP (exhibit properties); never null.
(package private)  int getCompletedUploadsThisSession()
          Get number of exhibits successfully uploaded this session; non-negative.
(package private)  GenProps getGenProps()
          Get the current set of GenProps (generic system properties); never null.
(package private)  UploaderLogic.UploadStatus getInProgressSlot(int index)
          Get the current contents of an in-progress slot; may return null.
(package private)  long getSmoothedUploadSpeedBps()
          Get current smoothed upload performance in bytes-per-second, initially -1.
 long getUserLastActive()
          Get the last time the user was active in this run, eg in the UI; initially zero.
private static java.net.URL makeAEPURL(javax.jnlp.BasicService bs)
          Make the AEP persistence URL; only viable when in JWS/JNLP.
private static java.net.URL makePropsURL(javax.jnlp.BasicService bs)
          Make the props persistence URL; only viable when in JWS/JNLP.
(package private)  void poll()
          Called (by a daemon thread) to perform async activity.
private  void saveProperties()
          Save persistent properties (if possible).
(package private)  void setAuthenticationInfo(java.lang.String userID, char[] passwd)
          Set authentication information for this user.
(package private)  void setUserLastActive(java.lang.String doingWhat)
          Note user as active.
(package private)  boolean shortNameValidAndUnique(java.lang.String newShortName)
          Returns true if this (short) exhibit name is valid and unique.
(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.
(package private)  void uibIncNumberIfNotZeroWhileNotUnique(UploadInfoBean uib)
          If our name is not unique then increment the number-in-series (if non-zero) until we get a unique name.
private  void updateSmoothedUploadSpeedBps(long Bps)
          Update our notion of mean upload speed (in bytes per second).
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

logger

final SimpleLoggerIF logger
Reference to central logger; never null. We make this package-visible, though the preferred access is via the Main class.


props

final UploaderProps props
Persistence properties; never null. Package-visible so as to be directly usable by GUI classes.


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.


fos

final javax.jnlp.FileOpenService fos
Handle on JWS file-open 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.


exs

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


tunnel

final ExhibitDataHTTPTunnelSource tunnel
Our end of main tunnel to server; null if no tunnel possible. Package-visible so as to be directly usable by GUI classes.


TC_SUSB

private static final int TC_SUSB
Time-constant for updating smoothedUploadSpeedBps; strictly positive. The larger this is, the more smoothed is the computed value.

A value of 1 gives no smoothing at all.

A power of two may result in very slightly faster computations.

A value in the range 2 to 64 is probably good.

See Also:
Constant Field Values

smoothedUploadSpeedBps

private final java.util.concurrent.atomic.AtomicLong smoothedUploadSpeedBps
Current smoothed upload performance in bytes-per-second, initially -1; never null. Initially -1 before any exhibit is uploaded. Thereafter updated via a smoothing (low-pass-filter) algorithm to reflect recent history.

This represents a conservative performance measure, ie including overheads such as connection set-up time, but not dead time between uploads.

AtomicLong allows thread-safe lockless access for read and write.


uploadedHashesMD5

private final java.util.Set<ROByteArray> uploadedHashesMD5
Set of MD5 hashes of exhibits already uploaded (or rejected as duplicate content); never null. This information currently does not persist from one run to the next, so can be cleared by restarting the app.

Private so as to prevent accidental deletion of entries!

Thread-safe.


MAX_CONC_UPLOADS

static final int MAX_CONC_UPLOADS
Maximum simultaneous uploads (to overcome network latency, etc); strictly positive. A value of much higher than 2 is more likely to cause network congestion than actually fix anything, so a value of 1 or 2 is probably optimal.

See Also:
Constant Field Values

uploaderWorkerThreads

private final java.util.List<java.lang.Thread> uploaderWorkerThreads
Our (daemon) uploader worker threads started by startup(); never null.


inProgressSlots

private final UploaderLogic.UploadStatus[] inProgressSlots
Our current uploads-in-progress; never null and always MAX_CONC_UPLOADS long. Each uploader worker thread controls the content of the slot/index indicated by its own index.

A slot is empty when not in use; all slots are initially empty.

Private so as to prevent accidental deletion of entries!

All access to the contents of this array should grab a lock on this array to ensure that an up-to-date/valid view is seen.

Worker threads keep a lock on this while looking for a file to start uploading, and thus the uploadingFiles instance lock may be grabbed inside this one; the reverse is not allowed so as to avoid deadlocks.


FNAME_MAIN_PROPS

private static final java.lang.String FNAME_MAIN_PROPS
Name under the codebase where we persist the properties/preferences.

See Also:
Constant Field Values

FNAME_AEP

private static final java.lang.String FNAME_AEP
Name under the codebase where we persist the AEP.

See Also:
Constant Field Values

selectedFiles

final SelectedFilesDB selectedFiles
Database of selected files; never null. Package-visible for direct manipulation by GUI classes.

Thread-safe.


uploadingFiles

final SelectedFilesDB uploadingFiles
Database of files queued for upload; never null. Package-visible for direct manipulation by GUI classes.

Thread-safe.


userLastActive

private volatile long userLastActive
Last time the user was active in this run, eg in the UI; initially zero. Volatile to allow access without a lock.


DEFAULT_EXHIBIT_NAME

final java.lang.String DEFAULT_EXHIBIT_NAME
Default exhibit name when there is an empty AEP.

See Also:
Constant Field Values

userID

private volatile java.lang.String userID
Our private copy of the (less sensitive) valid user ID, or null if none or invalid ID/pass presented.


passwd

private volatile java.lang.String passwd
Our private note of the password supplied.


userIDChanged

private volatile boolean userIDChanged
Set whenever the userID changes; cleared when we have attempted to test the connection. This is not critical, and may suffer races.

This is simply a device to try to get a new user ID/passwd tested quietly in the background.


aep

private volatile AllExhibitProperties aep
Exhibit properties; never null. Set by poll().

Volatile so as to be safe to access without a lock if need be.


gp

private volatile GenProps gp
Generic properties; never null. Set and used by poll().

Volatile so as to be safe to access without a lock if need be.


connectionGood

private volatile java.lang.Boolean connectionGood
Note of polled connection state; TRUE is good, FALSE is bad, null is unknown. Set and used by poll().

Volatile so as to be safe to access without a lock if need be.


lastAEPUpdatePoll

private volatile long lastAEPUpdatePoll
Time we last polled for GP/AEP updates. Set and used by poll() and used to put off another poll, so should always be set after a successful poll, but may also be set after some unsuccessful polls to reduce traffic to an unhappy master.

Volatile so as to be safe to access without a lock if need be.


MAX_AEP_POLL_MS

private static final int MAX_AEP_POLL_MS
Maximum interval between polls for new values of AEP (and GP); strictly positive. Relatively short for this interactive application.

Short enough to capture an AEP generated asynchronously for us at the server side of the HTTP tunnel.

We may suspend polling entirely if the UI/app appears to be idle.


AEP_EXPANSION_BYTES

private static final int AEP_EXPANSION_BYTES
Number of bytes of expansion room we allow for one growth in the AEP; non-negative. We can do this so that we do not ask the JNLP/user too often for expanded storage space.

Should typically allow for a few days' growth as new exhibits are added.

See Also:
Constant Field Values
Constructor Detail

UploaderLogic

UploaderLogic(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

getSmoothedUploadSpeedBps

final long getSmoothedUploadSpeedBps()
Get current smoothed upload performance in bytes-per-second, initially -1. Initially -1 before any exhibit is uploaded. Thereafter updated via a smoothing (low-pass-filter) algorithm to reflect recent history.

This represents a conservative performance measure, ie including overheads such as connection set-up time, but not dead time between uploads.

This is thread-safe and lock-free.

Package-visible to allow access by GUI classes.


updateSmoothedUploadSpeedBps

private void updateSmoothedUploadSpeedBps(long Bps)
Update our notion of mean upload speed (in bytes per second). The argument must be non-negative, and should be conservative, ie including overheads such as connection set-up time, but not dead time between uploads.

This will be used to update a smoothed performance measure.

This tries to allow for concurrent uploads, ie where the total throughput is shared by several workers.

This is thread-safe and lock-free.

Parameters:
Bps - non-negative speed of upload in bytes per second

checkIfAlreadyUploadedByHashMD5

boolean checkIfAlreadyUploadedByHashMD5(ROByteArray hashMD5)
Check (using the content MD5 hash) if a putative exhibit has already been uploaded (or rejected as duplicate content). Package-visible so as to be directly usable by GUI classes.


getCompletedUploadsThisSession

int getCompletedUploadsThisSession()
Get number of exhibits successfully uploaded this session; non-negative.


getInProgressSlot

UploaderLogic.UploadStatus getInProgressSlot(int index)
Get the current contents of an in-progress slot; may return null. Package-visible so as to be directly usable by GUI classes.


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.


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.


makePropsURL

private static java.net.URL makePropsURL(javax.jnlp.BasicService bs)
                                  throws java.io.IOException
Make the props persistence URL; only viable when in JWS/JNLP.

Throws:
java.io.IOException

makeAEPURL

private static java.net.URL makeAEPURL(javax.jnlp.BasicService bs)
                                throws java.io.IOException
Make the AEP persistence URL; only viable when in JWS/JNLP.

Throws:
java.io.IOException

setAuthenticationInfo

void setAuthenticationInfo(java.lang.String userID,
                           char[] passwd)
Set authentication information for this user. To set authentication arguments must be non-null and non-empty, else all arguments must be null to clear authentication data.

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

Ignored if there is no tunnel.


getAep

AllExhibitProperties getAep()
Get the current AEP (exhibit properties); never null.


getGenProps

GenProps getGenProps()
Get the current set of GenProps (generic system properties); never null.


poll

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.


cacheAEP

private void cacheAEP(AllExhibitProperties aepToSave)
               throws java.io.IOException
Save/cache local copy of AEP in persistent store. This is only possible if the PersistenceService is available, else this call is ignored.

This save may be prevented on grounds of size, etc, by the JNLP runtime.

This should NOT be called by more than one thread at once.

Parameters:
aepToSave - AEP to save; usually not null
Throws:
java.io.IOException

shortNameValidAndUnique

boolean shortNameValidAndUnique(java.lang.String newShortName)
Returns true if this (short) exhibit name is valid and unique. The name has to be syntactically valid, and the short name (and thus the whole name that contains it) not currently present in:
  • The Gallery exhibit set (the main AEP).
  • The uploading-files list.
  • The selected-files list.


  • uibIncNumberIfNotZeroWhileNotUnique

    void uibIncNumberIfNotZeroWhileNotUnique(UploadInfoBean uib)
    If our name is not unique then increment the number-in-series (if non-zero) until we get a unique name. This checks the (short) name against the AEP and other databases.


    addSelectedFiles

    java.lang.String addSelectedFiles(boolean autoGuessFormat,
                                      javax.jnlp.FileContents[] files,
                                      UploadInfoBean uib)
    Propose/select/add selected files for upload. Takes one or more files somehow selected by the user (eg with some sort of GUI front end) and a base exhibit name: before asking for the files to be uploaded.

    Duplicate entries may be silently discarded.

    Package-visible to be callable from GUI classes.

    Parameters:
    autoGuessFormat - if true then the routine may try to guess the type/format of files that do not match the type implied by the name
    files - one (or more if the number-in-series is not zero) files that the user has selected for upload; never null not zero-size no containing nulls
    uib - initialised with the first/desired name; never null and must be in a state where enoughValidUniqueInfo()==true
    Returns:
    null if all is well, else an error message (and no files added)

    saveProperties

    private void saveProperties()
    Save persistent properties (if possible). If we have PersistenceService then try to create/allocate space to save (ignoring errors if already there) and save the data.


    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 usable by the main GUI class.


    DHD Multimedia Gallery V1.57.21

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