Skip to main content

reddb_server/storage/engine/
encrypted-pager.rs

1//! Encrypted Pager (deprecated wrapper).
2//!
3//! This module used to host a separate `EncryptedPager` struct that
4//! wrapped `Pager` and added transparent AES-GCM encryption. The
5//! encryption ownership has moved into `Pager` itself
6//! (`PagerConfig::encryption` + `Pager::{read_page_decrypted,
7//! write_page_encrypted}`), so this file now exists only to keep the
8//! historical surface compiling for callers outside the engine crate.
9//!
10//! Migration path:
11//!   * Construct `Pager` with `PagerConfig { encryption: Some(key), .. }`.
12//!   * Replace `EncryptedPager::read_page` with `Pager::read_page_decrypted`.
13//!   * Replace `EncryptedPager::write_page` with `Pager::write_page_encrypted`.
14//!
15//! New code should not introduce additional `EncryptedPager` callers.
16
17use std::path::{Path, PathBuf};
18
19use super::pager::{Pager, PagerConfig, PagerError};
20use super::{Page, PageType, PAGE_SIZE};
21use crate::storage::encryption::{page_encryptor::OVERHEAD, SecureKey};
22
23/// Usable page content size after encryption overhead
24pub const ENCRYPTED_CONTENT_SIZE: usize = PAGE_SIZE - OVERHEAD;
25
26/// Errors emitted by the deprecated wrapper. Surface kept stable for
27/// existing callers; new code should use `PagerError` directly.
28#[derive(Debug)]
29pub enum EncryptedPagerError {
30    Pager(PagerError),
31    Encryption(String),
32    InvalidKey,
33    NotEncrypted,
34    AlreadyEncrypted,
35}
36
37impl std::fmt::Display for EncryptedPagerError {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        match self {
40            Self::Pager(e) => write!(f, "Pager error: {e}"),
41            Self::Encryption(msg) => write!(f, "Encryption error: {msg}"),
42            Self::InvalidKey => write!(f, "Invalid encryption key"),
43            Self::NotEncrypted => write!(f, "Database is not encrypted"),
44            Self::AlreadyEncrypted => write!(f, "Database is already encrypted"),
45        }
46    }
47}
48
49impl std::error::Error for EncryptedPagerError {}
50
51impl From<PagerError> for EncryptedPagerError {
52    fn from(e: PagerError) -> Self {
53        match e {
54            PagerError::InvalidKey => Self::InvalidKey,
55            PagerError::EncryptionRequired => Self::NotEncrypted,
56            PagerError::PlainDatabaseRefusesKey => Self::AlreadyEncrypted,
57            other => Self::Pager(other),
58        }
59    }
60}
61
62#[derive(Debug, Clone, Default)]
63pub struct EncryptedPagerConfig {
64    pub pager_config: PagerConfig,
65    pub key: Option<SecureKey>,
66}
67
68/// Thin wrapper around `Pager` that maps the legacy
69/// `EncryptedPager::{read_page, write_page}` calls onto the new
70/// `Pager::{read_page_decrypted, write_page_encrypted}` surface.
71#[deprecated(
72    note = "use Pager with PagerConfig::encryption + read_page_decrypted/write_page_encrypted"
73)]
74pub struct EncryptedPager {
75    inner: Pager,
76    is_encrypted: bool,
77    path: PathBuf,
78}
79
80#[allow(deprecated)]
81impl EncryptedPager {
82    pub fn open<P: AsRef<Path>>(
83        path: P,
84        config: EncryptedPagerConfig,
85    ) -> Result<Self, EncryptedPagerError> {
86        let path_buf = path.as_ref().to_path_buf();
87        let mut pager_config = config.pager_config;
88        let is_encrypted = config.key.is_some();
89        pager_config.encryption = config.key;
90        let inner = Pager::open(&path_buf, pager_config)?;
91        Ok(Self {
92            inner,
93            is_encrypted,
94            path: path_buf,
95        })
96    }
97
98    pub fn is_encrypted(&self) -> bool {
99        self.is_encrypted
100    }
101
102    pub fn read_page(&self, page_id: u32) -> Result<Page, EncryptedPagerError> {
103        Ok(self.inner.read_page_decrypted(page_id)?)
104    }
105
106    pub fn write_page(&self, page_id: u32, page: Page) -> Result<(), EncryptedPagerError> {
107        Ok(self.inner.write_page_encrypted(page_id, page)?)
108    }
109
110    pub fn allocate_page(&self, page_type: PageType) -> Result<Page, EncryptedPagerError> {
111        Ok(self.inner.allocate_page(page_type)?)
112    }
113
114    pub fn free_page(&self, page_id: u32) -> Result<(), EncryptedPagerError> {
115        Ok(self.inner.free_page(page_id)?)
116    }
117
118    pub fn sync(&self) -> Result<(), EncryptedPagerError> {
119        Ok(self.inner.sync()?)
120    }
121
122    pub fn page_count(&self) -> u32 {
123        self.inner.page_count().unwrap_or(0)
124    }
125
126    pub fn path(&self) -> &Path {
127        &self.path
128    }
129}