#![allow(unsafe_code)]
use crate::engine::EngineError;
use crate::panic_guard::FfiBoundary;
use crate::runtime;
use crate::runtime::FfiPtr;
fn write_u64(out: *mut u64, value: u64) {
if !out.is_null() {
unsafe { out.write(value) };
}
}
fn report_u64(value: Result<u64, EngineError>, out: *mut u64) -> i32 {
match value {
Ok(v) => {
if out.is_null() {
return EngineError::Internal.to_mysql_errno();
}
write_u64(out, v);
0
}
Err(e) => e.to_mysql_errno(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__page_track_start(start_id: *mut u64) -> i32 {
FfiBoundary::run_default(EngineError::Internal.to_mysql_errno(), || {
let result = match runtime::handlerton() {
Some(h) => h.page_track_start(),
None => Err(EngineError::Unsupported),
};
report_u64(result, start_id)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__page_track_stop(stop_id: *mut u64) -> i32 {
FfiBoundary::run_default(EngineError::Internal.to_mysql_errno(), || {
let result = match runtime::handlerton() {
Some(h) => h.page_track_stop(),
None => Err(EngineError::Unsupported),
};
report_u64(result, stop_id)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__page_track_purge(purge_id: *mut u64) -> i32 {
FfiBoundary::run_default(EngineError::Internal.to_mysql_errno(), || {
let requested = if purge_id.is_null() {
0
} else {
unsafe { purge_id.read() }
};
let result = match runtime::handlerton() {
Some(h) => h.page_track_purge(requested),
None => Err(EngineError::Unsupported),
};
report_u64(result, purge_id)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__page_track_get_page_ids(
start_id: *mut u64,
stop_id: *mut u64,
buffer: *mut u8,
buffer_len: usize,
) -> i32 {
FfiBoundary::run_default(EngineError::Internal.to_mysql_errno(), || {
let range_start = if start_id.is_null() {
return EngineError::Internal.to_mysql_errno();
} else {
unsafe { start_id.read() }
};
let range_stop = if stop_id.is_null() {
return EngineError::Internal.to_mysql_errno();
} else {
unsafe { stop_id.read() }
};
let buf: &mut [u8] = if buffer.is_null() {
&mut []
} else {
unsafe { FfiPtr::slice_mut(buffer, buffer_len) }
};
let result = match runtime::handlerton() {
Some(h) => h.page_track_get_page_ids(range_start, range_stop, buf),
None => Err(EngineError::Unsupported),
};
match result {
Ok(()) => 0,
Err(e) => e.to_mysql_errno(),
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__page_track_get_num_page_ids(
start_id: *mut u64,
stop_id: *mut u64,
num_pages: *mut u64,
) -> i32 {
FfiBoundary::run_default(EngineError::Internal.to_mysql_errno(), || {
let range_start = if start_id.is_null() {
return EngineError::Internal.to_mysql_errno();
} else {
unsafe { start_id.read() }
};
let range_stop = if stop_id.is_null() {
return EngineError::Internal.to_mysql_errno();
} else {
unsafe { stop_id.read() }
};
let result = match runtime::handlerton() {
Some(h) => h.page_track_get_num_page_ids(range_start, range_stop),
None => Err(EngineError::Unsupported),
};
report_u64(result, num_pages)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust__hton__page_track_get_status() {
FfiBoundary::run_void(|| {
if let Some(h) = runtime::handlerton() {
h.page_track_get_status();
}
});
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn report_u64_some_writes_and_returns_zero() {
let mut out: u64 = 0;
assert_eq!(report_u64(Ok(42), &raw mut out), 0);
assert_eq!(out, 42);
}
#[test]
fn report_u64_null_out_reports_internal_error() {
assert_eq!(
report_u64(Ok(7), core::ptr::null_mut()),
EngineError::Internal.to_mysql_errno()
);
}
#[test]
fn report_u64_err_propagates_errno() {
let mut out: u64 = 9;
assert_eq!(
report_u64(Err(EngineError::Unsupported), &raw mut out),
EngineError::Unsupported.to_mysql_errno()
);
assert_eq!(out, 9);
}
}