ckb_rocksdb/ops/
get_pinned.rs

1// Copyright 2019 Tyler Neely
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use crate::ffi;
17use libc::{c_char, size_t};
18
19use crate::{handle::Handle, ColumnFamily, DBPinnableSlice, Error, ReadOptions};
20
21pub trait GetPinned<'a> {
22    type ReadOptions;
23
24    /// Return the value associated with a key using RocksDB's PinnableSlice
25    /// so as to avoid unnecessary memory copy.
26    fn get_pinned_full<K: AsRef<[u8]>>(
27        &'a self,
28        key: K,
29        readopts: Option<Self::ReadOptions>,
30    ) -> Result<Option<DBPinnableSlice<'a>>, Error>;
31
32    /// Return the value associated with a key using RocksDB's PinnableSlice
33    /// so as to avoid unnecessary memory copy. Similar to get_pinned_opt but
34    /// leverages default options.
35    fn get_pinned<K: AsRef<[u8]>>(&'a self, key: K) -> Result<Option<DBPinnableSlice<'a>>, Error> {
36        self.get_pinned_full(key, None)
37    }
38
39    /// Return the value associated with a key using RocksDB's PinnableSlice
40    /// so as to avoid unnecessary memory copy.
41    fn get_pinned_opt<K: AsRef<[u8]>>(
42        &'a self,
43        key: K,
44        readopts: Self::ReadOptions,
45    ) -> Result<Option<DBPinnableSlice<'a>>, Error> {
46        self.get_pinned_full(key, Some(readopts))
47    }
48}
49
50pub trait GetPinnedCF<'a> {
51    type ColumnFamily;
52    type ReadOptions;
53
54    /// Return the value associated with a key using RocksDB's PinnableSlice
55    /// so as to avoid unnecessary memory copy.
56    fn get_pinned_cf_full<K: AsRef<[u8]>>(
57        &'a self,
58        cf: Option<Self::ColumnFamily>,
59        key: K,
60        readopts: Option<Self::ReadOptions>,
61    ) -> Result<Option<DBPinnableSlice<'a>>, Error>;
62
63    /// Return the value associated with a key using RocksDB's PinnableSlice
64    /// so as to avoid unnecessary memory copy.
65    fn get_pinned_cf<K: AsRef<[u8]>>(
66        &'a self,
67        cf: Self::ColumnFamily,
68        key: K,
69    ) -> Result<Option<DBPinnableSlice<'a>>, Error> {
70        self.get_pinned_cf_full(Some(cf), key, None)
71    }
72
73    /// Return the value associated with a key using RocksDB's PinnableSlice
74    /// so as to avoid unnecessary memory copy.
75    fn get_pinned_cf_opt<K: AsRef<[u8]>>(
76        &'a self,
77        cf: Self::ColumnFamily,
78        key: K,
79        readopts: Self::ReadOptions,
80    ) -> Result<Option<DBPinnableSlice<'a>>, Error> {
81        self.get_pinned_cf_full(Some(cf), key, Some(readopts))
82    }
83}
84
85impl<'a, T, R> GetPinned<'a> for T
86where
87    T: GetPinnedCF<'a, ReadOptions = R>,
88{
89    type ReadOptions = R;
90
91    fn get_pinned_full<K: AsRef<[u8]>>(
92        &'a self,
93        key: K,
94        readopts: Option<Self::ReadOptions>,
95    ) -> Result<Option<DBPinnableSlice<'a>>, Error> {
96        self.get_pinned_cf_full(None, key, readopts)
97    }
98}
99
100impl<'a, T> GetPinnedCF<'a> for T
101where
102    T: Handle<ffi::rocksdb_t> + super::Read,
103{
104    type ColumnFamily = &'a ColumnFamily;
105    type ReadOptions = &'a ReadOptions;
106
107    fn get_pinned_cf_full<K: AsRef<[u8]>>(
108        &'a self,
109        cf: Option<Self::ColumnFamily>,
110        key: K,
111        readopts: Option<Self::ReadOptions>,
112    ) -> Result<Option<DBPinnableSlice<'a>>, Error> {
113        let mut default_readopts = None;
114
115        let ro_handle = ReadOptions::input_or_default(readopts, &mut default_readopts)?;
116
117        let key = key.as_ref();
118        let key_ptr = key.as_ptr() as *const c_char;
119        let key_len = key.len() as size_t;
120
121        unsafe {
122            let val = match cf {
123                Some(cf) => ffi_try!(ffi::rocksdb_get_pinned_cf(
124                    self.handle(),
125                    ro_handle,
126                    cf.inner,
127                    key_ptr,
128                    key_len,
129                )),
130                None => ffi_try!(ffi::rocksdb_get_pinned(
131                    self.handle(),
132                    ro_handle,
133                    key_ptr,
134                    key_len,
135                )),
136            };
137
138            if val.is_null() {
139                Ok(None)
140            } else {
141                Ok(Some(DBPinnableSlice::from_c(val)))
142            }
143        }
144    }
145}