You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mediarepo/mediarepo-daemon/src/main.rs

156 lines
4.2 KiB
Rust

use std::path::PathBuf;
use structopt::StructOpt;
use tokio::fs;
use tokio::runtime;
use tokio::runtime::Runtime;
use mediarepo_core::error::RepoResult;
use mediarepo_core::futures;
use mediarepo_core::settings::{PathSettings, Settings};
use mediarepo_model::repo::Repo;
use mediarepo_socket::start_tcp_server;
use std::env;
use crate::utils::{create_paths_for_repo, get_repo, load_settings};
mod logging;
mod utils;
#[derive(Debug, StructOpt)]
#[structopt(name = "mediarepo", about = "A multimedia repository")]
struct Opt {
/// The path to the repository. Defaults to the current working directory
#[structopt(long, short, parse(from_os_str), default_value = ".")]
repo: PathBuf,
#[structopt(long, short)]
profile: bool,
/// The subcommand to invoke
#[structopt(subcommand)]
cmd: SubCommand,
}
#[derive(Clone, Debug, StructOpt)]
enum SubCommand {
/// Initializes an empty repository
Init {
/// Forces the creation of a new repository. This will delete everything in the repository
/// path to create an empty repository.
#[structopt(short, long)]
force: bool,
},
/// Starts the event server for the selected repository
Start,
}
fn main() -> RepoResult<()> {
let mut opt: Opt = Opt::from_args();
opt.repo = env::current_dir().unwrap().join(opt.repo);
let settings = if opt.repo.exists() {
opt.repo = opt.repo.canonicalize().unwrap();
load_settings(&opt.repo)?
} else {
Settings::default()
};
let mut guards = Vec::new();
if opt.profile {
guards.push(logging::init_tracing_flame());
} else {
guards.append(&mut logging::init_tracing(&opt.repo, &settings.logging));
}
let result = match opt.cmd.clone() {
SubCommand::Init { force } => get_single_thread_runtime().block_on(init(opt, force)),
SubCommand::Start => get_multi_thread_runtime().block_on(start_server(opt, settings)),
};
match result {
Ok(_) => Ok(()),
Err(e) => {
tracing::error!("a critical error occurred when running the daemon: {}", e);
Err(e)
}
}
}
fn get_single_thread_runtime() -> Runtime {
log::info!("Using current thread runtime");
runtime::Builder::new_current_thread()
.enable_all()
.max_blocking_threads(1)
.build()
.unwrap()
}
fn get_multi_thread_runtime() -> Runtime {
log::info!("Using multi thread runtime");
runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
}
async fn init_repo(opt: &Opt, paths: &PathSettings) -> RepoResult<Repo> {
let repo = get_repo(&opt.repo, paths).await?;
Ok(repo)
}
/// Starts the server
async fn start_server(opt: Opt, settings: Settings) -> RepoResult<()> {
let repo = init_repo(&opt, &settings.paths).await?;
let mut handles = Vec::new();
#[cfg(unix)]
{
let socket_path = opt.repo.join("repo.sock");
let handle = mediarepo_socket::create_unix_socket(
socket_path,
opt.repo.clone(),
settings.clone(),
repo.clone(),
)?;
handles.push(handle);
}
let (address, tcp_handle) = start_tcp_server(opt.repo.clone(), settings, repo)?;
handles.push(tcp_handle);
fs::write(opt.repo.join("repo.tcp"), &address.into_bytes()).await?;
futures::future::join_all(handles.into_iter()).await;
Ok(())
}
/// Initializes an empty repository
async fn init(opt: Opt, force: bool) -> RepoResult<()> {
log::info!("Initializing repository at {:?}", opt.repo);
if force {
log::debug!("Removing old repository");
fs::remove_dir_all(&opt.repo).await?;
}
let settings = Settings::default();
log::debug!("Creating paths");
create_paths_for_repo(&opt.repo, &settings.paths).await?;
if settings.paths.db_file_path(&opt.repo).exists() {
panic!("Database already exists in location. Use --force with init to delete everything and start a new repository");
}
log::debug!("Creating repo");
let _repo = get_repo(&opt.repo, &settings.paths).await?;
log::debug!("Writing settings");
settings.save(&opt.repo)?;
log::info!("Repository initialized");
Ok(())
}