Skip to main content

sochdb_kernel/
error.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// SochDB - LLM-Optimized Embedded Database
3// Copyright (C) 2026 Sushanth Reddy Vanagala (https://github.com/sushanthpy)
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18//! Kernel error types
19//!
20//! Minimal error hierarchy for ACID operations.
21
22use std::fmt;
23use thiserror::Error;
24
25/// Result type for kernel operations
26pub type KernelResult<T> = Result<T, KernelError>;
27
28/// Kernel error types - minimal set for ACID operations
29#[derive(Error, Debug)]
30pub enum KernelError {
31    /// I/O error during WAL or page operations
32    #[error("I/O error: {0}")]
33    Io(#[from] std::io::Error),
34
35    /// Transaction error
36    #[error("Transaction error: {kind}")]
37    Transaction { kind: TransactionErrorKind },
38
39    /// WAL error
40    #[error("WAL error: {kind}")]
41    Wal { kind: WalErrorKind },
42
43    /// Page manager error
44    #[error("Page error: {kind}")]
45    Page { kind: PageErrorKind },
46
47    /// Catalog error
48    #[error("Catalog error: {kind}")]
49    Catalog { kind: CatalogErrorKind },
50
51    /// Plugin error
52    #[error("Plugin error: {message}")]
53    Plugin { message: String },
54
55    /// Corruption detected
56    #[error("Data corruption detected: {details}")]
57    Corruption { details: String },
58
59    /// Recovery error
60    #[error("Recovery error: {details}")]
61    Recovery { details: String },
62}
63
64/// Transaction-specific error kinds
65#[derive(Debug, Clone, PartialEq, Eq)]
66pub enum TransactionErrorKind {
67    /// Transaction not found
68    NotFound(u64),
69    /// Transaction already committed
70    AlreadyCommitted,
71    /// Transaction already aborted
72    AlreadyAborted,
73    /// Write-write conflict detected
74    WriteWriteConflict { row_id: u64 },
75    /// Serialization failure (SSI)
76    SerializationFailure,
77    /// Deadlock detected
78    Deadlock,
79    /// Transaction timeout
80    Timeout,
81}
82
83impl fmt::Display for TransactionErrorKind {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        match self {
86            Self::NotFound(id) => write!(f, "transaction {} not found", id),
87            Self::AlreadyCommitted => write!(f, "transaction already committed"),
88            Self::AlreadyAborted => write!(f, "transaction already aborted"),
89            Self::WriteWriteConflict { row_id } => {
90                write!(f, "write-write conflict on row {}", row_id)
91            }
92            Self::SerializationFailure => write!(f, "serialization failure"),
93            Self::Deadlock => write!(f, "deadlock detected"),
94            Self::Timeout => write!(f, "transaction timeout"),
95        }
96    }
97}
98
99/// WAL-specific error kinds
100#[derive(Debug, Clone, PartialEq, Eq)]
101pub enum WalErrorKind {
102    /// Invalid LSN
103    InvalidLsn(u64),
104    /// Checksum mismatch
105    ChecksumMismatch { expected: u32, actual: u32 },
106    /// WAL corrupted
107    Corrupted,
108    /// WAL full
109    Full,
110    /// Fsync failed
111    FsyncFailed,
112}
113
114impl fmt::Display for WalErrorKind {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        match self {
117            Self::InvalidLsn(lsn) => write!(f, "invalid LSN: {}", lsn),
118            Self::ChecksumMismatch { expected, actual } => {
119                write!(
120                    f,
121                    "checksum mismatch: expected {}, got {}",
122                    expected, actual
123                )
124            }
125            Self::Corrupted => write!(f, "WAL corrupted"),
126            Self::Full => write!(f, "WAL full"),
127            Self::FsyncFailed => write!(f, "fsync failed"),
128        }
129    }
130}
131
132/// Page-specific error kinds
133#[derive(Debug, Clone, PartialEq, Eq)]
134pub enum PageErrorKind {
135    /// Page not found
136    NotFound(u64),
137    /// Page corrupted
138    Corrupted(u64),
139    /// Buffer pool full
140    BufferPoolFull,
141    /// Invalid page size
142    InvalidSize,
143}
144
145impl fmt::Display for PageErrorKind {
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        match self {
148            Self::NotFound(id) => write!(f, "page {} not found", id),
149            Self::Corrupted(id) => write!(f, "page {} corrupted", id),
150            Self::BufferPoolFull => write!(f, "buffer pool full"),
151            Self::InvalidSize => write!(f, "invalid page size"),
152        }
153    }
154}
155
156/// Catalog-specific error kinds
157#[derive(Debug, Clone, PartialEq, Eq)]
158pub enum CatalogErrorKind {
159    /// Table not found
160    TableNotFound(String),
161    /// Table already exists
162    TableExists(String),
163    /// Column not found
164    ColumnNotFound(String),
165    /// Schema mismatch
166    SchemaMismatch,
167}
168
169impl fmt::Display for CatalogErrorKind {
170    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171        match self {
172            Self::TableNotFound(name) => write!(f, "table '{}' not found", name),
173            Self::TableExists(name) => write!(f, "table '{}' already exists", name),
174            Self::ColumnNotFound(name) => write!(f, "column '{}' not found", name),
175            Self::SchemaMismatch => write!(f, "schema mismatch"),
176        }
177    }
178}