leveldb/database/
batch.rs1use leveldb_sys::*;
2use libc::{c_char, size_t, c_void};
3use std::{slice, ptr};
4use super::options::{WriteOptions, c_writeoptions};
5use super::error::Error;
6use super::db::Database;
7use super::key::IntoLevelDBKey;
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 == ptr::null_mut() {
45 Ok(())
46 } else {
47 Err(Error::new_from_char(error))
48 }
49 }
50 }
51}
52
53impl WriteBatch {
54 pub fn new() -> WriteBatch {
55 let ptr = unsafe { leveldb_writebatch_create() };
56 let raw = RawWriteBatch { ptr };
57
58 WriteBatch {
59 write_batch: raw,
60 }
61 }
62
63 pub fn clear(&self) {
65 unsafe { leveldb_writebatch_clear(self.write_batch.ptr) };
66 }
67
68 pub fn put(&self, key: &dyn IntoLevelDBKey, value: &[u8]) {
70 let _ = key.as_u8_slice_for_write(&|k| {
71 self.put_u8(k, value);
72
73 Ok(())
74 });
75 }
76
77
78 pub fn put_u8(&self, key: &[u8], value: &[u8]) {
79 unsafe {
80 leveldb_writebatch_put(self.write_batch.ptr,
81 key.as_ptr() as *mut c_char,
82 key.len() as size_t,
83 value.as_ptr() as *mut c_char,
84 value.len() as size_t);
85 }
86 }
87
88 pub fn delete(&self, key: &dyn IntoLevelDBKey) {
90 let _ = key.as_u8_slice_for_write(&|k| {
91 self.delete_u8(k);
92
93 Ok(())
94 });
95 }
96
97 pub fn delete_u8(&self, key: &[u8]) {
98 unsafe {
99 leveldb_writebatch_delete(self.write_batch.ptr,
100 key.as_ptr() as *mut c_char,
101 key.len() as size_t);
102 }
103 }
104
105 pub fn iterate<T: WriteBatchIterator>(&mut self, iterator: Box<T>) -> Box<T> {
107 unsafe {
108 let iter = Box::into_raw(iterator);
109 leveldb_writebatch_iterate(self.write_batch.ptr,
110 iter as *mut c_void,
111 put_callback::<T>,
112 deleted_callback::<T>);
113 Box::from_raw(iter)
114 }
115 }
116}
117
118pub trait WriteBatchIterator {
120 fn put_u8(&mut self, key: &[u8], value: &[u8]);
122
123 fn deleted_u8(&mut self, key: &[u8]);
125}
126
127extern "C" fn put_callback<T: WriteBatchIterator>(
128 state: *mut c_void,
129 key: *const c_char,
130 key_len: size_t,
131 val: *const c_char,
132 val_len: size_t) {
133
134 unsafe {
135 let iter: &mut T = &mut *(state as *mut T);
136 let key_slice = slice::from_raw_parts::<u8>(key as *const u8, key_len as usize);
137 let val_slice = slice::from_raw_parts::<u8>(val as *const u8, val_len as usize);
138
139 iter.put_u8(key_slice, val_slice);
140 }
141}
142
143extern "C" fn deleted_callback<T: WriteBatchIterator>(
144 state: *mut c_void,
145 key: *const c_char,
146 key_len: size_t
147) {
148 unsafe {
149 let iter: &mut T = &mut *(state as *mut T);
150 let key_slice = slice::from_raw_parts::<u8>(key as *const u8, key_len as usize);
151
152 iter.deleted_u8(key_slice);
153 }
154}