Skip to main content

Module lock

Module lock 

Source
Expand description

One target held by one apply at a time.

An apply reads the target, decides against what it read, stages, and renames. Two of them interleaved can each pass their own validation and then commit over each other, leaving one plan’s files beside another’s record: a target describing a landing that never happened. The transaction cannot see that, because it renames files it staged before the other run existed.

So an apply takes the target first and holds it until its postconditions have run. The lock is one file under the state root, named for the canonical target path, and what holds the target is the advisory lock the operating system puts on the open file, not the file’s existence. The kernel owns that lock: it releases when the holder exits, however it exits, so a run killed outright frees the target rather than stranding it. The file itself is left in place, because removing one another run has already opened would leave two runs holding locks on two different inodes under one name.

It lives outside the target because a target’s cleanliness is judged byte by byte, and a lock file inside it would be drift.

Where the lock cannot be taken, the apply refuses. A guard that silently does nothing is worse than none, because the call site still reads as guarded.

It is advisory, and it bounds this engine’s own runs rather than every writer: a hand edit during an apply is what the before-digests and the postconditions are for.

Structs§

TargetLock
One target held for the life of this value.

Constants§

LOCKS_DIR
The directory holding the locks, under the state root.

Functions§

acquire
Take target for this run, or refuse.
acquire_in
The acquisition against one locks directory, which is what the tests drive so no test has to move the state root out from under itself.