Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,11 +556,16 @@ fn build_ffi(
bridge_file: &str,
out_name: &str,
source_file: &str,
extra_cpp_files: &[&str],
bundled: bool,
include_paths: &Vec<PathBuf>,
) {
let mut build = cxx_build::bridge(bridge_file);
build.file(source_file);
for extra in extra_cpp_files {
build.file(extra);
println!("cargo:rerun-if-changed={extra}");
}

if bundled {
build.define("LBUG_BUNDLED", None);
Expand All @@ -576,6 +581,7 @@ fn build_ffi(
println!("cargo:rerun-if-env-changed=LBUG_SHARED");

println!("cargo:rerun-if-changed=include/lbug_rs.h");
println!("cargo:rerun-if-changed=include/lbug_partition_routing.h");
println!("cargo:rerun-if-changed=src/lbug_rs.cpp");
println!("cargo:rerun-if-changed={bridge_file}");
println!("cargo:rerun-if-changed={source_file}");
Expand Down Expand Up @@ -604,7 +610,7 @@ fn build_ffi(

fn main() {
if env::var("DOCS_RS").is_ok() {
// Do nothing; we're just building docs and don't need the C++ library
// Do nothing more; we're just building docs and don't need the C++ library
return;
}

Expand All @@ -628,13 +634,18 @@ fn main() {
println!("cargo:rustc-env=LBUG_PRECOMPILED_SOURCE=source");
println!("cargo:rustc-env=LBUG_PRECOMPILED_LIBRARY_DIR=");
}
// The partition routing shim compiles against the amalgamated `lbug.hpp` alone, so
// no source checkout is needed. It is always built: current headers carry the hooks
// (prebuilt archives since ladybug #1005).
let routing_cpp: &[&str] = &["src/lbug_partition_routing.cpp"];
if link_mode() == "static" {
link_libraries(link_bundled_deps);
}
build_ffi(
"src/ffi.rs",
"lbug_rs",
"src/lbug_rs.cpp",
routing_cpp,
bundled,
&include_paths,
);
Expand All @@ -644,6 +655,7 @@ fn main() {
"src/ffi/arrow.rs",
"lbug_arrow_rs",
"src/lbug_arrow.cpp",
&[],
bundled,
&include_paths,
);
Expand Down
69 changes: 69 additions & 0 deletions include/lbug_partition_routing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// C ABI for LadybugDB partition routing hooks.
//
// The engine's `common::PartitionRoutingHooks` struct is not FFI-safe (it carries
// `std::function` members and callbacks with C++-only signatures such as
// `transaction::Transaction*` and `const ValueVector*`). This header exposes the same
// contract through plain function pointers, implemented in
// `src/lbug_partition_routing.cpp`:
//
// - `locate` / `on_partition_create` / `on_partition_drop` map one-to-one to the engine
// hooks. A null function pointer means "not handled" (local storage for `locate`).
// - `insert_row` fires once per routed row (point writes call it directly; bulk writes fan
// out to it row-at-a-time in the shim). Cells arrive in parent schema order as borrowed
// `lbug::common::Value` objects, valid only for the duration of the call. The shim owns a
// row store per claimed partition and assigns node IDs from it; the callback observes
// rows (e.g. to replicate or assert them).
// - Reads of claimed partitions are served by a bundled scan function over that same row
// store; see `lbug_partition_routing_register_schema`. `lookupRow` is intentionally left
// unset, so MERGE against claimed partitions fails with the engine's "not supported"
// error, exactly as with no wrapper at all.

#pragma once

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

// Mirrors `lbug::common::PartitionRef`: (partitioned parent table ID, partition index).
typedef struct {
uint64_t parent_table_id;
uint64_t partition_index;
} lbug_partition_ref_t;

// Mirrors the engine hooks with C-compatible signatures. `context` is passed back verbatim.
typedef struct {
void* context;
// Return 1 + set *handle_out to claim the partition as remote, 0 for local storage.
uint8_t (*locate)(void* context, lbug_partition_ref_t ref, void** handle_out);
void (*on_partition_create)(void* context, lbug_partition_ref_t ref, void* handle);
void (*on_partition_drop)(void* context, lbug_partition_ref_t ref, void* handle);
// One call per routed row. `cells` borrows `n_cells` values, valid for the call only.
void (*insert_row)(void* context, lbug_partition_ref_t ref, void* handle,
const void* const* cells, size_t n_cells);
} lbug_partition_hooks_t;

// Install process-global routing hooks. Must be called before opening any Database.
// Returns 0 on success, 1 if hooks are already installed (reset with
// `lbug_partition_routing_uninstall` first). The pointed-to struct is copied.
int lbug_partition_routing_install(const lbug_partition_hooks_t* hooks);

// Reset engine hooks to null (local behavior). Existing Database objects must be dropped
// first; the registry keeps no state of its own beyond the installed flag.
void lbug_partition_routing_uninstall(void);

// Returns 1 while hooks are installed, 0 otherwise.
uint8_t lbug_partition_routing_is_installed(void);

// Register a parent table's scan schema so claimed partitions can be read back through the
// bundled scan function: `prop_names[i]` / `type_ids[i]` describe the parent's properties in
// schema order (`type_ids` are `lbug::common::LogicalTypeID` discriminants; scalar types
// only). Returns 0 on success, 1 on an unsupported type or a null argument.
int lbug_partition_routing_register_schema(uint64_t parent_table_id,
const char* const* prop_names, const uint8_t* type_ids, size_t n_props);

#ifdef __cplusplus
}
#endif
Loading
Loading