Side of Software
Persistence Library 2.0

sos.db
Class AbstractSerializationDatabase

java.lang.Object
  extended by sos.db.AbstractDatabase
      extended by sos.db.AbstractSerializationDatabase
All Implemented Interfaces:
java.io.Serializable, Database
Direct Known Subclasses:
FileDatabase, InMemoryDatabase

public abstract class AbstractSerializationDatabase
extends AbstractDatabase
implements java.io.Serializable

A partial implementation of a serialization-based database.

This abstract class saves objects by serializing them and assigning them a unique id. The root object and all objects passed to addObject must be serializable using Java's standard serialization framework. Once this class serializes an object to an array of bytes, it leaves it up to the subclass as to where these bytes should be stored. The subclass must define:

Subclasses need not worry about proxy objects nor the transaction policy. These are handled by AbstractSerializationDatabase.

Caching

This class caches the most recently used objects, avoiding the repeated serialization and deserialization of frequently-accessed objects. The cache is memory sensitive; that is, if the virtual machine is about to run out of memory, entries are removed from the cache.

Logging

This class logs database activity with Database.logger. It logs messages for the following activities:

ActivitySeverity
The database is createdINFO
The database is closedINFO
The database is deletedINFO
The database is openedINFO
A transaction is startedFINE
A transaction is committedFINE
A transaction is abortedFINE
An object is added to the databaseFINER
An object is resaved in the databaseFINER
An object is removed from the databaseFINER

Subclasses may change the log messages or severity by overriding the logXxx methods.

The transaction policy may log additional activity, such as lock acquisition and release.

External Serialization

Proxy objects produced by instances of this class can be serialized to a stream outside of its database. This allows the client to save a database object in the preferences, for example. When a proxy object is serialized, a reference to the database object is saved. When the proxy object is deserialized, it attaches to its home database (i.e. the database in which it was created). Therefore, the database must be open and must still contain the database object when the proxy is deserialized. The deserialized proxy references the current state of the object, not necessarily the state of the object at the time the proxy was serialized in the outside stream.

Warning: Externally serializing a database object does not prevent the object from being automatically removed from the database when it is no longer reachable from database objects. Therefore, clients should ensure that externally serialized database objects are also reachable from the root database object.

Since:
1.0
See Also:
Database, TransactionPolicy

Field Summary
 
Fields inherited from interface sos.db.Database
logger
 
Constructor Summary
protected AbstractSerializationDatabase(java.lang.String databaseName, TransactionPolicy policy)
          Creates an AbstractSerializationDatabase with the specified database name and transaction policy.
 
Method Summary
protected  TransactionPolicy createDefaultTransactionPolicy()
          Creates and returns a default transaction policy.
protected  void doAbortTransaction()
          Performs the action of abortTransaction.
protected  java.lang.Object doAddObject(java.lang.Object object)
          Performs the action of addObject.
protected  void doClose()
          Performs the action of close.
protected  void doCommitTransaction(Progress progress)
          Performs the action of commitTransaction.
protected  boolean doContainsObject(java.lang.Object object)
          Performs the action of containsObject.
protected  boolean doCreate(java.lang.Object root)
          Performs the action of create.
protected  boolean doDelete()
          Performs the action of delete.
protected abstract  byte[] doFetchObject(long id)
          Returns the serialized object associated with id.
protected abstract  boolean doFlush(LongMap<byte[]> newObjects, LongMap<byte[]> modifiedObjects, Progress progress)
          Adds new objects, re-saves modified objects, and removes old objects from this database in a single, atomic step.
protected  java.lang.Object doGetRoot()
          Performs the action of getRoot.
protected abstract  long doNextKey(long fromKey)
          Returns the next key greater than or equal to fromKey that corresponds to an object in this database.
protected  void doOpen(boolean readOnly)
          Performs the action of open.
protected abstract  void doRemoveObject(long oldKey)
          Removes the specified object from this database.
protected  void doStartTransaction()
          Performs the action of startTransaction.
protected  int doTransactionDepth()
          Performs the action of transactionDepth.
protected  boolean enableReplaceObject(boolean enable)
          Enables the substitution of objects during serialization.
 java.lang.String getName()
          Returns the name of this database.
 TransactionPolicy getTransactionPolicy()
          Returns the transaction policy governing the transactions.
protected  void logDatabaseClosed()
          Records that this database has been closed.
protected  void logDatabaseCreated()
          Records that this database has been created.
protected  void logDatabaseDeleted()
          Records that this database has been deleted.
protected  void logDatabaseOpened()
          Records that this database has been opened.
protected  void logObjectAdded(long id, java.lang.Class objectClass)
          Records that this database added an object with the specified id.
protected  void logObjectRemoved(long id)
          Records that this database has removed the object with the specified id.
protected  void logObjectResaved(long id)
          Records that this database has resaved the object with the specified id.
protected  void logTransactionAborted()
          Records that the transaction for the current thread has aborted.
protected  void logTransactionCommitted()
          Records that the transaction for the current thread has committed.
protected  void logTransactionStarted()
          Records that a transaction for the current thread has started.
protected  java.lang.Object readResolve()
          Returns a deserialized version of this database.
protected  java.lang.Object replaceObject(java.lang.Object obj)
          Allows subclasses to substitute one object for another during serialization.
protected  java.lang.Object resolveObject(java.lang.Object obj)
          Allows subclasses to substitute one object for another during deserialization.
 void setAutoCreateTransactions(boolean autoCreateTransactions)
          Sets whether or not this database allows a method invocation on a database object when there is no current transaction.
 
Methods inherited from class sos.db.AbstractDatabase
abortTransaction, addObject, close, commitTransaction, containsObject, create, delete, doExists, exists, getRoot, isOpen, open, startTransaction, transactionDepth
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

AbstractSerializationDatabase

protected AbstractSerializationDatabase(java.lang.String databaseName,
                                        TransactionPolicy policy)
Creates an AbstractSerializationDatabase with the specified database name and transaction policy. If policy is null, this methods invokes createDefaultTransactionPolicy to create a default transaction policy.

Parameters:
databaseName - name of the database
policy - policy to use to control transactions (may be null)
Method Detail

createDefaultTransactionPolicy

protected TransactionPolicy createDefaultTransactionPolicy()
Creates and returns a default transaction policy.

Returns:
a default transaction policy

doContainsObject

protected boolean doContainsObject(java.lang.Object object)
Description copied from class: AbstractDatabase
Performs the action of containsObject. This method is called inside containsObject if this database is in an acceptable state. It has the same semantics as containsObject.

Specified by:
doContainsObject in class AbstractDatabase
Parameters:
object - the object to check for containment
Returns:
true if this database contains object

doAbortTransaction

protected void doAbortTransaction()
Description copied from class: AbstractDatabase
Performs the action of abortTransaction. This method is called inside abortTransaction if this database is in an acceptable state. It has the same semantics as abortTransaction.

Specified by:
doAbortTransaction in class AbstractDatabase
See Also:
AbstractDatabase.abortTransaction()

doAddObject

protected java.lang.Object doAddObject(java.lang.Object object)
                                throws TransactionAbortedException
Description copied from class: AbstractDatabase
Performs the action of addObject. This method is called inside addObject if this database is in an acceptable state. It has the same semantics as addObject.

Specified by:
doAddObject in class AbstractDatabase
Parameters:
object - object to add to the database
Returns:
a proxy object that implements the same interfaces as object
Throws:
TransactionAbortedException - if this database cannot add object and the transaction has been aborted as a result
See Also:
AbstractDatabase.addObject(java.lang.Object)

doClose

protected void doClose()
                throws java.io.IOException
Description copied from class: AbstractDatabase
Performs the action of close. This method is called inside close if this database is in an acceptable state. It has the same semantics as close.

Specified by:
doClose in class AbstractDatabase
Throws:
java.io.IOException - if an I/O error occurs
See Also:
AbstractDatabase.close()

doCommitTransaction

protected void doCommitTransaction(Progress progress)
                            throws TransactionAbortedException
Description copied from class: AbstractDatabase
Performs the action of commitTransaction. This method is called inside commitTransaction if this database is in an acceptable state. It has the same semantics as commitTransaction.

Specified by:
doCommitTransaction in class AbstractDatabase
Parameters:
progress - an object to be updated and checked while the commit is in progress (may be null to indicate that no updating/checking is necessary)
Throws:
TransactionAbortedException - if this database cannot commit the transaction or if the progress is canceled
See Also:
AbstractDatabase.commitTransaction(sos.db.Progress)

doCreate

protected boolean doCreate(java.lang.Object root)
                    throws java.io.IOException
Description copied from class: AbstractDatabase
Performs the action of create. This method is called inside create if this database is in an acceptable state. It has the same semantics as create.

Specified by:
doCreate in class AbstractDatabase
Parameters:
root - the root of this database
Returns:
true if this database does not exist and was successfully created; false if this database already exists
Throws:
java.io.IOException - if an I/O error occurs
See Also:
AbstractDatabase.create(java.lang.Object)

doDelete

protected boolean doDelete()
                    throws java.io.IOException
Description copied from class: AbstractDatabase
Performs the action of delete. This method is called inside delete if this database is in an acceptable state. It has the same semantics as delete.

Specified by:
doDelete in class AbstractDatabase
Returns:
true if this database is successfully deleted
Throws:
java.io.IOException - if an I/O error occurs
See Also:
AbstractDatabase.delete()

doFetchObject

protected abstract byte[] doFetchObject(long id)
                                 throws java.io.IOException
Returns the serialized object associated with id.

This method is called while holding this database's monitor.

Parameters:
id - id of object to fetch
Returns:
the serialized object associated with id
Throws:
java.io.IOException - if an I/O error occurs

doFlush

protected abstract boolean doFlush(LongMap<byte[]> newObjects,
                                   LongMap<byte[]> modifiedObjects,
                                   Progress progress)
                            throws java.io.IOException
Adds new objects, re-saves modified objects, and removes old objects from this database in a single, atomic step. If any of these steps should fail, the database should roll back to its state prior to the call.

This method is called when a top-level transaction commits. It is called while holding this database's monitor.

Parameters:
newObjects - a mapping of new ids (as Longs) to new database objects (as byte[]s)
modifiedObjects - a mapping of ids (as Longs) to modified database objects (as byte[]s)
progress - an object to be updated and checked as the flush is occurring (may be null)
Returns:
false if it is interrupted because the progress is canceled; true otherwise
Throws:
java.io.IOException - if an I/O error occurs

doGetRoot

protected java.lang.Object doGetRoot()
                              throws TransactionAbortedException
Description copied from class: AbstractDatabase
Performs the action of getRoot. This method is called inside getRoot if this database is in an acceptable state. It has the same semantics as getRoot.

Specified by:
doGetRoot in class AbstractDatabase
Returns:
this database's root object (may be null)
Throws:
TransactionAbortedException - if the root object cannot be retrieved and the transaction has been aborted as a result.
See Also:
AbstractDatabase.getRoot()

doOpen

protected void doOpen(boolean readOnly)
               throws java.io.IOException
Description copied from class: AbstractDatabase
Performs the action of open. This method is called inside open if this database is in an acceptable state. It has the same semantics as open.

Specified by:
doOpen in class AbstractDatabase
Parameters:
readOnly - true if database updates are not allowed
Throws:
java.io.IOException - if an I/O error occurs
See Also:
AbstractDatabase.open

doNextKey

protected abstract long doNextKey(long fromKey)
                           throws java.io.IOException
Returns the next key greater than or equal to fromKey that corresponds to an object in this database. This method is called while holding this database's monitor.

Parameters:
fromKey - key from which to start the search
Returns:
the key of the next database object or -1, if no more database objects
Throws:
java.io.IOException - if an I/O error occurs
Since:
2.0

doRemoveObject

protected abstract void doRemoveObject(long oldKey)
                                throws java.io.IOException
Removes the specified object from this database.

This method is called when a garbage collection finds the object unreachable. It is called while holding this database's monitor.

Parameters:
oldKey - keys of the object to remove from this database
Throws:
java.io.IOException - if an I/O error occurs
Since:
2.0

doStartTransaction

protected void doStartTransaction()
                           throws TransactionAbortedException
Description copied from class: AbstractDatabase
Performs the action of startTransaction. This method is called inside startTransaction if this database is in an acceptable state. It has the same semantics as startTransaction.

Specified by:
doStartTransaction in class AbstractDatabase
Throws:
TransactionAbortedException - if the transaction cannot be started
See Also:
AbstractDatabase.startTransaction()

doTransactionDepth

protected int doTransactionDepth()
Description copied from class: AbstractDatabase
Performs the action of transactionDepth. This method is called inside transactionDepth if this database is in an acceptable state. It has the same semantics as transactionDepth.

Specified by:
doTransactionDepth in class AbstractDatabase
Returns:
the nesting depth of the transaction associated with the current thread
See Also:
AbstractDatabase.transactionDepth()

enableReplaceObject

protected boolean enableReplaceObject(boolean enable)
Enables the substitution of objects during serialization. A value of true instructs this database to invoke replaceObject during serialization, thereby allowing subclasses to replace objects before they are written to an output stream.

This method is similar to java.io.ObjectOutputStream.enableReplaceObject.

Subclasses that call this method with true will typically override replaceObject.

Parameters:
enable - a flag indicating whether or not replaceObject should be invoked
Returns:
the previous setting
Since:
2.0
See Also:
replaceObject(java.lang.Object)

getName

public java.lang.String getName()
Description copied from interface: Database
Returns the name of this database.

Specified by:
getName in interface Database
Returns:
this database's name

getTransactionPolicy

public TransactionPolicy getTransactionPolicy()
Description copied from interface: Database
Returns the transaction policy governing the transactions.

Specified by:
getTransactionPolicy in interface Database
Returns:
this database's transaction policy

logDatabaseClosed

protected void logDatabaseClosed()
Records that this database has been closed.

This implementation uses the localized message for key "logDatabaseClosed". The message takes one parameter: the name of this database.

See Also:
Database.logger

logDatabaseCreated

protected void logDatabaseCreated()
Records that this database has been created.

This implementation uses the localized message for key "logDatabaseCreated". The message takes one parameter: the name of this database.

See Also:
Database.logger

logDatabaseDeleted

protected void logDatabaseDeleted()
Records that this database has been deleted.

This implementation uses the localized message for key "logDatabaseDeleted". The message takes one parameter: the name of this database.

See Also:
Database.logger

logDatabaseOpened

protected void logDatabaseOpened()
Records that this database has been opened.

This implementation uses the localized message for key "logDatabaseOpened". The message takes one parameter: the name of this database.

See Also:
Database.logger

logObjectAdded

protected void logObjectAdded(long id,
                              java.lang.Class objectClass)
Records that this database added an object with the specified id.

This implementation uses the localized message for key "logObjectAdded". The message takes four parameters: the name of this database, the transaction thread, the id, and the class of the new object.

Parameters:
id - id of object being added
objectClass - class of the object being added
See Also:
Database.logger

logObjectRemoved

protected void logObjectRemoved(long id)
Records that this database has removed the object with the specified id.

This implementation uses the localized message for key "logObjectRemoved". The message takes three parameters: the name of this database, the transaction thread, and the id.

Parameters:
id - id of the object being removed
See Also:
Database.logger

logObjectResaved

protected void logObjectResaved(long id)
Records that this database has resaved the object with the specified id.

This implementation uses the localized message for key "logObjectResaved". The message takes three parameters: the name of this database, the transaction thread, and the id.

Parameters:
id - id of the object being resaved
See Also:
Database.logger

logTransactionAborted

protected void logTransactionAborted()
Records that the transaction for the current thread has aborted.

This implementation uses the localized message for key "logTransactionAborted". The message takes two parameters: the name of this database and the transaction thread.

See Also:
Database.logger

logTransactionCommitted

protected void logTransactionCommitted()
Records that the transaction for the current thread has committed.

This implementation uses the localized message for key "logTransactionCommitted". The message takes two parameters: the name of this database and the transaction thread.

See Also:
Database.logger

logTransactionStarted

protected void logTransactionStarted()
Records that a transaction for the current thread has started.

This implementation uses the localized message for key "logTransactionStarted". The message takes two parameters: the name of this database and the transaction thread.

See Also:
Database.logger

replaceObject

protected java.lang.Object replaceObject(java.lang.Object obj)
                                  throws java.io.IOException
Allows subclasses to substitute one object for another during serialization. This method is called only if enableReplaceObject has been called with true.

This method is similar to java.io.ObjectOutputStream.replaceObject.

The default implementation simply returns the object parameter. Subclasses can override this method to provide a different implementation.

Parameters:
obj - object to be replaced
Returns:
an object to substitute for obj
Throws:
java.io.IOException - if this database cannot replace the specified object
Since:
2.0
See Also:
enableReplaceObject(boolean), resolveObject(java.lang.Object)

readResolve

protected java.lang.Object readResolve()
                                throws java.io.ObjectStreamException
Returns a deserialized version of this database. When a database is written to an output stream, only a marker is written to the stream. Upon deserialization, the actual database object is substituted for the marker. This method is protected (rather than private) to allow subclasses to be serialized.

Returns:
the actual database referenced by the database being deserialized
Throws:
java.io.ObjectStreamException - if an error occurs
Since:
2.0

resolveObject

protected java.lang.Object resolveObject(java.lang.Object obj)
Allows subclasses to substitute one object for another during deserialization.

This method is similar to java.io.ObjectInputStream.resolveObject.

The default implementation simply returns the object parameter. Subclasses can override this method to provide a different implementation. This method can be used to limit the number of objects resulting from deserialization. For examples, subclasses can intern java.lang.String objects (or other objects) as they are deserialized.

Parameters:
obj - object to be replaced
Returns:
an object to substitute for obj
Throws:
java.io.IOException - if this database cannot replace the specified object
Since:
2.0
See Also:
replaceObject(java.lang.Object)

setAutoCreateTransactions

public void setAutoCreateTransactions(boolean autoCreateTransactions)
Sets whether or not this database allows a method invocation on a database object when there is no current transaction. Clients can use this method if they want to verify that all database calls are executed while in a transaction.

Parameters:
autoCreateTransactions - if true, this database automatically starts and ends a transaction when a method invocation is not wrapped in an explicit transaction
Since:
2.0

Side of Software
Persistence Library 2.0

Copyright 2004-08 Side of Software (SOS). All rights reserved.