From cf7951be22651128e963d09570108c0469a04e03 Mon Sep 17 00:00:00 2001 From: Sergey V <sv@picodata.io> Date: Mon, 14 Mar 2022 17:26:46 +0600 Subject: [PATCH] feat: rebootstrap initial implementation --- src/main.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/main.rs b/src/main.rs index 68a57d94c4..9ee48aedd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ use std::os::raw::{c_char, c_int, c_void}; +use std::os::unix::process::CommandExt; +use std::process::Command; use structopt::StructOpt; use ::raft::prelude as raft; @@ -75,6 +77,7 @@ fn picolib_setup(args: args::Run) { // // Export public API + luamod.set("rebootstrap", tlua::function0(rebootstrap)); luamod.set("run", tlua::function0(move || start(&args))); luamod.set("raft_status", tlua::function0(raft_status)); luamod.set("raft_tick", tlua::function1(raft_tick)); @@ -330,6 +333,25 @@ macro_rules! tarantool_main { } } +extern "C" { + static mut wal_dir_lock: i32; + fn close(fd: i32) -> i32; +} + +const REBOOTSTRAP_ENV_VAR: &str = "PICODATA_REBOOTSTRAP"; + +static mut ARGV: Vec<String> = vec![]; + +fn rebootstrap() { + std::env::set_var(REBOOTSTRAP_ENV_VAR, "1"); + unsafe { + tarantool::eval("box.cfg{listen=''}; require'fiber'.sleep(0.2)"); + close(dbg!(wal_dir_lock)); + tlog!(Warning, "Calling exec with: {:?}", &ARGV); + let _ = Command::new(&ARGV[0]).args(&ARGV[1..]).exec(); + } +} + fn run(args: args::Run) -> Result<(), String> { // Tarantool implicitly parses some environment variables. // We don't want them to affect the behavior and thus filter them out. @@ -339,10 +361,35 @@ fn run(args: args::Run) -> Result<(), String> { } } + unsafe { + ARGV = std::env::args().collect(); // Used in rebootstrap + } + tarantool_main!(args.tt_args()?, args => |args: args::Run| { + if std::env::var(REBOOTSTRAP_ENV_VAR).is_ok() { + std::env::remove_var(REBOOTSTRAP_ENV_VAR); + tlog!(Warning, "re-bootstrapping..."); + // cleanup data dir + std::fs::read_dir(&args.data_dir) + .expect("failed reading data_dir") + .map(|entry| entry.unwrap_or_else(|e| panic!("Failed reading directory entry: {}", e))) + .map(|entry| entry.path()) + .filter(|path| path.is_file()) + .filter(|f| { + f.extension() + .map(|ext| ext == "xlog" || ext == "snap") + .unwrap_or(false) + }) + .for_each(|f| { + tlog!(Warning, "removing file: {}", (&f).to_string_lossy()); + std::fs::remove_file(f).unwrap(); + }); + }; + if args.autorun { start(&args); } + picolib_setup(args); }) } -- GitLab