leveldb/database/
batch.rs1use super::db::Database;
2use super::error::Error;
3use super::key::IntoLevelDBKey;
4use super::options::{c_writeoptions, WriteOptions};
5use cruzbit_leveldb_sys::*;
6use libc::{c_char, c_void, size_t};
7use std::{ptr, slice};
8
9pub(crate) struct RawWriteBatch {
10 pub(crate) ptr: *mut leveldb_writebatch_t,
11}
12
13impl Drop for RawWriteBatch {
14 fn drop(&mut self) {
15 unsafe {
16 leveldb_writebatch_destroy(self.ptr);
17 }
18 }
19}
20
21pub struct WriteBatch {
22 pub(crate) write_batch: RawWriteBatch,
23}
24
25pub trait Batch {
27 fn write(&self, options: &WriteOptions, batch: &WriteBatch) -> Result<(), Error>;
29}
30
31impl Batch for Database {
32 fn write(&self, options: &WriteOptions, batch: &WriteBatch) -> Result<(), Error> {
33 unsafe {
34 let mut error = ptr::null_mut();
35 let c_write_options = c_writeoptions(options);
36
37 leveldb_write(
38 self.database.ptr,
39 c_write_options,
40 batch.write_batch.ptr,
41 &mut error,
42 );
43
44 if error.is_null() {
45 Ok(())
46 } else {
47 Err(Error::new_from_char(error))
48 }
49 }
50 }
51}
52
53impl Default for WriteBatch {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl WriteBatch {
60 pub fn new() -> WriteBatch {
61 let ptr = unsafe { leveldb_writebatch_create() };
62 let raw = RawWriteBatch { ptr };
63
64 WriteBatch { write_batch: raw }
65 }
66
67 pub fn clear(&self) {
69 unsafe { leveldb_writebatch_clear(self.write_batch.ptr) };
70 }
71
72 pub fn put(&self, key: &dyn IntoLevelDBKey, value: &[u8]) {
74 let _ = key.as_u8_slice_for_write(&|k| {
75 self.put_u8(k, value);
76
77 Ok(())
78 });
79 }
80
81 pub fn put_u8(&self, key: &[u8], value: &[u8]) {
82 unsafe {
83 leveldb_writebatch_put(
84 self.write_batch.ptr,
85 key.as_ptr() as *mut c_char,
86 key.len() as size_t,
87 value.as_ptr() as *mut c_char,
88 value.len() as size_t,
89 );
90 }
91 }
92
93 pub fn delete(&self, key: &dyn IntoLevelDBKey) {
95 let _ = key.as_u8_slice_for_write(&|k| {
96 self.delete_u8(k);
97
98 Ok(())
99 });
100 }
101
102 pub fn delete_u8(&self, key: &[u8]) {
103 unsafe {
104 leveldb_writebatch_delete(
105 self.write_batch.ptr,
106 key.as_ptr() as *mut c_char,
107 key.len() as size_t,
108 );
109 }
110 }
111
112 pub fn iterate<T: WriteBatchIterator>(&mut self, iterator: Box<T>) -> Box<T> {
114 unsafe {
115 let iter = Box::into_raw(iterator);
116 leveldb_writebatch_iterate(
117 self.write_batch.ptr,
118 iter as *mut c_void,
119 put_callback::<T>,
120 deleted_callback::<T>,
121 );
122 Box::from_raw(iter)
123 }
124 }
125}
126
127pub trait WriteBatchIterator {
129 fn put_u8(&mut self, key: &[u8], value: &[u8]);
131
132 fn deleted_u8(&mut self, key: &[u8]);
134}
135
136extern "C" fn put_callback<T: WriteBatchIterator>(
137 state: *mut c_void,
138 key: *const c_char,
139 key_len: size_t,
140 val: *const c_char,
141 val_len: size_t,
142) {
143 unsafe {
144 let iter: &mut T = &mut *(state as *mut T);
145 let key_slice = slice::from_raw_parts::<u8>(key as *const u8, key_len);
146 let val_slice = slice::from_raw_parts::<u8>(val as *const u8, val_len);
147
148 iter.put_u8(key_slice, val_slice);
149 }
150}
151
152extern "C" fn deleted_callback<T: WriteBatchIterator>(
153 state: *mut c_void,
154 key: *const c_char,
155 key_len: size_t,
156) {
157 unsafe {
158 let iter: &mut T = &mut *(state as *mut T);
159 let key_slice = slice::from_raw_parts::<u8>(key as *const u8, key_len);
160
161 iter.deleted_u8(key_slice);
162 }
163}