picodata_plugin/internal/
mod.rs1pub mod cas;
3pub(crate) mod ffi;
4pub mod types;
5
6use crate::internal::ffi::{
7 pico_ffi_cluster_uuid, pico_ffi_instance_info, pico_ffi_raft_info, pico_ffi_rpc_version,
8 pico_ffi_version,
9};
10use crate::internal::types::InstanceInfo;
11use abi_stable::derive_macro_reexports::RResult;
12use std::{env, fs, io, process};
13use tarantool::error::BoxError;
14
15#[deprecated(note = "use [`authentication::authenticate`] instead")]
16pub use crate::authentication::authenticate;
17
18pub fn picodata_version() -> &'static str {
20 let ptr_and_len = unsafe { pico_ffi_version() };
21 let slice = unsafe { std::slice::from_raw_parts(ptr_and_len.0, ptr_and_len.1) };
23 std::str::from_utf8(slice).expect("should be valid utf8")
24}
25
26pub fn rpc_version() -> &'static str {
28 let ptr_and_len = unsafe { pico_ffi_rpc_version() };
29 let slice = unsafe { std::slice::from_raw_parts(ptr_and_len.0, ptr_and_len.1) };
31 std::str::from_utf8(slice).expect("should be valid utf8")
32}
33
34pub fn cluster_uuid() -> Result<String, BoxError> {
36 match unsafe { pico_ffi_cluster_uuid() } {
37 RResult::ROk(rstring) => Ok(rstring.into()),
38 RResult::RErr(_) => {
39 let error = BoxError::last();
40 Err(error)
41 }
42 }
43}
44
45pub fn instance_info() -> Result<InstanceInfo, BoxError> {
47 match unsafe { pico_ffi_instance_info() } {
48 RResult::ROk(info) => Ok(info),
49 RResult::RErr(_) => {
50 let error = BoxError::last();
51 Err(error)
52 }
53 }
54}
55
56pub fn raft_info() -> types::RaftInfo {
58 unsafe { pico_ffi_raft_info() }
59}
60
61fn dump_backtrace(msg: &str) -> Result<(), io::Error> {
64 let should_dump = env::var("PICODATA_INTERNAL_BACKTRACE_DUMP")
65 .map(|v| !v.is_empty())
66 .unwrap_or(false);
67
68 if !should_dump {
69 return Ok(());
70 }
71
72 let name = format!("picodata-{}.backtrace", process::id());
73 let path = env::current_dir()?.join(&name);
74
75 fs::write(&name, msg)
76 .map(|_| tarantool::say_info!("dumped panic backtrace to `{}`", path.display()))
77 .inspect_err(|e| tarantool::say_info!("{}", e))?;
78
79 Ok(())
80}
81
82#[inline]
83pub fn set_panic_hook() {
84 std::panic::set_hook(Box::new(|info| {
88 let version = crate::internal::picodata_version();
89
90 let backtrace = std::backtrace::Backtrace::force_capture();
92 let message = format!(
93 "Picodata {version}\n\n{info}\n\nbacktrace:\n{backtrace}\naborting due to panic"
94 );
95
96 tarantool::say_crit!("\n\n{message}");
98 dump_backtrace(&message)
99 .unwrap_or_else(|e| tarantool::say_info!("Failed to dump panic backtrace: {}", e));
100
101 std::process::abort();
102 }));
103}
104
105#[derive(thiserror::Error, Debug)]
106pub enum InternalError {
107 #[error("timeout")]
108 Timeout,
109 #[error("internal error: {0}")]
110 Any(BoxError),
111}