Resource Forks
From VCGR Wiki
Contents |
Basic Idea
The basic idea for the resource fork is derived from the fork concept in the (I believe) Mach kernel). Basically, a single resource may have multiple personalities, or facades (called forks) that represent various abilities of that resource. In concept these are virtual access interfaces to a single resource (which we will call the owning resource). However, from an implementation point of view, WS-Naming requires us to instantiate these as actual endpoints. The difference should be transparent however.
There are a couple of points to consider when thinking about forks:
- A service which chooses to utilize the forks mechanism must by necessity implement the RNS interface and I recommend that it do so using a canned piece of code which I'll call the ForkRootManager. This manager implements RNS as a static rns directory from whence fork instances can be linked.
- Right now we'd implement a Fork service which would call back to the fork handlers to implement methods, but this approach would require a set mapping of Read/Write/Execute to the various functions which may not be appropriate for all forks. Not sure what to do about this yet. Perhaps the Fork could indicate the methods as open and leave it up to the backend to allow or dis-allow an action.
The eventual goal will be to have a directory tree for a resource like a Queue which might look like this:
/some-queue
|
|- BES Containers
| |- Container 1
| | |- Endpoint
| | |- Slots
| |
| |- Container 2
| |- Endpoint
| |- Slots
|
|- Queued Jobs
| |- Job 1
| |- Job 2
|
|- Finished Jobs
| |- Job 3
| |- Job 4
|
|- Jobs in Error
|- Job 5
|- Job 6
Design
The fork code is made up of an interface for a ForkFactory which is used to create fork instance classes (giving users flexibility in fork implementation). At a high level, they would look like this (note that these interfaces are not meant to be syntactically correct or complete -- they are meant only to convey general design):
public interface IFork
{
public EndpointReferenceType getEPR();
public MessageElement[] getResourceProperties(QName []qnames)
throws ResourcePropertyExceptions;
public void setResourceProperties(MessageElement []rps)
throws ResourcePropertyExceptions;
}
public interface IByteIOFork extends IFork
{
/* This is just a place holder */
}
public interface IRandomByteIOFork extends IByteIOFork
{
public byte[] read(long offset, long length) throws ByteIOExceptions;
public void write(long offset, byte []data) throws ByteIOExceptions;
public void truncAppend(long offset, byte []data) throws ByteIOExceptions;
}
public interface IStreamableByteIOFork extends IByteIOFork
{
public byte[] seekRead(SeekWhence whence, long offset, long length)
throws ByteIOExceptions;
public void seekWrite(SeekWhence whence, long offset, byte []data)
throws BYteIOExceptions;
}
public interface IRNSFork extends IFork
{
public RNSEntry[] list(RegularExpression expr) throws RNSExceptions;
public void add(RNSEntry newEntry) throws RNSExceptions;
public RNSEntry[] remove(RegularExpression expr) throws RNSExceptions;
public IFork createFile(String newName) throws RNSException;
public IRNSFork createDirectory(String newName) throws RNSException;
}
public interface IForkFactory
{
public IFork create(EndpointReferenceType ownerResource,
Serializable userData) throws ForkException;
public IFork lookup(EndpointReferenceType targetFork)
throws ForkException;
public void destroy(EndpointReferenceType targetFork)
throws ForkException;
}
We would also need a ForkRootsManager class that the owner resource could use in it's RNS methods (we'd probably end up creating a new base class derived off of GenesisIIBase that would automatically implement the RNS methods to be a fork root).
Further, to make this work, we would assume the following mandatory database tables.
ForkTable
- fork-key
- This column is the key contained in the reference parameters and used to uniquely identify the fork.
- fork-factory
- This column is a string which holds the class name of the factory that manages the fork instance.
- owner-epr
- A BLOB containing the EPR of the owner resource for the fork.
- user-info
- A BLOB containing the user data object passed in during creation of the fork.
ForkRootsTable
- entryid
- An auto-generated database key for this entry
- resourceid
- The unique string matching the resource parameters of the owner resource.
- entry-name
- The human readable name of an entry inside of the resource's root fork.
- fork-epr
- A BLOB representing the EPR of a fork entry inside the root of a fork.
Example
As an example, here is some pseudo-code of what the list method of the fork service might look like.
public ListResult list(ListRequest request) throws RNSExceptions
{
/* First, get our resource id AND our EPR */
String rKey = ResourceManager.getCurrent().getKey();
EndpointReferenceType myEPR = WorkingContext.getMyEPR();
/* Now, look up the fork factory for this fork in the database */
IForkFactory factory = ForkFactoryManager.findFactoryForFork(rKey);
/* With the factory, create a fork instance to handle the method */
IFork fork = factory.lookup(myEPR);
/* Because we are a generic service (implementing all applicable port types) we
* need to check that the fork actually implements the correct interface.
*/
if (!(fork instanceof IRNSFork))
throw new UnimplementedException("RNS method list not implemented in fork.");
/* Finally, everything looks good, so let the fork handle it */
return new ListResult(fork.list(request.getRegularExpression()));
}
