pub struct FileStorage { /* private fields */ }Expand description
A Storage backed by one file per key, under the OS’s per-app data
directory (data_dir).
The folder holds <key>.ron, the value, and <key>.ron.bak, the
value before it (ticket 3045). A <key>.ron.tmp is there only between
a crash and the next write, which removes it. A sync of the folder
(Steam Auto-Cloud) must carry the .bak files with the .ron files:
a key whose .ron is gone reads its good .bak, so a save deleted on
one machine would come back from its backup on another.
A write puts the new value in <key>.ron.tmp and flushes it to the
disk, copies the old <key>.ron (when it is a good copy: not empty,
not all zero bytes, UTF-8) to <key>.ron.bak and flushes that, renames
the .tmp onto the .ron, and syncs the folder. A read of a .ron
that is missing, empty, all zero bytes or not UTF-8 beside a good
.bak reads the .bak, and logs a warning. What that promises:
- a crash of the game, on every OS: the key reads the old value or the new one;
- a power cut or a crash of the system, on Linux (the Steam Deck)
and macOS: the key reads the old value or the new one, and a write
that returned
Okreads the new one, since the file and the folder are flushed before it returns (F_FULLFSYNCon macOS). A file system that can’t sync a folder (it answersUnsupported) keeps the rename only as well as it journals it; - a power cut on Windows:
stdopens no folder for a sync, so the folder isn’t flushed. NTFS journals the rename, so the key reads the old value or the new one, never damage; a write that returned in the moments before the cut may read the old one.
A key written "" or only \0 characters keeps no backup, so it reads
back as written and not as damage.
Implementations§
Source§impl FileStorage
impl FileStorage
Trait Implementations§
Source§impl Debug for FileStorage
impl Debug for FileStorage
Source§impl Storage for FileStorage
impl Storage for FileStorage
Source§fn read(&self, key: &str) -> Result<Option<String>, StorageError>
fn read(&self, key: &str) -> Result<Option<String>, StorageError>
key, or None if nothing has been written
there (or it was deleted).Source§fn write(&mut self, key: &str, value: &str) -> Result<(), StorageError>
fn write(&mut self, key: &str, value: &str) -> Result<(), StorageError>
value at key, replacing whatever was there.