#![allow(unsafe_code)]
use crate::hton::{TablespaceType, TsCommandType};
use crate::panic_guard::FfiBoundary;
use crate::runtime;
use crate::runtime::FfiPtr;
use crate::sys;
fn report_tablespace_type(value: Option<TablespaceType>, out: *mut u32) -> bool {
match value {
Some(t) => {
if !out.is_null() {
unsafe { out.write(t.to_raw()) };
}
false
}
None => true,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__is_valid_tablespace_name(
cmd: i32,
name: *const u8,
name_len: usize,
) -> bool {
FfiBoundary::run_default(false, || {
let decoded = unsafe { FfiPtr::bytes_to_str(name, name_len) };
match (decoded, runtime::handlerton()) {
(Ok(s), Some(h)) => h.is_valid_tablespace_name(TsCommandType::from_raw(cmd), s),
_ => true,
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__get_tablespace(
thd: *const sys::THD,
db: *const u8,
db_len: usize,
table: *const u8,
table_len: usize,
) -> i32 {
FfiBoundary::run(|| {
let (db_str, table_str) = unsafe {
match (
FfiPtr::bytes_to_str(db, db_len),
FfiPtr::bytes_to_str(table, table_len),
) {
(Ok(a), Ok(b)) => (a, b),
(Err(e), _) | (_, Err(e)) => return Err(e),
}
};
let thd_ref = unsafe { thd.as_ref() };
match runtime::handlerton() {
Some(h) => h.get_tablespace(thd_ref, db_str, table_str),
None => Ok(()),
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__alter_tablespace(
thd: *const sys::THD,
ts_info: *const sys::StAlterTablespace,
) -> i32 {
FfiBoundary::run(|| {
let thd_ref = unsafe { thd.as_ref() };
let ts_ref = unsafe { ts_info.as_ref() };
match runtime::handlerton() {
Some(h) => h.alter_tablespace(thd_ref, ts_ref),
None => Ok(()),
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__tablespace_filename_ext() -> *const core::ffi::c_char {
FfiBoundary::run_default(core::ptr::null(), || match runtime::handlerton() {
Some(h) => match h.tablespace_filename_ext() {
Some(ext) => ext.as_ptr(),
None => core::ptr::null(),
},
None => core::ptr::null(),
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__upgrade_tablespace(thd: *const sys::THD) -> i32 {
FfiBoundary::run(|| {
let thd_ref = unsafe { thd.as_ref() };
match runtime::handlerton() {
Some(h) => h.upgrade_tablespace(thd_ref),
None => Ok(()),
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__upgrade_space_version(
tablespace: *const sys::DdTablespace,
) -> bool {
FfiBoundary::run_default(true, || {
let ts_ref = unsafe { tablespace.as_ref() };
match runtime::handlerton() {
Some(h) => match h.upgrade_space_version(ts_ref) {
Ok(()) => false,
Err(_) => true,
},
None => false,
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__get_tablespace_type(
tablespace: *const sys::DdTablespace,
out: *mut u32,
) -> bool {
FfiBoundary::run_default(true, || {
let ts_ref = unsafe { tablespace.as_ref() };
let value = match runtime::handlerton() {
Some(h) => h.get_tablespace_type(ts_ref),
None => None,
};
report_tablespace_type(value, out)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__get_tablespace_type_by_name(
name: *const u8,
name_len: usize,
out: *mut u32,
) -> bool {
FfiBoundary::run_default(true, || {
let decoded = unsafe { FfiPtr::bytes_to_str(name, name_len) };
let value = match (decoded, runtime::handlerton()) {
(Ok(s), Some(h)) => h.get_tablespace_type_by_name(s),
_ => None,
};
report_tablespace_type(value, out)
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn report_tablespace_type_writes_on_some_and_returns_false() {
let mut out: u32 = 0xAAAA_AAAA;
let res = report_tablespace_type(Some(TablespaceType::Undo), &raw mut out);
assert!(!res);
assert_eq!(out, TablespaceType::Undo.to_raw());
}
#[test]
fn report_tablespace_type_none_leaves_buffer_and_returns_true() {
let mut out: u32 = 7;
let res = report_tablespace_type(None, &raw mut out);
assert!(res);
assert_eq!(out, 7);
}
#[test]
fn report_tablespace_type_tolerates_null_out() {
assert!(!report_tablespace_type(
Some(TablespaceType::System),
core::ptr::null_mut()
));
assert!(report_tablespace_type(None, core::ptr::null_mut()));
}
}