Expand description
Saving/loading timestamps to disk
Storing timestamps on disk is not so straightforward. We need to use wall clock time in order to survive restarts. But wall clocks can be wrong, so we need at least to apply some sanity checks.
This module encapsulates those checks, and some error handling choices.
It allows Instants to be used while the system is running,
with bespoke types for loading/saving.
See Loading::load_future for the load/save guarantees provided.
The initial entrypoints are Storing::start and Loading::start.
Granularity is 1 second and the precise rounding behaviour is not specified.
ยงData model
To mitigate clock skew, we store the wall clock time at which
each timestamp was saved to disk (Reference)
and the offset from now to that timestamp (FutureTimestamp).
The same storage time can be used for multiple timestamps that are stored together.
ยงExample
use serde::{Serialize, Deserialize};
use tor_rtcompat::{PreferredRuntime, SleepProvider as _};
use web_time_compat::{Duration, Instant};
use crate::time_store;
let runtime = PreferredRuntime::create().unwrap();
#[derive(Serialize, Deserialize, Debug)]
struct Stored {
time_ref: time_store::Reference,
t0: time_store::FutureTimestamp,
}
let t0: Instant = runtime.now() + Duration::from_secs(60);
let storing = time_store::Storing::start(&runtime);
let data = Stored {
time_ref: storing.store_ref(),
t0: storing.store_future(t0),
};
let json = serde_json::to_string(&data).unwrap();
// later:
let data: Stored = serde_json::from_str(&json).unwrap();
let loading = time_store::Loading::start(&runtime, data.time_ref);
let t0: Instant = loading.load_future(data.t0);
assert!(t0 - runtime.now() <= Duration::from_secs(60));ยงTime arithmetic overflows and stupid system time settings
Arithmetic is done with signed 64-bit numbers of seconds. So overflow cannot occur unless the clock is completely ludicrous. If the clock is ludicrous, time calculations are going to be a mess. We treat this as clock skew, using saturating arithmetic, rather than returning errors. Reasonable operation will resume when the clock becomes sane.
Macrosยง
- derive_
deftly_ ๐template_ RawConversions - Define
as_rawandfrom_rawmethods (for a struct with a single field) - derive_
deftly_ ๐template_ Serde String OrTransparent - Define
SerializeandDeserializevia string rep or transparently, depending
Structsยง
- Deserialize
Future ๐Timestamp String Visitor - Visitor for deserializing from a string
- Deserialize
Reference ๐String Visitor - Visitor for deserializing from a string
- Future
Timestamp - Representation of an absolute time, in the future, suitable for storing to disk
- Loading
- Context for loading
Instants from disk - Now ๐
- The two notions of the current time, for internal use
- Parse
Error - Error parsing a timestamp or reference
- Reference
- On-disk representation of a reference time, used as context for stored timestamps
- Storing
- Context for storing
Instants to disk
Functionsยง
- system_
time_ ๐max - Maximum value of SystemTime
- system_
time_ ๐min - Minimum value of SystemTime
- system_
time_ ๐to_ time_ t - Convert a
SystemTimeto ani64time_t - time_
t_ ๐to_ system_ time - Convert a
SystemTimeto ani64time_t