aboutsummaryrefslogblamecommitdiff
path: root/src/garage/server.rs
blob: 36f7de5c2f307d7c58a085ca20258ec68607f9db (plain) (tree)
1
2
3
4
5
6
7
8
9
10








                               
                               
                                 
                                      
                               







                                                                                 
                                

              
                                                     
                                                  










                                                                                   




                                                                 
                                          
                                                                                          

                                                                
                                                                                                  
 
                                                        
                                                                                  
                                       

                                           




                                                                                       
                                                                                         
                                                                                 
                           
                                    
                                                
                              
                   






                                                   


                                                   

                                                                    






                                             
use std::path::PathBuf;
use std::sync::Arc;

use futures_util::future::*;
use tokio::sync::watch;

use garage_util::background::*;
use garage_util::config::*;
use garage_util::error::Error;

use garage_api::run_api_server;
use garage_model::garage::Garage;
use garage_rpc::rpc_server::RpcServer;
use garage_web::run_web_server;

use crate::admin_rpc::*;

async fn shutdown_signal(send_cancel: watch::Sender<bool>) -> Result<(), Error> {
	// Wait for the CTRL+C signal
	tokio::signal::ctrl_c()
		.await
		.expect("failed to install CTRL+C signal handler");
	info!("Received CTRL+C, shutting down.");
	send_cancel.send(true)?;
	Ok(())
}

async fn wait_from(mut chan: watch::Receiver<bool>) {
	while !*chan.borrow() {
		if chan.changed().await.is_err() {
			return;
		}
	}
}

pub async fn run_server(config_file: PathBuf) -> Result<(), Error> {
	info!("Loading configuration...");
	let config = read_config(config_file).expect("Unable to read config file");

	info!("Opening database...");
	let mut db_path = config.metadata_dir.clone();
	db_path.push("db");
	let db = sled::Config::default()
		.path(&db_path)
		.cache_capacity(config.sled_cache_capacity)
		.flush_every_ms(Some(config.sled_flush_every_ms))
		.open()
		.expect("Unable to open sled DB");

	info!("Initialize RPC server...");
	let mut rpc_server = RpcServer::new(config.rpc_bind_addr, config.rpc_tls.clone());

	info!("Initializing background runner...");
	let (send_cancel, watch_cancel) = watch::channel(false);
	let (background, await_background_done) = BackgroundRunner::new(16, watch_cancel.clone());

	info!("Initializing Garage main data store...");
	let garage = Garage::new(config.clone(), db, background, &mut rpc_server);
	let bootstrap = garage.system.clone().bootstrap(
		config.bootstrap_peers,
		config.consul_host,
		config.consul_service_name,
	);

	info!("Crate admin RPC handler...");
	AdminRpcHandler::new(garage.clone()).register_handler(&mut rpc_server);

	info!("Initializing RPC and API servers...");
	let run_rpc_server = Arc::new(rpc_server).run(wait_from(watch_cancel.clone()));
	let api_server = run_api_server(garage.clone(), wait_from(watch_cancel.clone()));
	let web_server = run_web_server(garage, wait_from(watch_cancel.clone()));

	futures::try_join!(
		bootstrap.map(|()| {
			info!("Bootstrap done");
			Ok(())
		}),
		run_rpc_server.map(|rv| {
			info!("RPC server exited");
			rv
		}),
		api_server.map(|rv| {
			info!("API server exited");
			rv
		}),
		web_server.map(|rv| {
			info!("Web server exited");
			rv
		}),
		await_background_done.map(|rv| {
			info!("Background runner exited: {:?}", rv);
			Ok(())
		}),
		shutdown_signal(send_cancel),
	)?;

	info!("Cleaning up...");

	Ok(())
}