Run simulator on C code

This commit is contained in:
Arthur Petukhovsky
2023-05-31 16:55:16 +00:00
parent 7b5123edda
commit aa0763d49d
14 changed files with 101 additions and 16 deletions

1
Cargo.lock generated
View File

@@ -4655,6 +4655,7 @@ dependencies = [
"postgres",
"rand",
"regex",
"safekeeper",
"serde",
"thiserror",
"utils",

View File

@@ -138,6 +138,7 @@ postgres_ffi = { version = "0.1", path = "./libs/postgres_ffi/" }
pq_proto = { version = "0.1", path = "./libs/pq_proto/" }
remote_storage = { version = "0.1", path = "./libs/remote_storage/" }
safekeeper_api = { version = "0.1", path = "./libs/safekeeper_api" }
safekeeper = { path = "./safekeeper/" }
storage_broker = { version = "0.1", path = "./storage_broker/" } # Note: main broker code is inside the binary crate, so linking with the library shouldn't be heavy.
tenant_size_model = { version = "0.1", path = "./libs/tenant_size_model/" }
tracing-utils = { version = "0.1", path = "./libs/tracing-utils/" }

View File

@@ -1,2 +1,3 @@
*.a
*.o
*.tmp

View File

@@ -18,6 +18,7 @@ memoffset.workspace = true
thiserror.workspace = true
serde.workspace = true
utils.workspace = true
safekeeper.workspace = true
workspace_hack.workspace = true

View File

@@ -8,3 +8,4 @@
// #include "walproposer.h"
int TestFunc(int a, int b);
void RunClientC();

View File

@@ -125,6 +125,7 @@ fn main() -> anyhow::Result<()> {
// included header files changed.
.parse_callbacks(Box::new(CargoCallbacks))
.allowlist_function("TestFunc")
.allowlist_function("RunClientC")
// .allowlist_function("WalProposerRust")
// .clang_arg(format!("-I{inc_server_path}"))
// .clang_arg(format!("-I{inc_pgxn_path}"))

View File

@@ -4,3 +4,5 @@
#include <stdlib.h>
void rust_function(uint32_t a);
void sim_sleep(uint64_t ms);

View File

@@ -6,23 +6,16 @@ pub mod bindings {
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
pub use bindings::{TestFunc};
use std::cell::RefCell;
thread_local! {
pub static TMP_TEST: RefCell<Vec<u32>> = RefCell::new(vec![]);
}
#[no_mangle]
pub extern "C" fn rust_function(a: u32) {
println!("Hello from Rust!");
println!("a: {}", a);
TMP_TEST.with(|f| {
f.borrow_mut().push(a);
println!("TMP_TEST: {:?}", f.borrow());
});
}
pub mod sim;
#[cfg(test)]
mod test;
#[cfg(test)]
pub mod simtest;

View File

@@ -0,0 +1,27 @@
use std::cell::RefCell;
use safekeeper::simlib::node_os::NodeOs;
thread_local! {
pub static CURRENT_NODE_OS: RefCell<Option<NodeOs>> = RefCell::new(None);
}
/// Get the current node os.
fn os() -> NodeOs {
CURRENT_NODE_OS.with(|cell| {
cell.borrow().clone().expect("no node os set")
})
}
/// Should be called before calling any of the C functions.
pub fn c_attach_node_os(os: NodeOs) {
CURRENT_NODE_OS.with(|cell| {
*cell.borrow_mut() = Some(os);
});
}
#[no_mangle]
pub extern "C" fn sim_sleep(ms: u64) {
println!("got a call to sleep for {} ms", ms);
os().sleep(ms);
}

View File

@@ -0,0 +1,41 @@
use std::sync::Arc;
use safekeeper::simlib::{network::{NetworkOptions, Delay}, world::World};
use crate::{bindings::RunClientC, sim::c_attach_node_os};
#[test]
fn run_rust_c_test() {
let delay = Delay {
min: 1,
max: 60,
fail_prob: 0.4,
};
let network = NetworkOptions {
timeout: Some(50),
connect_delay: delay.clone(),
send_delay: delay.clone(),
};
let seed = 1337;
start_simulation_2(seed, network.clone(), 1_000_000);
}
fn start_simulation_2(seed: u64, network: NetworkOptions, time_limit: u64) {
let network = Arc::new(network);
let world = Arc::new(World::new(seed, network));
world.register_world();
let client_node = world.new_node();
client_node.launch(move |os| {
c_attach_node_os(os);
unsafe { RunClientC() }
});
world.await_all();
while world.step() && world.now() < time_limit {
println!("made a step");
}
}

View File

@@ -1,8 +1,12 @@
use crate::{TestFunc, TMP_TEST};
use crate::bindings::{TestFunc, RunClientC};
#[test]
fn run_test() {
fn test_rust_c_calls() {
let res = unsafe { TestFunc(1, 2) };
// unsafe { WalProposerRust(); }
println!("res: {}", res);
}
#[test]
fn test_sim_bindings() {
unsafe { RunClientC(); }
}

View File

@@ -16,3 +16,14 @@ int TestFunc(int a, int b) {
printf("After rust_function\n");
return a + b;
}
// This is a quick experiment with rewriting existing Rust code in C.
void RunClientC() {
MemoryContextInit();
elog(LOG, "started client");
for (int i = 0; i < 10; i++) {
sim_sleep(100);
}
}

View File

@@ -10,6 +10,7 @@ use super::{
};
/// Abstraction with all functions (aka syscalls) available to the node.
#[derive(Clone)]
pub struct NodeOs {
world: Arc<World>,
internal: Arc<Node>,

View File

@@ -14,7 +14,7 @@ use crate::{
};
#[test]
fn run_test() {
fn run_pure_rust_test() {
let delay = Delay {
min: 1,
max: 60,