An instance of the WFS class is created through methods on the WFSFactory class. Instances of WFS (or any of its subclasses) should never be created directly.
The WFS class and its associated interfaces (WFSCell and WFSCellDirectory) enable the reading and writing of WFSs. These sets of abstractions are meant to be low-level: they are simply Java class representations of the directory and file concepts defined by WFS.
The cells contained within the root WFS directory are represented by the WFSRootDirectory class and obtained via the WFS.getRootDirectory() method.
The structure and content of the WFS that resides in memory may be updated programmatically. Changes do not take effect to the underyling medium until explictly done so. Updating the WFS to its underlying medium (e.g. disk) can happen in one of several ways: only the configuration parameters of a cell may be updated, or a cell and all of its children may be updated (representing a subtree of the WFS), or the entire WFS tree may be updated. Updates to the medium are done with the minimum amount of disruption to any existing structure--new cells are added, while old cells are removed (versus obliterating an existing structure and rewriting from scratch).
A WFS may also exist as a jar file that encodes the proper directory and file structure. The jar file may be located on a disk locally, or it may be fetched from the network. The WFSFactory.open(URL) method opens a WFS encoded as a jar file, whether on disk locally (with the 'file:' protocol) or over the network (with the 'http:' protocol). See the ArchiveWFS class for more details on the format of the URL in these cases. This API supports only reading of jar files at this time.
In the final case, the WFS resides entirely in memory and may be serlialized at once to an output stream, encoded as a jar file. This usage is typically used if one wishes to create a WFS from scratch and write it out over a network connection.
This locking scheme was implemented for a couple of reasons. First, updates to a WFS typically happen over a series of updates such as creating new cells, and deleting or modifying existing cells. Second, locking the entire WFS tree simplifies what is locked.
It is expected that threads that lock a WFS only do so to update the WFS tree quickly and then release the lock. It is up to the calling thread to release the lock, especially under exceptional conditions it may encounter.
It is generally expected that updates made directly to the underlying medium constitute significant re-arrangements of the layout of the world and that a mechanism that exists at a level higher than this API should first quiesce all activity related to updating the WFS.
The WFS (or any subcomponent thereof) may be told to "reload" itself via the WFS.setReload() method. (This method also exists on the WFSCell and WFSCellDirectory classes). This method call has the effect of marking the object, and all subobjects as "dirty", so that the next time information is read by threads from the API, information is re-read from the underlying medium. The objects within the API are updated intelligently: that is, when cells have been added or removed from a directory, existing WFSCell objects are left alone, and only the needed new cells are created or removed.
To note: the reload mechanism obeys the principle of the API to perform "lazy" loads of information from the underlying medium. For example, if a cell directory has been told to "reload", it does not fetch the information from the directory on the underlying medium until the next getCells() method call, for example.
The setReload() methods require the calling thread to own the write lock for the WFS. There is still, however, some synchronization risks:
These two examples illustrate the necessity of insuring that all other activity that could interact with the WFS API quiesce before updates are made directly to the underlying medium. The decision on how to quiesce other activity is left to high software layers.
@author Jordan Slott
|
|
|
|
|
|
|
|