#[macro_use]
extern crate sozu_lib as sozu;
#[macro_use]
extern crate sozu_command_lib;
#[cfg(target_os = "linux")]
extern crate num_cpus;
use sozu_lib::metrics::names;
#[cfg(all(feature = "jemallocator", not(libc_jemalloc)))]
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
mod cli;
mod command;
mod ctl;
mod upgrade;
pub mod util;
mod worker;
use std::panic;
use cli::Args;
use command::{StartError, begin_main_process};
use ctl::CtlError;
use sozu::metrics::METRICS;
use upgrade::UpgradeError;
use worker::WorkerError;
#[derive(thiserror::Error, Debug)]
enum MainError {
#[error("failed to start Sōzu: {0}")]
StartMain(StartError),
#[error("failed to start new worker: {0}")]
BeginWorker(WorkerError),
#[error("failed to start new main process: {0}")]
BeginNewMain(UpgradeError),
#[error("{0}")]
Cli(CtlError),
#[error("paw io error: {0}")]
Io(std::io::Error),
}
impl From<std::io::Error> for MainError {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}
#[paw::main]
fn main(args: Args) -> Result<(), MainError> {
register_panic_hook();
let result = match args.cmd {
cli::SubCmd::Start => begin_main_process(&args).map_err(MainError::StartMain),
cli::SubCmd::Worker {
fd: worker_to_main_channel_fd,
scm: worker_to_main_scm_fd,
configuration_state_fd,
id,
command_buffer_size,
max_command_buffer_size,
} => {
let max_command_buffer_size =
resolve_max_command_buffer_size(command_buffer_size, max_command_buffer_size);
worker::begin_worker_process(
worker_to_main_channel_fd,
worker_to_main_scm_fd,
configuration_state_fd,
id,
command_buffer_size,
max_command_buffer_size,
)
.map_err(MainError::BeginWorker)
}
cli::SubCmd::Main {
fd,
upgrade_fd,
command_buffer_size,
max_command_buffer_size,
} => {
let max_command_buffer_size =
resolve_max_command_buffer_size(command_buffer_size, max_command_buffer_size);
upgrade::begin_new_main_process(
fd,
upgrade_fd,
command_buffer_size,
max_command_buffer_size,
)
.map_err(MainError::BeginNewMain)
}
_ => ctl::ctl(args).map_err(MainError::Cli),
};
if let Err(main_error) = &result {
eprintln!("\n{main_error}\n");
}
result
}
fn resolve_max_command_buffer_size(command_buffer_size: u64, explicit_max: Option<u64>) -> u64 {
match explicit_max {
Some(max) => max,
None => {
let default_max = command_buffer_size * 2;
debug_assert!(
default_max >= command_buffer_size,
"defaulted max_command_buffer_size must be >= command_buffer_size"
);
default_max
}
}
}
fn register_panic_hook() {
let original_panic_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| {
incr!(names::misc::PANIC);
METRICS.with(|metrics| {
(*metrics.borrow_mut()).send_data();
});
(*original_panic_hook)(panic_info)
}));
}