absurder_sql/storage/
metadata.rs

1//! Metadata module extracted from block_storage.rs
2//! This module contains the ACTUAL checksum and metadata logic moved from BlockStorage
3
4use std::collections::HashMap;
5use crate::types::DatabaseError;
6
7#[cfg(target_arch = "wasm32")]
8#[allow(unused_imports)]
9use js_sys::Date;
10
11#[cfg(not(target_arch = "wasm32"))]
12#[allow(unused_imports)]
13use std::time::{SystemTime, UNIX_EPOCH};
14
15// MOVED from block_storage.rs lines 38-41
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17#[allow(dead_code)]
18#[cfg_attr(feature = "fs_persist", derive(serde::Serialize, serde::Deserialize))]
19pub enum ChecksumAlgorithm {
20    FastHash,
21    CRC32
22}
23
24// MOVED from block_storage.rs lines 43-54
25#[derive(Clone, Debug)]
26#[cfg_attr(feature = "fs_persist", derive(serde::Serialize, serde::Deserialize))]
27pub struct BlockMetadataPersist {
28    pub checksum: u64,
29    #[allow(dead_code)]
30    pub last_modified_ms: u64,
31    #[allow(dead_code)]
32    pub version: u32,
33    #[allow(dead_code)]
34    pub algo: ChecksumAlgorithm,
35}
36
37/// Metadata manager that encapsulates the checksum logic extracted from BlockStorage
38pub struct ChecksumManager {
39    /// Per-block checksums (MOVED from BlockStorage.checksums)
40    checksums: HashMap<u64, u64>,
41    /// Per-block checksum algorithms (MOVED from BlockStorage.checksum_algos)
42    checksum_algos: HashMap<u64, ChecksumAlgorithm>,
43    /// Default algorithm for new blocks (MOVED from BlockStorage.checksum_algo_default)
44    checksum_algo_default: ChecksumAlgorithm,
45}
46
47impl ChecksumManager {
48    /// Create new checksum manager with default algorithm
49    pub fn new(default_algorithm: ChecksumAlgorithm) -> Self {
50        Self {
51            checksums: HashMap::new(),
52            checksum_algos: HashMap::new(),
53            checksum_algo_default: default_algorithm,
54        }
55    }
56
57    /// Initialize with existing data (used during restoration)
58    pub fn with_data(
59        checksums: HashMap<u64, u64>,
60        checksum_algos: HashMap<u64, ChecksumAlgorithm>,
61        default_algorithm: ChecksumAlgorithm,
62    ) -> Self {
63        Self {
64            checksums,
65            checksum_algos,
66            checksum_algo_default: default_algorithm,
67        }
68    }
69
70    /// MOVED from BlockStorage::compute_checksum_with (lines 1803-1818)
71    pub fn compute_checksum_with(data: &[u8], algo: ChecksumAlgorithm) -> u64 {
72        match algo {
73            ChecksumAlgorithm::FastHash => {
74                use std::collections::hash_map::DefaultHasher;
75                use std::hash::Hash;
76                use std::hash::Hasher;
77                let mut hasher = DefaultHasher::new();
78                data.hash(&mut hasher);
79                hasher.finish()
80            }
81            ChecksumAlgorithm::CRC32 => {
82                let mut hasher = crc32fast::Hasher::new();
83                hasher.update(data);
84                hasher.finalize() as u64
85            }
86        }
87    }
88
89    /// Store checksum for a block (MOVED from lines 2442-2444)
90    pub fn store_checksum(&mut self, block_id: u64, data: &[u8]) {
91        let algo = self.checksum_algos
92            .get(&block_id)
93            .copied()
94            .unwrap_or(self.checksum_algo_default);
95        let csum = Self::compute_checksum_with(data, algo);
96        self.checksums.insert(block_id, csum);
97        self.checksum_algos.insert(block_id, algo);
98    }
99
100    /// Validate checksum for a block (MOVED from lines 1843-1870)
101    pub fn validate_checksum(&self, block_id: u64, data: &[u8]) -> Result<(), DatabaseError> {
102        if let Some(expected) = self.checksums.get(&block_id) {
103            let algo = self
104                .checksum_algos
105                .get(&block_id)
106                .copied()
107                .unwrap_or(self.checksum_algo_default);
108            let actual = Self::compute_checksum_with(data, algo);
109            if *expected != actual {
110                // Try other known algorithms to detect algorithm mismatch (MOVED from lines 1851-1869)
111                let known_algos = [ChecksumAlgorithm::FastHash, ChecksumAlgorithm::CRC32];
112                for alt in known_algos.iter().copied().filter(|a| *a != algo) {
113                    let alt_sum = Self::compute_checksum_with(data, alt);
114                    if *expected == alt_sum {
115                        return Err(DatabaseError::new(
116                            "ALGO_MISMATCH",
117                            &format!(
118                                "Checksum algorithm mismatch for block {}: stored algo {:?}, but data matches {:?}",
119                                block_id, algo, alt
120                            ),
121                        ));
122                    }
123                }
124                return Err(DatabaseError::new(
125                    "CHECKSUM_MISMATCH",
126                    &format!(
127                        "Checksum mismatch for block {}: expected {}, got {}",
128                        block_id, expected, actual
129                    ),
130                ));
131            }
132        }
133        Ok(())
134    }
135
136    /// Remove checksum for a block (MOVED from lines 1709-1710)
137    pub fn remove_checksum(&mut self, block_id: u64) {
138        self.checksums.remove(&block_id);
139        self.checksum_algos.remove(&block_id);
140    }
141
142    /// Get checksum for a block
143    pub fn get_checksum(&self, block_id: u64) -> Option<u64> {
144        self.checksums.get(&block_id).copied()
145    }
146
147    /// Get algorithm for a block
148    pub fn get_algorithm(&self, block_id: u64) -> ChecksumAlgorithm {
149        self.checksum_algos
150            .get(&block_id)
151            .copied()
152            .unwrap_or(self.checksum_algo_default)
153    }
154
155    /// Replace all checksums (MOVED from lines 1331-1332, 1500-1501)
156    pub fn replace_all(
157        &mut self,
158        new_checksums: HashMap<u64, u64>,
159        new_algos: HashMap<u64, ChecksumAlgorithm>,
160    ) {
161        self.checksums = new_checksums;
162        self.checksum_algos = new_algos;
163    }
164
165    /// Get reference to internal checksums map (for compatibility)
166    pub fn checksums(&self) -> &HashMap<u64, u64> {
167        &self.checksums
168    }
169
170    /// Get reference to internal algorithms map (for compatibility)
171    pub fn algorithms(&self) -> &HashMap<u64, ChecksumAlgorithm> {
172        &self.checksum_algos
173    }
174
175    /// Get default algorithm
176    pub fn default_algorithm(&self) -> ChecksumAlgorithm {
177        self.checksum_algo_default
178    }
179
180    /// Set checksum for testing purposes
181    #[cfg(any(test, debug_assertions))]
182    pub fn set_checksum_for_testing(&mut self, block_id: u64, checksum: u64) {
183        self.checksums.insert(block_id, checksum);
184    }
185    
186    /// Clear all checksums (useful after database import)
187    pub fn clear_checksums(&mut self) {
188        self.checksums.clear();
189        self.checksum_algos.clear();
190    }
191}