| The Casbah Project: APIs and Reference Manual: Developer's Release 1 | ||
|---|---|---|
| Prev | The Casbah Project: NatrounAPI | Next |
The following methods must be supported by a Conformant Natroun Driver: __cb_get__, __cb_put__, __cb_delete__, __cb_stat__, __cb_info__, and __cb_path__.
__cb_get__(path: CaList, options: CaDict) returns CaObject
__cb_get__ fetches an object and returns it. options is a CaDict providing a variable number of arguments to the Natroun driver. The following table presents the required options and how they must be supported. If an option is not supplied, the driver must assume the default value presented below. If a driver does not understand an option provided in the CaDict, it must ignore it. If a driver needs to invoke the services of another driver, it must pass the options CaDict on to the sub-driver.
recurse-depth. Number of levels of depth to copy the object. A depth of 0 means just this object's immediate atomic values, a depth of 1 means to copy this object, its immediates, its children and their immediates. Any objects not copied must have proxies returned for them. A recurse-depth of -1 is special, asking that a proxy must be returned for this object itself. An application may ask for all objects by using the recurse-deth of 2,147,483,647. A Conformant Natroun Driver must ignore this option for any object that is not a CaList or CaDict.
Type: CaInt32
Default Value: -1
Table 2. __cb_put__ method
return type | method name | method arguments |
|---|---|---|
CaBoolean | __cb_put__ | (CaList path, CaObject value, CaDict options) |
Stores a value at a path, completely replacing path. Should the operation fail, path must be left intact as if __cb_put__ was never called.
options is a CaDict providing a variable number of arguments to the Natroun driver. The following table lists the required options and how they must be supported. If an option is not supplied, the driver must assume the default value presented below. If a driver does not understand an option provided in the CaDict, it must ignore it. If a driver needs to invoke the services of another driver, it must pass the options CaDict on to the sub-driver.
Table 3. Required Options
Name | Type | Meaning | Default Value |
|---|---|---|---|
store-as | CaString | Converts value to the Casbah object type named in the option. If the driver cannot do the conversion, it must throw an exception and leave path unmodified. | not supplied |
Table 4. __cb_delete__ method
return type | method name | method arguments |
|---|---|---|
CaBoolean | __cb_delete__ | (CaList path) |
Deletes everything at path recursively. Should the operation fail, path must be left intact as if __cb_delete__ was never called.
If the Natroun driver supports __cb_lock__ and __cb_monitor__ and the last element of path is of type CaBinary delete must act as if __cb_unlock__ was called on the lock token which was supplied as the last element of path.
Table 5. __cb_stat__ parameters
return type | method name | method arguments |
|---|---|---|
CaDict | __cb_stat__ | (CaList path, CaDict options) |
Gets summarized information for the object at path. This information must be returned in a CaDict, where the keys are from the following table. Required keys must be supported by all Conformant Natroun Drivers, while optional keys may be supported. Keys whose "Class" is "default" must be returned as part of the status information for each object.
All Conformant Natroun Drivers which support __cb_lock__, must also support the keys which are marked with "__cb_lock__-required".
Table 6. Result Keys and Meanings
Required | Class | Key | Value Type | Meaning |
|---|---|---|---|---|
required | default | value | depends | The value will depend on the object itself and its datatypes. See the next table for a complete description of this key. Exception: If the item is a lock-token, the entire lock token must be returned, not just the first 32 bytes. |
required | default | size | CaUInt64 | Contains the size of an object. This varies based on the object type. See Datatype and Value Mappings for a description of what this key should hold for various object types. |
required | default | type | CaString | Contains the actual type of the object. Types must be in Casbah type-notation. If the object is a CaDict and contains the key "__cb_type__", this key must contain the value of the CaDict's "__cb_type__" member. |
optional | specified | last-accessed | CaDateTime | Date and time of last access (read). Some drivers may not store this information. This information must only be available on items of type CaDict, all other items must not have this information attached to them. |
optional | specified | last-modified | CaDateTime | Date and time of last modification (write). Some drivers may not store this information. This information must only be available on items of type CaDict, all other items must not have this information attached to them. |
optional | specified | created | CaDateTime | Date and time this object was created. Some drivers may not store this information. This information must only be available on items of type CaDict, all other items must not have this information attached to them. |
optional | specified | created-by | CaString | User (in form "user@realm") that created this object. Some drivers may not store this information. This information must only be available on items of type CaDict, all other items must not have this information attached to them. |
__cb_lock__-required | specified by "get-lock-tokens" | lock-owner | CaString | User that holds this lock token. |
__cb_lock__-required | specified by "get-lock-tokens" | lock-granted-at | CaDateTime | Date and time that the lock token was granted. If the lock has not been granted yet, this key is nonsensical and therefore must be ignored by applications. |
__cb_lock__-required | specified by "get-lock-tokens" | lock-granted | CaBoolean | Has this token been granted yet? |
__cb_lock__-required | specified by 'get-lock-tokens' | lock-method | CaInt32 | Method/Type of this lock. This is the value that was passed to __cb_lock__ as the method argument. (See __cb_lock__ for a complete description.) |
__cb_lock__-required | specified by "get-lock-tokens" | lock-experiation | CaDateTime | Date and time that the lock token will expire. |
Table 7. Datatype and Value Mappings
Object Type | Value Type | Size | Value |
|---|---|---|---|
CaString | CaString | number of characters in string | first 40 characters |
CaInt* | CaInt* | not used | actual value of number |
CaFloat, CaDouble | CaFloat, CaDouble | not used | actual value of number |
CaDict | CaUInt32 | not used | either the number of pairs in the dictionary or the result of doing a __cb_stat__ operation on the dicationary itself. (this depends on the current depth and the value of the "recurse-depth" option.) |
CaList | CaList | number of elements in list | return the first 4 items of the list. Each of these items should be returned in their "short" form, which can be obtained from this table. CaDicts embedded in a CaList are a special case: an empty CaDict must be returned in place of the original CaDict. |
CaBinary | CaBinary | number of bytes in binary | first 32 bytes of binary |
options is a dictionary providing a variable number of arguments to the Natroun driver. The following table lists the required options and how they must be supported. If an option is not supplied, the driver must assume the default value presented below. If a driver does not understand an option provided in the dictionary, it must ignore it. If a driver needs to invoke the services of another driver, it must pass the options dictionary on to the sub-driver.
Table 8. Required Options
Name | Type | Meaning | Default Value |
|---|---|---|---|
recurse-depth | CaInt32 | How many levels deep to stat if the object(s) is a table. A depth of 0 means just this object's contents. A depth of 1 means this object and its children, 2 this object, its children, and its children's children. | 0 |
stat-info | CaList of CaString | A list containing the result keys which the driver must return during this stat operation. | [] (the empty list) |
get-lock-tokens | CaBoolean | If TRUE, __cb_stat__ returns information on the lock tokens for this object instead of information on the object itself. If recurse-depth is supplied, it must be ignored as you may only get the lock tokens for an explicit object. | FALSE |
Example result for a __cb_stat__ operation on a CaString object.
{
"type" => "CaString",
"value" => "This is an example string"
}
Example 1. __cb_stat__
Example result for a __cb_stat__ operation on a CaDict with depth of 1.
{
"myString" => {
"type" => "CaString",
"value" => "This is an example string...",
"size" => 82
},
"myFloat" => {
"type" => "CaFloat",
"value" => 4.2
},
"theStates" => {
"type" => "CaDict",
"value" => 50
}
}
The __cb_info__ method must be implemented in a Conformant Natroun Driver. __cb_info__ returns a dictionary of driver metadata. The following key/value pairs must be returned in __cb_info__'s dictionary.
Table 9. __cb_info__
Method | Prototype | Returns (Type) |
|---|---|---|
__cb_path__ | () | CaDict |
Table 10. __cb_info__ key/value pairs
Key Name (type) | Example Value (type) | Description |
|---|---|---|
name (CaString) | NatrounFS (CaString) | A short, descriptive filename-like name for the driver. |
description (CaString) | Provides raw filesystem access within the Casbah Virtual Namespace (CaString) | A sentence or two that describes the functions the driver performs. |
author (CaString) | Niel Bornstein (CaString) | The full name of the primary developer of the driver. |
contact (CaString) | <niel@casbah.org> (CaString) | Contact information for the driver author; typically an email address. |
api (CaString) | natroun (CaString) | Specifies which API the driver implements. For Natroun drivers, this is always the string "natroun". |
revision (CaString) | 1.15 (CaString) | The CVS driver revision. Used for quality control and support. This is not the API version number. |
__cb_path__ moves the job of resolving a path to a driver-specific resource into a single method, while as a side effect moving all driver-to-driver hand off behavior into CairoAdapter/Cairo.
Table 11. __cb_path__
Method | Prototype | Returns (Type) |
|---|---|---|
__cb_path__ | (options CaDict) | options (CaDict) |
The options CaDict will contain keys unrelated to __cb_path__; these must not be modified by __cb_path__. The key that must be dealt with is path, which maps to a CaList of path elements.
When a Natroun driver's __cb_path__ method is called, it should retrieve the path key from the dict and attempt to resolve as much of the path as possible.
Example 2. Path Resolution
If NatrounFile encounters [ home, scgmille, foo.txt ] it should resolve as many elements in this list as it can, (in this case, all of them). It should then generate an opaque value that it can use in the future to reference that element, and then store that opaque reference in the options dictionary with the key internal_reference.[1] It should then return the options CaDict.
If it is resolving a path and finds that it cannot resolve all of the path elements, it should attempt to determine the type of the last path element it could resolve and insert that into the options dict with the key type, as well as an internal reference for the last resolved element. It should leave the unprocessed path elements in the options CaDict.
Example 3. Driver Hand Off
In the case of a path like [ home, scgmille, foo.jpg, width ], NatrounFile should parse as far as foo.jpg, but fail on width. It determines that foo.jpg is a jpeg file and so inserts the mapping "type"->"image/jpeg"[2] into the options CaDict. The options CaDict should now contain the following relevant information: { "path"=[width], "type"="image/jpeg", "internal_reference"=java.io.File@0cb3 }.
In this case the internal reference is the reference generated for foo.jpg, not the width element. This reference will be given to the next driver's activate options as an Entity.
Entities are pairs of Natroun drivers and internal references. With this kind of pair, any single element in the Casbah Virtual Namespace can be identified. A Conformant Natroun Driver has an activate method that takes an options dictionary. When a driver hand off has occured (as above, when NatrounFile hands off to NatrounJPEG), the child driver will be given the key root in its activate options dictionary. The root key will map to a CaList whose first element is a Natroun driver, the second, an opaque value that is that drivers internal reference.
A handle is simply an entity that is issued through the handle retrieval mechanism of __cb_get__. A handle has the additional behavior of ensuring that the resource it points to will not be made unavailable as long as the handle is outstanding.
Therefore, when a child Natroun driver wishes to make a Natroun query to retrieve information about its target, it can use the Entity (handle) as the path in a call to CairoAdapter's __cb_get__, __cb_stat__, etc.
In the example above, NatrounJPEG would be passed the option "root"=[org.casbah.natroun.file.NatrounFile@30c3, java.io.File@0cb3]. It would store the entity in a local variable of some sort, and use this value as a handle for further natroun calls (in order to read the jpeg file to retrieve its width, for example). CairoAdapter, upon seeing an entity, will circumvent the usual path lookup behavior and give the natroun call directly to the driver in the entity, and set the "internal_reference" key of the options to the internal reference in the entity.
__cb_path__ and the Entity construct have a few major consequences.
A Conformant Natroun Driver needn't worry about handles any more, CairoAdapter will unwrap handles and present them as normal natroun queries.
This means that all Natroun calls are handle-calls. The path resolution was already accomplished in __cb_path__, and all other Natroun methods expect to find a well-formed internal_reference key in the options CaDict. It is an error to noot find this key in any Natroun method call that deals with path.
Natroun drivers needn't worry about handing off to other drivers. They should merely determine the type of a dead-end object and insert it into the dictionary, and then return in __cb_path__. CairoAdapter and Cairo will make the necessary decisions to find an appropriate Natroun driver for a given type.
Path parsing need only happen in __cb_path__, and only to the extent necessary for that particular driver. If a driver wants a complex path grammar, it can have one, if it doesn't need anything more complex than "/" split paths, it needn't implement a single extra line of code.
The case of mounting another Natroun driver within the CVN remains to be examined. This is done using placeholder objects. A placeholder object behaves like a directory, except that it is merely an atomic entry in the CVN that forces the containing driver to assume the placeholder object has a certain type. For example, consider NatrounRAM having the following entries: ['/', '/foobar'].
foobar is a placeholder object. How the object is represented in the driver's resource space is undefined. All that is important is that NatrounRAM must know that when it encounters a placeholder object, it must consider that object as being a certain type. NatrounRAM may, for example, implement the placeholder object as a dictionary with keys: placeholder and type. When encountering /foobar/baz as a path, it cannot resolve bar and inserts the type of foobar, in this case the value of the type key, into the options CaDict, generates the internal reference for foobar, and then return.
Type, in this case, is the way Cairo is able to determine that a driver needs to be mounted there. The placeholder object for foobar might be the type of casbah/natroun/NatrounFile. This means that Cairo's bootstap type-handler map, say the types.conf, must have an appropriate mapping defined, in which case it will instantiate NatrounFile, with the root key of its activate options set to [NatrounRAM, 'internal reference for foobar']. __cb_path__ would then continue in NatrounFile, with the path list [baz].
| [1] | A Java File object might be an example of this value for NatrounFile. |
| [2] | See MIME and MIME-like Type Identifiers for more details about the use of MIME and MIME-like type identifiers. |