Unverified Commit fe19e2b5 authored by Qi Yu's avatar Qi Yu Committed by GitHub

Reduce boxing in callback structs (#663)

Close #513.
Signed-off-by: 's avataryuqi1129 <yuqi4733@gmail.com>
parent 0d2028ff
......@@ -2733,7 +2733,7 @@ mod test {
use std::{fs, ptr, slice};
fn tempdir_with_prefix(prefix: &str) -> tempfile::TempDir {
tempfile::Builder::new().prefix(prefix).tempdir().expect()
tempfile::Builder::new().prefix(prefix).tempdir().expect("")
}
#[test]
......
......@@ -229,108 +229,83 @@ pub trait EventListener: Send + Sync {
fn on_stall_conditions_changed(&self, _: &WriteStallInfo) {}
}
extern "C" fn destructor(ctx: *mut c_void) {
extern "C" fn destructor<E: EventListener>(ctx: *mut c_void) {
unsafe {
Box::from_raw(ctx as *mut Box<dyn EventListener>);
Box::from_raw(ctx as *mut E);
}
}
// Maybe we should reuse db instance?
// TODO: refactor DB implement so that we can convert DBInstance to DB.
extern "C" fn on_flush_begin(ctx: *mut c_void, _: *mut DBInstance, info: *const DBFlushJobInfo) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const FlushJobInfo),
)
};
extern "C" fn on_flush_begin<E: EventListener>(
ctx: *mut c_void,
_: *mut DBInstance,
info: *const DBFlushJobInfo,
) {
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const FlushJobInfo)) };
ctx.on_flush_begin(info);
}
extern "C" fn on_flush_completed(
extern "C" fn on_flush_completed<E: EventListener>(
ctx: *mut c_void,
_: *mut DBInstance,
info: *const DBFlushJobInfo,
) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const FlushJobInfo),
)
};
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const FlushJobInfo)) };
ctx.on_flush_completed(info);
}
extern "C" fn on_compaction_begin(
extern "C" fn on_compaction_begin<E: EventListener>(
ctx: *mut c_void,
_: *mut DBInstance,
info: *const DBCompactionJobInfo,
) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const CompactionJobInfo),
)
};
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const CompactionJobInfo)) };
ctx.on_compaction_begin(info);
}
extern "C" fn on_compaction_completed(
extern "C" fn on_compaction_completed<E: EventListener>(
ctx: *mut c_void,
_: *mut DBInstance,
info: *const DBCompactionJobInfo,
) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const CompactionJobInfo),
)
};
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const CompactionJobInfo)) };
ctx.on_compaction_completed(info);
}
extern "C" fn on_subcompaction_begin(ctx: *mut c_void, info: *const DBSubcompactionJobInfo) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const SubcompactionJobInfo),
)
};
extern "C" fn on_subcompaction_begin<E: EventListener>(
ctx: *mut c_void,
info: *const DBSubcompactionJobInfo,
) {
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const SubcompactionJobInfo)) };
ctx.on_subcompaction_begin(info);
}
extern "C" fn on_subcompaction_completed(ctx: *mut c_void, info: *const DBSubcompactionJobInfo) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const SubcompactionJobInfo),
)
};
extern "C" fn on_subcompaction_completed<E: EventListener>(
ctx: *mut c_void,
info: *const DBSubcompactionJobInfo,
) {
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const SubcompactionJobInfo)) };
ctx.on_subcompaction_completed(info);
}
extern "C" fn on_external_file_ingested(
extern "C" fn on_external_file_ingested<E: EventListener>(
ctx: *mut c_void,
_: *mut DBInstance,
info: *const DBIngestionInfo,
) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const IngestionInfo),
)
};
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const IngestionInfo)) };
ctx.on_external_file_ingested(info);
}
extern "C" fn on_background_error(
extern "C" fn on_background_error<E: EventListener>(
ctx: *mut c_void,
reason: DBBackgroundErrorReason,
status: *mut DBStatusPtr,
) {
let (ctx, result) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(ctx as *mut E),
|| -> Result<(), String> {
ffi_try!(crocksdb_status_ptr_get_error(status));
Ok(())
......@@ -340,31 +315,29 @@ extern "C" fn on_background_error(
ctx.on_background_error(reason, result);
}
extern "C" fn on_stall_conditions_changed(ctx: *mut c_void, info: *const DBWriteStallInfo) {
let (ctx, info) = unsafe {
(
&*(ctx as *mut Box<dyn EventListener>),
&*(info as *const WriteStallInfo),
)
};
extern "C" fn on_stall_conditions_changed<E: EventListener>(
ctx: *mut c_void,
info: *const DBWriteStallInfo,
) {
let (ctx, info) = unsafe { (&*(ctx as *mut E), &*(info as *const WriteStallInfo)) };
ctx.on_stall_conditions_changed(info);
}
pub fn new_event_listener<L: EventListener>(l: L) -> *mut DBEventListener {
let p: Box<dyn EventListener> = Box::new(l);
pub fn new_event_listener<E: EventListener>(e: E) -> *mut DBEventListener {
let p: Box<dyn EventListener> = Box::new(e);
unsafe {
crocksdb_ffi::crocksdb_eventlistener_create(
Box::into_raw(Box::new(p)) as *mut c_void,
destructor,
on_flush_begin,
on_flush_completed,
on_compaction_begin,
on_compaction_completed,
on_subcompaction_begin,
on_subcompaction_completed,
on_external_file_ingested,
on_background_error,
on_stall_conditions_changed,
Box::into_raw(p) as *mut c_void,
destructor::<E>,
on_flush_begin::<E>,
on_flush_completed::<E>,
on_compaction_begin::<E>,
on_compaction_completed::<E>,
on_subcompaction_begin::<E>,
on_subcompaction_completed::<E>,
on_external_file_ingested::<E>,
on_background_error::<E>,
on_stall_conditions_changed::<E>,
)
}
}
......@@ -10,15 +10,15 @@ pub trait Logger: Send + Sync {
fn logv(&self, log_level: InfoLogLevel, log: &str);
}
extern "C" fn destructor(ctx: *mut c_void) {
extern "C" fn destructor<L: Logger>(ctx: *mut c_void) {
unsafe {
Box::from_raw(ctx as *mut Box<dyn Logger>);
Box::from_raw(ctx as *mut L);
}
}
extern "C" fn logv(ctx: *mut c_void, log_level: InfoLogLevel, log: *const c_char) {
extern "C" fn logv<L: Logger>(ctx: *mut c_void, log_level: InfoLogLevel, log: *const c_char) {
unsafe {
let logger = &*(ctx as *mut Box<dyn Logger>);
let logger = &*(ctx as *mut L);
let log = CStr::from_ptr(log);
logger.logv(log_level, &log.to_string_lossy());
}
......@@ -28,9 +28,9 @@ pub fn new_logger<L: Logger>(l: L) -> *mut DBLogger {
unsafe {
let p: Box<dyn Logger> = Box::new(l);
crocksdb_ffi::crocksdb_logger_create(
Box::into_raw(Box::new(p)) as *mut c_void,
destructor,
logv,
Box::into_raw(p) as *mut c_void,
destructor::<L>,
logv::<L>,
)
}
}
......
......@@ -44,6 +44,7 @@ use table_properties_collector_factory::{
new_table_properties_collector_factory, TablePropertiesCollectorFactory,
};
use titan::TitanDBOptions;
use TablePropertiesCollector;
#[derive(Default, Debug)]
pub struct HistogramData {
......@@ -474,15 +475,15 @@ impl ReadOptions {
}
}
pub fn set_table_filter(&mut self, filter: Box<dyn TableFilter>) {
pub fn set_table_filter<T: TableFilter>(&mut self, filter: T) {
unsafe {
let f = Box::into_raw(Box::new(filter));
let f = f as *mut c_void;
crocksdb_ffi::crocksdb_readoptions_set_table_filter(
self.inner,
f,
table_filter,
destroy_table_filter,
table_filter::<T>,
destroy_table_filter::<T>,
);
}
}
......@@ -1429,10 +1430,13 @@ impl ColumnFamilyOptions {
}
}
pub fn add_table_properties_collector_factory(
pub fn add_table_properties_collector_factory<
C: TablePropertiesCollector,
T: TablePropertiesCollectorFactory<C>,
>(
&mut self,
fname: &str,
factory: Box<dyn TablePropertiesCollectorFactory>,
factory: T,
) {
unsafe {
let f = new_table_properties_collector_factory(fname, factory);
......
......@@ -24,16 +24,19 @@ pub trait TableFilter {
fn table_filter(&self, props: &TableProperties) -> bool;
}
pub extern "C" fn table_filter(ctx: *mut c_void, props: *const DBTableProperties) -> c_uchar {
pub extern "C" fn table_filter<T: TableFilter>(
ctx: *mut c_void,
props: *const DBTableProperties,
) -> c_uchar {
unsafe {
let filter = &*(ctx as *mut Box<dyn TableFilter>);
let filter = &*(ctx as *mut T);
let props = &*(props as *const TableProperties);
filter.table_filter(props) as c_uchar
}
}
pub extern "C" fn destroy_table_filter(filter: *mut c_void) {
pub extern "C" fn destroy_table_filter<T: TableFilter>(filter: *mut c_void) {
unsafe {
Box::from_raw(filter as *mut Box<dyn TableFilter>);
Box::from_raw(filter as *mut T);
}
}
......@@ -33,13 +33,13 @@ pub trait TablePropertiesCollector {
fn finish(&mut self) -> HashMap<Vec<u8>, Vec<u8>>;
}
struct TablePropertiesCollectorHandle {
struct TablePropertiesCollectorHandle<T: TablePropertiesCollector> {
name: CString,
rep: Box<dyn TablePropertiesCollector>,
rep: T,
}
impl TablePropertiesCollectorHandle {
fn new(name: &str, rep: Box<dyn TablePropertiesCollector>) -> TablePropertiesCollectorHandle {
impl<T: TablePropertiesCollector> TablePropertiesCollectorHandle<T> {
fn new(name: &str, rep: T) -> TablePropertiesCollectorHandle<T> {
TablePropertiesCollectorHandle {
name: CString::new(name).unwrap(),
rep: rep,
......@@ -47,20 +47,20 @@ impl TablePropertiesCollectorHandle {
}
}
extern "C" fn name(handle: *mut c_void) -> *const c_char {
extern "C" fn name<T: TablePropertiesCollector>(handle: *mut c_void) -> *const c_char {
unsafe {
let handle = &mut *(handle as *mut TablePropertiesCollectorHandle);
let handle = &mut *(handle as *mut TablePropertiesCollectorHandle<T>);
handle.name.as_ptr()
}
}
extern "C" fn destruct(handle: *mut c_void) {
extern "C" fn destruct<T: TablePropertiesCollector>(handle: *mut c_void) {
unsafe {
Box::from_raw(handle as *mut TablePropertiesCollectorHandle);
Box::from_raw(handle as *mut TablePropertiesCollectorHandle<T>);
}
}
pub extern "C" fn add(
pub extern "C" fn add<T: TablePropertiesCollector>(
handle: *mut c_void,
key: *const u8,
key_len: size_t,
......@@ -71,7 +71,7 @@ pub extern "C" fn add(
file_size: u64,
) {
unsafe {
let handle = &mut *(handle as *mut TablePropertiesCollectorHandle);
let handle = &mut *(handle as *mut TablePropertiesCollectorHandle<T>);
let key = slice::from_raw_parts(key, key_len);
let value = slice::from_raw_parts(value, value_len);
handle
......@@ -80,9 +80,12 @@ pub extern "C" fn add(
}
}
pub extern "C" fn finish(handle: *mut c_void, props: *mut DBUserCollectedProperties) {
pub extern "C" fn finish<T: TablePropertiesCollector>(
handle: *mut c_void,
props: *mut DBUserCollectedProperties,
) {
unsafe {
let handle = &mut *(handle as *mut TablePropertiesCollectorHandle);
let handle = &mut *(handle as *mut TablePropertiesCollectorHandle<T>);
for (key, value) in handle.rep.finish() {
crocksdb_ffi::crocksdb_user_collected_properties_add(
props,
......@@ -95,16 +98,16 @@ pub extern "C" fn finish(handle: *mut c_void, props: *mut DBUserCollectedPropert
}
}
pub unsafe fn new_table_properties_collector(
pub unsafe fn new_table_properties_collector<T: TablePropertiesCollector>(
cname: &str,
collector: Box<dyn TablePropertiesCollector>,
collector: T,
) -> *mut DBTablePropertiesCollector {
let handle = TablePropertiesCollectorHandle::new(cname, collector);
crocksdb_ffi::crocksdb_table_properties_collector_create(
Box::into_raw(Box::new(handle)) as *mut c_void,
name,
destruct,
add,
finish,
name::<T>,
destruct::<T>,
add::<T>,
finish::<T>,
)
}
......@@ -14,65 +14,81 @@
use crocksdb_ffi::{self, DBTablePropertiesCollector, DBTablePropertiesCollectorFactory};
use libc::{c_char, c_void};
use std::ffi::CString;
use std::marker::PhantomData;
use table_properties_collector::{new_table_properties_collector, TablePropertiesCollector};
/// Constructs `TablePropertiesCollector`.
/// Internals create a new `TablePropertiesCollector` for each new table.
pub trait TablePropertiesCollectorFactory {
pub trait TablePropertiesCollectorFactory<T: TablePropertiesCollector> {
/// Has to be thread-safe.
fn create_table_properties_collector(&mut self, cf: u32) -> Box<dyn TablePropertiesCollector>;
fn create_table_properties_collector(&mut self, cf: u32) -> T;
}
struct TablePropertiesCollectorFactoryHandle {
struct TablePropertiesCollectorFactoryHandle<C, T>
where
C: TablePropertiesCollector,
T: TablePropertiesCollectorFactory<C>,
{
name: CString,
rep: Box<dyn TablePropertiesCollectorFactory>,
rep: T,
_phantom: PhantomData<C>,
}
impl TablePropertiesCollectorFactoryHandle {
fn new(
name: &str,
rep: Box<dyn TablePropertiesCollectorFactory>,
) -> TablePropertiesCollectorFactoryHandle {
TablePropertiesCollectorFactoryHandle {
impl<C: TablePropertiesCollector, T: TablePropertiesCollectorFactory<C>>
TablePropertiesCollectorFactoryHandle<C, T>
{
fn new(name: &str, rep: T) -> TablePropertiesCollectorFactoryHandle<C, T> {
TablePropertiesCollectorFactoryHandle::<C, T> {
name: CString::new(name).unwrap(),
rep: rep,
_phantom: PhantomData,
}
}
}
extern "C" fn name(handle: *mut c_void) -> *const c_char {
extern "C" fn name<C: TablePropertiesCollector, T: TablePropertiesCollectorFactory<C>>(
handle: *mut c_void,
) -> *const c_char {
unsafe {
let handle = &mut *(handle as *mut TablePropertiesCollectorFactoryHandle);
let handle = &mut *(handle as *mut TablePropertiesCollectorFactoryHandle<C, T>);
handle.name.as_ptr()
}
}
extern "C" fn destruct(handle: *mut c_void) {
extern "C" fn destruct<C: TablePropertiesCollector, T: TablePropertiesCollectorFactory<C>>(
handle: *mut c_void,
) {
unsafe {
Box::from_raw(handle as *mut TablePropertiesCollectorFactoryHandle);
Box::from_raw(handle as *mut TablePropertiesCollectorFactoryHandle<C, T>);
}
}
extern "C" fn create_table_properties_collector(
extern "C" fn create_table_properties_collector<
C: TablePropertiesCollector,
T: TablePropertiesCollectorFactory<C>,
>(
handle: *mut c_void,
cf: u32,
) -> *mut DBTablePropertiesCollector {
unsafe {
let handle = &mut *(handle as *mut TablePropertiesCollectorFactoryHandle);
let handle = &mut *(handle as *mut TablePropertiesCollectorFactoryHandle<C, T>);
let collector = handle.rep.create_table_properties_collector(cf);
new_table_properties_collector(handle.name.to_str().unwrap(), collector)
}
}
pub unsafe fn new_table_properties_collector_factory(
pub unsafe fn new_table_properties_collector_factory<
C: TablePropertiesCollector,
T: TablePropertiesCollectorFactory<C>,
>(
fname: &str,
factory: Box<dyn TablePropertiesCollectorFactory>,
factory: T,
) -> *mut DBTablePropertiesCollectorFactory {
let handle = TablePropertiesCollectorFactoryHandle::new(fname, factory);
crocksdb_ffi::crocksdb_table_properties_collector_factory_create(
Box::into_raw(Box::new(handle)) as *mut c_void,
name,
destruct,
create_table_properties_collector,
name::<C, T>,
destruct::<C, T>,
create_table_properties_collector::<C, T>,
)
}
......@@ -132,9 +132,9 @@ impl ExampleFactory {
}
}
impl TablePropertiesCollectorFactory for ExampleFactory {
fn create_table_properties_collector(&mut self, _: u32) -> Box<dyn TablePropertiesCollector> {
Box::new(ExampleCollector::new())
impl TablePropertiesCollectorFactory<ExampleCollector> for ExampleFactory {
fn create_table_properties_collector(&mut self, _: u32) -> ExampleCollector {
ExampleCollector::new()
}
}
......@@ -168,7 +168,10 @@ fn test_table_properties_collector_factory() {
let mut opts = DBOptions::new();
let mut cf_opts = ColumnFamilyOptions::new();
opts.create_if_missing(true);
cf_opts.add_table_properties_collector_factory("example-collector", Box::new(f));
cf_opts.add_table_properties_collector_factory::<ExampleCollector, ExampleFactory>(
"example-collector",
f,
);
let path = tempdir_with_prefix("_rust_rocksdb_collectortest");
let db = DB::open_cf(
......@@ -242,8 +245,10 @@ fn test_table_properties_with_table_filter() {
let mut opts = DBOptions::new();
let mut cf_opts = ColumnFamilyOptions::new();
opts.create_if_missing(true);
cf_opts.add_table_properties_collector_factory("example-collector", Box::new(f));
cf_opts.add_table_properties_collector_factory::<ExampleCollector, ExampleFactory>(
"example-collector",
f,
);
let path = tempdir_with_prefix("_rust_rocksdb_collector_with_table_filter");
let db = DB::open_cf(
opts,
......@@ -279,7 +284,7 @@ fn test_table_properties_with_table_filter() {
// Scan with table filter
let f = BigTableFilter::new(2);
let mut ropts = ReadOptions::new();
ropts.set_table_filter(Box::new(f));
ropts.set_table_filter::<BigTableFilter>(f);
let mut iter = db.iter_opt(ropts);
let key = b"key";
let key5 = b"key5";
......
......@@ -81,9 +81,9 @@ impl TablePropertiesCollector for TitanCollector {
#[derive(Default)]
struct TitanCollectorFactory {}
impl TablePropertiesCollectorFactory for TitanCollectorFactory {
fn create_table_properties_collector(&mut self, _: u32) -> Box<dyn TablePropertiesCollector> {
Box::new(TitanCollector::default())
impl TablePropertiesCollectorFactory<TitanCollector> for TitanCollectorFactory {
fn create_table_properties_collector(&mut self, _: u32) -> TitanCollector {
TitanCollector::default()
}
}
......@@ -122,8 +122,10 @@ fn test_titandb() {
let mut cf_opts = ColumnFamilyOptions::new();
let f = TitanCollectorFactory::default();
cf_opts.set_titandb_options(&tdb_opts);
cf_opts.add_table_properties_collector_factory("titan-collector", Box::new(f));
cf_opts.add_table_properties_collector_factory::<TitanCollector, TitanCollectorFactory>(
"titan-collector",
f,
);
let mut db = DB::open_cf(
opts,
path.path().to_str().unwrap(),
......@@ -263,7 +265,10 @@ fn test_titan_delete_files_in_ranges() {
opts.set_titandb_options(&tdb_opts);
let mut cf_opts = ColumnFamilyOptions::new();
let f = TitanCollectorFactory::default();
cf_opts.add_table_properties_collector_factory("titan-collector", Box::new(f));
cf_opts.add_table_properties_collector_factory::<TitanCollector, TitanCollectorFactory>(
"titan-collector",
f,
);
cf_opts.set_titandb_options(&tdb_opts);
let db = DB::open_cf(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment