Skip to main content

reddb_server/storage/
embedded.rs

1//! Server-facing wrapper for the RedDB file artifact layer.
2//!
3//! The physical `.rdb` format, WAL, checkpoint, locking, and recovery
4//! implementation lives in `reddb-file`. This module keeps the historical
5//! `crate::storage::EmbeddedRdbArtifact` API and maps file-layer errors onto
6//! `RedDBError`.
7
8use std::path::Path;
9
10use crate::api::{RedDBError, RedDBResult};
11
12pub use reddb_file::{
13    EmbeddedRdbManifest, EmbeddedRdbOpen, EmbeddedRdbSuperblock, EMBEDDED_RDB_MANIFEST_0_OFFSET,
14    EMBEDDED_RDB_MANIFEST_1_OFFSET, EMBEDDED_RDB_MANIFEST_SLOT_SIZE,
15    EMBEDDED_RDB_MANIFEST_ZONE_END, EMBEDDED_RDB_SUPERBLOCK_0_OFFSET,
16    EMBEDDED_RDB_SUPERBLOCK_1_OFFSET, EMBEDDED_RDB_SUPERBLOCK_SIZE,
17};
18
19pub struct EmbeddedRdbArtifact;
20
21pub(crate) struct EmbeddedCommitSession(reddb_file::embedded::EmbeddedGroupCommitSession);
22
23impl EmbeddedCommitSession {
24    pub(crate) fn fence_interrupted_write(&self) {
25        self.0.fence_interrupted_write();
26    }
27    pub(crate) fn check(&self) -> RedDBResult<()> {
28        map_result(self.0.check())
29    }
30    pub(crate) fn append(
31        &self,
32        payloads: &[Vec<u8>],
33        options: reddb_file::embedded::EmbeddedGroupCommitOptions,
34    ) -> RedDBResult<EmbeddedRdbOpen> {
35        map_result(self.0.append(payloads, options))
36    }
37    pub(crate) fn enqueue(
38        &self,
39        payloads: &[Vec<u8>],
40        options: reddb_file::embedded::EmbeddedGroupCommitOptions,
41    ) -> RedDBResult<PendingEmbeddedAppend> {
42        map_result(self.0.enqueue(payloads, options)).map(PendingEmbeddedAppend)
43    }
44}
45
46pub(crate) struct PendingEmbeddedAppend(reddb_file::embedded::PendingEmbeddedAppend);
47
48impl PendingEmbeddedAppend {
49    pub(crate) fn wait(&self) -> RedDBResult<EmbeddedRdbOpen> {
50        map_result(self.0.wait())
51    }
52}
53
54impl EmbeddedRdbArtifact {
55    pub(crate) fn group_commit_session(path: impl AsRef<Path>) -> EmbeddedCommitSession {
56        EmbeddedCommitSession(reddb_file::EmbeddedRdbArtifact::group_commit_session(path))
57    }
58    pub fn create(path: impl AsRef<Path>) -> RedDBResult<EmbeddedRdbOpen> {
59        map_result(reddb_file::EmbeddedRdbArtifact::create(path))
60    }
61
62    pub fn create_with_snapshot(
63        path: impl AsRef<Path>,
64        snapshot: &[u8],
65    ) -> RedDBResult<EmbeddedRdbOpen> {
66        map_result(reddb_file::EmbeddedRdbArtifact::create_with_snapshot(
67            path, snapshot,
68        ))
69    }
70
71    pub fn open(path: impl AsRef<Path>) -> RedDBResult<EmbeddedRdbOpen> {
72        map_result(reddb_file::EmbeddedRdbArtifact::open(path))
73    }
74
75    pub fn open_strict_manifest(path: impl AsRef<Path>) -> RedDBResult<EmbeddedRdbOpen> {
76        map_result(reddb_file::EmbeddedRdbArtifact::open_strict_manifest(path))
77    }
78
79    pub fn read_snapshot(open: &EmbeddedRdbOpen) -> RedDBResult<Option<Vec<u8>>> {
80        map_result(reddb_file::EmbeddedRdbArtifact::read_snapshot(open))
81    }
82
83    pub fn write_snapshot(path: impl AsRef<Path>, snapshot: &[u8]) -> RedDBResult<EmbeddedRdbOpen> {
84        map_result(reddb_file::EmbeddedRdbArtifact::write_snapshot(
85            path, snapshot,
86        ))
87    }
88
89    pub fn wal_payloads_encoded_len(payloads: &[Vec<u8>]) -> RedDBResult<u64> {
90        map_result(reddb_file::EmbeddedRdbArtifact::wal_payloads_encoded_len(
91            payloads,
92        ))
93    }
94
95    pub fn write_snapshot_with_wal_capacity(
96        path: impl AsRef<Path>,
97        snapshot: &[u8],
98        min_wal_bytes: u64,
99    ) -> RedDBResult<EmbeddedRdbOpen> {
100        map_result(
101            reddb_file::EmbeddedRdbArtifact::write_snapshot_with_wal_capacity(
102                path,
103                snapshot,
104                min_wal_bytes,
105            ),
106        )
107    }
108
109    pub fn read_wal_payloads(open: &EmbeddedRdbOpen) -> RedDBResult<Vec<Vec<u8>>> {
110        map_result(reddb_file::EmbeddedRdbArtifact::read_wal_payloads(open))
111    }
112
113    pub fn append_wal_payloads(
114        path: impl AsRef<Path>,
115        payloads: &[Vec<u8>],
116    ) -> RedDBResult<EmbeddedRdbOpen> {
117        map_result(reddb_file::EmbeddedRdbArtifact::append_wal_payloads(
118            path, payloads,
119        ))
120    }
121}
122
123fn map_result<T>(result: reddb_file::RdbFileResult<T>) -> RedDBResult<T> {
124    result.map_err(map_error)
125}
126
127fn map_error(err: reddb_file::RdbFileError) -> RedDBError {
128    match err {
129        reddb_file::RdbFileError::InvalidOperation(msg) => RedDBError::InvalidOperation(msg),
130        reddb_file::RdbFileError::Io(err) => RedDBError::Io(err),
131        // The zone message names the zone and points at scrub/salvage
132        // (ADR 0074 §2/§4); keep it verbatim rather than flattening it.
133        err @ reddb_file::RdbFileError::ZoneUnrecoverable { .. } => {
134            RedDBError::InvalidOperation(err.to_string())
135        }
136    }
137}