38 PSpaceDos

DOS stands for Dirty Object Set.

a PSpaceDos records a set of pointers to IPersistable objects - for all the dirty objects within a single PSpace. Dirty means one of the following:

  • it is a new object and needs to be written to the LSS for the first time
  • the object has been modified and needs to be rewritten to the LSS
  • the object has been marked as permanently deleted (because the application called SyncPermanentlyDeleteObject() on the object) and DeleteSerialElement() needs to be called on the LSS

IPersistable objects have a bit flag DBP_PO_DIRTY in the ObjSysState for whether the object is dirty. The DOS exactly contains the objects which are marked as dirty in this way.

IPersistable objects also have a bit flag DBP_PO_SYNC_DELETED for whether the object has been marked as permanently deleted.

The dirty objects in the DOS are visted by the CSpace GC to ensure they are not evicted from memory (this includes the objects that have been marked as permanently deleted).

Implementation

An xdeque is used because it can grow efficiently.

m_dirtyObjectSet is only accessed by threads that have locked the CSpace:

  • A thread has locked two PSpaces and moves the dirty objects from one to the other with a call to Transfer().
  • A thread has locked the PSpace and marks an object as dirty so it is added to m_dirtyObjectSet with a call to AddDirtyObject().
  • The GC thread has locked the CSpace and calls VisitObjects() which in turn iterates through m_dirtyObjectSet.
  • The DosWriter has locked the CSpace and calls WriteChangesToLSS(). This iterates through m_dirtyObjectSet and clears it.

m_dirty flag

PSpaceDos has a std::atomic<bool> flag m_dirty which is true if and only there's a need to write changes to the LSS. todo: is this equivalent to checking whether the xdeque is empty?

This flag is set by a thread that makes changes while locking the PSpace. It is cleared by the call to WriteChangesToLSS(), typically made by the DosWriter after locking the PSpace. We see therefore that there can be no racing conditions with the setting and clearing of this flag. When the flag transitions to true the PSpace is added to the DirtyPSpaceList, and when it transitions to false the PSpace is removed from the DirtyPSpaceList.

DosWriter::PrivateProcessPSpaceTxnGroup() reads the m_dirty flag without locking the PSpace to see whether any of the PSpaces in a given group are dirty. This is essentially polling.

AddDirtyObject()

It is assumed the IPersistable object already has the DBP_PO_DIRTY bit set when AddDirtyObject() is called to add it to the DOS

We should be able to assert that the given object hasn't already been pushed onto the xvector. However scanning the xvector is too slow, even in debug builds.

WriteChangesToLSS()

This function is called from PSpace::WriteDirtyObjectsToLss() which is in turn called from DosWriter::ProcessPSpaceTxnGroup() while locks are held on the relevant CSpaces.

This allows for gathering a consistent snapshot of the objects in memory for writing to the LSS in a single LSS transaction.

At the top of this function we swap m_dirtyObjectSet with a local deque. Therefore while this function runs, m_dirtyObjectSet is cleared. Note that we are quite happy for the objects to be evicted after WriteChangesToLSS() has completed.

For each object in the dirty set
    if the DBP_PO_SYNC_DELETED bit flag is set then DeleteSerialElement() is called
    otherwise                                       WriteSerialElement() is called

It is actually possible that an object is created in memory and later marked as permanently deleted and yet it has never been written to the LSS! In that case DeleteSerialElement() returns false to indicate that no serial element with that OID exists. We don't treat this as an error.

As the dirty objects are written to the LSS, the bit flag DBP_PO_DIRTY is cleared.

PSpaceDos.h

Source: Ceda/cxPersistStore/src/PSpaceDos.h

PSpaceDos.cpp

Source: Ceda/cxPersistStore/src/PSpaceDos.cpp