ccs.beetree
Class BeeObject

java.lang.Object
  extended by ccs.beetree.BeeObject
Direct Known Subclasses:
BeeGeneric, CDBObject

public abstract class BeeObject
extends java.lang.Object

A BeeObject is an object that is marshalled and stored in a BeeTree database file. This includes stored blobs, and the other entities required to index them; these count as BeeTree internals and are not documented.

Every BeeObject contains a nestable (ie. re-entrant) mutex. This is used to guard accesses to that part of the BeeObject's state which is package- protected; this state is documented below, and for the most part is either set exactly once when the object is created, or is reserved for the use of the BeeTree.

Experience has shown that BeeObjects are rarely shared among threads. However, where this happens, it is often better to use the BeeObject's mutex explicitly rather than relying on synchronized methods. In particular, relying on synchronized methods is error-prone where a BeeObject calculates its own length; the state may change between the call to obtain the length and that which marshals the (new) state, and if the length of the new state is different from the old then the marshal will fail and mark the BeeTree as corrupt.

See Also:
BeeTree

Field Summary
protected  Cipher cipher
          The Cipher object which should be used to encrypt this object.
protected  long encodedLength
          The encoded length of the object, for informational purposes.
protected  boolean isBodiless
          Whether this object has no body.
protected  boolean isForceDirectDecrypt
          Whether the object should always be decrypted directly.
protected  boolean isZip
          Whether this object should be compressed.
protected  int slack
          The minimum amount of slack space that should be made available if the object has to be moved.
 
Constructor Summary
BeeObject()
          creates a BeeObject, with an invalidated set of attributes.
 
Method Summary
 java.lang.String getKey()
          Return the key for this object - the String used to find this object within the BeeTree.
 long getMarshalledLength()
          Returns the marshalled length.
 void lock()
          Acquire one hold on the BeeObject's nestable mutex.
abstract  void marshal(java.io.DataOutputStream dest)
          Implement this function to marshal - write as a succession of fields - your object's data onto the supplied stream.
 void preMarshal()
          Prepare to marshal.
 void preUnmarshal()
          Prepare to unmarshal.
 void setKey(java.lang.String key)
          sets the key for this object.
 void unlock()
          Release one hold on the the mutex obtained by lock.
abstract  void unmarshal(java.io.DataInputStream src)
          Implement this function to de-serialise your object's properties from the supplied input stream.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

slack

protected int slack
The minimum amount of slack space that should be made available if the object has to be moved. Slack space is extra space, on top of the amount currently required by the object, provided in order to allow it to grow without having to be moved. Zero by default.


isZip

protected boolean isZip
Whether this object should be compressed. Compression is expensive, so should only be attempted where you have good grounds to believe that it will have a useful effect. Do compress: Don't compress:


isBodiless

protected boolean isBodiless
Whether this object has no body. This is legitimate - in particular, cross-reference objects are common in many applications and tend to only have a key. (The key is split into multiple fields, but this is beyond the scope of the BeeTree layer; see eg. ccs.cdb.MKCDBObject). Bodiless objects *will* be premarshalled, but not marshalled (there's nothing to marshal, by definition). This saves useful amounts of overhead - cross-reference objects in particular tend to be very numerous. Objects should only set this if they never have a body over the lifetime of the current class definition, not if they normally do but it happens to be zero-length for the present instance. Different stored versions of the same object, whereby one version has a body and the other doesn't, can co-exist.


cipher

protected Cipher cipher
The Cipher object which should be used to encrypt this object. Set to null (the default) to have the BeeTree use its own Cipher. Some schemes require individual objects to have their own Ciphers, but this causes significant problems so don't do it unless you really mean it. In particular:


encodedLength

protected transient long encodedLength
The encoded length of the object, for informational purposes. This is not stored and is only available after the object has been written; it's not available after it's been read. Not generally useful.


isForceDirectDecrypt

protected boolean isForceDirectDecrypt
Whether the object should always be decrypted directly. When an object has its own Cipher, the BeeTree will usually decrypt it first and only attempt to unmarshal after the decrypt has succeeded. This means that a failed decrypt (due to eg. wrong password) will be reported as such, rather than manifesting as wierd unmarshalling errors whose cause is far from obvious. If you want to override this in the interests of efficiency (and risk frightening your users), set this flag to true. All of this only applies to objects which have their own Ciphers. Most don't.

Constructor Detail

BeeObject

public BeeObject()
creates a BeeObject, with an invalidated set of attributes. These should be set up before use.

Method Detail

lock

public void lock()
          throws DeadlockException
Acquire one hold on the BeeObject's nestable mutex. Where a BeeObject is shared between threads, and at least one thread may be trying to perform any operation which causes the BeeObject to interact with a BeeTree, any code which affects the BeeObject's state MUST gain this lock first. This uses the optional deadlock timeout specified by BeeTree.setDeadlockTimeoutMillis.

Throws:
DeadlockException

unlock

public void unlock()
Release one hold on the the mutex obtained by lock. The current thread must own the lock.


preMarshal

public void preMarshal()
                throws java.io.IOException
Prepare to marshal. This is called by BeeTree just before marshalling the object for insert or update: override it to ensure that the object is ready to be marshalled. Throw either IOException or a suitable RuntimeException if it isn't ready; if the marshal itself fails for some reason it marks the BeeTree as corrupt. The default implementation does nothing.

Throws:
java.io.IOException - if the object isn't ready.

preUnmarshal

public void preUnmarshal()
                  throws java.io.IOException
Prepare to unmarshal. This is called by BeeTree just before unmarshalling the object for find / next / prev; override to ensure that the object is ready to be unmarshalled. The key has been set to its proper value by the time this is called (e.g. for find the key on entry to the BeeTree routine would be partial, for next the key would be null or irrelevant). Throw either IOException or a suitable RuntimeException if it isn't ready. The default implementation does nothing.

Throws:
java.io.IOException - if the object isn't ready.

getKey

public java.lang.String getKey()
Return the key for this object - the String used to find this object within the BeeTree. The default implementation returns null, and you must override it.

Returns:
The key.

setKey

public void setKey(java.lang.String key)
sets the key for this object. Used by find / next / prev / match to furnish the (non-unmarshalled) object with its own key. Called before unmarshalling. The default implementation does nothing. The key may be set (to provisional values) several times during searching so this routine should be fast - do any associated processing during unmarshal instead.

Parameters:
key - The full, but possibly provisional, key to this object.

marshal

public abstract void marshal(java.io.DataOutputStream dest)
                      throws java.io.IOException
Implement this function to marshal - write as a succession of fields - your object's data onto the supplied stream. Either use the Java serialisation mechanism or write your own. Your marshalling code should not, in general, directly marshal other objects to which your object has references; marshal a crossreference key, and store the referenced object in the BeeTree in its own right.

If you have given a marshalled length, then the stream will throw an IOException if you exceed it, or do not use all of it. If the key is a basic field of your object, rather than being some function of your object's state, then you don't have to marshal it. Do not close the stream. Don't marshal the data members of BeeObject - the BeeTree engine will do that for you; just marshal the members of your subclass. You should synchronize this method when you override it.

Parameters:
dest - The stream to write onto.
Throws:
java.io.IOException - if an error occurs.

unmarshal

public abstract void unmarshal(java.io.DataInputStream src)
                        throws java.io.IOException
Implement this function to de-serialise your object's properties from the supplied input stream. As for marshal either use Java serialisation or write your own. The data members of BeeObject itself will have been correctly set up before this function is called. You should synchronize this method when you override it.

Parameters:
src - the stream to read from.
Throws:
java.io.IOException - if an error occurs.

getMarshalledLength

public long getMarshalledLength()
Returns the marshalled length. If the serialised (marshalled and encrypted) length of a serialised object can be calculated cheaply before it is encoded, then a more efficient method can be employed than is otherwise the case. If your object is such that you can calculate its marshalled length without having to marshal it, or perform a procedure as expensive as marshalling it, then override this function to return the marshalled length. The version in this class returns -1, indicating that this cannot be done. This function is not called if isZip is true, since the compressed length of an object depends on its content and cannot be precomputed.

Returns:
The marshalled length of this object.