<commit_before>//! # runner
//!
//! Runs the requested tasks.

//! The flow is as follows:
//!
//! * Load env variables
//! * Create an execution plan based on the requested task and its dependencies
//! * Run all tasks defined in the execution plan
//!

#[cfg(test)]
#[path = "./runner_test.rs"]
mod runner_test;

use crate::command;
use crate::condition;
use crate::environment;
use crate::execution_plan::create as create_execution_plan;
use crate::functions;
use crate::installer;
use crate::logger;
use crate::profile;
use crate::scriptengine;
use crate::types::{
    CliArgs, Config, EnvInfo, EnvValue, ExecutionPlan, FlowInfo, RunTaskInfo, RunTaskRoutingInfo,
    Step, Task, TaskWatchOptions,
};
use indexmap::IndexMap;
use std::env;
use std::time::SystemTime;

fn validate_condition(flow_info: &FlowInfo, step: &Step) -> bool {
    condition::validate_condition_for_step(&flow_info, &step)
}

pub(crate) fn get_sub_task_info_for_routing_info(
    flow_info: &FlowInfo,
    routing_info: &Vec<RunTaskRoutingInfo>,
) -> (Option<String>, bool) {
    let mut task_name = None;

    let mut fork = false;
    for routing_step in routing_info {
        let invoke = condition::validate_conditions(
            &flow_info,
            &routing_step.condition,
            &routing_step.condition_script,
            None,
        );

        if invoke {
            task_name = Some(routing_step.name.clone());
            fork = routing_step.fork.unwrap_or(false);
            break;
        }
    }

    (task_name, fork)
}

fn create_fork_step(flow_info: &FlowInfo) -> Step {
    let fork_task = create_proxy_task(&flow_info.task, true, true);

    Step {
        name: "cargo_make_run_fork".to_string(),
        config: fork_task,
    }
}

fn run_forked_task(flow_info: &FlowInfo) {
    // run task as a sub process
    let step = create_fork_step(&flow_info);
    run_task(&flow_info, &step);
}

/// runs a sub task and returns true/false based if a sub task was actually invoked
fn run_sub_task_and_report(flow_info: &FlowInfo, sub_task: &RunTaskInfo) -> bool {
    let (task_name, fork) = match sub_task {
        RunTaskInfo::Name(ref name) => (Some(name.to_string()), false),
        RunTaskInfo::Details(ref details) => {
            (Some(details.name.clone()), details.fork.unwrap_or(false))
        }
        RunTaskInfo::Routing(ref routing_info) => {
            get_sub_task_info_for_routing_info(&flow_info, routing_info)
        }
    };

    if task_name.is_some() {
        let mut sub_flow_info = flow_info.clone();
        sub_flow_info.task = task_name.unwrap();

        if fork {
            run_forked_task(&sub_flow_info);
        } else {
            run_flow(&sub_flow_info, true);
        }

        true
    } else {
        false
    }
}

fn run_sub_task(flow_info: &FlowInfo, sub_task: &RunTaskInfo) {
    run_sub_task_and_report(&flow_info, &sub_task);
}

fn create_watch_task_name(task: &str) -> String {
    let mut watch_task_name = "".to_string();
    watch_task_name.push_str(&task);
    watch_task_name.push_str("-watch");

    watch_task_name
}

fn create_watch_step(task: &str, options: Option<TaskWatchOptions>) -> Step {
    let watch_task = create_watch_task(&task, options);

    let watch_task_name = create_watch_task_name(&task);

    Step {
        name: watch_task_name,
        config: watch_task,
    }
}

fn watch_task(flow_info: &FlowInfo, task: &str, options: Option<TaskWatchOptions>) {
    let step = create_watch_step(&task, options);

    run_task(&flow_info, &step);
}

fn is_watch_enabled() -> bool {
    !envmnt::is_or("CARGO_MAKE_DISABLE_WATCH", false)
}

fn should_watch(task: &Task) -> bool {
    match task.watch {
        Some(ref watch_value) => match watch_value {
            TaskWatchOptions::Boolean(watch_bool) => {
                if *watch_bool {
                    is_watch_enabled()
                } else {
                    false
                }
            }
            TaskWatchOptions::Options(_) => is_watch_enabled(),
        },
        None => false,
    }
}

fn run_task(flow_info: &FlowInfo, step: &Step) {
    info!("Running Task: {}", &step.name);

    if validate_condition(&flow_info, &step) {
        if !step.config.is_valid() {
            error!(
                "Invalid task, contains multiple actions.\n{:#?}",
                &step.config
            );
        }

        //get profile
        let profile_name = profile::get();

        let env = match step.config.env {
            Some(ref env) => env.clone(),
            None => IndexMap::new(),
        };
        environment::set_env(env);

        //make sure profile env is not overwritten
        profile::set(&profile_name);

        // modify step using env and functions
        let mut updated_step = functions::run(&step);
        updated_step = environment::expand_env(&updated_step);

        let watch = should_watch(&step.config);

        if watch {
            watch_task(&flow_info, &step.name, step.config.watch.clone());
        } else {
            installer::install(&updated_step.config);

            match step.config.run_task {
                Some(ref sub_task) => run_sub_task(&flow_info, sub_task),
                None => {
                    let revert_directory = match step.config.cwd {
                        Some(ref cwd) => {
                            if cwd.len() > 0 {
                                let directory = envmnt::get_or("CARGO_MAKE_WORKING_DIRECTORY", "");

                                environment::setup_cwd(Some(cwd));

                                directory
                            } else {
                                "".to_string()
                            }
                        }
                        None => "".to_string(),
                    };

                    // get cli arguments
                    let cli_arguments = match flow_info.cli_arguments {
                        Some(ref args) => args.clone(),
                        None => vec![],
                    };

                    // run script
                    let script_runner_done =
                        scriptengine::invoke(&updated_step.config, &cli_arguments);

                    // run command
                    if !script_runner_done {
                        command::run(&updated_step);
                    };

                    // revert to original cwd
                    match step.config.cwd {
                        Some(_) => environment::setup_cwd(Some(&revert_directory)),
                        _ => (),
                    };
                }
            };
        }
    } else {
        debug!("Task: {} disabled", &step.name);
    }
}

fn run_task_flow(flow_info: &FlowInfo, execution_plan: &ExecutionPlan) {
    for step in &execution_plan.steps {
        run_task(&flow_info, &step);
    }
}

fn create_watch_task(task: &str, options: Option<TaskWatchOptions>) -> Task {
    let mut task_config = create_proxy_task(&task, true, true);

    let mut env_map = task_config.env.unwrap_or(IndexMap::new());
    env_map.insert(
        "CARGO_MAKE_DISABLE_WATCH".to_string(),
        EnvValue::Value("true".to_string()),
    );
    task_config.env = Some(env_map);

    let make_args = task_config.args.unwrap();
    let make_command = &make_args.join(" ");

    let mut watch_args = vec!["watch".to_string(), "-q".to_string()];

    match options {
        Some(task_watch_options) => match task_watch_options {
            TaskWatchOptions::Options(watch_options) => {
                let watch_version = match watch_options.version {
                    Some(value) => value.to_string(),
                    _ => "7.0.8".to_string(), // currently certified version
                };
                task_config.install_crate_args = Some(vec!["--version".to_string(), watch_version]);

                match watch_options.postpone {
                    Some(value) => {
                        if value {
                            watch_args.push("--postpone".to_string());
                        }
                    }
                    _ => (),
                };

                match watch_options.ignore_pattern {
                    Some(value) => watch_args.extend_from_slice(&["-i".to_string(), value]),
                    _ => (),
                };

                match watch_options.no_git_ignore {
                    Some(value) => {
                        if value {
                            watch_args.push("--no-gitignore".to_string());
                        }
                    }
                    _ => (),
                };
            }
            _ => (),
        },
        _ => (),
    }

    watch_args.extend_from_slice(&["-x".to_string(), make_command.to_string()]);

    task_config.args = Some(watch_args);

    task_config
}

fn create_proxy_task(task: &str, allow_private: bool, skip_init_end_tasks: bool) -> Task {
    //get log level name
    let log_level = logger::get_log_level();

    let mut log_level_arg = "--loglevel=".to_string();
    log_level_arg.push_str(&log_level);

    //get profile
    let profile_name = profile::get();

    let mut profile_arg = "--profile=\"".to_string();
    profile_arg.push_str(&profile_name);
    profile_arg.push_str("\"");

    //setup common args
    let mut args = vec![
        "make".to_string(),
        "--disable-check-for-updates".to_string(),
        "--no-on-error".to_string(),
        log_level_arg.to_string(),
        profile_arg.to_string(),
    ];

    if allow_private {
        args.push("--allow-private".to_string());
    }

    if skip_init_end_tasks {
        args.push("--skip-init-end-tasks".to_string());
    }

    //get makefile location
    match env::var("CARGO_MAKE_MAKEFILE_PATH") {
        Ok(makefile_path) => {
            if makefile_path.len() > 0 {
                let mut makefile_arg = "--makefile=".to_string();
                makefile_arg.push_str(&makefile_path);

                args.push(makefile_arg.to_string());
            }
        }
        _ => {}
    };

    args.push(task.to_string());

    let mut proxy_task = Task::new();
    proxy_task.command = Some("cargo".to_string());
    proxy_task.args = Some(args);

    proxy_task.get_normalized_task()
}

fn run_flow(flow_info: &FlowInfo, sub_flow: bool) {
    let allow_private = sub_flow || flow_info.allow_private;

    let execution_plan = create_execution_plan(
        &flow_info.config,
        &flow_info.task,
        flow_info.disable_workspace,
        allow_private,
        sub_flow,
    );
    debug!("Created execution plan: {:#?}", &execution_plan);

    run_task_flow(&flow_info, &execution_plan);
}

fn run_protected_flow(flow_info: &FlowInfo) {
    let proxy_task = create_proxy_task(
        &flow_info.task,
        flow_info.allow_private,
        flow_info.skip_init_end_tasks,
    );

    let exit_code = command::run_command(&proxy_task.command.unwrap(), &proxy_task.args, false);

    if exit_code != 0 {
        match flow_info.config.config.on_error_task {
            Some(ref on_error_task) => {
                let mut error_flow_info = flow_info.clone();
                error_flow_info.disable_on_error = true;
                error_flow_info.task = on_error_task.clone();

                run_flow(&error_flow_info, false);
            }
            _ => (),
        };

        error!("Task error detected, exit code: {}", &exit_code);
    }
}

/// Runs the requested tasks.

/// The flow is as follows:
///
/// * Create an execution plan based on the requested task and its dependencies
/// * Run all tasks defined in the execution plan
pub(crate) fn run(config: Config, task: &str, env_info: EnvInfo, cli_args: &CliArgs) {
    let start_time = SystemTime::now();

    let flow_info = FlowInfo {
        config,
        task: task.to_string(),
        env_info,
        disable_workspace: cli_args.disable_workspace,
        disable_on_error: cli_args.disable_on_error,
        allow_private: cli_args.allow_private,
        skip_init_end_tasks: cli_args.skip_init_end_tasks,
        cli_arguments: cli_args.arguments.clone(),
    };

    if flow_info.disable_on_error || flow_info.config.config.on_error_task.is_none() {
        run_flow(&flow_info, false);
    } else {
        run_protected_flow(&flow_info);
    }

    let time_string = match start_time.elapsed() {
        Ok(elapsed) => {
            let mut string = " in ".to_string();
            string.push_str(&elapsed.as_secs().to_string());
            string.push_str(" seconds");

            string
        }
        _ => "".to_string(),
    };

    info!("Build Done {}.", &time_string);
}
<commit_msg>Changed default version of cargo-watch to a working one<commit_after>//! # runner
//!
//! Runs the requested tasks.

//! The flow is as follows:
//!
//! * Load env variables
//! * Create an execution plan based on the requested task and its dependencies
//! * Run all tasks defined in the execution plan
//!

#[cfg(test)]
#[path = "./runner_test.rs"]
mod runner_test;

use crate::command;
use crate::condition;
use crate::environment;
use crate::execution_plan::create as create_execution_plan;
use crate::functions;
use crate::installer;
use crate::logger;
use crate::profile;
use crate::scriptengine;
use crate::types::{
    CliArgs, Config, EnvInfo, EnvValue, ExecutionPlan, FlowInfo, RunTaskInfo, RunTaskRoutingInfo,
    Step, Task, TaskWatchOptions,
};
use indexmap::IndexMap;
use std::env;
use std::time::SystemTime;

fn validate_condition(flow_info: &FlowInfo, step: &Step) -> bool {
    condition::validate_condition_for_step(&flow_info, &step)
}

pub(crate) fn get_sub_task_info_for_routing_info(
    flow_info: &FlowInfo,
    routing_info: &Vec<RunTaskRoutingInfo>,
) -> (Option<String>, bool) {
    let mut task_name = None;

    let mut fork = false;
    for routing_step in routing_info {
        let invoke = condition::validate_conditions(
            &flow_info,
            &routing_step.condition,
            &routing_step.condition_script,
            None,
        );

        if invoke {
            task_name = Some(routing_step.name.clone());
            fork = routing_step.fork.unwrap_or(false);
            break;
        }
    }

    (task_name, fork)
}

fn create_fork_step(flow_info: &FlowInfo) -> Step {
    let fork_task = create_proxy_task(&flow_info.task, true, true);

    Step {
        name: "cargo_make_run_fork".to_string(),
        config: fork_task,
    }
}

fn run_forked_task(flow_info: &FlowInfo) {
    // run task as a sub process
    let step = create_fork_step(&flow_info);
    run_task(&flow_info, &step);
}

/// runs a sub task and returns true/false based if a sub task was actually invoked
fn run_sub_task_and_report(flow_info: &FlowInfo, sub_task: &RunTaskInfo) -> bool {
    let (task_name, fork) = match sub_task {
        RunTaskInfo::Name(ref name) => (Some(name.to_string()), false),
        RunTaskInfo::Details(ref details) => {
            (Some(details.name.clone()), details.fork.unwrap_or(false))
        }
        RunTaskInfo::Routing(ref routing_info) => {
            get_sub_task_info_for_routing_info(&flow_info, routing_info)
        }
    };

    if task_name.is_some() {
        let mut sub_flow_info = flow_info.clone();
        sub_flow_info.task = task_name.unwrap();

        if fork {
            run_forked_task(&sub_flow_info);
        } else {
            run_flow(&sub_flow_info, true);
        }

        true
    } else {
        false
    }
}

fn run_sub_task(flow_info: &FlowInfo, sub_task: &RunTaskInfo) {
    run_sub_task_and_report(&flow_info, &sub_task);
}

fn create_watch_task_name(task: &str) -> String {
    let mut watch_task_name = "".to_string();
    watch_task_name.push_str(&task);
    watch_task_name.push_str("-watch");

    watch_task_name
}

fn create_watch_step(task: &str, options: Option<TaskWatchOptions>) -> Step {
    let watch_task = create_watch_task(&task, options);

    let watch_task_name = create_watch_task_name(&task);

    Step {
        name: watch_task_name,
        config: watch_task,
    }
}

fn watch_task(flow_info: &FlowInfo, task: &str, options: Option<TaskWatchOptions>) {
    let step = create_watch_step(&task, options);

    run_task(&flow_info, &step);
}

fn is_watch_enabled() -> bool {
    !envmnt::is_or("CARGO_MAKE_DISABLE_WATCH", false)
}

fn should_watch(task: &Task) -> bool {
    match task.watch {
        Some(ref watch_value) => match watch_value {
            TaskWatchOptions::Boolean(watch_bool) => {
                if *watch_bool {
                    is_watch_enabled()
                } else {
                    false
                }
            }
            TaskWatchOptions::Options(_) => is_watch_enabled(),
        },
        None => false,
    }
}

fn run_task(flow_info: &FlowInfo, step: &Step) {
    info!("Running Task: {}", &step.name);

    if validate_condition(&flow_info, &step) {
        if !step.config.is_valid() {
            error!(
                "Invalid task, contains multiple actions.\n{:#?}",
                &step.config
            );
        }

        //get profile
        let profile_name = profile::get();

        let env = match step.config.env {
            Some(ref env) => env.clone(),
            None => IndexMap::new(),
        };
        environment::set_env(env);

        //make sure profile env is not overwritten
        profile::set(&profile_name);

        // modify step using env and functions
        let mut updated_step = functions::run(&step);
        updated_step = environment::expand_env(&updated_step);

        let watch = should_watch(&step.config);

        if watch {
            watch_task(&flow_info, &step.name, step.config.watch.clone());
        } else {
            installer::install(&updated_step.config);

            match step.config.run_task {
                Some(ref sub_task) => run_sub_task(&flow_info, sub_task),
                None => {
                    let revert_directory = match step.config.cwd {
                        Some(ref cwd) => {
                            if cwd.len() > 0 {
                                let directory = envmnt::get_or("CARGO_MAKE_WORKING_DIRECTORY", "");

                                environment::setup_cwd(Some(cwd));

                                directory
                            } else {
                                "".to_string()
                            }
                        }
                        None => "".to_string(),
                    };

                    // get cli arguments
                    let cli_arguments = match flow_info.cli_arguments {
                        Some(ref args) => args.clone(),
                        None => vec![],
                    };

                    // run script
                    let script_runner_done =
                        scriptengine::invoke(&updated_step.config, &cli_arguments);

                    // run command
                    if !script_runner_done {
                        command::run(&updated_step);
                    };

                    // revert to original cwd
                    match step.config.cwd {
                        Some(_) => environment::setup_cwd(Some(&revert_directory)),
                        _ => (),
                    };
                }
            };
        }
    } else {
        debug!("Task: {} disabled", &step.name);
    }
}

fn run_task_flow(flow_info: &FlowInfo, execution_plan: &ExecutionPlan) {
    for step in &execution_plan.steps {
        run_task(&flow_info, &step);
    }
}

fn create_watch_task(task: &str, options: Option<TaskWatchOptions>) -> Task {
    let mut task_config = create_proxy_task(&task, true, true);

    let mut env_map = task_config.env.unwrap_or(IndexMap::new());
    env_map.insert(
        "CARGO_MAKE_DISABLE_WATCH".to_string(),
        EnvValue::Value("true".to_string()),
    );
    task_config.env = Some(env_map);

    let make_args = task_config.args.unwrap();
    let make_command = &make_args.join(" ");

    let mut watch_args = vec!["watch".to_string(), "-q".to_string()];

    match options {
        Some(task_watch_options) => match task_watch_options {
            TaskWatchOptions::Options(watch_options) => {
                let watch_version = match watch_options.version {
                    Some(value) => value.to_string(),
                    _ => "7.2.1".to_string(), // current version
                };
                task_config.install_crate_args = Some(vec!["--version".to_string(), watch_version]);

                match watch_options.postpone {
                    Some(value) => {
                        if value {
                            watch_args.push("--postpone".to_string());
                        }
                    }
                    _ => (),
                };

                match watch_options.ignore_pattern {
                    Some(value) => watch_args.extend_from_slice(&["-i".to_string(), value]),
                    _ => (),
                };

                match watch_options.no_git_ignore {
                    Some(value) => {
                        if value {
                            watch_args.push("--no-gitignore".to_string());
                        }
                    }
                    _ => (),
                };
            }
            _ => (),
        },
        _ => (),
    }

    watch_args.extend_from_slice(&["-x".to_string(), make_command.to_string()]);

    task_config.args = Some(watch_args);

    task_config
}

fn create_proxy_task(task: &str, allow_private: bool, skip_init_end_tasks: bool) -> Task {
    //get log level name
    let log_level = logger::get_log_level();

    let mut log_level_arg = "--loglevel=".to_string();
    log_level_arg.push_str(&log_level);

    //get profile
    let profile_name = profile::get();

    let mut profile_arg = "--profile=\"".to_string();
    profile_arg.push_str(&profile_name);
    profile_arg.push_str("\"");

    //setup common args
    let mut args = vec![
        "make".to_string(),
        "--disable-check-for-updates".to_string(),
        "--no-on-error".to_string(),
        log_level_arg.to_string(),
        profile_arg.to_string(),
    ];

    if allow_private {
        args.push("--allow-private".to_string());
    }

    if skip_init_end_tasks {
        args.push("--skip-init-end-tasks".to_string());
    }

    //get makefile location
    match env::var("CARGO_MAKE_MAKEFILE_PATH") {
        Ok(makefile_path) => {
            if makefile_path.len() > 0 {
                let mut makefile_arg = "--makefile=".to_string();
                makefile_arg.push_str(&makefile_path);

                args.push(makefile_arg.to_string());
            }
        }
        _ => {}
    };

    args.push(task.to_string());

    let mut proxy_task = Task::new();
    proxy_task.command = Some("cargo".to_string());
    proxy_task.args = Some(args);

    proxy_task.get_normalized_task()
}

fn run_flow(flow_info: &FlowInfo, sub_flow: bool) {
    let allow_private = sub_flow || flow_info.allow_private;

    let execution_plan = create_execution_plan(
        &flow_info.config,
        &flow_info.task,
        flow_info.disable_workspace,
        allow_private,
        sub_flow,
    );
    debug!("Created execution plan: {:#?}", &execution_plan);

    run_task_flow(&flow_info, &execution_plan);
}

fn run_protected_flow(flow_info: &FlowInfo) {
    let proxy_task = create_proxy_task(
        &flow_info.task,
        flow_info.allow_private,
        flow_info.skip_init_end_tasks,
    );

    let exit_code = command::run_command(&proxy_task.command.unwrap(), &proxy_task.args, false);

    if exit_code != 0 {
        match flow_info.config.config.on_error_task {
            Some(ref on_error_task) => {
                let mut error_flow_info = flow_info.clone();
                error_flow_info.disable_on_error = true;
                error_flow_info.task = on_error_task.clone();

                run_flow(&error_flow_info, false);
            }
            _ => (),
        };

        error!("Task error detected, exit code: {}", &exit_code);
    }
}

/// Runs the requested tasks.

/// The flow is as follows:
///
/// * Create an execution plan based on the requested task and its dependencies
/// * Run all tasks defined in the execution plan
pub(crate) fn run(config: Config, task: &str, env_info: EnvInfo, cli_args: &CliArgs) {
    let start_time = SystemTime::now();

    let flow_info = FlowInfo {
        config,
        task: task.to_string(),
        env_info,
        disable_workspace: cli_args.disable_workspace,
        disable_on_error: cli_args.disable_on_error,
        allow_private: cli_args.allow_private,
        skip_init_end_tasks: cli_args.skip_init_end_tasks,
        cli_arguments: cli_args.arguments.clone(),
    };

    if flow_info.disable_on_error || flow_info.config.config.on_error_task.is_none() {
        run_flow(&flow_info, false);
    } else {
        run_protected_flow(&flow_info);
    }

    let time_string = match start_time.elapsed() {
        Ok(elapsed) => {
            let mut string = " in ".to_string();
            string.push_str(&elapsed.as_secs().to_string());
            string.push_str(" seconds");

            string
        }
        _ => "".to_string(),
    };

    info!("Build Done {}.", &time_string);
}
<|endoftext|>


<commit_before>use request::Request;
use response::Response;
use nickel_error::NickelError;

pub type MiddlewareResult = Result<Action, NickelError>;

#[deriving(PartialEq)]
pub enum Action {
  Continue,
  Halt
}

// the usage of + Send is weird here because what we really want is + Static
// but that's not possible as of today. We have to use + Send for now.
pub trait Middleware: Send + Sync {
    fn invoke<'a, 'b>(&'a self, _req: &mut Request<'b, 'a>, _res: &mut Response) -> MiddlewareResult {
        Ok(Continue)
    }
}

pub trait ErrorHandler: Send + Sync {
    fn invoke(&self, _err: &NickelError, _req: &mut Request, _res: &mut Response) -> MiddlewareResult {
        Ok(Continue)
    }
}

impl Middleware for fn(&Request, &mut Response) -> MiddlewareResult {
    fn invoke(&self, req: &mut Request, res: &mut Response) -> MiddlewareResult {
        (*self)(req, res)
    }
}

impl ErrorHandler for fn(&NickelError, &Request, &mut Response) -> MiddlewareResult {
    fn invoke(&self, err: &NickelError, req: &mut Request, res: &mut Response) -> MiddlewareResult {
        (*self)(err, req, res)
    }
}

pub struct MiddlewareStack {
    handlers: Vec<Box<Middleware + Send + Sync>>,
    error_handlers: Vec<Box<ErrorHandler + Send + Sync>>
}

impl MiddlewareStack {
    pub fn add_middleware<T: Middleware> (&mut self, handler: T) {
        self.handlers.push(box handler);
    }

    pub fn add_error_handler<T: ErrorHandler> (&mut self, handler: T) {
        self.error_handlers.push(box handler);
    }

    pub fn invoke<'a, 'b>(&'a self, req: &mut Request<'b, 'a>, res: &mut Response) {
        self.handlers.iter().all(|handler| {
            match (*handler).invoke(req, res) {
                Ok(Continue) => true,
                Ok(Halt)     => false,
                Err(err)     => {
                    let mut err = err;
                    self.error_handlers.iter().rev().all(|error_handler| {
                        match (*error_handler).invoke(&err, req, res) {
                            Ok(Continue) => true,
                            Ok(Halt)     => false,
                            Err(new_err)     => {
                                // change the error so that other ErrorHandler down the stack receive
                                // the new error.
                                err = new_err;
                                true
                            }
                        }
                    })
                }
            }
        });
    }

    pub fn new () -> MiddlewareStack {
        MiddlewareStack{
            handlers: Vec::new(),
            error_handlers: Vec::new()
        }
    }
}
<commit_msg>refactor(middleware): use forloop instead of iter.all()<commit_after>use request::Request;
use response::Response;
use nickel_error::NickelError;

pub type MiddlewareResult = Result<Action, NickelError>;

#[deriving(PartialEq)]
pub enum Action {
  Continue,
  Halt
}

// the usage of + Send is weird here because what we really want is + Static
// but that's not possible as of today. We have to use + Send for now.
pub trait Middleware: Send + Sync {
    fn invoke<'a, 'b>(&'a self, _req: &mut Request<'b, 'a>, _res: &mut Response) -> MiddlewareResult {
        Ok(Continue)
    }
}

pub trait ErrorHandler: Send + Sync {
    fn invoke(&self, _err: &NickelError, _req: &mut Request, _res: &mut Response) -> MiddlewareResult {
        Ok(Continue)
    }
}

impl Middleware for fn(&Request, &mut Response) -> MiddlewareResult {
    fn invoke(&self, req: &mut Request, res: &mut Response) -> MiddlewareResult {
        (*self)(req, res)
    }
}

impl ErrorHandler for fn(&NickelError, &Request, &mut Response) -> MiddlewareResult {
    fn invoke(&self, err: &NickelError, req: &mut Request, res: &mut Response) -> MiddlewareResult {
        (*self)(err, req, res)
    }
}

pub struct MiddlewareStack {
    handlers: Vec<Box<Middleware + Send + Sync>>,
    error_handlers: Vec<Box<ErrorHandler + Send + Sync>>
}

impl MiddlewareStack {
    pub fn add_middleware<T: Middleware> (&mut self, handler: T) {
        self.handlers.push(box handler);
    }

    pub fn add_error_handler<T: ErrorHandler> (&mut self, handler: T) {
        self.error_handlers.push(box handler);
    }

    pub fn invoke<'a, 'b>(&'a self, req: &mut Request<'b, 'a>, res: &mut Response) {
        for handler in self.handlers.iter() {
            match handler.invoke(req, res) {
                Ok(Halt) => return,
                Ok(Continue) => {},
                Err(mut err) => {
                    for error_handler in self.error_handlers.iter().rev() {
                        match error_handler.invoke(&err, req, res) {
                            Ok(Continue) => {},
                            Ok(Halt) => return,
                            // change the error so that other ErrorHandler
                            // down the stack receive the new error.
                            Err(new_err) => err = new_err,
                        }
                    }
                }
            }
        }
    }

    pub fn new () -> MiddlewareStack {
        MiddlewareStack{
            handlers: Vec::new(),
            error_handlers: Vec::new()
        }
    }
}
<|endoftext|>


<commit_before>
#[derive(Debug, PartialEq)]
pub enum Op {
    Increment,
    Decrement,
    Output,
    Right,
    Left,
    Input,
    Jump,
    JumpBack,
    Unknown,
}

pub trait ToOp {
    fn to_op(&self) -> Op;
}

impl ToOp for String {
    fn to_op(&self) -> Op {
        match self.as_slice() {
            "iamgroot" => Op::Increment,
            "IamGroot" => Op::Decrement,
            "IAMGROOOT" => Op::Output,
            "IAMGROOT" => Op::Right,
            "Iamgroot" => Op::Left,
            "I'mGroot" => Op::Jump,
            "WeareGroot" => Op::JumpBack,
            "Iamgrooot" => Op::Input,
            _ => Op::Unknown,
        }
    }
}

<commit_msg>BACON!<commit_after>
#[derive(Debug, PartialEq)]
pub enum Op {
    Increment,
    Decrement,
    Output,
    Right,
    Left,
    Input,
    Jump,
    JumpBack,
    Unknown,
}

pub trait ToOp {
    fn to_op(&self) -> Op;
}

impl ToOp for String {
    fn to_op(&self) -> Op {
        match self.as_slice() {
            "Bacon+" => Op::Increment,
            "Bacon-" => Op::Decrement,
            "Bacon." => Op::Output,
            "Bacon>" => Op::Right,
            "Bacon<" => Op::Left,
            "Bacon^" => Op::Jump,
            "Bacon?" => Op::JumpBack,
            "Bacon|" => Op::Input,
            _ => Op::Unknown,
        }
    }
}

<|endoftext|>


<commit_before>use node::NodeKind;
use node;
use typing::Type;
use node::{BinOps, CompBinOps};
use closure::{Closure, Prog, FuncDef};

use std::collections::{HashMap, HashSet};

extern crate ordered_float;
use self::ordered_float::OrderedFloat;

use parser::EXTENV;

type ArgsTypes = Vec<Type>;

fn retrieve_var_name(e: &Closure) -> Option<String> {
    if let &Closure::Var(ref name) = e {
        Some(name.clone())
    } else {
        None
    }
}

// TODO: MUST FIX THIS DIRTY CODE!!

pub fn h(f: FuncDef, p: &mut HashMap<String, Vec<ArgsTypes>>) -> Vec<FuncDef> {
    let mut fundefs = Vec::new();
    let (name, ty) = f.name;
    let poly_args = if let Some(a) = p.get(&name).cloned() {
        a
    } else {
        return vec![];
    };
    for pargs in poly_args {
        let mut env = HashMap::new();
        let mut name_mangled = name.clone() + "#";
        let mut actual_params = vec![];
        for (actual_ty, &(ref param_name, _)) in pargs.iter().zip(&f.params.clone()) {
            env.insert(param_name.clone(), actual_ty.clone());
            actual_params.push((param_name.clone(), actual_ty.clone()));
            name_mangled += actual_ty.clone().to_string().as_str();
        }
        let (body, ret_ty) = g(*f.body.clone(), &env, p);
        fundefs.push(FuncDef {
            name: (
                name_mangled,
                Type::Func(
                    actual_params.iter().map(|x| x.1.clone()).collect(),
                    Box::new(ret_ty),
                ),
            ),
            params: actual_params,
            formal_fv: f.formal_fv.clone(),
            body: Box::new(body),
        });
    }
    fundefs
}

pub fn g(
    e: Closure,
    env: &HashMap<String, Type>,
    p: &mut HashMap<String, Vec<ArgsTypes>>,
) -> (Closure, Type) {
    macro_rules! g_seq {
        ($es:expr) => ({
            let mut tys = Vec::new();
            for e in $es { tys.push(g(e, env, p)); }
            tys
        });
    }
    match e {
        Closure::Unit => (e, Type::Unit),
        Closure::Bool(_) => (e, Type::Bool),
        Closure::Int(_) => (e, Type::Int),
        Closure::Float(_) => (e, Type::Float),
        Closure::Var(ref name) => {
            if let Some(ty) = env.get(name.as_str()).cloned() {
                (e.clone(), ty)
            } else {
                panic!()
            }
        }
        Closure::IntBinaryOp(op, lhs, rhs) => {
            (
                Closure::IntBinaryOp(op, Box::new(g(*lhs, env, p).0), Box::new(g(*rhs, env, p).0)),
                Type::Int,
            )
        }
        Closure::LetExpr((name, ty), expr, body) => {
            let mut new_env = env.clone();
            let (expr, expr_ty) = g(*expr, &env, p);
            let ty = if ty.contained_var() { expr_ty } else { ty };
            new_env.insert(name.clone(), ty.clone());
            let (body, body_ty) = g(*body, &new_env, p);
            (
                Closure::LetExpr((name, ty), Box::new(expr), Box::new(body)),
                body_ty,
            )
        }
        Closure::AppCls(callee, args) |
        Closure::AppDir(callee, args) => {
            let name = retrieve_var_name(&*callee).unwrap();
            if EXTENV.lock().unwrap().contains_key(name.as_str()) {
                let args2 = g_seq!(args.clone());
                let mut args = vec![];
                for (e, a) in args2.clone() {
                    args.push(e);
                }
                return (Closure::AppCls(callee, args), Type::Unit);
            }
            let args = g_seq!(args.clone());
            let mut name_mangled = name.clone() + "#";
            let mut args_expr = vec![];
            let mut args_ty = vec![];
            for (e, t) in args.clone() {
                name_mangled += t.to_string().as_str();
                args_expr.push(e);
                args_ty.push(t);
            }
            (*p.entry(name).or_insert(vec![])).push(args_ty);
            (
                Closure::AppCls(Box::new(Closure::Var(name_mangled)), args_expr),
                Type::Unit,
            )
        }
        _ => panic!(),
    }
}

pub fn f(e: Prog) -> Prog {
    let Prog(fundef, expr) = e.clone();
    let mut new_fundef = Vec::new();
    let mut poly_map = HashMap::new();
    let expr = g(expr, &HashMap::new(), &mut poly_map).0;

    for f in fundef {
        new_fundef.extend(h(f, &mut poly_map).iter().cloned());
    }
    Prog(new_fundef, expr)
}

impl Type {
    fn contained_var(&self) -> bool {
        macro_rules! seq {
            ($es:expr) => ({
                for e in $es { if e.contained_var() { return true } }
            });
        }
        match self {
            &Type::Unit | &Type::Char | &Type::Int | &Type::Float => false,
            &Type::Func(ref params_ty, ref ret_ty) => {
                seq!(params_ty);
                ret_ty.contained_var()
            }
            &Type::Var(_) => true,
            _ => panic!(format!("{:?}", self)),
        }
    }
}
<commit_msg>refine code<commit_after>use node::NodeKind;
use node;
use typing::Type;
use node::{BinOps, CompBinOps};
use closure::{Closure, Prog, FuncDef};

use std::collections::{HashMap, HashSet};

extern crate ordered_float;
use self::ordered_float::OrderedFloat;

use parser::EXTENV;

type ArgsTypes = Vec<Type>;

fn retrieve_var_name(e: &Closure) -> Option<String> {
    if let &Closure::Var(ref name) = e {
        Some(name.clone())
    } else {
        None
    }
}

// TODO: MUST FIX THIS DIRTY CODE!!

pub fn h(f: FuncDef, p: &mut HashMap<String, Vec<ArgsTypes>>) -> Vec<FuncDef> {
    let (name, ty) = f.name;
    let args_tys_list = if let Some(args_tys_list) = p.get(&name).cloned() {
        args_tys_list
    } else {
        // the function named 'name' is not a polymorphic function.
        return vec![];
    };

    let mut fundefs = Vec::new();
    for args_tys in args_tys_list {
        let mut env = HashMap::new();
        // TODO: should make a func for mangling.
        let mut name_mangled = name.clone() + "#";
        let mut actual_params = vec![];
        for (actual_ty, &(ref param_name, _)) in args_tys.iter().zip(&f.params.clone()) {
            env.insert(param_name.clone(), actual_ty.clone());
            actual_params.push((param_name.clone(), actual_ty.clone()));
            name_mangled += actual_ty.clone().to_string().as_str();
        }
        let (body, ret_ty) = g(*f.body.clone(), &env, p);
        fundefs.push(FuncDef {
            name: (
                name_mangled,
                Type::Func(
                    actual_params.iter().map(|x| x.1.clone()).collect(),
                    Box::new(ret_ty),
                ),
            ),
            params: actual_params,
            formal_fv: f.formal_fv.clone(),
            body: Box::new(body),
        });
    }
    fundefs
}

pub fn g(
    e: Closure,
    env: &HashMap<String, Type>,
    p: &mut HashMap<String, Vec<ArgsTypes>>,
) -> (Closure, Type) {
    macro_rules! g_seq {
        ($es:expr) => ({
            let mut tys = Vec::new();
            for e in $es { tys.push(g(e, env, p)); }
            tys
        });
    }
    match e {
        Closure::Unit => (e, Type::Unit),
        Closure::Bool(_) => (e, Type::Bool),
        Closure::Int(_) => (e, Type::Int),
        Closure::Float(_) => (e, Type::Float),
        Closure::Var(ref name) => {
            if let Some(ty) = env.get(name.as_str()).cloned() {
                (e.clone(), ty)
            } else {
                panic!()
            }
        }
        Closure::IntBinaryOp(op, lhs, rhs) => {
            (
                Closure::IntBinaryOp(op, Box::new(g(*lhs, env, p).0), Box::new(g(*rhs, env, p).0)),
                Type::Int,
            )
        }
        Closure::LetExpr((name, ty), expr, body) => {
            let mut new_env = env.clone();
            let (expr, expr_ty) = g(*expr, &env, p);
            let ty = if ty.contained_var() { expr_ty } else { ty };
            new_env.insert(name.clone(), ty.clone());
            let (body, body_ty) = g(*body, &new_env, p);
            (
                Closure::LetExpr((name, ty), Box::new(expr), Box::new(body)),
                body_ty,
            )
        }
        Closure::AppCls(callee, args) |
        Closure::AppDir(callee, args) => {
            let name = retrieve_var_name(&*callee).unwrap();
            if EXTENV.lock().unwrap().contains_key(name.as_str()) {
                let args2 = g_seq!(args.clone());
                let mut args = vec![];
                for (e, a) in args2.clone() {
                    args.push(e);
                }
                return (Closure::AppCls(callee, args), Type::Unit);
            }
            let args = g_seq!(args.clone());
            let mut name_mangled = name.clone() + "#";
            let mut args_expr = vec![];
            let mut args_ty = vec![];
            for (e, t) in args.clone() {
                name_mangled += t.to_string().as_str();
                args_expr.push(e);
                args_ty.push(t);
            }
            (*p.entry(name).or_insert(vec![])).push(args_ty);
            (
                Closure::AppCls(Box::new(Closure::Var(name_mangled)), args_expr),
                Type::Unit,
            )
        }
        _ => panic!(),
    }
}

pub fn f(e: Prog) -> Prog {
    let Prog(fundef, expr) = e.clone();
    let mut new_fundef = Vec::new();
    let mut poly_map = HashMap::new();
    let expr = g(expr, &HashMap::new(), &mut poly_map).0;

    for f in fundef {
        new_fundef.extend(h(f, &mut poly_map).iter().cloned());
    }
    Prog(new_fundef, expr)
}

impl Type {
    fn contained_var(&self) -> bool {
        macro_rules! seq {
            ($es:expr) => ({
                for e in $es { if e.contained_var() { return true } }
            });
        }
        match self {
            &Type::Unit | &Type::Char | &Type::Int | &Type::Float => false,
            &Type::Func(ref params_ty, ref ret_ty) => {
                seq!(params_ty);
                ret_ty.contained_var()
            }
            &Type::Var(_) => true,
            _ => panic!(format!("{:?}", self)),
        }
    }
}
<|endoftext|>


<commit_before>use alloc::arc::Arc;
use collections::{BTreeMap, Vec};
use core::{cmp, str};
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::{Mutex, RwLock};

use context;
use syscall::data::Stat;
use syscall::error::*;
use syscall::flag::{MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END};
use syscall::scheme::Scheme;

#[derive(Clone)]
struct Handle {
    data: Arc<Mutex<Vec<u8>>>,
    mode: u16,
    seek: usize
}

pub struct EnvScheme {
    next_id: AtomicUsize,
    handles: RwLock<BTreeMap<usize, Handle>>
}

impl EnvScheme {
    pub fn new() -> EnvScheme {
        EnvScheme {
            next_id: AtomicUsize::new(0),
            handles: RwLock::new(BTreeMap::new())
        }
    }
}

impl Scheme for EnvScheme {
    fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
        let path = str::from_utf8(path).or(Err(Error::new(ENOENT)))?.trim_matches('/');

        let env_lock = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            context.env.clone()
        };

        if path.is_empty() {
            let mut list = Vec::new();
            {
                let env = env_lock.lock();
                for entry in env.iter() {
                    if ! list.is_empty() {
                        list.push(b'\n');
                    }
                    list.extend_from_slice(&entry.0);
                    list.push(b'=');
                    list.extend_from_slice(&entry.1.lock());
                }
            }

            let id = self.next_id.fetch_add(1, Ordering::SeqCst);
            self.handles.write().insert(id, Handle {
                data: Arc::new(Mutex::new(list)),
                mode: MODE_FILE,
                seek: 0
            });

            Ok(id)
        } else {
            let data = {
                let mut env = env_lock.lock();
                if env.contains_key(path.as_bytes()) {
                    env[path.as_bytes()].clone()
                } else /*if flags & O_CREAT == O_CREAT*/ {
                    let name = path.as_bytes().to_vec().into_boxed_slice();
                    let data = Arc::new(Mutex::new(Vec::new()));
                    env.insert(name, data.clone());
                    data
                }
            };

            let id = self.next_id.fetch_add(1, Ordering::SeqCst);
            self.handles.write().insert(id, Handle {
                data: data,
                mode: MODE_FILE,
                seek: 0
            });

            Ok(id)
        }
    }

    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
        let new_handle = {
            let handles = self.handles.read();
            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
            handle.clone()
        };

        let id = self.next_id.fetch_add(1, Ordering::SeqCst);
        self.handles.write().insert(id, new_handle);

        Ok(id)
    }

    fn read(&self, id: usize, buffer: &mut [u8]) -> Result<usize> {
        let mut handles = self.handles.write();
        let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        let data = handle.data.lock();

        let mut i = 0;
        while i < buffer.len() && handle.seek < data.len() {
            buffer[i] = data[handle.seek];
            i += 1;
            handle.seek += 1;
        }

        Ok(i)
    }

    fn write(&self, id: usize, buffer: &[u8]) -> Result<usize> {
        let mut handles = self.handles.write();
        let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        let mut data = handle.data.lock();

        let mut i = 0;
        while i < buffer.len() && handle.seek < data.len() {
            data[handle.seek] = buffer[i];
            i += 1;
            handle.seek += 1;
        }

        while i < buffer.len() {
            data.push(buffer[i]);
            i += 1;
            handle.seek += 1;
        }

        Ok(i)
    }

    fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
        let mut handles = self.handles.write();
        let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        let len = handle.data.lock().len();
        handle.seek = match whence {
            SEEK_SET => cmp::min(len, pos),
            SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.seek as isize + pos as isize)) as usize,
            SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize,
            _ => return Err(Error::new(EINVAL))
        };

        Ok(handle.seek)
    }

    fn fcntl(&self, id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
        let handles = self.handles.read();
        let _handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        Ok(0)
    }

    fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let handles = self.handles.read();
        let _handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        let mut i = 0;
        //TODO: Get env name
        let scheme_path = b"env:";
        while i < buf.len() && i < scheme_path.len() {
            buf[i] = scheme_path[i];
            i += 1;
        }
        Ok(i)
    }

    fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
        let handles = self.handles.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        stat.st_mode = handle.mode;
        stat.st_size = handle.data.lock().len() as u64;

        Ok(0)
    }

    fn fsync(&self, id: usize) -> Result<usize> {
        let handles = self.handles.read();
        let _handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        Ok(0)
    }

    fn ftruncate(&self, id: usize, len: usize) -> Result<usize> {
        let handles = self.handles.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        let mut data = handle.data.lock();
        if len < data.len() {
            data.truncate(len)
        } else {
            while len > data.len() {
                data.push(0);
            }
        }

        Ok(0)
    }

    fn close(&self, id: usize) -> Result<usize> {
        self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0))
    }
}
<commit_msg>Make env: return ENOENT on non-existent; support unlink()<commit_after>use alloc::arc::Arc;
use collections::{BTreeMap, Vec};
use core::{cmp, str};
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::{Mutex, RwLock};

use context;
use syscall::data::Stat;
use syscall::error::*;
use syscall::flag::{MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END, O_CREAT};
use syscall::scheme::Scheme;

#[derive(Clone)]
struct Handle {
    data: Arc<Mutex<Vec<u8>>>,
    mode: u16,
    seek: usize
}

pub struct EnvScheme {
    next_id: AtomicUsize,
    handles: RwLock<BTreeMap<usize, Handle>>
}

impl EnvScheme {
    pub fn new() -> EnvScheme {
        EnvScheme {
            next_id: AtomicUsize::new(0),
            handles: RwLock::new(BTreeMap::new())
        }
    }
}

impl Scheme for EnvScheme {
    fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
        let path = str::from_utf8(path).or(Err(Error::new(ENOENT)))?.trim_matches('/');

        let env_lock = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            context.env.clone()
        };

        if path.is_empty() {
            let mut list = Vec::new();
            {
                let env = env_lock.lock();
                for entry in env.iter() {
                    if ! list.is_empty() {
                        list.push(b'\n');
                    }
                    list.extend_from_slice(&entry.0);
                    list.push(b'=');
                    list.extend_from_slice(&entry.1.lock());
                }
            }

            let id = self.next_id.fetch_add(1, Ordering::SeqCst);
            self.handles.write().insert(id, Handle {
                data: Arc::new(Mutex::new(list)),
                mode: MODE_FILE,
                seek: 0
            });

            Ok(id)
        } else {
            let data = {
                let mut env = env_lock.lock();
                if env.contains_key(path.as_bytes()) {
                    env[path.as_bytes()].clone()
                } else if flags & O_CREAT == O_CREAT {
                    let name = path.as_bytes().to_vec().into_boxed_slice();
                    let data = Arc::new(Mutex::new(Vec::new()));
                    env.insert(name, data.clone());
                    data
                } else {
                    return Err(Error::new(ENOENT));
                }
            };

            let id = self.next_id.fetch_add(1, Ordering::SeqCst);
            self.handles.write().insert(id, Handle {
                data: data,
                mode: MODE_FILE,
                seek: 0
            });

            Ok(id)
        }
    }

    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
        let new_handle = {
            let handles = self.handles.read();
            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
            handle.clone()
        };

        let id = self.next_id.fetch_add(1, Ordering::SeqCst);
        self.handles.write().insert(id, new_handle);

        Ok(id)
    }

    fn read(&self, id: usize, buffer: &mut [u8]) -> Result<usize> {
        let mut handles = self.handles.write();
        let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        let data = handle.data.lock();

        let mut i = 0;
        while i < buffer.len() && handle.seek < data.len() {
            buffer[i] = data[handle.seek];
            i += 1;
            handle.seek += 1;
        }

        Ok(i)
    }

    fn write(&self, id: usize, buffer: &[u8]) -> Result<usize> {
        let mut handles = self.handles.write();
        let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        let mut data = handle.data.lock();

        let mut i = 0;
        while i < buffer.len() && handle.seek < data.len() {
            data[handle.seek] = buffer[i];
            i += 1;
            handle.seek += 1;
        }

        while i < buffer.len() {
            data.push(buffer[i]);
            i += 1;
            handle.seek += 1;
        }

        Ok(i)
    }

    fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
        let mut handles = self.handles.write();
        let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        let len = handle.data.lock().len();
        handle.seek = match whence {
            SEEK_SET => cmp::min(len, pos),
            SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.seek as isize + pos as isize)) as usize,
            SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize,
            _ => return Err(Error::new(EINVAL))
        };

        Ok(handle.seek)
    }

    fn fcntl(&self, id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
        let handles = self.handles.read();
        let _handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        Ok(0)
    }

    fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let handles = self.handles.read();
        let _handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        let mut i = 0;
        //TODO: Get env name
        let scheme_path = b"env:";
        while i < buf.len() && i < scheme_path.len() {
            buf[i] = scheme_path[i];
            i += 1;
        }
        Ok(i)
    }

    fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
        let handles = self.handles.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        stat.st_mode = handle.mode;
        stat.st_size = handle.data.lock().len() as u64;

        Ok(0)
    }

    fn fsync(&self, id: usize) -> Result<usize> {
        let handles = self.handles.read();
        let _handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        Ok(0)
    }

    fn ftruncate(&self, id: usize, len: usize) -> Result<usize> {
        let handles = self.handles.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        let mut data = handle.data.lock();
        if len < data.len() {
            data.truncate(len)
        } else {
            while len > data.len() {
                data.push(0);
            }
        }

        Ok(0)
    }

    fn close(&self, id: usize) -> Result<usize> {
        self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0))
    }

    fn unlink(&self, path: &[u8], uid: u32, _gid: u32) -> Result<usize> {
        let env_lock = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            context.env.clone()
        };

        let mut env = env_lock.lock();

        if let Some(_) = env.remove(path) {
            Ok(0)
        } else {
            Err(Error::new(ENOENT))
        }
    }
}
<|endoftext|>


<commit_before>//! HTTP Server
//!
//! A `Server` is created to listen on a port, parse HTTP requests, and hand
//! them off to a `Service`.
//!
//! There are two levels of APIs provide for constructing HTTP servers:
//!
//! - The higher-level [`Server`](Server) type.
//! - The lower-level [`conn`](conn) module.
//!
//! # Server
//!
//! The [`Server`](Server) is main way to start listening for HTTP requests.
//! It wraps a listener with a [`MakeService`](crate::service), and then should
//! be executed to start serving requests.
//!
//! [`Server`](Server) accepts connections in both HTTP1 and HTTP2 by default.
//!
//! ## Example
//!
//! ```no_run
//! use std::convert::Infallible;
//! use std::net::SocketAddr;
//! use hyper::{Body, Request, Response, Server};
//! use hyper::service::{make_service_fn, service_fn};
//!
//! async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
//!     Ok(Response::new(Body::from("Hello World")))
//! }
//!
//! # #[cfg(feature = "runtime")]
//! #[tokio::main]
//! async fn main() {
//!     // Construct our SocketAddr to listen on...
//!     let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
//!
//!     // And a MakeService to handle each connection...
//!     let make_service = make_service_fn(|_conn| async {
//!         Ok::<_, Infallible>(service_fn(handle))
//!     });
//!
//!     // Then bind and serve...
//!     let server = Server::bind(&addr).serve(make_service);
//!
//!     // And run forever...
//!     if let Err(e) = server.await {
//!         eprintln!("server error: {}", e);
//!     }
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```
//!
//! If you don't need the connection and your service implements `Clone` you can use
//! [`tower::make::Shared`] instead of `make_service_fn` which is a bit simpler:
//!
//! ```no_run
//! # use std::convert::Infallible;
//! # use std::net::SocketAddr;
//! # use hyper::{Body, Request, Response, Server};
//! # use hyper::service::{make_service_fn, service_fn};
//! # use tower::make::Shared;
//! # async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
//! #     Ok(Response::new(Body::from("Hello World")))
//! # }
//! # #[cfg(feature = "runtime")]
//! #[tokio::main]
//! async fn main() {
//!     // Construct our SocketAddr to listen on...
//!     let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
//!
//!     // Shared is a MakeService that produces services by cloning an inner service...
//!     let make_service = Shared::new(service_fn(handle));
//!
//!     // Then bind and serve...
//!     let server = Server::bind(&addr).serve(make_service);
//!
//!     // And run forever...
//!     if let Err(e) = server.await {
//!         eprintln!("server error: {}", e);
//!     }
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```
//!
//! [`tower::make::Shared`]: https://docs.rs/tower/latest/tower/make/struct.Shared.html

pub mod accept;

cfg_feature! {
    #![any(feature = "http1", feature = "http2")]

    pub use self::server::{Builder, Server};

    pub mod conn;
    mod server;
    mod shutdown;

    cfg_feature! {
        #![feature = "tcp"]

        mod tcp;
    }
}
<commit_msg>docs(server): add bigger example to server module (#2539)<commit_after>//! HTTP Server
//!
//! A `Server` is created to listen on a port, parse HTTP requests, and hand
//! them off to a `Service`.
//!
//! There are two levels of APIs provide for constructing HTTP servers:
//!
//! - The higher-level [`Server`](Server) type.
//! - The lower-level [`conn`](conn) module.
//!
//! # Server
//!
//! The [`Server`](Server) is main way to start listening for HTTP requests.
//! It wraps a listener with a [`MakeService`](crate::service), and then should
//! be executed to start serving requests.
//!
//! [`Server`](Server) accepts connections in both HTTP1 and HTTP2 by default.
//!
//! ## Examples
//!
//! ```no_run
//! use std::convert::Infallible;
//! use std::net::SocketAddr;
//! use hyper::{Body, Request, Response, Server};
//! use hyper::service::{make_service_fn, service_fn};
//!
//! async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
//!     Ok(Response::new(Body::from("Hello World")))
//! }
//!
//! # #[cfg(feature = "runtime")]
//! #[tokio::main]
//! async fn main() {
//!     // Construct our SocketAddr to listen on...
//!     let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
//!
//!     // And a MakeService to handle each connection...
//!     let make_service = make_service_fn(|_conn| async {
//!         Ok::<_, Infallible>(service_fn(handle))
//!     });
//!
//!     // Then bind and serve...
//!     let server = Server::bind(&addr).serve(make_service);
//!
//!     // And run forever...
//!     if let Err(e) = server.await {
//!         eprintln!("server error: {}", e);
//!     }
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```
//!
//! If you don't need the connection and your service implements `Clone` you can use
//! [`tower::make::Shared`] instead of `make_service_fn` which is a bit simpler:
//!
//! ```no_run
//! # use std::convert::Infallible;
//! # use std::net::SocketAddr;
//! # use hyper::{Body, Request, Response, Server};
//! # use hyper::service::{make_service_fn, service_fn};
//! # use tower::make::Shared;
//! # async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
//! #     Ok(Response::new(Body::from("Hello World")))
//! # }
//! # #[cfg(feature = "runtime")]
//! #[tokio::main]
//! async fn main() {
//!     // Construct our SocketAddr to listen on...
//!     let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
//!
//!     // Shared is a MakeService that produces services by cloning an inner service...
//!     let make_service = Shared::new(service_fn(handle));
//!
//!     // Then bind and serve...
//!     let server = Server::bind(&addr).serve(make_service);
//!
//!     // And run forever...
//!     if let Err(e) = server.await {
//!         eprintln!("server error: {}", e);
//!     }
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```
//!
//! Passing data to your request handler can be done like so:
//!
//! ```no_run
//! use std::convert::Infallible;
//! use std::net::SocketAddr;
//! use hyper::{Body, Request, Response, Server};
//! use hyper::service::{make_service_fn, service_fn};
//! use hyper::server::conn::AddrStream;
//!
//! #[derive(Clone)]
//! struct AppContext {
//!     // Whatever data your application needs can go here
//! }
//!
//! async fn handle(
//!     context: AppContext,
//!     addr: SocketAddr,
//!     req: Request<Body>
//! ) -> Result<Response<Body>, Infallible> {
//!     Ok(Response::new(Body::from("Hello World")))
//! }
//!
//! # #[cfg(feature = "runtime")]
//! #[tokio::main]
//! async fn main() {
//!     let context = AppContext {
//!         // ...
//!     };
//!
//!     // A `MakeService` that produces a `Service` to handle each connection.
//!     let make_service = make_service_fn(move |conn: &AddrStream| {
//!         // We have to clone the context to share it with each invocation of
//!         // `make_service`. If your data doesn't implement `Clone` consider using
//!         // an `std::sync::Arc`.
//!         let context = context.clone();
//!
//!         // You can grab the address of the incoming connection like so.
//!         let addr = conn.remote_addr();
//!
//!         // Create a `Service` for responding to the request.
//!         let service = service_fn(move |req| {
//!             handle(context.clone(), addr, req)
//!         });
//!
//!         // Return the service to hyper.
//!         async move { Ok::<_, Infallible>(service) }
//!     });
//!
//!     // Run the server like above...
//!     let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
//!
//!     let server = Server::bind(&addr).serve(make_service);
//!
//!     if let Err(e) = server.await {
//!         eprintln!("server error: {}", e);
//!     }
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```
//!
//! [`tower::make::Shared`]: https://docs.rs/tower/latest/tower/make/struct.Shared.html

pub mod accept;

cfg_feature! {
    #![any(feature = "http1", feature = "http2")]

    pub use self::server::{Builder, Server};

    pub mod conn;
    mod server;
    mod shutdown;

    cfg_feature! {
        #![feature = "tcp"]

        mod tcp;
    }
}
<|endoftext|>


<commit_before>mod store;
mod server;
mod connset;
mod server_conn;
mod traffic_cop;

pub use server::server::Server;
pub use server::connset::ConnSet;
pub use server::server_conn::ServerConn;

use std::collections::{BTreeMap};
use std::io::{Error, ErrorKind};
use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::ops::{Add, Sub};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{self, Sender, Receiver};
use std::thread;
use std::usize;

use bytes::{alloc, Buf, ByteBuf, MutByteBuf, SliceBuf};
use mio;
use mio::{EventLoop, EventSet, PollOpt, Handler, Token, TryWrite, TryRead};
use mio::tcp::{TcpListener, TcpStream, TcpSocket};
use mio::util::Slab;
use rand::{Rng, thread_rng};
use rocksdb::{DB, Writable};
use protobuf;
use protobuf::Message;
use time;

pub const SERVER_CLIENTS: Token = Token(0);
pub const SERVER_PEERS: Token = Token(1);
pub const PEER_BROADCAST: Token = Token(usize::MAX);

lazy_static! {
    pub static ref LEADER_DURATION: time::Duration =
        time::Duration::seconds(12);
    pub static ref LEADER_REFRESH: time::Duration =
        time::Duration::seconds(6);
}

pub type TXID = u64;
pub type Term = u64;
pub type PeerID = String;

#[derive(Debug)]
pub struct LogEntry<T> {
    txid: TXID,
    term: Term,
    last_txid: TXID,
    last_term: Term,
    entry: T,
}

#[derive(Debug)]
pub struct Acked<T> {
    acks: Vec<PeerID>,
    inner: T,
}

// Leaders and Followers have an AckedLog for handling replication.
// Leaders have quorums of cluster_sz / 2 + 1, and Followers have
// a quorum of 1 (need a single subsequent ack from leader)
#[derive(Debug)]
pub struct AckedLog<T> {
    pending: BTreeMap<TXID, Acked<LogEntry<T>>>,
    committed: BTreeMap<TXID, LogEntry<T>>,
    quorum: usize,
    last_learned_txid: TXID,
    last_accepted_txid: TXID,
    last_accepted_term: Term,
}

impl<T: Clone> AckedLog<T> {
    pub fn append(&mut self, term: Term, txid: TXID, entry: T) {
        self.pending.insert(txid, Acked{
            acks: vec![],
            inner: LogEntry {
                txid: txid,
                term: term,
                last_txid: self.last_accepted_txid,
                last_term: self.last_accepted_term,
                entry: entry,
            },
        });
        self.last_accepted_txid = txid;
        self.last_accepted_term = term;
    }

    pub fn get(&self, txid: TXID) -> Option<T> {
        self.pending.get(&txid)
            .map(|al| al.inner.entry.clone())
            .or(self.committed.get(&txid).map(|l| l.entry.clone()))
    }

    // Used by leaders to know when they've gotten enough acks.
    // returns a set of txid's that have reached quorum
    pub fn ack_up_to(&mut self, txid: TXID, peer: PeerID) -> Vec<(Term, TXID)> {
        // append ack
        for (txid, ent) in self.pending.iter_mut() {
            if ent.inner.txid <= *txid {
                if !ent.acks.contains(&peer) {
                    ent.acks.push(peer)
                }
                break
            }
        }
        let mut reached_quorum = vec![];
        loop {
            if self.pending.len() == 0 {
                break;
            }
            let txid = self.pending.keys().cloned().next().unwrap();
            if self.pending.get(&txid).unwrap().acks.len() < self.quorum {
                break;
            }
            // TODO(tyler) work out persistence story so we don't lose
            // logs during server crash between remove and push.
            let ent = self.pending.remove(&txid).unwrap();
            self.last_learned_txid = ent.inner.txid;
            reached_quorum.push((ent.inner.term, ent.inner.txid));
            self.committed.insert(txid, ent.inner);
        }
        reached_quorum
    }

    // Used by followers to commit where the leader told them they should
    // be learning up to.
    // returns the set of txids that have reached quorum
    pub fn commit_up_to(&mut self, txid: TXID) -> Vec<(Term, TXID)> {
        let mut reached_quorum = vec![];
        loop {
            if self.pending.len() == 0 {
                break;
            }
            let next_txid = self.pending.keys().cloned().next().unwrap();
            if next_txid > txid {
                break;
            }
            let ent = self.pending.remove(&next_txid).unwrap();

            // TODO(tyler) work out persistence story so we don't lose
            // logs during server crash between remove and push.
            self.last_learned_txid = ent.inner.txid;
            reached_quorum.push((ent.inner.term, ent.inner.txid));
            self.committed.insert(txid, ent.inner);
        }
        reached_quorum
    }
}

pub struct Envelope {
    address: Option<SocketAddr>,
    tok: Token,
    msg: ByteBuf,
}

#[derive(Debug, PartialEq)]
pub struct Peer {
    addr: SocketAddr,
    sock: Option<Token>,
}

#[derive(Debug, PartialEq)]
pub struct RepPeer {
    last_accepted_term: Term,
    last_accepted_txid: TXID,
    max_sent_txid: TXID,
    tok: Token,
    id: PeerID,
    addr: Option<SocketAddr>,
}

#[derive(Debug, Clone)]
enum State {
    Leader {
        term: Term,
        have: Vec<Token>,
        need: u8,
        until: time::Timespec,
    },
    Candidate {
        term: Term,
        have: Vec<Token>,
        need: u8,
        until: time::Timespec,
    },
    Follower {
        term: Term,
        id: PeerID,
        tok: Token,
        leader_addr: SocketAddr,
        until: time::Timespec,
    },
    Init,
}

impl State {
    fn valid_leader(&self) -> bool {
        match *self {
            State::Leader{term:_, have:_, need:_, until: until} =>
                time::now().to_timespec() < until,
            State::Follower{
                term:_, id:_, leader_addr: _, until: until, tok: _
            } =>
                time::now().to_timespec() < until,
            _ => false,
        }
    }

    fn valid_candidate(&self) -> bool {
        match *self {
            State::Candidate{term:_, until: until, have:_, need:_} =>
                time::now().to_timespec() < until,
            _ => false,
        }
    }

    fn is_leader(&self) -> bool {
        match *self {
            State::Leader{term:_, have:_, need:_, until:_} =>
                true,
            _ => false,
        }
    }

    fn is_follower(&self) -> bool {
        match *self {
            State::Follower{term:_, id:_, leader_addr: _, until: _, tok: _} =>
                true,
            _ => false,
        }
    }

    fn is_following(&self, id: PeerID) -> bool {
        match *self {
            State::Follower{
                term:_, id: ref lid, leader_addr: _, until: _, tok: _
            } =>
                *lid == id,
            _ => false,
        }
    }

    fn is_candidate(&self) -> bool {
        match *self {
            State::Candidate{term:_, have:_, need:_, until:_} =>
                true,
            _ => false,
        }
    }

    fn should_extend_leadership(&self) -> bool {
        match *self {
            State::Leader{term:_, have:_, need:_, until: until} => {
                let now = time::now().to_timespec();
                now.add(*LEADER_REFRESH) >= until && now < until
            },
            _ => false,
        }
    }

    fn can_extend_lead(&self) -> bool {
        match *self {
            State::Candidate{term:_, until:_, have: ref have, need: need} =>
                have.len() > need as usize,
            State::Leader{term:_, have: ref have, need: need, until:_} =>
                have.len() > need as usize,
            _ =>
                false,
        }
    }

    fn following(&self, id: PeerID) -> bool {
        match *self {
            State::Follower{
                term:_, id: ref fid, leader_addr: _, until: until, tok: _
            } =>
                id == *fid,
            _ => false,
        }
    }

    fn until(&self) -> Option<time::Timespec> {
        match *self {
            State::Leader{term:_, have:_, need:_, until: until} =>
                Some(until),
            State::Candidate{term:_, until: until, have: _, need: _} =>
                Some(until),
            State::Follower{
                term:_, id:_, leader_addr: _, until: until, tok: _
            } =>
                Some(until),
            _ => None,
        }
    }

    fn term(&self) -> Option<Term> {
        match *self {
            State::Leader{term: term, have:_, need:_, until: _} =>
                Some(term),
            State::Candidate{term: term, until:_, have: _, need: _} =>
                Some(term),
            State::Follower{
                term: term, id:_, leader_addr: _, until: _, tok: _
            } =>
                Some(term),
            _ => None,
        }
    }
}

<commit_msg>remove unnecessary pattern matching<commit_after>mod store;
mod server;
mod connset;
mod server_conn;
mod traffic_cop;

pub use server::server::Server;
pub use server::connset::ConnSet;
pub use server::server_conn::ServerConn;

use std::collections::{BTreeMap};
use std::io::{Error, ErrorKind};
use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::ops::{Add, Sub};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{self, Sender, Receiver};
use std::thread;
use std::usize;

use bytes::{alloc, Buf, ByteBuf, MutByteBuf, SliceBuf};
use mio;
use mio::{EventLoop, EventSet, PollOpt, Handler, Token, TryWrite, TryRead};
use mio::tcp::{TcpListener, TcpStream, TcpSocket};
use mio::util::Slab;
use rand::{Rng, thread_rng};
use rocksdb::{DB, Writable};
use protobuf;
use protobuf::Message;
use time;

pub const SERVER_CLIENTS: Token = Token(0);
pub const SERVER_PEERS: Token = Token(1);
pub const PEER_BROADCAST: Token = Token(usize::MAX);

lazy_static! {
    pub static ref LEADER_DURATION: time::Duration =
        time::Duration::seconds(12);
    pub static ref LEADER_REFRESH: time::Duration =
        time::Duration::seconds(6);
}

pub type TXID = u64;
pub type Term = u64;
pub type PeerID = String;

pub struct PendingReq<T> {
    env: Envelope,
    entry: T,
}

#[derive(Debug)]
pub struct LogEntry<T> {
    txid: TXID,
    term: Term,
    last_txid: TXID,
    last_term: Term,
    entry: T,
}

#[derive(Debug)]
pub struct Acked<T> {
    acks: Vec<PeerID>,
    inner: T,
}

// Leaders and Followers have an AckedLog for handling replication.
// Leaders have quorums of cluster_sz / 2 + 1, and Followers have
// a quorum of 1 (need a single subsequent ack from leader)
#[derive(Debug)]
pub struct AckedLog<T> {
    pending: BTreeMap<TXID, Acked<LogEntry<T>>>,
    committed: BTreeMap<TXID, LogEntry<T>>,
    quorum: usize,
    last_learned_txid: TXID,
    last_accepted_txid: TXID,
    last_accepted_term: Term,
}

impl<T: Clone> AckedLog<T> {
    pub fn append(&mut self, term: Term, txid: TXID, entry: T) {
        self.pending.insert(txid, Acked{
            acks: vec![],
            inner: LogEntry {
                txid: txid,
                term: term,
                last_txid: self.last_accepted_txid,
                last_term: self.last_accepted_term,
                entry: entry,
            },
        });
        self.last_accepted_txid = txid;
        self.last_accepted_term = term;
    }

    pub fn get(&self, txid: TXID) -> Option<T> {
        self.pending.get(&txid)
            .map(|al| al.inner.entry.clone())
            .or(self.committed.get(&txid).map(|l| l.entry.clone()))
    }

    // Used by leaders to know when they've gotten enough acks.
    // returns a set of txid's that have reached quorum
    pub fn ack_up_to(&mut self, txid: TXID, peer: PeerID) -> Vec<(Term, TXID)> {
        // append ack
        for (txid, ent) in self.pending.iter_mut() {
            if ent.inner.txid <= *txid {
                if !ent.acks.contains(&peer) {
                    ent.acks.push(peer)
                }
                break
            }
        }
        let mut reached_quorum = vec![];
        loop {
            if self.pending.len() == 0 {
                break;
            }
            let txid = self.pending.keys().cloned().next().unwrap();
            if self.pending.get(&txid).unwrap().acks.len() < self.quorum {
                break;
            }
            // TODO(tyler) work out persistence story so we don't lose
            // logs during server crash between remove and push.
            let ent = self.pending.remove(&txid).unwrap();
            self.last_learned_txid = ent.inner.txid;
            reached_quorum.push((ent.inner.term, ent.inner.txid));
            self.committed.insert(txid, ent.inner);
        }
        reached_quorum
    }

    // Used by followers to commit where the leader told them they should
    // be learning up to.
    // returns the set of txids that have reached quorum
    pub fn commit_up_to(&mut self, txid: TXID) -> Vec<(Term, TXID)> {
        let mut reached_quorum = vec![];
        loop {
            if self.pending.len() == 0 {
                break;
            }
            let next_txid = self.pending.keys().cloned().next().unwrap();
            if next_txid > txid {
                break;
            }
            let ent = self.pending.remove(&next_txid).unwrap();

            // TODO(tyler) work out persistence story so we don't lose
            // logs during server crash between remove and push.
            self.last_learned_txid = ent.inner.txid;
            reached_quorum.push((ent.inner.term, ent.inner.txid));
            self.committed.insert(txid, ent.inner);
        }
        reached_quorum
    }
}

pub struct Envelope {
    address: Option<SocketAddr>,
    tok: Token,
    msg: ByteBuf,
}

#[derive(Debug, PartialEq)]
pub struct Peer {
    addr: SocketAddr,
    sock: Option<Token>,
}

#[derive(Debug, PartialEq)]
pub struct RepPeer {
    last_accepted_term: Term,
    last_accepted_txid: TXID,
    max_sent_txid: TXID,
    tok: Token,
    id: PeerID,
    addr: Option<SocketAddr>,
}

#[derive(Debug, Clone)]
enum State {
    Leader {
        term: Term,
        have: Vec<Token>,
        need: u8,
        until: time::Timespec,
    },
    Candidate {
        term: Term,
        have: Vec<Token>,
        need: u8,
        until: time::Timespec,
    },
    Follower {
        term: Term,
        id: PeerID,
        tok: Token,
        leader_addr: SocketAddr,
        until: time::Timespec,
    },
    Init,
}

impl State {
    fn valid_leader(&self) -> bool {
        match *self {
            State::Leader{until: until, ..} =>
                time::now().to_timespec() < until,
            State::Follower{
                term:_, id:_, leader_addr: _, until: until, tok: _
            } =>
                time::now().to_timespec() < until,
            _ => false,
        }
    }

    fn valid_candidate(&self) -> bool {
        match *self {
            State::Candidate{until: until, ..} =>
                time::now().to_timespec() < until,
            _ => false,
        }
    }

    fn is_leader(&self) -> bool {
        match *self {
            State::Leader{..} =>
                true,
            _ => false,
        }
    }

    fn is_follower(&self) -> bool {
        match *self {
            State::Follower{..} =>
                true,
            _ => false,
        }
    }

    fn is_following(&self, id: PeerID) -> bool {
        match *self {
            State::Follower{id: ref lid, .. } =>
                *lid == id,
            _ => false,
        }
    }

    fn is_candidate(&self) -> bool {
        match *self {
            State::Candidate{..} =>
                true,
            _ => false,
        }
    }

    fn should_extend_leadership(&self) -> bool {
        match *self {
            State::Leader{until: until, ..} => {
                let now = time::now().to_timespec();
                now.add(*LEADER_REFRESH) >= until && now < until
            },
            _ => false,
        }
    }

    fn can_extend_lead(&self) -> bool {
        match *self {
            State::Candidate{have: ref have, need: need, ..} =>
                have.len() > need as usize,
            State::Leader{have: ref have, need: need, ..} =>
                have.len() > need as usize,
            _ =>
                false,
        }
    }

    fn following(&self, id: PeerID) -> bool {
        match *self {
            State::Follower{id: ref fid, until: until, .. } =>
                id == *fid,
            _ => false,
        }
    }

    fn until(&self) -> Option<time::Timespec> {
        match *self {
            State::Leader{until: until, ..} =>
                Some(until),
            State::Candidate{until: until, ..} =>
                Some(until),
            State::Follower{ until: until, .. } =>
                Some(until),
            _ => None,
        }
    }

    fn term(&self) -> Option<Term> {
        match *self {
            State::Leader{term: term, ..} =>
                Some(term),
            State::Candidate{term: term, ..} =>
                Some(term),
            State::Follower{term: term, .. } =>
                Some(term),
            _ => None,
        }
    }
}

<|endoftext|>


<commit_before>use std::io::Read;

use itertools::Itertools;

use crate::common::ordered;

fn compute_groups<'a>(it: impl IntoIterator<Item = &'a usize>) -> Vec<(usize, usize)> {
    let mut it = it.into_iter().copied().dedup_with_count();

    let (mut population, mut last_pos) = it.next().unwrap();
    let mut last_cost = 0;

    let mut costs = vec![(last_pos, 0)];

    for (number, pos) in it {
        let (first, last) = ordered(last_pos, pos);
        let new_cost = last_cost + population * (last - first);

        costs.push((pos, new_cost));

        population += number;
        last_pos = pos;
        last_cost = new_cost;
    }

    costs
}

fn read_input(input: &mut dyn Read) -> Vec<usize> {
    let mut buf = String::new();
    input.read_to_string(&mut buf).unwrap();

    let mut crabs: Vec<usize> = buf
        .trim_end()
        .split(',')
        .map(|s| s.parse().unwrap())
        .collect();

    crabs.sort_unstable();

    crabs
}

pub fn part1(input: &mut dyn Read) -> String {
    let crabs = read_input(input);

    let forward_costs = compute_groups(&crabs);
    let backwards_costs = compute_groups(crabs.iter().rev());

    backwards_costs
        .into_iter()
        .rev()
        .zip(forward_costs)
        .map(|((pos_b, cost_b), (pos_f, cost_f))| {
            debug_assert_eq!(pos_f, pos_b);

            cost_f + cost_b
        })
        .min()
        .unwrap()
        .to_string()
}

pub fn sum_until(end: usize) -> usize {
    (end * (1 + end)) / 2
}

fn cost_at(pos: usize, groups: &[(usize, usize)]) -> usize {
    groups
        .iter()
        .map(|&(number, new_pos)| {
            let (first, last) = ordered(pos, new_pos);

            number * sum_until(last - first)
        })
        .sum()
}

pub fn part2(input: &mut dyn Read) -> String {
    let crabs = read_input(input);
    let groups: Vec<_> = crabs.into_iter().dedup_with_count().collect();

    let min = groups.first().unwrap().1;
    let max = groups.last().unwrap().1;

    // Brute force approach, better version later
    (min..=max)
        .map(|pos| cost_at(pos, &groups))
        .min()
        .unwrap()
        .to_string()
}

#[cfg(test)]
mod tests {
    use crate::test_implementation;

    use super::*;

    const SAMPLE: &[u8] = &*b"16,1,2,0,4,2,7,1,2,14";

    #[test]
    fn sample_part1() {
        test_implementation(part1, SAMPLE, 37);
    }

    #[test]
    fn sample_part2() {
        test_implementation(part2, SAMPLE, 168);
    }

    #[test]
    fn test_maths() {
        assert_eq!(sum_until(1), 1);
        assert_eq!(sum_until(2), 3);
        assert_eq!(sum_until(3), 6);
        assert_eq!(sum_until(4), 10);
    }
}
<commit_msg>Improve part 2 with binary search<commit_after>use std::io::Read;

use itertools::Itertools;

use crate::common::ordered;

fn compute_groups<'a>(it: impl IntoIterator<Item = &'a usize>) -> Vec<(usize, usize)> {
    let mut it = it.into_iter().copied().dedup_with_count();

    let (mut population, mut last_pos) = it.next().unwrap();
    let mut last_cost = 0;

    let mut costs = vec![(last_pos, 0)];

    for (number, pos) in it {
        let (first, last) = ordered(last_pos, pos);
        let new_cost = last_cost + population * (last - first);

        costs.push((pos, new_cost));

        population += number;
        last_pos = pos;
        last_cost = new_cost;
    }

    costs
}

fn read_input(input: &mut dyn Read) -> Vec<usize> {
    let mut buf = String::new();
    input.read_to_string(&mut buf).unwrap();

    let mut crabs: Vec<usize> = buf
        .trim_end()
        .split(',')
        .map(|s| s.parse().unwrap())
        .collect();

    crabs.sort_unstable();

    crabs
}

pub fn part1(input: &mut dyn Read) -> String {
    let crabs = read_input(input);

    let forward_costs = compute_groups(&crabs);
    let backwards_costs = compute_groups(crabs.iter().rev());

    backwards_costs
        .into_iter()
        .rev()
        .zip(forward_costs)
        .map(|((pos_b, cost_b), (pos_f, cost_f))| {
            debug_assert_eq!(pos_f, pos_b);

            cost_f + cost_b
        })
        .min()
        .unwrap()
        .to_string()
}

pub fn sum_until(end: usize) -> usize {
    (end * (1 + end)) / 2
}

fn cost_at(pos: usize, groups: &[(usize, usize)]) -> usize {
    groups
        .iter()
        .map(|&(number, new_pos)| {
            let (first, last) = ordered(pos, new_pos);

            number * sum_until(last - first)
        })
        .sum()
}

fn ternary_search(groups: &[(usize, usize)], min: usize, max: usize) -> usize {
    if max - min <= 6 {
        // ternary search isn't effective in small ranges, just iterate instead.
        (min..=max).map(|pos| cost_at(pos, groups)).min().unwrap()
    } else {
        let mid1 = min + (max - min) / 3;
        let mid2 = max - (max - min) / 3;

        let cost1 = cost_at(mid1, groups);
        let cost2 = cost_at(mid2, groups);

        if cost1 < cost2 {
            ternary_search(groups, min, mid2 - 1)
        } else {
            ternary_search(groups, mid1 + 1, max)
        }
    }
}

pub fn part2(input: &mut dyn Read) -> String {
    let crabs = read_input(input);
    let groups: Vec<_> = crabs.into_iter().dedup_with_count().collect();

    let min = groups.first().unwrap().1;
    let max = groups.last().unwrap().1;

    // Brute force approach, better version later
    ternary_search(&groups, min, max).to_string()
}

#[cfg(test)]
mod tests {
    use crate::test_implementation;

    use super::*;

    const SAMPLE: &[u8] = &*b"16,1,2,0,4,2,7,1,2,14";

    #[test]
    fn sample_part1() {
        test_implementation(part1, SAMPLE, 37);
    }

    #[test]
    fn sample_part2() {
        test_implementation(part2, SAMPLE, 168);
    }

    #[test]
    fn test_maths() {
        assert_eq!(sum_until(1), 1);
        assert_eq!(sum_until(2), 3);
        assert_eq!(sum_until(3), 6);
        assert_eq!(sum_until(4), 10);
    }
}
<|endoftext|>


<commit_before>extern crate chrono;

use postgres_protocol::types;
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC, Local,
                   FixedOffset};
use std::error::Error;

use types::{FromSql, ToSql, IsNull, Type};

fn base() -> NaiveDateTime {
    NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0)
}

impl FromSql for NaiveDateTime {
    fn from_sql(_: &Type,
                raw: &[u8])
                -> Result<NaiveDateTime, Box<Error + Sync + Send>> {
        let t = try!(types::timestamp_from_sql(raw));
        Ok(base() + Duration::microseconds(t))
    }

    accepts!(Type::Timestamp);
}

impl ToSql for NaiveDateTime {
    fn to_sql(&self,
              _: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        let time = match self.signed_duration_since(base()).num_microseconds() {
            Some(time) => time,
            None => return Err("value too large to transmit".into()),
        };
        types::timestamp_to_sql(time, w);
        Ok(IsNull::No)
    }

    accepts!(Type::Timestamp);
    to_sql_checked!();
}

impl FromSql for DateTime<UTC> {
    fn from_sql(type_: &Type,
                raw: &[u8])
                -> Result<DateTime<UTC>, Box<Error + Sync + Send>> {
        let naive = try!(NaiveDateTime::from_sql(type_, raw, info));
        Ok(DateTime::from_utc(naive, UTC))
    }

    accepts!(Type::Timestamptz);
}

impl ToSql for DateTime<UTC> {
    fn to_sql(&self,
              type_: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        self.naive_utc().to_sql(type_, w, info)
    }

    accepts!(Type::Timestamptz);
    to_sql_checked!();
}

impl FromSql for DateTime<Local> {
    fn from_sql(type_: &Type,
                raw: &[u8])
                -> Result<DateTime<Local>, Box<Error + Sync + Send>> {
        let utc = try!(DateTime::<UTC>::from_sql(type_, raw, info));
        Ok(utc.with_timezone(&Local))
    }

    accepts!(Type::Timestamptz);
}

impl ToSql for DateTime<Local> {
    fn to_sql(&self,
              type_: &Type,
              mut w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        self.with_timezone(&UTC).to_sql(type_, w, info)
    }

    accepts!(Type::Timestamptz);
    to_sql_checked!();
}

impl FromSql for DateTime<FixedOffset> {
    fn from_sql(type_: &Type,
                raw: &[u8])
                -> Result<DateTime<FixedOffset>, Box<Error + Sync + Send>> {
        let utc = try!(DateTime::<UTC>::from_sql(type_, raw, info));
        Ok(utc.with_timezone(&FixedOffset::east(0)))
    }

    accepts!(Type::Timestamptz);
}

impl ToSql for DateTime<FixedOffset> {
    fn to_sql(&self,
              type_: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        self.with_timezone(&UTC).to_sql(type_, w, info)
    }

    accepts!(Type::Timestamptz);
    to_sql_checked!();
}

impl FromSql for NaiveDate {
    fn from_sql(_: &Type,
                raw: &[u8])
                -> Result<NaiveDate, Box<Error + Sync + Send>> {
        let jd = try!(types::date_from_sql(raw));
        Ok(base().date() + Duration::days(jd as i64))
    }

    accepts!(Type::Date);
}

impl ToSql for NaiveDate {
    fn to_sql(&self,
              _: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        let jd = self.signed_duration_since(base().date()).num_days();
        if jd > i32::max_value() as i64 || jd < i32::min_value() as i64 {
            return Err("value too large to transmit".into());
        }

        types::date_to_sql(jd as i32, w);
        Ok(IsNull::No)
    }

    accepts!(Type::Date);
    to_sql_checked!();
}

impl FromSql for NaiveTime {
    fn from_sql(_: &Type,
                raw: &[u8])
                -> Result<NaiveTime, Box<Error + Sync + Send>> {
        let usec = try!(types::time_from_sql(raw));
        Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(usec))
    }

    accepts!(Type::Time);
}

impl ToSql for NaiveTime {
    fn to_sql(&self,
              _: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        let delta = self.signed_duration_since(NaiveTime::from_hms(0, 0, 0));
        let time = match delta.num_microseconds() {
            Some(time) => time,
            None => return Err("value too large to transmit".into()),
        };
        types::time_to_sql(time, w);
        Ok(IsNull::No)
    }

    accepts!(Type::Time);
    to_sql_checked!();
}
<commit_msg>Fix build<commit_after>extern crate chrono;

use postgres_protocol::types;
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC, Local,
                   FixedOffset};
use std::error::Error;

use types::{FromSql, ToSql, IsNull, Type};

fn base() -> NaiveDateTime {
    NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0)
}

impl FromSql for NaiveDateTime {
    fn from_sql(_: &Type,
                raw: &[u8])
                -> Result<NaiveDateTime, Box<Error + Sync + Send>> {
        let t = try!(types::timestamp_from_sql(raw));
        Ok(base() + Duration::microseconds(t))
    }

    accepts!(Type::Timestamp);
}

impl ToSql for NaiveDateTime {
    fn to_sql(&self,
              _: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        let time = match self.signed_duration_since(base()).num_microseconds() {
            Some(time) => time,
            None => return Err("value too large to transmit".into()),
        };
        types::timestamp_to_sql(time, w);
        Ok(IsNull::No)
    }

    accepts!(Type::Timestamp);
    to_sql_checked!();
}

impl FromSql for DateTime<UTC> {
    fn from_sql(type_: &Type,
                raw: &[u8])
                -> Result<DateTime<UTC>, Box<Error + Sync + Send>> {
        let naive = try!(NaiveDateTime::from_sql(type_, raw));
        Ok(DateTime::from_utc(naive, UTC))
    }

    accepts!(Type::Timestamptz);
}

impl ToSql for DateTime<UTC> {
    fn to_sql(&self,
              type_: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        self.naive_utc().to_sql(type_, w)
    }

    accepts!(Type::Timestamptz);
    to_sql_checked!();
}

impl FromSql for DateTime<Local> {
    fn from_sql(type_: &Type,
                raw: &[u8])
                -> Result<DateTime<Local>, Box<Error + Sync + Send>> {
        let utc = try!(DateTime::<UTC>::from_sql(type_, raw));
        Ok(utc.with_timezone(&Local))
    }

    accepts!(Type::Timestamptz);
}

impl ToSql for DateTime<Local> {
    fn to_sql(&self,
              type_: &Type,
              mut w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        self.with_timezone(&UTC).to_sql(type_, w)
    }

    accepts!(Type::Timestamptz);
    to_sql_checked!();
}

impl FromSql for DateTime<FixedOffset> {
    fn from_sql(type_: &Type,
                raw: &[u8])
                -> Result<DateTime<FixedOffset>, Box<Error + Sync + Send>> {
        let utc = try!(DateTime::<UTC>::from_sql(type_, raw));
        Ok(utc.with_timezone(&FixedOffset::east(0)))
    }

    accepts!(Type::Timestamptz);
}

impl ToSql for DateTime<FixedOffset> {
    fn to_sql(&self,
              type_: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        self.with_timezone(&UTC).to_sql(type_, w)
    }

    accepts!(Type::Timestamptz);
    to_sql_checked!();
}

impl FromSql for NaiveDate {
    fn from_sql(_: &Type,
                raw: &[u8])
                -> Result<NaiveDate, Box<Error + Sync + Send>> {
        let jd = try!(types::date_from_sql(raw));
        Ok(base().date() + Duration::days(jd as i64))
    }

    accepts!(Type::Date);
}

impl ToSql for NaiveDate {
    fn to_sql(&self,
              _: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        let jd = self.signed_duration_since(base().date()).num_days();
        if jd > i32::max_value() as i64 || jd < i32::min_value() as i64 {
            return Err("value too large to transmit".into());
        }

        types::date_to_sql(jd as i32, w);
        Ok(IsNull::No)
    }

    accepts!(Type::Date);
    to_sql_checked!();
}

impl FromSql for NaiveTime {
    fn from_sql(_: &Type,
                raw: &[u8])
                -> Result<NaiveTime, Box<Error + Sync + Send>> {
        let usec = try!(types::time_from_sql(raw));
        Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(usec))
    }

    accepts!(Type::Time);
}

impl ToSql for NaiveTime {
    fn to_sql(&self,
              _: &Type,
              w: &mut Vec<u8>)
              -> Result<IsNull, Box<Error + Sync + Send>> {
        let delta = self.signed_duration_since(NaiveTime::from_hms(0, 0, 0));
        let time = match delta.num_microseconds() {
            Some(time) => time,
            None => return Err("value too large to transmit".into()),
        };
        types::time_to_sql(time, w);
        Ok(IsNull::No)
    }

    accepts!(Type::Time);
    to_sql_checked!();
}
<|endoftext|>