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) andDeleteSerialElement()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
PSpaceand marks an object as dirty so it is added tom_dirtyObjectSetwith a call to AddDirtyObject(). - The GC thread has locked the
CSpaceand calls VisitObjects() which in turn iterates throughm_dirtyObjectSet. - The DosWriter has locked the
CSpaceand calls WriteChangesToLSS(). This iterates throughm_dirtyObjectSetand 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