Settings
Help

Module time_store

Module time_store 

Source
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 std::time::{Duration, Instant};
use tor_rtcompat::{PreferredRuntime, SleepProvider as _};

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_raw and from_raw methods (for a struct with a single field)
derive_deftly_template_SerdeStringOrTransparent πŸ”’
Define Serialize and Deserialize via string rep or transparently, depending

StructsΒ§

DeserializeFutureTimestampStringVisitor πŸ”’
Visitor for deserializing from a string
DeserializeReferenceStringVisitor πŸ”’
Visitor for deserializing from a string
FutureTimestamp
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
ParseError
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 SystemTime to an i64 time_t
time_t_to_system_time πŸ”’
Convert a SystemTime to an i64 time_t