1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
use super::Handler;
use crate::thd::ThdKillLevel;
use crate::{bindings, MemRoot, TableShare, Thd};
pub enum Error {}
pub type Result<T = (), E = Error> = std::result::Result<T, E>;
pub struct HandlertonCtx<'a> {
hton: &'a mut bindings::handlerton,
thd: &'a mut bindings::THD,
}
impl<'a> HandlertonCtx<'a> {
unsafe fn new(hton: *mut bindings::handlerton, thd: *mut bindings::THD) -> Self {
debug_assert!(!hton.is_null());
debug_assert!(!thd.is_null());
Self {
hton: unsafe { &mut *hton },
thd: unsafe { &mut *thd },
}
}
}
pub struct HandlertonThd<'a> {
thd: &'a mut Thd<'a>,
slot: usize,
}
impl<'a> HandlertonThd<'a> {
unsafe fn new(hton: *mut bindings::handlerton, thd: *mut bindings::THD) -> Self {
debug_assert!(!hton.is_null());
debug_assert!(!thd.is_null());
Self {
thd: unsafe { Thd::new_mut(thd) },
slot: unsafe { (*hton).slot }.try_into().unwrap(),
}
}
fn data(&self) {
todo!()
// let x = self.thd.0.ha_data[self.slot];
}
}
// TODO: do we really have a `self`? I.e., can a `handlerton` contain arbitrary data?
/// A "handlerton" ("handler singleton") is the entrypoint for a storage engine handler.
///
/// This defines registration and creation information.
pub trait Handlerton {
type Handler: Handler;
/// A type of data that is stored during a savepoint.
type SavePoint;
const FLAGS: u32 = 0;
/// Extensions of files created for a single table in the database directory
/// (`datadir/db_name/`).
const TABLEFILE_EXTENSIONS: &'static [&'static str] = &[];
// fn close_connection(thd: &HandlertonThd) -> Result;
// fn kill_query(thd: &HandlertonThd, level: ThdKillLevel);
// TODO: should Savepoint be its own trait?
// /// Create a new savepoint
// fn savepoint_set(thd: &HandlertonThd) -> Result<Self::SavePoint>;
// /// Restore to a previous savepoint
// fn savepoint_rollback(thd: &HandlertonThd, sv: &mut Self::SavePoint) -> Result;
// fn savepoint_rollback_can_release_mdl(thd: &HandlertonThd) -> bool {
// false
// }
// fn savepoint_release(thd: &HandlertonThd, sv: &mut Self::SavePoint) -> Result;
// /// Perform the commit.
// ///
// /// If `is_true_commit` is false, we are in an end of statement within a transaction
// fn commit(thd: &HandlertonThd, is_true_commit: bool) -> Result;
// fn commit_ordered(thd: &HandlertonThd, is_true_commit: bool) -> Result;
// fn rollback(thd: &HandlertonThd, is_true_commit: bool) -> Result;
// fn prepare(thd: &HandlertonThd, is_true_commit: bool) -> Result;
// fn prepare_ordered(thd: &HandlertonThd, is_true_commit: bool) -> Result;
//... more to do
}
// TODO: also take table_options, field_options, and index_options. Maybe we can put these
// into traits?
pub fn initialize_handlerton<T: Handlerton>(hton: &mut bindings::handlerton) {
hton.kill_query = Some(wrap_kill_query::<T>);
}
#[allow(clippy::extra_unused_type_parameters)] // expected until H is used
#[allow(improper_ctypes_definitions)] // level is not FFI-safe
unsafe extern "C" fn wrap_kill_query<H: Handlerton>(
hton: *mut bindings::handlerton,
thd: *mut bindings::THD,
level: bindings::thd_kill_levels::Type,
) {
let ctx = unsafe { HandlertonCtx::new(hton, thd) };
todo!()
}