Class UploadReservation

java.lang.Object
com.iizix.server.upload.UploadReservation
All Implemented Interfaces:
IUploadReservation

public final class UploadReservation extends Object implements IUploadReservation
One live upload reservation as the registry holds it: the sidecar record, the file entries, the limits it was granted under, its per-reservation listener, and the one lock that serializes every chunk of every one of its files.

Concurrency. Strictly one chunk in flight per reservation: the servlet takes tryLock() around its state check, offset compare, append, sidecar rewrite and timer re-arm; a second concurrent request for the same reservation fails the try-lock and is answered 409 busy without reading its body. The registry takes the same lock for cancellation, pause, resume and state changes.

Nobody waits for a chunk. A chunk can take as long as the client's network makes it, so a pause, resume, cancellation or consumption that finds the lock taken is not made to wait: the registry hands it to defer(Runnable), and it is run, in the order of the calls, by whoever holds the lock - at the latest when that thread releases it (unlock()), and earlier by the servlet, which gives up the chunk it is receiving when a call that stops the file is waiting (UploadFileEntry.isInterruptPending()).

Pause. A file is UploadState.PAUSED while the App or the client holds it; the reservation is paused as a whole (isPaused()) when no file is receiving and at least one is paused, and then its idle and start timers are suspended and the maximum pause timer runs. The registry keeps the flags and timers; this class only reads them.

Author:
Christopher Mindus
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    cancel(int fileIndex, String reason)
    Cancels one file or the whole reservation.
    int
    Gets the chunk size the client must use, in bytes.
    getFile(int fid)
    Gets a file entry by index.
    Gets the files, accepted or refused, in the order they were requested; a file's index in this list is its IUploadFile.getFileIndex().
    --- IUploadReservation ---
    int
    Gets the idle timeout in force, in seconds.
    Gets the limits in force when the reservation was made.
    Gets the per-reservation listener.
    int
    Gets the maximum file count per reservation in force.
    int
    Gets the maximum pause time in force, in seconds: how long the reservation may stay paused (by the App or the client) before it is cancelled with reason maxPause.
    Gets the relative upload path, ending with '/'.
    Gets the permitted media types in force, as configured, empty for any.
    Gets the reason the whole reservation was refused.
    long
    Gets the remaining allowance after this reservation, i.e.
    getSecret(int fileIndex)
    Gets the per-file secret.
    Gets the application session UUID this reservation belongs to.
    long
    Sums the declared sizes of the files that still hold quota: every file whose state is not terminal.
    boolean
    Checks if the reservation as a whole was accepted.
    boolean
    Checks if the reservation was cancelled as a whole.
    boolean
    Checks if every file has reached a terminal state or been verified, i.e.
    boolean
    Checks if the current thread holds the lock.
    boolean
    Checks if the App wants the automatic failure notice for this reservation: a cancellation only the server knows about (idle, start, maxPause) is then shown to the client as one message box listing the files.
    boolean
    Checks if the reservation is paused as a whole: no file is receiving chunks and at least one is UploadState.PAUSED.
    static boolean
    Checks if a file is accepted and not final: the servlet may append to it.
    boolean
    Checks if every file is terminal, i.e.
    void
    Takes the reservation lock, waiting if necessary (registry and service use; the servlet uses tryLock() so a second chunk in flight is refused rather than queued).
    void
    pause(int fileIndex, String reason)
    Pauses one file or every receiving file: the client is told to stop sending and a chunk sent anyway is refused as paused, never as a failure.
    void
    resume(int fileIndex)
    Resumes one file or every file the App paused: the client is told it may send again.
    void
    Runs the changes that found the lock taken, in the order of the calls; the caller holds the lock.
    Outputs to string.
    boolean
    Tries to take the reservation lock without waiting.
    void
    Releases the reservation lock, and when that frees it, runs the changes that found it taken meanwhile (defer(Runnable)).

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • Method Details

    • tryLock

      public boolean tryLock()
      Tries to take the reservation lock without waiting.
      Returns:
      true if taken; the caller must unlock().
    • lock

      public void lock()
      Takes the reservation lock, waiting if necessary (registry and service use; the servlet uses tryLock() so a second chunk in flight is refused rather than queued).
    • getSessionUUID

      public String getSessionUUID()
      Gets the application session UUID this reservation belongs to.
      Returns:
      The UUID string.
    • getLimits

      public UploadLimits getLimits()
      Gets the limits in force when the reservation was made.
      Returns:
      The limits.
    • getListener

      public IFileUploadListener getListener()
      Gets the per-reservation listener.
      Returns:
      The listener, or null.
    • unlock

      public void unlock()
      Releases the reservation lock, and when that frees it, runs the changes that found it taken meanwhile (defer(Runnable)).
    • runPending

      public void runPending()
      Runs the changes that found the lock taken, in the order of the calls; the caller holds the lock.
      Throws:
      IllegalStateException - If the lock is not held by the current thread.
    • isLockedByCurrentThread

      public boolean isLockedByCurrentThread()
      Checks if the current thread holds the lock.
      Returns:
      true if held.
    • getID

      public String getID()
      --- IUploadReservation ---
      Specified by:
      getID in interface IUploadReservation
      Returns:
      The ID.
    • getPath

      public String getPath()
      Description copied from interface: IUploadReservation
      Gets the relative upload path, ending with '/'. The client resolves it against the origin it already uses for its WebSocket; the server never composes a scheme, host or port.
      Specified by:
      getPath in interface IUploadReservation
      Returns:
      The path, e.g. /iizi-upload/.
    • isAccepted

      public boolean isAccepted()
      Description copied from interface: IUploadReservation
      Checks if the reservation as a whole was accepted. A refused reservation has no accepted files and IUploadReservation.getRefusalReason() says why.
      Specified by:
      isAccepted in interface IUploadReservation
      Returns:
      true if accepted.
    • getRefusalReason

      public String getRefusalReason()
      Description copied from interface: IUploadReservation
      Gets the reason the whole reservation was refused.
      Specified by:
      getRefusalReason in interface IUploadReservation
      Returns:
      The reason, or null if accepted.
    • getFiles

      public List<UploadFileEntry> getFiles()
      Description copied from interface: IUploadReservation
      Gets the files, accepted or refused, in the order they were requested; a file's index in this list is its IUploadFile.getFileIndex().
      Specified by:
      getFiles in interface IUploadReservation
      Returns:
      The files, never null.
    • getFile

      public UploadFileEntry getFile(int fid)
      Gets a file entry by index.
      Parameters:
      fid - The file index.
      Returns:
      The entry, or null if out of range.
    • getSecret

      public String getSecret(int fileIndex)
      Description copied from interface: IUploadReservation
      Gets the per-file secret. Never log it.
      Specified by:
      getSecret in interface IUploadReservation
      Parameters:
      fileIndex - The file index.
      Returns:
      The secret as base64url without padding, or null if the file was refused.
    • getChunkSize

      public int getChunkSize()
      Description copied from interface: IUploadReservation
      Gets the chunk size the client must use, in bytes.
      Specified by:
      getChunkSize in interface IUploadReservation
      Returns:
      The chunk size.
    • getRemainingBytes

      public long getRemainingBytes()
      Description copied from interface: IUploadReservation
      Gets the remaining allowance after this reservation, i.e. the most a further reservation of the same session could declare, in bytes.
      Specified by:
      getRemainingBytes in interface IUploadReservation
      Returns:
      The remaining bytes, or Long.MAX_VALUE if unlimited.
    • getMaxFiles

      public int getMaxFiles()
      Description copied from interface: IUploadReservation
      Gets the maximum file count per reservation in force.
      Specified by:
      getMaxFiles in interface IUploadReservation
      Returns:
      The count.
    • getPermittedTypes

      public String getPermittedTypes()
      Description copied from interface: IUploadReservation
      Gets the permitted media types in force, as configured, empty for any.
      Specified by:
      getPermittedTypes in interface IUploadReservation
      Returns:
      The comma-separated list.
    • getIdleTimeout

      public int getIdleTimeout()
      Description copied from interface: IUploadReservation
      Gets the idle timeout in force, in seconds.
      Specified by:
      getIdleTimeout in interface IUploadReservation
      Returns:
      The seconds after which an idle reservation is cancelled.
    • getMaxPause

      public int getMaxPause()
      Description copied from interface: IUploadReservation
      Gets the maximum pause time in force, in seconds: how long the reservation may stay paused (by the App or the client) before it is cancelled with reason maxPause. The idle timeout does not run while paused.
      Specified by:
      getMaxPause in interface IUploadReservation
      Returns:
      The seconds.
    • isNoticeEnabled

      public boolean isNoticeEnabled()
      Description copied from interface: IUploadReservation
      Checks if the App wants the automatic failure notice for this reservation: a cancellation only the server knows about (idle, start, maxPause) is then shown to the client as one message box listing the files. On by default.
      Specified by:
      isNoticeEnabled in interface IUploadReservation
      Returns:
      true if the notice is shown, false if the App reports failures its own way.
    • isPaused

      public boolean isPaused()
      Description copied from interface: IUploadReservation
      Checks if the reservation is paused as a whole: no file is receiving chunks and at least one is UploadState.PAUSED. The idle timeout is suspended and the maximum pause time runs.
      Specified by:
      isPaused in interface IUploadReservation
      Returns:
      true if paused as a whole.
    • isClosed

      public boolean isClosed()
      Description copied from interface: IUploadReservation
      Checks if every file has reached a terminal state or been verified, i.e. no further byte is expected.
      Specified by:
      isClosed in interface IUploadReservation
      Returns:
      true if closed.
    • isCancelled

      public boolean isCancelled()
      Description copied from interface: IUploadReservation
      Checks if the reservation was cancelled as a whole.
      Specified by:
      isCancelled in interface IUploadReservation
      Returns:
      true if cancelled.
    • isTerminal

      public boolean isTerminal()
      Checks if every file is terminal, i.e. the reservation holds no quota and can leave the registry.
      Returns:
      true if fully terminal.
    • heldBytes

      public long heldBytes()
      Sums the declared sizes of the files that still hold quota: every file whose state is not terminal.
      Returns:
      The bytes held against the quotas.
    • cancel

      public void cancel(int fileIndex, String reason)
      Description copied from interface: IUploadReservation
      Cancels one file or the whole reservation. Cancel means cancel: the staged bytes are deleted immediately and the quota is released.
      Specified by:
      cancel in interface IUploadReservation
      Parameters:
      fileIndex - The file index, or -1 for the whole reservation.
      reason - The reason, recorded on the file(s) and reported to the listener.
    • pause

      public void pause(int fileIndex, String reason)
      Description copied from interface: IUploadReservation
      Pauses one file or every receiving file: the client is told to stop sending and a chunk sent anyway is refused as paused, never as a failure. The listener sees IFileUploadListener.onFilePaused(IUploadReservation, IUploadFile, String). A file that is complete, verified or terminal is left alone; a file the client has already paused is additionally held by the App.
      Specified by:
      pause in interface IUploadReservation
      Parameters:
      fileIndex - The file index, or -1 for every file.
      reason - The reason, reported to the listener and the client; null or empty means paused.
    • resume

      public void resume(int fileIndex)
      Description copied from interface: IUploadReservation
      Resumes one file or every file the App paused: the client is told it may send again. A file the client has also paused stays paused until the client resumes it.
      Specified by:
      resume in interface IUploadReservation
      Parameters:
      fileIndex - The file index, or -1 for every file.
    • isReceiving

      public static boolean isReceiving(IUploadFile file)
      Checks if a file is accepted and not final: the servlet may append to it.
      Parameters:
      file - The file.
      Returns:
      true if the file can receive chunks.
    • toString

      public String toString()
      Outputs to string.
      Overrides:
      toString in class Object