2.2.4. StateManager

The TxCore class StateManager manages the state of an object and provides all of the basic support mechanisms required by an object for state management purposes. StateManager is responsible for creating and registering appropriate resources concerned with the persistence and recovery of the transactional object. If a transaction is nested, then StateManager will also propagate these resources between child transactions and their parents at commit time.
Objects in TxCore are assumed to be of three possible basic flavours. They may simply be recoverable, in which case StateManager will attempt to generate and maintain appropriate recovery information for the object (as instances of the class Input/OutputObjectState) . Such objects have lifetimes that do not exceed the application program that creates them. Objects may be recoverable and persistent, in which case the lifetime of the object is assumed to be greater than that of the creating or accessing application so that in addition to maintaining recovery information StateManager will attempt to automatically load (unload) any existing persistent state for the object by calling the activate (deactivate) operation at appropriate times. Finally, objects may possess none of these capabilities in which case no recovery information is ever kept nor is object activation/deactivation ever automatically attempted. This object property is selected at object construction time and cannot be changed thereafter. Thus an object cannot gain (or lose) recovery capabilities at some arbitrary point during its lifetime.
public class ObjectStatus
{
    public static final int PASSIVE;
    public static final int PASSIVE_NEW;
    public static final int ACTIVE;
    public static final int ACTIVE_NEW;
    public static final int UNKNOWN_STATUS;
};

public class ObjectType
{
    public static final int RECOVERABLE;
    public static final int ANDPERSISTENT;
    public static final int NEITHER;
};

public abstract class StateManager
{
    public synchronized boolean activate ();
    public synchronized boolean activate (String storeRoot);
    public synchronized boolean deactivate ();
    public synchronized boolean deactivate (String storeRoot, boolean commit);
    
    public synchronized void destroy ();
    
    public final Uid get_uid ();
    
    public boolean restore_state (InputObjectState, int ObjectType);
    public boolean save_state (OutputObjectState, int ObjectType);
    public String type ();
    . . .
    
    protected StateManager ();
    protected StateManager (int ObjectType, ObjectName attr);
    protected StateManager (Uid uid);
    protected StateManager (Uid uid, ObjectName attr);
    . . .
    
    protected final void modified ();
    . . .
};

public class ObjectModel
{
    public static final int SINGLE;
    public static final int MULTIPLE;
};
If an object is recoverable (or persistent) then StateManager will invoke the operations save_state (while performing deactivation), restore_state (while performing activate) and type at various points during the execution of the application. These operations must be implemented by the programmer since StateManager does not have access to a runtime description of the layout of an arbitrary Java object in memory and thus cannot implement a default policy for converting the in memory version of the object to its passive form. However, the capabilities provided by Input/OutputObjectState make the writing of these routines fairly simple. For example, the save_state implementation for a class Example that had member variables called A, B and C could simply be the following:
public boolean save_state ( OutputObjectState os, int ObjectType )
{
    if (!super.save_state(os, ObjectType))
    return false;
    
    try
    {
        os.packInt(A);
        os.packString(B);
        os.packFloat(C);
    
        return true;
    }
    catch (IOException e)
    {
        return false;
    }
}
In order to support crash recovery for persistent objects it is necessary for all save_state and restore_state methods of user objects to call super.save_state and super.restore_state.

Note

The type method is used to determine the location in the object store where the state of instances of that class will be saved and ultimately restored. This can actually be any valid string. However, you should avoid using the hash character (#) as this is reserved for special directories that TxCore requires.
The get_uid operation of StateManager provides read only access to an object’s internal system name for whatever purpose the programmer requires (such as registration of the name in a name server). The value of the internal system name can only be set when an object is initially constructed - either by the provision of an explicit parameter or by generating a new identifier when the object is created.
The destroy method can be used to remove the object’s state from the object store. This is an atomic operation, and therefore will only remove the state if the top-level transaction within which it is invoked eventually commits. The programmer must obtain exclusive access to the object prior to invoking this operation.
Since object recovery and persistence essentially have complimentary requirements (the only difference being where state information is stored and for what purpose) StateManager effectively combines the management of these two properties into a single mechanism. That is, it uses instances of the class Input/OutputObjectState both for recovery and persistence purposes. An additional argument passed to the save_state and restore_state operations allows the programmer to determine the purpose for which any given invocation is being made thus allowing different information to be saved for recovery and persistence purposes.