Skip to main content

Module filelock

Module filelock 

Source
Expand description

One writer at a time on a file that two parts of Sioul change: the window marks a dose in the doses’ record while the sharing writes in it what your other devices marked. One writing an older copy over the other would lose a dose taken, and the sharing would then take it out on every device. An advisory lock on a hidden file beside it (.<name>.lock, which the sharing never carries), held while the file is read, changed and written.

Structs§

FileStamp
A file as it was when it was read, to know before replacing it that it still is (its device and number, its size and time; size and time only where a file has no number: Windows).
Placed
A replacement made: what is left once the lock is let go. No reader that takes that lock holds the old file then (it reads within its own hold, by the file’s name, which names the new file), and a reader that does not reads through read_whole, which never returns what follows.
Prepared
New bytes for a file, written beside it under a hidden name (which the sharing and the watcher pass over), yours alone, and on the disk, waiting to take its place; taken out if they never do. The slow part of a replacement, done before any lock is taken.
Read
A TOML file as it was read, kept beside the state read from it (a field that serde skips): saved, only what changed since it was read is written over what the file holds then (save_merged), so that a change your other devices brought in meanwhile (the sharing writes under the same lock) stays. Equal to any other, so that it changes no comparison of the state.

Constants§

HELD 🔒
The locks this thread holds: one taken again inside (a writer calling another of the same file) is already held, never waited for.
READ_AGAIN 🔒
How many times a file replaced while it was read is read again before that is said (“Interrupted”).

Statics§

EMPTY 🔒

Functions§

copy_whole
from copied to to as one of its versions held it whole, with read_whole’s check: through its descriptor, then again, a few times, when the file copied lost its name meanwhile or from names another one. to is made yours alone (on Unix). Returns the bytes copied.
has_lock
Whether a writer of path takes its lock here (its hidden lock file is there): for files the sharing writes without it otherwise (a note, which most writers do not lock), so that a file one of Sioul’s own writers changes under its lock (the letters’ list) is written under it too.
lock_path 🔒
merge 🔒
What changed from base to new, set over current. A list or a table on one side only stands against an empty one on the other: emptied, it takes out what it held, never what another writer added since; filled from nothing, it adds to what another writer put there.
overwrite 🔒
A file without a name left, its bytes overwritten with zeros, on the disk.
read_through 🔒
read_whole_with, each file opened by open (a test replaces the file between its opening and its reading).
read_whole
A file’s bytes as one of its versions held them whole, never the zeros Placed::finish writes over the file it replaced: read through its descriptor, then checked that the file read still has a name and that path names it (still_named); else read again, a few times. A file replaced while it was read has no name, and its bytes may be zeros by then; one replaced after it was read is an older version: both are read again. Where a file has no number to tell (Windows), read once: there nothing is overwritten.
read_whole_with
read_whole, with what the descriptor said of the file read, after the read: its size and time are those of the bytes returned.
rename_over 🔒
from renamed over to. On Windows a file another thread or program has open for a moment (a reader of the same state) refuses to be replaced: tried again a few times, for a tenth of a second at most (CI’s Windows job of 22 October 2026: a calendar’s kinds lost so).
replace
Bytes written beside path under a hidden name of their own, then renamed over it: a reader never finds the file empty or half written (the sharing reads without the lock), and a full disk leaves the file as it was rather than empty (review of 5 October 2026, F10).
replace_wiping
bytes in place of path’s content, what it held overwritten where the filesystem lets it be (docs/client.md, “What a disk keeps”): Prepared, Prepared::place and Placed::finish at once, for a file no other part of Sioul reads meanwhile but through read_whole. A file that readers take a lock for is replaced in those three steps, the place alone under that lock (draftcopies: the sharing’s exchange lock).
save_merged
state written into path, under its lock, the file read again first: what changed from read (the file as it was read) to state is set over what the file holds now, field by field (a list as a set: what was added added, what was taken out taken out; a list or table missing on one side is an empty one, as a state skips an empty field); the rest stays as the file holds it. A file missing when it was read is read as empty. Nothing read before that could be merged (a file that did not read): state whole. Written beside, then moved.
save_merged_by
The same, settle then given the merged table and the file as it was just before (none when missing): for what a field-by-field merge cannot say (a mark that must never go backwards).
still_named 🔒
Whether the file read through a descriptor (held: what it says after the read) still has a name, and path is it.
with_lock
f, with the lock on path held: other threads and programs wait for it. Where no lock can be taken (a folder not writable), f runs all the same: writing it fails there anyway. Taken again by the thread holding it, it is held already.