ckb_rocksdb/
read_only_db.rs1use crate::ffi;
17
18use crate::{
19 db_iterator::DBRawIterator,
20 db_options::{OptionsMustOutliveDB, ReadOptions},
21 handle::Handle,
22 open_raw::{OpenRaw, OpenRawFFI},
23 ops, ColumnFamily, Error,
24};
25
26use libc::c_uchar;
27use std::collections::BTreeMap;
28use std::fmt;
29use std::marker::PhantomData;
30use std::path::{Path, PathBuf};
31
32pub struct ReadOnlyDB {
33 pub(crate) inner: *mut ffi::rocksdb_t,
34 cfs: BTreeMap<String, ColumnFamily>,
35 path: PathBuf,
36 _outlive: Vec<OptionsMustOutliveDB>,
37}
38
39impl ReadOnlyDB {
40 pub fn path(&self) -> &Path {
41 self.path.as_path()
42 }
43}
44
45#[derive(Default)]
46pub struct ReadOnlyOpenDescriptor {
47 error_if_log_file_exists: bool,
48}
49
50impl ops::Open for ReadOnlyDB {}
51impl ops::OpenCF for ReadOnlyDB {}
52
53impl OpenRaw for ReadOnlyDB {
54 type Pointer = ffi::rocksdb_t;
55 type Descriptor = ReadOnlyOpenDescriptor;
56
57 fn open_ffi(input: OpenRawFFI<'_, Self::Descriptor>) -> Result<*mut Self::Pointer, Error> {
58 let error_if_log_file_exists = input.open_descriptor.error_if_log_file_exists as c_uchar;
59 let pointer = unsafe {
60 if input.num_column_families <= 0 {
61 ffi_try!(ffi::rocksdb_open_for_read_only(
62 input.options,
63 input.path,
64 error_if_log_file_exists,
65 ))
66 } else {
67 ffi_try!(ffi::rocksdb_open_for_read_only_column_families(
68 input.options,
69 input.path,
70 input.num_column_families,
71 input.column_family_names,
72 input.column_family_options,
73 input.column_family_handles,
74 error_if_log_file_exists,
75 ))
76 }
77 };
78
79 Ok(pointer)
80 }
81
82 fn build<I>(
83 path: PathBuf,
84 _open_descriptor: Self::Descriptor,
85 pointer: *mut Self::Pointer,
86 column_families: I,
87 outlive: Vec<OptionsMustOutliveDB>,
88 ) -> Result<Self, Error>
89 where
90 I: IntoIterator<Item = (String, *mut ffi::rocksdb_column_family_handle_t)>,
91 {
92 let cfs: BTreeMap<_, _> = column_families
93 .into_iter()
94 .map(|(k, h)| (k, ColumnFamily::new(h)))
95 .collect();
96 Ok(ReadOnlyDB {
97 inner: pointer,
98 cfs,
99 path,
100 _outlive: outlive,
101 })
102 }
103}
104
105impl Handle<ffi::rocksdb_t> for ReadOnlyDB {
106 fn handle(&self) -> *mut ffi::rocksdb_t {
107 self.inner
108 }
109}
110
111impl ops::Iterate for ReadOnlyDB {
112 fn get_raw_iter<'a: 'b, 'b>(&'a self, readopts: &ReadOptions) -> DBRawIterator<'b> {
113 unsafe {
114 DBRawIterator {
115 inner: ffi::rocksdb_create_iterator(self.inner, readopts.handle()),
116 db: PhantomData,
117 }
118 }
119 }
120}
121
122impl ops::IterateCF for ReadOnlyDB {
123 fn get_raw_iter_cf<'a: 'b, 'b>(
124 &'a self,
125 cf_handle: &ColumnFamily,
126 readopts: &ReadOptions,
127 ) -> Result<DBRawIterator<'b>, Error> {
128 unsafe {
129 Ok(DBRawIterator {
130 inner: ffi::rocksdb_create_iterator_cf(
131 self.inner,
132 readopts.handle(),
133 cf_handle.inner,
134 ),
135 db: PhantomData,
136 })
137 }
138 }
139}
140
141impl ops::GetColumnFamilys for ReadOnlyDB {
142 fn get_cfs(&self) -> &BTreeMap<String, ColumnFamily> {
143 &self.cfs
144 }
145 fn get_mut_cfs(&mut self) -> &mut BTreeMap<String, ColumnFamily> {
146 &mut self.cfs
147 }
148}
149
150impl ops::Read for ReadOnlyDB {}
151
152unsafe impl Send for ReadOnlyDB {}
153unsafe impl Sync for ReadOnlyDB {}
154
155impl Drop for ReadOnlyDB {
156 fn drop(&mut self) {
157 unsafe {
158 for cf in self.cfs.values() {
159 ffi::rocksdb_column_family_handle_destroy(cf.inner);
160 }
161 ffi::rocksdb_close(self.inner);
162 }
163 }
164}
165
166impl fmt::Debug for ReadOnlyDB {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "Read-only RocksDB {{ path: {:?} }}", self.path())
169 }
170}