hexz_core/store/mod.rs
1//! Storage backends for snapshot byte access.
2//!
3//! Implements the `StorageBackend` trait for local files, HTTP (blocking and
4//! async), memory-mapped files, and S3-compatible object storage. Higher
5//! layers use these backends to fetch raw bytes without caring about the
6//! transport.
7
8use bytes::Bytes;
9use hexz_common::Result;
10use std::fmt::Debug;
11
12/// Abstract interface for all byte-addressable snapshot storage backends.
13///
14/// **Architectural intent:** Decouples the snapshot decoding logic from the
15/// physical storage medium so that files, HTTP endpoints, memory maps, or
16/// object stores can be swapped without changing higher layers.
17///
18/// **Constraints:** Implementations must be thread-safe (`Send + Sync`) and
19/// provide stable, random-access reads over an immutable byte region whose
20/// length does not change during the lifetime of the backend.
21///
22/// **Side effects:** Individual calls may perform disk or network I/O and may
23/// block the calling thread; callers are responsible for scheduling behavior.
24pub trait StorageBackend: Send + Sync + Debug {
25 /// Reads exactly `len` bytes starting at `offset` from the underlying store.
26 ///
27 /// **Architectural intent:** Provides the minimal primitive needed by the
28 /// format layer to fetch headers, indices, and compressed blocks.
29 ///
30 /// **Constraints:** `offset + len` must not exceed `self.len()`; callers
31 /// should treat short reads or I/O errors as fatal for the current
32 /// operation.
33 ///
34 /// **Side effects:** May perform synchronous I/O and allocate a new
35 /// `Bytes` buffer per call; repeated small reads can be expensive.
36 fn read_exact(&self, offset: u64, len: usize) -> Result<Bytes>;
37
38 /// Returns the total logical size of the underlying snapshot in bytes.
39 ///
40 /// **Architectural intent:** Allows upper layers to validate range
41 /// requests and compute offsets into the header and index regions.
42 ///
43 /// **Constraints:** The length is assumed to be immutable for the lifetime
44 /// of the backend; changing it concurrently is undefined behavior.
45 fn len(&self) -> u64;
46
47 /// Returns `true` if the underlying store has zero length.
48 ///
49 /// **Architectural intent:** Convenience helper to avoid repeated `len()`
50 /// comparisons in call sites that need to quickly reject empty inputs.
51 ///
52 /// **Constraints:** Equivalent to `self.len() == 0`; implementations
53 /// should not override the default semantics.
54 fn is_empty(&self) -> bool {
55 self.len() == 0
56 }
57}
58
59pub mod utils;
60
61/// Local file-based storage backends.
62///
63/// Provides `StorageBackend` implementations that read directly from local
64/// files or memory-mapped regions.
65///
66/// - `FileBackend`: Traditional file I/O using `pread(2)` system calls
67/// - `MmapBackend`: Memory-mapped file access leveraging the OS page cache
68///
69/// ## Choosing a Backend
70///
71/// | Scenario | Recommended Backend | Rationale |
72/// |----------|-------------------|-----------|
73/// | Sequential scans | `FileBackend` | Lower kernel overhead, predictable I/O scheduling |
74/// | Random access with locality | `MmapBackend` | OS page cache provides transparent prefetch and caching |
75/// | Small files (<100MB) | `MmapBackend` | Entire file likely stays resident, near-zero overhead |
76/// | Large files (>1GB) with sparse access | `FileBackend` | Avoids address space fragmentation, explicit control |
77/// | Containers/restricted environments | `FileBackend` | No special kernel capabilities required |
78///
79/// ## Thread Safety
80///
81/// Both backends are fully thread-safe:
82/// - `FileBackend` uses offset-based I/O (`pread`) that bypasses file cursor state
83/// - `MmapBackend` wraps the memory map in `Arc<Mmap>` for safe shared access
84pub mod local;
85
86/// HTTP storage backends (blocking and async).
87///
88/// Enables reading snapshots served over HTTP using range requests.
89///
90/// The `HttpBackend` type wraps the `reqwest` async client in an embedded Tokio runtime,
91/// allowing synchronous callers to use HTTP without managing an async runtime.
92pub mod http;
93
94/// S3-compatible object storage backends.
95///
96/// Allows snapshots to be stored and accessed from S3 or S3-like object
97/// stores while still presenting the `StorageBackend` abstraction.
98///
99/// The `S3Backend` type wraps the `rust-s3` async client in an embedded Tokio runtime,
100/// providing a synchronous interface for snapshot access.
101pub mod s3;