Skip to main content

retia_rocks/bridge/
mod.rs

1/*
2 * Copyright 2022, The Cozo Project Authors.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
5 * If a copy of the MPL was not distributed with this file,
6 * You can obtain one at https://mozilla.org/MPL/2.0/.
7 */
8
9use std::error::Error;
10use std::fmt::{Display, Formatter};
11
12use miette::{Diagnostic, Severity};
13
14use crate::StatusSeverity;
15
16pub(crate) mod db;
17pub(crate) mod iter;
18pub(crate) mod tx;
19
20#[cxx::bridge]
21pub(crate) mod ffi {
22    #[derive(Debug, Clone)]
23    struct DbOpts {
24        pub db_path: Vec<u8>,
25        pub options_path: Vec<u8>,
26        pub prepare_for_bulk_load: bool,
27        pub increase_parallelism: usize,
28        pub optimize_level_style_compaction: bool,
29        pub create_if_missing: bool,
30        pub paranoid_checks: bool,
31        pub enable_blob_files: bool,
32        pub min_blob_size: usize,
33        pub blob_file_size: usize,
34        pub enable_blob_garbage_collection: bool,
35        pub use_bloom_filter: bool,
36        pub bloom_filter_bits_per_key: f64,
37        pub bloom_filter_whole_key_filtering: bool,
38        pub use_capped_prefix_extractor: bool,
39        pub capped_prefix_extractor_len: usize,
40        pub use_fixed_prefix_extractor: bool,
41        pub fixed_prefix_extractor_len: usize,
42        pub destroy_on_exit: bool,
43        pub block_cache_size: usize,
44    }
45
46    #[derive(Clone, Debug, Eq, PartialEq)]
47    pub struct RocksDbStatus {
48        pub code: StatusCode,
49        pub subcode: StatusSubCode,
50        pub severity: StatusSeverity,
51        pub message: String,
52    }
53
54    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
55    pub enum StatusCode {
56        kOk = 0,
57        kNotFound = 1,
58        kCorruption = 2,
59        kNotSupported = 3,
60        kInvalidArgument = 4,
61        kIOError = 5,
62        kMergeInProgress = 6,
63        kIncomplete = 7,
64        kShutdownInProgress = 8,
65        kTimedOut = 9,
66        kAborted = 10,
67        kBusy = 11,
68        kExpired = 12,
69        kTryAgain = 13,
70        kCompactionTooLarge = 14,
71        kColumnFamilyDropped = 15,
72        kMaxCode,
73    }
74
75    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
76    pub enum StatusSubCode {
77        kNone = 0,
78        kMutexTimeout = 1,
79        kLockTimeout = 2,
80        kLockLimit = 3,
81        kNoSpace = 4,
82        kDeadlock = 5,
83        kStaleFile = 6,
84        kMemoryLimit = 7,
85        kSpaceLimit = 8,
86        kPathNotFound = 9,
87        KMergeOperandsInsufficientCapacity = 10,
88        kManualCompactionPaused = 11,
89        kOverwritten = 12,
90        kTxnNotPrepared = 13,
91        kIOFenced = 14,
92        kMergeOperatorFailed = 15,
93        kMergeOperandThresholdExceeded = 16,
94        kMaxSubCode,
95    }
96
97    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
98    pub enum StatusSeverity {
99        kNoError = 0,
100        kSoftError = 1,
101        kHardError = 2,
102        kFatalError = 3,
103        kUnrecoverableError = 4,
104        kMaxSeverity,
105    }
106
107    unsafe extern "C++" {
108        include!("bridge.h");
109
110        type StatusCode;
111        type StatusSubCode;
112        type StatusSeverity;
113        type WriteOptions;
114        type PinnableSlice;
115        fn convert_pinnable_slice_back(s: &PinnableSlice) -> &[u8];
116
117        fn set_w_opts_sync(o: Pin<&mut WriteOptions>, val: bool);
118        fn set_w_opts_disable_wal(o: Pin<&mut WriteOptions>, val: bool);
119        fn set_w_opts_no_slowdown(o: Pin<&mut WriteOptions>, val: bool);
120
121        // type ReadOptions;
122
123        pub type SnapshotBridge;
124
125        type RocksDbBridge;
126        fn get_db_path(self: &RocksDbBridge) -> &CxxString;
127        fn open_db(builder: &DbOpts, status: &mut RocksDbStatus) -> SharedPtr<RocksDbBridge>;
128        fn transact(self: &RocksDbBridge) -> UniquePtr<TxBridge>;
129        fn del_range(self: &RocksDbBridge, lower: &[u8], upper: &[u8], status: &mut RocksDbStatus);
130        fn put(self: &RocksDbBridge, key: &[u8], val: &[u8], status: &mut RocksDbStatus);
131        fn compact_range(
132            self: &RocksDbBridge,
133            lower: &[u8],
134            upper: &[u8],
135            status: &mut RocksDbStatus,
136        );
137        fn get_sst_writer(
138            self: &RocksDbBridge,
139            path: &str,
140            status: &mut RocksDbStatus,
141        ) -> UniquePtr<SstFileWriterBridge>;
142        fn ingest_sst(self: &RocksDbBridge, path: &str, status: &mut RocksDbStatus);
143
144        type SstFileWriterBridge;
145        fn put(
146            self: Pin<&mut SstFileWriterBridge>,
147            key: &[u8],
148            val: &[u8],
149            status: &mut RocksDbStatus,
150        );
151        fn finish(self: Pin<&mut SstFileWriterBridge>, status: &mut RocksDbStatus);
152
153        type TxBridge;
154        // fn get_r_opts(self: Pin<&mut TxBridge>) -> Pin<&mut ReadOptions>;
155        fn verify_checksums(self: Pin<&mut TxBridge>, val: bool);
156        fn fill_cache(self: Pin<&mut TxBridge>, val: bool);
157        fn get_w_opts(self: Pin<&mut TxBridge>) -> Pin<&mut WriteOptions>;
158        fn start(self: Pin<&mut TxBridge>);
159        fn set_snapshot(self: Pin<&mut TxBridge>, val: bool);
160        fn clear_snapshot(self: Pin<&mut TxBridge>);
161        fn get(
162            self: &TxBridge,
163            key: &[u8],
164            for_update: bool,
165            status: &mut RocksDbStatus,
166        ) -> UniquePtr<PinnableSlice>;
167        fn exists(self: &TxBridge, key: &[u8], for_update: bool, status: &mut RocksDbStatus);
168        fn put(self: &TxBridge, key: &[u8], val: &[u8], status: &mut RocksDbStatus);
169        fn del(self: &TxBridge, key: &[u8], status: &mut RocksDbStatus);
170        fn commit(self: Pin<&mut TxBridge>, status: &mut RocksDbStatus);
171        fn rollback(self: Pin<&mut TxBridge>, status: &mut RocksDbStatus);
172        fn rollback_to_savepoint(self: Pin<&mut TxBridge>, status: &mut RocksDbStatus);
173        fn pop_savepoint(self: Pin<&mut TxBridge>, status: &mut RocksDbStatus);
174        fn set_savepoint(self: Pin<&mut TxBridge>);
175        fn iterator(self: &TxBridge) -> UniquePtr<IterBridge>;
176
177        type IterBridge;
178        fn start(self: Pin<&mut IterBridge>);
179        fn reset(self: Pin<&mut IterBridge>);
180        // fn get_r_opts(self: Pin<&mut IterBridge>) -> Pin<&mut ReadOptions>;
181        fn clear_bounds(self: Pin<&mut IterBridge>);
182        fn set_lower_bound(self: Pin<&mut IterBridge>, bound: &[u8]);
183        fn set_upper_bound(self: Pin<&mut IterBridge>, bound: &[u8]);
184        fn verify_checksums(self: Pin<&mut IterBridge>, val: bool);
185        fn fill_cache(self: Pin<&mut IterBridge>, val: bool);
186        fn tailing(self: Pin<&mut IterBridge>, val: bool);
187        fn total_order_seek(self: Pin<&mut IterBridge>, val: bool);
188        fn auto_prefix_mode(self: Pin<&mut IterBridge>, val: bool);
189        fn prefix_same_as_start(self: Pin<&mut IterBridge>, val: bool);
190        fn pin_data(self: Pin<&mut IterBridge>, val: bool);
191
192        fn to_start(self: Pin<&mut IterBridge>);
193        fn to_end(self: Pin<&mut IterBridge>);
194        fn seek(self: Pin<&mut IterBridge>, key: &[u8]);
195        fn seek_backward(self: Pin<&mut IterBridge>, key: &[u8]);
196        fn is_valid(self: &IterBridge) -> bool;
197        fn next(self: Pin<&mut IterBridge>);
198        fn prev(self: Pin<&mut IterBridge>);
199        fn status(self: &IterBridge, status: &mut RocksDbStatus);
200        fn key(self: &IterBridge) -> &[u8];
201        fn val(self: &IterBridge) -> &[u8];
202    }
203}
204
205impl Default for ffi::RocksDbStatus {
206    #[inline]
207    fn default() -> Self {
208        ffi::RocksDbStatus {
209            code: ffi::StatusCode::kOk,
210            subcode: ffi::StatusSubCode::kNone,
211            severity: ffi::StatusSeverity::kNoError,
212            message: "".to_string(),
213        }
214    }
215}
216
217impl Error for ffi::RocksDbStatus {}
218
219impl Display for ffi::RocksDbStatus {
220    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
221        if self.message.is_empty() {
222            write!(f, "RocksDB error: {self:?}")
223        } else {
224            write!(f, "RocksDB error: {}", self.message)
225        }
226    }
227}
228
229impl Diagnostic for ffi::RocksDbStatus {
230    fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
231        if self.is_ok() {
232            None
233        } else {
234            Some(Box::new(format!(
235                "rocksdb::{:?}::{:?}",
236                self.code, self.subcode
237            )))
238        }
239    }
240    fn severity(&self) -> Option<Severity> {
241        match self.severity {
242            StatusSeverity::kNoError => None,
243            _ => Some(Severity::Error),
244        }
245    }
246    fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
247        Some(Box::new("This error is usually outside Retia's control"))
248    }
249}
250
251impl ffi::RocksDbStatus {
252    #[inline(always)]
253    pub fn is_ok(&self) -> bool {
254        self.code == ffi::StatusCode::kOk
255    }
256    #[inline(always)]
257    pub fn is_not_found(&self) -> bool {
258        self.code == ffi::StatusCode::kNotFound
259    }
260    #[inline(always)]
261    pub fn is_ok_or_not_found(&self) -> bool {
262        self.is_ok() || self.is_not_found()
263    }
264}