PersistStore

A PersistStore allows C++ objects to persist on non-volatile storage, such as a hard disk drive or solid state drive.

Within a given PersistStore each persistent object has a unique 64 bit identifier called an OID (Object Identifier).

These persistent objects are heap allocated object instances of C++ classes that are reference types, and implement the interface IPersistable which is a sub-interface of IObject.

They form object graphs using pointers ("references"). On non-volatile storage the references are recorded using 64 bit OIDs, and in memory they are represented using C++ object pointers.

A PersistStore could be regarded as providing an Object Oriented Database (OODB). It is well suited to being a low level layer on which to implement data structures such as data records, linked lists, B-Trees, key-value stores, indexes etc. Indeed it is well suited for being a layer on which a relational database (RDB) is implemented.

The persistable objects in a PersistStore are partitioned into mutually exclusive PSpaces.

To open or create a PersistStore, call the function OpenPersistStore.

Embedded database

All the objects in a PersistStore are written to a single file, which is opened exclusively by a single process. In that sense a PersistStore is an embedded database.

Any number of PersistStores can be opened within a given process.

Implementation in terms of the LSS

A PersistStore is implemented using a CEDA Log Structured Store (LSS) to record the serialised states of the objects.

An LSS is essentially a key-value store where the keys are 64 bit identifiers called Seids (Serial Element Identifiers) and the values are octet streams called Serial Elements.

Each persistent C++ object in a PersistStore is represented in the LSS as a (seid,serial-element) pair where the Seid is the object's OID and the serial element is the serialised state of the object.

Dirty Object Set

A PersistStore keeps track of the objects which have been updated and not yet written back to disk. This is called the Dirty Object Set (DOS).

A PersistStore keeps track of the objects which currently reside in memory. This is called the Resident Object Table (ROT).

API


$adt+ PersistStore
{
    void Close();
    bool CreatedNew() const;
    ILogStructuredStore* GetLss();
    void StartObjectDeletion();
    void WriteAllDirtyObjectsToLss(bool flushToDisk);
    PersistStoreTxn* OpenTxn(PSpaceLockMode* L, ssize_t n);
    int32 GetDosPeriod() const;
    void SetDosPeriod(int32 time);
    ssize_t GetNumPSpaces() const;
    ssize_t GetNumPersistableObjects() const;
    TypeOpsId GetTypeOpsId(const ReflectionByteCodeValue& rbcv, const TypeOps& typeOps);
    BcTypeOps GetTypeOps(TypeOpsId tid);
};


void Close()

Close the PersistStore.

Failing to close the PersistStore may cause data loss!

Note that all transactions on the store must have been closed, and all its PSpaces must have been closed.


bool CreatedNew() const

Indicates whether PersistStore was created for the first time, in the call to OpenPersistStore.


ILogStructuredStore* GetLss()

Get direct access to the associated LSS. Never returns NULL


void StartObjectDeletion()

See PersistStoreSettings. If the store was opened with PersistStoreSettings::startObjectDeletion = false then this function can be called to enable lazy object deletion. This might be useful if object deletion depends on relevant DLLs being loaded in order to avoid ReflectedClassNotFoundException exceptions.


void WriteAllDirtyObjectsToLss(bool flushToDisk)

Ensures that all changes in all PSpaces are written to the LSS. If flushToDisk = true then the LSS transaction(s) are also flushed to disk.

It is inappropriate to call this function midway through a transaction because it can mean objects are written to the store in an intermediate state, breaking transaction atomicity guarantees.


PersistStoreTxn* OpenTxn(PSpaceLockMode* L, ssize_t n)

Open a PersistStoreTxn on this PersistStore. L is an array of PSpaceLockMode of size n defining the PSpaces to be accessed by the transaction, and whether read or write access is required. Each PSpace specified in L must belong to this PersistStore. Note that L can be NULL with n=0. All the associated CSpaces must have already been locked before calling this function. Furthermore if L specifies ECSpaceLockMode::Exclusive for a PSpace then the associated CSpace must have also been locked with the ECSpaceLockMode::Exclusive mode. The CSpaces must remain locked until after the transaction is closed. Never returns NULL.


int32 GetDosPeriod() const

Get the time in milliseconds between each processing of the dirty object set.


void SetDosPeriod(int32 time)

Set the time in milliseconds between each processing of the dirty object set.

Wakes up the thread used to process the dirty object set if it's currently asleep.


ssize_t GetNumPSpaces() const


ssize_t GetNumPersistableObjects() const

Get the number of IPersistable objects in the PersistStore, accounting for the number of serial elements used for special purposes by the PersistStore and by each PSpace, and assuming all remaining serial elements are used for IPersistable objects. The implementation of this function first calls WriteAllDirtyObjectsToLss(false) to flush all changes to all PSpaces to the LSS, so that the number of serial elements in the LSS can be used to determine the number of IPersistable objects. This function treats pending asynchronous deletions as though the objects haven't been deleted yet. Therefore repeated calls to GetNumPersistableObjects() can give decreasing values as IPersistable objects are being asynchronously deleted.

It is inappropriate to call this function midway through a transaction because it can mean objects are written to the store in an intermediate state, breaking transaction atomicity guarantees.


TypeOpsId GetTypeOpsId(const ReflectionByteCodeValue& rbcv, const TypeOps& typeOps)

Get the TypeOpsId for the given ReflectionByteCodeValue. Creates a new entry if required


BcTypeOps GetTypeOps(TypeOpsId tid)

Get the TypeOps and ReflectionByteCodeValue for the given TypeOpsId.

Throws

Never returns a BcTypeOps with NULL values for rbcv or typeOps

Reserved OIDs

The PersistStore reserves some OIDs for internal purposes. See reserved OIDs.