mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-06-26 00:49:27 +00:00
fix(indexer_ffi): use already FFI-safe Runtime
This commit is contained in:
parent
5d51e0b59c
commit
2195937400
@ -24,35 +24,6 @@ typedef enum FfiBedrockStatus {
|
||||
Finalized,
|
||||
} FfiBedrockStatus;
|
||||
|
||||
/**
|
||||
* FFI-owned indexer.
|
||||
*
|
||||
* Has three fields behind `c_void` (so that cbindgen never needs to see their Rust layout):
|
||||
* - An [`IndexerCore`] used to answer queries
|
||||
* - The background task [`JoinHandle`] that drives ingestion (consuming the block stream so the
|
||||
* store stays populated)
|
||||
* - The [`Runtime`] they run on. It owns the underlying tokio runtime when we created it (and
|
||||
* drops it on teardown) and merely borrows it when the caller supplied one.
|
||||
*/
|
||||
typedef struct IndexerServiceFFI {
|
||||
void *core;
|
||||
void *ingest_handle;
|
||||
void *runtime;
|
||||
} IndexerServiceFFI;
|
||||
|
||||
/**
|
||||
* Simple wrapper around a pointer to a value or an error.
|
||||
*
|
||||
* Pointer is not guaranteed. You should check the error field before
|
||||
* dereferencing the pointer.
|
||||
*/
|
||||
typedef struct PointerResult_IndexerServiceFFI__OperationStatus {
|
||||
struct IndexerServiceFFI *value;
|
||||
enum OperationStatus error;
|
||||
} PointerResult_IndexerServiceFFI__OperationStatus;
|
||||
|
||||
typedef struct PointerResult_IndexerServiceFFI__OperationStatus InitializedIndexerServiceFFIResult;
|
||||
|
||||
typedef enum PointerKind_Tag {
|
||||
Owned,
|
||||
Borrowed,
|
||||
@ -82,6 +53,34 @@ typedef struct Runtime {
|
||||
struct Pointer_Runtime inner;
|
||||
} Runtime;
|
||||
|
||||
/**
|
||||
* FFI-owned indexer.
|
||||
*
|
||||
* - An [`IndexerCore`] used to answer queries
|
||||
* - The background task [`JoinHandle`] that drives ingestion (consuming the block stream so the
|
||||
* store stays populated)
|
||||
* - The [`Runtime`] used to run async queries against the store (either owned or borrowed),
|
||||
* already FFI-safe.
|
||||
*/
|
||||
typedef struct IndexerServiceFFI {
|
||||
void *core;
|
||||
void *ingest_handle;
|
||||
struct Runtime runtime;
|
||||
} IndexerServiceFFI;
|
||||
|
||||
/**
|
||||
* Simple wrapper around a pointer to a value or an error.
|
||||
*
|
||||
* Pointer is not guaranteed. You should check the error field before
|
||||
* dereferencing the pointer.
|
||||
*/
|
||||
typedef struct PointerResult_IndexerServiceFFI__OperationStatus {
|
||||
struct IndexerServiceFFI *value;
|
||||
enum OperationStatus error;
|
||||
} PointerResult_IndexerServiceFFI__OperationStatus;
|
||||
|
||||
typedef struct PointerResult_IndexerServiceFFI__OperationStatus InitializedIndexerServiceFFIResult;
|
||||
|
||||
/**
|
||||
* Result of [`query_last_block`], returned **inline** (no heap allocation, so
|
||||
* there is no corresponding `free_*` to call).
|
||||
|
||||
@ -7,17 +7,16 @@ use crate::Runtime;
|
||||
|
||||
/// FFI-owned indexer.
|
||||
///
|
||||
/// Has three fields behind `c_void` (so that cbindgen never needs to see their Rust layout):
|
||||
/// - An [`IndexerCore`] used to answer queries
|
||||
/// - The background task [`JoinHandle`] that drives ingestion (consuming the block stream so the
|
||||
/// store stays populated)
|
||||
/// - The [`Runtime`] they run on. It owns the underlying tokio runtime when we created it (and
|
||||
/// drops it on teardown) and merely borrows it when the caller supplied one.
|
||||
/// - The [`Runtime`] used to run async queries against the store (either owned or borrowed),
|
||||
/// already FFI-safe.
|
||||
#[repr(C)]
|
||||
pub struct IndexerServiceFFI {
|
||||
core: *mut c_void,
|
||||
ingest_handle: *mut c_void,
|
||||
runtime: *mut c_void,
|
||||
runtime: Runtime,
|
||||
}
|
||||
|
||||
impl IndexerServiceFFI {
|
||||
@ -26,7 +25,7 @@ impl IndexerServiceFFI {
|
||||
Self {
|
||||
core: Box::into_raw(Box::new(core)).cast::<c_void>(),
|
||||
ingest_handle: Box::into_raw(Box::new(ingest_handle)).cast::<c_void>(),
|
||||
runtime: Box::into_raw(Box::new(runtime)).cast::<c_void>(),
|
||||
runtime,
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,38 +43,24 @@ impl IndexerServiceFFI {
|
||||
/// Borrow the runtime to `block_on` an async store query.
|
||||
#[must_use]
|
||||
pub const fn runtime(&self) -> &Runtime {
|
||||
unsafe {
|
||||
self.runtime
|
||||
.cast::<Runtime>()
|
||||
.as_ref()
|
||||
.expect("Runtime must be a non-null pointer")
|
||||
}
|
||||
&self.runtime
|
||||
}
|
||||
}
|
||||
|
||||
// Implement Drop to stop ingestion and free the boxed resources.
|
||||
impl Drop for IndexerServiceFFI {
|
||||
fn drop(&mut self) {
|
||||
let Self {
|
||||
core,
|
||||
ingest_handle,
|
||||
runtime,
|
||||
} = self;
|
||||
|
||||
if !ingest_handle.is_null() {
|
||||
// Stop the background ingestion task before tearing down the core.
|
||||
let handle = unsafe { Box::from_raw(ingest_handle.cast::<JoinHandle<()>>()) };
|
||||
if !self.ingest_handle.is_null() {
|
||||
let handle = unsafe { Box::from_raw(self.ingest_handle.cast::<JoinHandle<()>>()) };
|
||||
// stop the background ingestion task before tearing down the core.
|
||||
handle.abort();
|
||||
drop(handle);
|
||||
}
|
||||
if !core.is_null() {
|
||||
drop(unsafe { Box::from_raw(core.cast::<IndexerCore>()) });
|
||||
}
|
||||
// Dropping the `Runtime` shuts down the tokio runtime only if we own it
|
||||
// (a borrowed one is left for its external owner). Done last, and from
|
||||
// the consumer thread, so it never drops from within a runtime worker.
|
||||
if !runtime.is_null() {
|
||||
drop(unsafe { Box::from_raw(runtime.cast::<Runtime>()) });
|
||||
if !self.core.is_null() {
|
||||
drop(unsafe { Box::from_raw(self.core.cast::<IndexerCore>()) });
|
||||
}
|
||||
|
||||
// `runtime` field is dropped automatically on return here:
|
||||
// - if runtime was owned, it is shutdown at this point
|
||||
// - if it was borrowed, it continues to live within the external owner
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user