Skip to content

Commit 959f29e

Browse files
authored
Avoid copy for merge operator result using delete_callback (rust-rocksdb#457)
1 parent 10a059a commit 959f29e

2 files changed

Lines changed: 22 additions & 19 deletions

File tree

src/db_options.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ impl Options {
947947
Some(merge_operator::destructor_callback),
948948
Some(full_merge_callback),
949949
Some(partial_merge_callback),
950-
None,
950+
Some(merge_operator::delete_callback),
951951
Some(merge_operator::name_callback),
952952
);
953953
ffi::rocksdb_options_set_merge_operator(self.inner, mo);

src/merge_operator.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ pub unsafe extern "C" fn destructor_callback(raw_cb: *mut c_void) {
7373
let _: Box<MergeOperatorCallback> = mem::transmute(raw_cb);
7474
}
7575

76+
pub unsafe extern "C" fn delete_callback(
77+
_raw_cb: *mut c_void,
78+
value: *const c_char,
79+
value_length: size_t,
80+
) {
81+
if !value.is_null() {
82+
let _ = Box::from_raw(slice::from_raw_parts_mut(
83+
value as *mut u8,
84+
value_length as usize,
85+
));
86+
}
87+
}
88+
7689
pub unsafe extern "C" fn name_callback(raw_cb: *mut c_void) -> *const c_char {
7790
let cb = &mut *(raw_cb as *mut MergeOperatorCallback);
7891
cb.name.as_ptr()
@@ -101,18 +114,13 @@ pub unsafe extern "C" fn full_merge_callback(
101114
existing_value_len as usize,
102115
))
103116
};
104-
if let Some(mut result) = (cb.full_merge_fn)(key, oldval, operands) {
105-
result.shrink_to_fit();
106-
// TODO(tan) investigate zero-copy techniques to improve performance
107-
let buf = libc::malloc(result.len() as size_t);
108-
assert!(!buf.is_null());
117+
if let Some(result) = (cb.full_merge_fn)(key, oldval, operands) {
109118
*new_value_length = result.len() as size_t;
110-
*success = 1 as u8;
111-
ptr::copy(result.as_ptr() as *mut c_void, &mut *buf, result.len());
112-
buf as *mut c_char
119+
*success = 1_u8;
120+
Box::into_raw(result.into_boxed_slice()) as *mut c_char
113121
} else {
114122
*new_value_length = 0;
115-
*success = 0 as u8;
123+
*success = 0_u8;
116124
ptr::null_mut() as *mut c_char
117125
}
118126
}
@@ -130,18 +138,13 @@ pub unsafe extern "C" fn partial_merge_callback(
130138
let cb = &mut *(raw_cb as *mut MergeOperatorCallback);
131139
let operands = &mut MergeOperands::new(operands_list, operands_list_len, num_operands);
132140
let key = slice::from_raw_parts(raw_key as *const u8, key_len as usize);
133-
if let Some(mut result) = (cb.partial_merge_fn)(key, None, operands) {
134-
result.shrink_to_fit();
135-
// TODO(tan) investigate zero-copy techniques to improve performance
136-
let buf = libc::malloc(result.len() as size_t);
137-
assert!(!buf.is_null());
141+
if let Some(result) = (cb.partial_merge_fn)(key, None, operands) {
138142
*new_value_length = result.len() as size_t;
139-
*success = 1 as u8;
140-
ptr::copy(result.as_ptr() as *mut c_void, &mut *buf, result.len());
141-
buf as *mut c_char
143+
*success = 1_u8;
144+
Box::into_raw(result.into_boxed_slice()) as *mut c_char
142145
} else {
143146
*new_value_length = 0;
144-
*success = 0 as u8;
147+
*success = 0_u8;
145148
ptr::null_mut::<c_char>()
146149
}
147150
}

0 commit comments

Comments
 (0)