Struct corundum::stm::Log [−][src]
pub struct Log<A: MemPool>(_, _);
Expand description
The Log
type for pool A
It is pair of LogEnum
and Notifier
to keep a log in the Journal
.
A Journal
comprises multiple pages with a fixed number of log slots.
Each slot can be filled by one Log
. The Journal
object uses these logs
to provide data consistency. Logs reside in the persistent region and their
durability is ensured by flushing the cache lines after each log.
The default mechanism of taking logs is copy-on-write which takes a log when
the object is mutably dereferenced. This requires two clflush
es: one for
the log, and one for the update to the original data.
Implementations
Sets the off
and len
of the log
This function is used for low-level atomic allocation. The algorithm is as follows:
- Take a neutral drop log (
off = u64::MAX
) in a log slot in theJournal
- Prepare allocation using
pre_alloc()
- Add a low-level log for updating the
off
andlen
of the drop log usingset
function - Perform the prepared changes to the allocator
Note that the deallocation of owned objects are handled through RAII.
To reclaim the allocation of any sort on a failure, low-level
DropOnFailure
log is provided with the allocation.
If a crash happens before step 4, all changes are discarded and the drop log remains neutral. If a crash happens in the middle of step 4, the recovery procedure continues performing the changes, including the low-level logs for updating the drop log. Once it has the high-level drop log, the high-level recovery procedure reclaims the allocation as the crash happened inside a transaction.
Examples
P::transaction(|j| unsafe { // Create a neutral high-level log to drop the allocation on failure. // It is different from the low-level drop log which is inside the // allocator's ring buffer. Unlike that, this log is stored in the // journal object. let mut log = Log::drop_on_failure(u64::MAX, 1, j); // Prepare an allocation. The allocation is not durable yet. In case // of a crash, the prepared allocated space is gone. It is fine // because it has not been used. The `atomic_` functions // form a low-level atomic section. let (obj, off, len, zone) = P::atomic_new([1,2,3,4,5]); // Set the offset and size of the allocation to make the log valid. // Note that the changes will be effective after the allocation is // successfully performed. log.set(off, len, zone); // It is fine to work with the prepared raw pointer. All changes in // the low-level atomic section are considered as part of the // allocation and will be gone in case of a crash, as the allocation // will be dropped. obj[1] = 20; // Transaction ends here. The perform function sets the `operating` // flag to show that the prepared changes are being materialized. // This flag remains set until the end of materialization. In case // of a crash while operating, the recovery procedure first continues // the materialization, and then uses the `DropOnFailure` logs to // reclaim the allocation. `perform` function realizes the changes // made by the `pre_` function on the given memory zone. P::perform(zone); }).unwrap();
Takes a log of x
into journal
and notifies the owner that log is
taken if notifier
is specified.
Takes a log of &[x]
into journal
and notifies the owner that log is
taken if notifier
is specified.
Creates a new DropOnCommit
log and writes it on journal
Creates a new DropOnAbort
log and writes it on journal
Creates a new DropOnFailure
log and writes it on journal
Creates a new UnlockOnCommit
for locking data in a thread
Creates a new DropOnCommit
log and writes it on journal
Clears this log and notifies the owner
- If it is a
DataLog
, it reclaims the allocation for the log. - If it is a
UnlockOnCommit
, it unlocks the mutex.
Trait Implementations
Auto Trait Implementations
impl<A> LooseTxInUnsafe for Log<A> where
A: LooseTxInUnsafe,
impl<A> RefUnwindSafe for Log<A> where
A: RefUnwindSafe,
impl<A> UnwindSafe for Log<A> where
A: UnwindSafe,
Blanket Implementations
Mutably borrows from an owned value. Read more
pub fn vzip(self) -> V