A file system in an ETS table, for the Concuerror scenarios of the
blob store (test/concurrency/blob_test.ex): Roux.Blob.IO answers a
process's operations from it once the process enter/2s it, so the
store's own code runs over a file system whose every step is a
scheduling point Concuerror can interleave.
A name is a row, {{:name, path}, kind, inode} (kind :file or
:dir); an inode is {{:inode, inode}, content, mtime, mode}, its
bytes written once. A hard link is another name for the inode: it
shares bytes, time and mode, and survives the removal of the name it
was made from.
stat(2), utime(2) and chmod(2) resolve a name and read or change its inode in one system call. Here they resolve the name, read or change the inode, and look again: a name no longer on that inode reports ENOENT, as a call made after the name went would (a change, on the inode, can only keep an entry a collection would otherwise take — never lose one). A read resolves the name once, as an open does: the bytes of a file removed after that are still read.
Every operation is one step on a name, as a system call is — except the one that is not atomic on APFS: a rename that REPLACES an existing name removes the name, then installs the new inode under it, so a concurrent link(2) or open between the two finds no name. A rename onto a free name is one step (a lookup may briefly see both names, which nothing here minds).
Each actor names the model OS process it belongs to (enter/2's
ospid), which is what Roux.Blob.IO.ospid/0 returns to it; its
Roux.Blob.IO.unique/0 counts from 1 per model OS process, as a new
VM's unique integers restart.
Summary
Functions
Makes the calling process one of model OS process ospid's, on table.
A fresh file system holding the root directory.
Functions
Makes the calling process one of model OS process ospid's, on table.
A fresh file system holding the root directory.