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