1// Copyright 2020 Lucjan Suski
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//`
1516use crate::{ffi, ffi_util::to_cpath, Error, Options};
1718use libc::{self, c_char, size_t};
19use std::{ffi::CString, marker::PhantomData, path::Path};
2021/// SstFileWriter is used to create sst files that can be added to database later
22/// All keys in files generated by SstFileWriter will have sequence number = 0.
23pub struct SstFileWriter<'a> {
24pub(crate) inner: *mut ffi::rocksdb_sstfilewriter_t,
25// Options are needed to be alive when calling open(),
26 // so let's make sure it doesn't get, dropped for the lifetime of SstFileWriter
27phantom: PhantomData<&'a Options>,
28}
2930unsafe impl<'a> Send for SstFileWriter<'a> {}
31unsafe impl<'a> Sync for SstFileWriter<'a> {}
3233struct EnvOptions {
34 inner: *mut ffi::rocksdb_envoptions_t,
35}
3637impl Drop for EnvOptions {
38fn drop(&mut self) {
39unsafe {
40 ffi::rocksdb_envoptions_destroy(self.inner);
41 }
42 }
43}
4445impl Default for EnvOptions {
46fn default() -> Self {
47let opts = unsafe { ffi::rocksdb_envoptions_create() };
48Self { inner: opts }
49 }
50}
5152impl<'a> SstFileWriter<'a> {
53/// Initializes SstFileWriter with given DB options.
54pub fn create(opts: &'a Options) -> Self {
55let env_options = EnvOptions::default();
5657let writer = Self::create_raw(opts, &env_options);
5859Self {
60 inner: writer,
61 phantom: PhantomData,
62 }
63 }
6465fn create_raw(opts: &Options, env_opts: &EnvOptions) -> *mut ffi::rocksdb_sstfilewriter_t {
66unsafe { ffi::rocksdb_sstfilewriter_create(env_opts.inner, opts.inner) }
67 }
6869/// Prepare SstFileWriter to write into file located at "file_path".
70pub fn open<P: AsRef<Path>>(&'a self, path: P) -> Result<(), Error> {
71let cpath = to_cpath(&path)?;
72self.open_raw(&cpath)
73 }
7475fn open_raw(&'a self, cpath: &CString) -> Result<(), Error> {
76unsafe {
77ffi_try!(ffi::rocksdb_sstfilewriter_open(
78self.inner,
79 cpath.as_ptr() as *const _
80));
8182Ok(())
83 }
84 }
8586/// Finalize writing to sst file and close file.
87pub fn finish(&mut self) -> Result<(), Error> {
88unsafe {
89ffi_try!(ffi::rocksdb_sstfilewriter_finish(self.inner,));
90Ok(())
91 }
92 }
9394/// returns the current file size
95pub fn file_size(&self) -> u64 {
96let mut file_size: u64 = 0;
97unsafe {
98 ffi::rocksdb_sstfilewriter_file_size(self.inner, &mut file_size);
99 }
100 file_size
101 }
102103/// Adds a Put key with value to currently opened file
104 /// REQUIRES: key is after any previously added key according to comparator.
105pub fn put<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
106where
107K: AsRef<[u8]>,
108 V: AsRef<[u8]>,
109 {
110let key = key.as_ref();
111let value = value.as_ref();
112113unsafe {
114ffi_try!(ffi::rocksdb_sstfilewriter_put(
115self.inner,
116 key.as_ptr() as *const c_char,
117 key.len() as size_t,
118 value.as_ptr() as *const c_char,
119 value.len() as size_t,
120 ));
121Ok(())
122 }
123 }
124125/// Adds a Merge key with value to currently opened file
126 /// REQUIRES: key is after any previously added key according to comparator.
127pub fn merge<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
128where
129K: AsRef<[u8]>,
130 V: AsRef<[u8]>,
131 {
132let key = key.as_ref();
133let value = value.as_ref();
134135unsafe {
136ffi_try!(ffi::rocksdb_sstfilewriter_merge(
137self.inner,
138 key.as_ptr() as *const c_char,
139 key.len() as size_t,
140 value.as_ptr() as *const c_char,
141 value.len() as size_t,
142 ));
143Ok(())
144 }
145 }
146147/// Adds a deletion key to currently opened file
148 /// REQUIRES: key is after any previously added key according to comparator.
149pub fn delete<K: AsRef<[u8]>>(&mut self, key: K) -> Result<(), Error> {
150let key = key.as_ref();
151152unsafe {
153ffi_try!(ffi::rocksdb_sstfilewriter_delete(
154self.inner,
155 key.as_ptr() as *const c_char,
156 key.len() as size_t,
157 ));
158Ok(())
159 }
160 }
161}
162163impl<'a> Drop for SstFileWriter<'a> {
164fn drop(&mut self) {
165unsafe {
166 ffi::rocksdb_sstfilewriter_destroy(self.inner);
167 }
168 }
169}