<commit_before>// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax::abi::{Abi};
use syntax::ast;

use rustc::ty::{self, TyCtxt};
use rustc::mir::repr::{self, Mir};

use bitslice::BitSlice;

use super::super::gather_moves::MovePath;
use super::{bitwise, Union, Subtract};
use super::BitDenotation;
use super::DataflowResults;
use super::HasMoveData;

pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                mir: &Mir<'tcx>,
                                                id: ast::NodeId,
                                                _attributes: &[ast::Attribute],
                                                flow_ctxt: &O::Ctxt,
                                                results: &DataflowResults<O>)
    where O: BitDenotation<Bit=MovePath<'tcx>>, O::Ctxt: HasMoveData<'tcx>
{
    debug!("sanity_check_via_rustc_peek id: {:?}", id);
    // FIXME: this is not DRY. Figure out way to abstract this and
    // `dataflow::build_sets`. (But see note below about how the
    // behavior of this traversal is a bit different than that
    // performed by `build_sets`.)

    let blocks = mir.all_basic_blocks();
    'next_block: for bb in blocks {
        let bb_data = mir.basic_block_data(bb);
        let &repr::BasicBlockData { ref statements,
                                    ref terminator,
                                    is_cleanup: _ } = bb_data;

        let (args, span) = if let Some(repr::Terminator { ref kind, span, .. }) = *terminator {
            if let repr::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind
            {
                if let repr::Operand::Constant(ref func) = *oper
                {
                    if let ty::TyFnDef(def_id, _, &ty::BareFnTy { abi, .. }) = func.ty.sty
                    {
                        let name = tcx.item_name(def_id);
                        if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
                            if name.as_str() == "rustc_peek" {
                                (args, span)
                            } else {
                                continue;
                            }
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                } else {
                    continue;
                }
            } else {
                continue;
            }
        } else {
            continue;
        };
        assert!(args.len() == 1);
        let peek_arg_lval = match args[0] {
            repr::Operand::Consume(ref lval @ repr::Lvalue::Temp(_)) => {
                lval
            }
            repr::Operand::Consume(_) => {
                bug!("dataflow::sanity_check cannot feed a non-temp to rustc_peek.");
            }
            repr::Operand::Constant(_) => {
                bug!("dataflow::sanity_check cannot feed a constant to rustc_peek.");
            }
        };

        let mut entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
        let mut gen = results.0.sets.gen_set_for(bb.index()).to_owned();
        let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned();

        let move_data = flow_ctxt.move_data();

        // Emulate effect of all statements in the block up to (but
        // not including) the assignment to `peek_arg_lval`. Do *not*
        // include terminator (since we are peeking the state of the
        // argument at time immediate preceding Call to `rustc_peek`).

        let mut sets = super::BlockSets { on_entry: &mut entry[..],
                                          gen_set: &mut gen[..],
                                          kill_set: &mut kill[..] };
        // Unfortunately if we just re-do the same thing that dataflow does, then
        // it will always appear like Lvalues are initialized; e.g. in
        // a case like:
        //
        // <bitset maps var1 to 0>
        // tmp13 = var1;
        // tmp14 = &tmp13;
        // rustc_peek(tmp14)
        //
        // The gen_set for normal dataflow would treat tmp13 as
        // initialized, even though it's source expression is
        // uninitialized.
        //
        // Work around this for rustc_peek by explicitly propagating
        // the relevant bitvector state when computing the effect of a
        // statement.

        for (j, stmt) in statements.iter().enumerate() {
            debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
            let (lvalue, rvalue) = match stmt.kind {
                repr::StatementKind::Assign(ref lvalue, ref rvalue) => {
                    (lvalue, rvalue)
                }
            };

            if lvalue == peek_arg_lval {
                if let repr::Rvalue::Ref(_,
                                         repr::BorrowKind::Shared,
                                         ref peeking_at_lval) = *rvalue {
                    // Okay, our search is over.
                    let peek_mpi = move_data.rev_lookup.find(peeking_at_lval);
                    let bit_state = sets.on_entry.get_bit(peek_mpi.idx());
                    debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
                           lvalue, peeking_at_lval, bit_state);
                    if !bit_state {
                        tcx.sess.span_err(span, &format!("rustc_peek: bit not set"));
                    }
                    continue 'next_block;
                } else {
                    // Our search should have been over, but the input
                    // does not match expectations of `rustc_peek` for
                    // this sanity_check.
                    tcx.sess.span_err(span, &format!("rustc_peek: argument expression \
                                                      must be immediate borrow of form `&expr`"));
                }
            }

            enum Effect<'a, 'tcx:'a> { Propagate(&'a repr::Lvalue<'tcx>), Compute }
            let lvalue_effect: Effect = match *rvalue {
                // tmp = rhs
                repr::Rvalue::Use(repr::Operand::Consume(ref rhs_lval)) =>
                    Effect::Propagate(rhs_lval),

                repr::Rvalue::Use(repr::Operand::Constant(_)) =>
                    Effect::Compute,

                _ => {
                    // (fall back to BitDenotation for all other kinds of Rvalues
                    Effect::Compute
                }
            };

            let lhs_mpi = move_data.rev_lookup.find(lvalue);

            if let Effect::Propagate(rhs_lval) = lvalue_effect {
                let rhs_mpi = move_data.rev_lookup.find(rhs_lval);
                let state = sets.on_entry.get_bit(rhs_mpi.idx());
                debug!("rustc_peek: propagate into lvalue {:?} ({:?}) from rhs: {:?} state: {}",
                       lvalue, lhs_mpi, rhs_lval, state);
                if state {
                    sets.on_entry.set_bit(lhs_mpi.idx());
                } else {
                    sets.on_entry.clear_bit(lhs_mpi.idx());
                }
            } else {
                debug!("rustc_peek: computing effect on lvalue: {:?} ({:?}) in stmt: {:?}",
                       lvalue, lhs_mpi, stmt);
                // reset GEN and KILL sets before emulating their effect.
                for e in &mut sets.gen_set[..] { *e = 0; }
                for e in &mut sets.kill_set[..] { *e = 0; }
                results.0.operator.statement_effect(flow_ctxt, &mut sets, bb, j);
                bitwise(sets.on_entry, sets.gen_set, &Union);
                bitwise(sets.on_entry, sets.kill_set, &Subtract);
            }
        }

        tcx.sess.span_err(span, &format!("rustc_peek: MIR did not match \
                                          anticipated pattern; note that \
                                          rustc_peek expects input of \
                                          form `&expr`"));
    }
}
<commit_msg>Fix comments in `mir::dataflow::sanity_check`.<commit_after>// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax::abi::{Abi};
use syntax::ast;

use rustc::ty::{self, TyCtxt};
use rustc::mir::repr::{self, Mir};

use bitslice::BitSlice;

use super::super::gather_moves::MovePath;
use super::{bitwise, Union, Subtract};
use super::BitDenotation;
use super::DataflowResults;
use super::HasMoveData;

/// This function scans `mir` for all calls to the intrinsic
/// `rustc_peek` that have the expression form `rustc_peek(&expr)`.
///
/// For each such call, determines what the dataflow bit-state is for
/// the L-value corresponding to `expr`; if the bit-state is a 1, then
/// that call to `rustc_peek` is ignored by the sanity check. If the
/// bit-state is a 0, then this pass emits a error message saying
/// "rustc_peek: bit not set".
///
/// The intention is that one can write unit tests for dataflow by
/// putting code into a compile-fail test and using `rustc_peek` to
/// make observations about the results of dataflow static analyses.
///
/// (If there are any calls to `rustc_peek` that do not match the
/// expression form above, then that emits an error as well, but those
/// errors are not intended to be used for unit tests.)
pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                mir: &Mir<'tcx>,
                                                id: ast::NodeId,
                                                _attributes: &[ast::Attribute],
                                                flow_ctxt: &O::Ctxt,
                                                results: &DataflowResults<O>)
    where O: BitDenotation<Bit=MovePath<'tcx>>, O::Ctxt: HasMoveData<'tcx>
{
    debug!("sanity_check_via_rustc_peek id: {:?}", id);
    // FIXME: this is not DRY. Figure out way to abstract this and
    // `dataflow::build_sets`. (But note it is doing non-standard
    // stuff, so such generalization may not be realistic.)

    let blocks = mir.all_basic_blocks();
    'next_block: for bb in blocks {
        let bb_data = mir.basic_block_data(bb);
        let &repr::BasicBlockData { ref statements,
                                    ref terminator,
                                    is_cleanup: _ } = bb_data;

        let (args, span) = if let Some(repr::Terminator { ref kind, span, .. }) = *terminator {
            if let repr::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind
            {
                if let repr::Operand::Constant(ref func) = *oper
                {
                    if let ty::TyFnDef(def_id, _, &ty::BareFnTy { abi, .. }) = func.ty.sty
                    {
                        let name = tcx.item_name(def_id);
                        if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
                            if name.as_str() == "rustc_peek" {
                                (args, span)
                            } else {
                                continue;
                            }
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                } else {
                    continue;
                }
            } else {
                continue;
            }
        } else {
            continue;
        };
        assert!(args.len() == 1);
        let peek_arg_lval = match args[0] {
            repr::Operand::Consume(ref lval @ repr::Lvalue::Temp(_)) => {
                lval
            }
            repr::Operand::Consume(_) => {
                bug!("dataflow::sanity_check cannot feed a non-temp to rustc_peek.");
            }
            repr::Operand::Constant(_) => {
                bug!("dataflow::sanity_check cannot feed a constant to rustc_peek.");
            }
        };

        let mut entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
        let mut gen = results.0.sets.gen_set_for(bb.index()).to_owned();
        let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned();

        let move_data = flow_ctxt.move_data();

        // Emulate effect of all statements in the block up to (but
        // not including) the assignment to `peek_arg_lval`. Do *not*
        // include terminator (since we are peeking the state of the
        // argument at time immediate preceding Call to `rustc_peek`).

        let mut sets = super::BlockSets { on_entry: &mut entry[..],
                                          gen_set: &mut gen[..],
                                          kill_set: &mut kill[..] };

        for (j, stmt) in statements.iter().enumerate() {
            debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
            let (lvalue, rvalue) = match stmt.kind {
                repr::StatementKind::Assign(ref lvalue, ref rvalue) => {
                    (lvalue, rvalue)
                }
            };

            if lvalue == peek_arg_lval {
                if let repr::Rvalue::Ref(_,
                                         repr::BorrowKind::Shared,
                                         ref peeking_at_lval) = *rvalue {
                    // Okay, our search is over.
                    let peek_mpi = move_data.rev_lookup.find(peeking_at_lval);
                    let bit_state = sets.on_entry.get_bit(peek_mpi.idx());
                    debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
                           lvalue, peeking_at_lval, bit_state);
                    if !bit_state {
                        tcx.sess.span_err(span, &format!("rustc_peek: bit not set"));
                    }
                    continue 'next_block;
                } else {
                    // Our search should have been over, but the input
                    // does not match expectations of `rustc_peek` for
                    // this sanity_check.
                    tcx.sess.span_err(span, &format!("rustc_peek: argument expression \
                                                      must be immediate borrow of form `&expr`"));
                }
            }

            enum Effect<'a, 'tcx:'a> { Propagate(&'a repr::Lvalue<'tcx>), Compute }
            let lvalue_effect: Effect = match *rvalue {
                // tmp = rhs
                repr::Rvalue::Use(repr::Operand::Consume(ref rhs_lval)) =>
                    Effect::Propagate(rhs_lval),

                repr::Rvalue::Use(repr::Operand::Constant(_)) =>
                    Effect::Compute,

                _ => {
                    // (fall back to BitDenotation for all other kinds of Rvalues
                    Effect::Compute
                }
            };

            let lhs_mpi = move_data.rev_lookup.find(lvalue);

            if let Effect::Propagate(rhs_lval) = lvalue_effect {
                let rhs_mpi = move_data.rev_lookup.find(rhs_lval);
                let state = sets.on_entry.get_bit(rhs_mpi.idx());
                debug!("rustc_peek: propagate into lvalue {:?} ({:?}) from rhs: {:?} state: {}",
                       lvalue, lhs_mpi, rhs_lval, state);
                if state {
                    sets.on_entry.set_bit(lhs_mpi.idx());
                } else {
                    sets.on_entry.clear_bit(lhs_mpi.idx());
                }
            } else {
                debug!("rustc_peek: computing effect on lvalue: {:?} ({:?}) in stmt: {:?}",
                       lvalue, lhs_mpi, stmt);
                // reset GEN and KILL sets before emulating their effect.
                for e in &mut sets.gen_set[..] { *e = 0; }
                for e in &mut sets.kill_set[..] { *e = 0; }
                results.0.operator.statement_effect(flow_ctxt, &mut sets, bb, j);
                bitwise(sets.on_entry, sets.gen_set, &Union);
                bitwise(sets.on_entry, sets.kill_set, &Subtract);
            }
        }

        tcx.sess.span_err(span, &format!("rustc_peek: MIR did not match \
                                          anticipated pattern; note that \
                                          rustc_peek expects input of \
                                          form `&expr`"));
    }
}
<|endoftext|>


<commit_before>use crate::{
    cluster::Cluster,
    health::{Commit, Event, LogTail, ValidatorEvent},
    instance::Instance,
    util::unix_timestamp_now,
};
use debug_interface::{
    self,
    proto::{
        node_debug_interface::{Event as DebugInterfaceEvent, GetEventsRequest},
        node_debug_interface_grpc::NodeDebugInterfaceClient,
    },
};
use grpcio::{self, ChannelBuilder, EnvBuilder};
use serde_json::{self, value as json};
use std::{
    env,
    sync::{atomic::AtomicI64, mpsc, Arc},
    thread,
    time::Duration,
};

pub struct DebugPortLogThread {
    instance: Instance,
    client: NodeDebugInterfaceClient,
    event_sender: mpsc::Sender<ValidatorEvent>,
}

impl DebugPortLogThread {
    pub fn spawn_new(cluster: &Cluster) -> LogTail {
        let (event_sender, event_receiver) = mpsc::channel();
        let env = Arc::new(EnvBuilder::new().name_prefix("grpc-log-tail-").build());
        for instance in cluster.instances() {
            let ch =
                ChannelBuilder::new(env.clone()).connect(&format!("{}:{}", instance.ip(), 6191));
            let client = NodeDebugInterfaceClient::new(ch);
            let debug_port_log_thread = DebugPortLogThread {
                instance: instance.clone(),
                client,
                event_sender: event_sender.clone(),
            };
            thread::Builder::new()
                .name(format!("log-tail-{}", instance.short_hash()))
                .spawn(move || debug_port_log_thread.run())
                .expect("Failed to spawn log tail thread");
        }
        LogTail {
            event_receiver,
            pending_messages: Arc::new(AtomicI64::new(0)),
        }
    }
}

impl DebugPortLogThread {
    pub fn run(self) {
        let print_failures = env::var("VERBOSE").is_ok();
        loop {
            let opts = grpcio::CallOption::default().timeout(Duration::from_secs(5));
            match self.client.get_events_opt(&GetEventsRequest::new(), opts) {
                Err(e) => {
                    if print_failures {
                        println!("Failed to get events from {}: {:?}", self.instance, e);
                    }
                    thread::sleep(Duration::from_secs(1));
                }
                Ok(resp) => {
                    for event in resp.events.into_iter() {
                        if let Some(e) = self.parse_event(event) {
                            let _ignore = self.event_sender.send(e);
                        }
                    }
                    thread::sleep(Duration::from_millis(200));
                }
            }
        }
    }

    fn parse_event(&self, event: DebugInterfaceEvent) -> Option<ValidatorEvent> {
        let json: json::Value =
            serde_json::from_str(&event.json).expect("Failed to parse json from debug interface");

        let e = if event.name == "committed" {
            Self::parse_commit(json)
        } else {
            println!("Unknown event: {} from {}", event.name, self.instance);
            return None;
        };
        Some(ValidatorEvent {
            validator: self.instance.short_hash().clone(),
            timestamp: Duration::from_millis(event.get_timestamp() as u64),
            received_timestamp: unix_timestamp_now(),
            event: e,
        })
    }

    fn parse_commit(json: json::Value) -> Event {
        Event::Commit(Commit {
            commit: json
                .get("block_id")
                .expect("No block_id in commit event")
                .as_str()
                .expect("block_id is not string")
                .to_string(),
            round: json
                .get("round")
                .expect("No round in commit event")
                .as_u64()
                .expect("round is not u64"),
            parent: json
                .get("parent_id")
                .expect("No parent_id in commit event")
                .as_str()
                .expect("parent_id is not string")
                .to_string(),
        })
    }
}
<commit_msg>[cluster_test] Fix startup of debug_interface_log_tail<commit_after>use crate::{
    cluster::Cluster,
    health::{Commit, Event, LogTail, ValidatorEvent},
    instance::Instance,
    util::unix_timestamp_now,
};
use debug_interface::{
    self,
    proto::{
        node_debug_interface::{Event as DebugInterfaceEvent, GetEventsRequest},
        node_debug_interface_grpc::NodeDebugInterfaceClient,
    },
};
use grpcio::{self, ChannelBuilder, EnvBuilder};
use serde_json::{self, value as json};
use std::{
    env,
    sync::{atomic::AtomicI64, mpsc, Arc},
    thread,
    time::Duration,
};

pub struct DebugPortLogThread {
    instance: Instance,
    client: NodeDebugInterfaceClient,
    event_sender: mpsc::Sender<ValidatorEvent>,
    started_sender: Option<mpsc::Sender<()>>,
}

impl DebugPortLogThread {
    pub fn spawn_new(cluster: &Cluster) -> LogTail {
        let (event_sender, event_receiver) = mpsc::channel();
        let env = Arc::new(EnvBuilder::new().name_prefix("grpc-log-tail-").build());
        let mut started_receivers = vec![];
        for instance in cluster.instances() {
            let ch =
                ChannelBuilder::new(env.clone()).connect(&format!("{}:{}", instance.ip(), 6191));
            let (started_sender, started_receiver) = mpsc::channel();
            started_receivers.push(started_receiver);
            let client = NodeDebugInterfaceClient::new(ch);
            let debug_port_log_thread = DebugPortLogThread {
                instance: instance.clone(),
                client,
                event_sender: event_sender.clone(),
                started_sender: Some(started_sender),
            };
            thread::Builder::new()
                .name(format!("log-tail-{}", instance.short_hash()))
                .spawn(move || debug_port_log_thread.run())
                .expect("Failed to spawn log tail thread");
        }
        for r in started_receivers {
            if let Err(e) = r.recv() {
                panic!("Failed to start one of debug port log threads: {:?}", e);
            }
        }
        LogTail {
            event_receiver,
            pending_messages: Arc::new(AtomicI64::new(0)),
        }
    }
}

impl DebugPortLogThread {
    pub fn run(mut self) {
        let print_failures = env::var("VERBOSE").is_ok();
        loop {
            let opts = grpcio::CallOption::default().timeout(Duration::from_secs(5));
            match self.client.get_events_opt(&GetEventsRequest::new(), opts) {
                Err(e) => {
                    if print_failures {
                        println!("Failed to get events from {}: {:?}", self.instance, e);
                    }
                    thread::sleep(Duration::from_secs(1));
                }
                Ok(resp) => {
                    for event in resp.events.into_iter() {
                        if let Some(e) = self.parse_event(event) {
                            let _ignore = self.event_sender.send(e);
                        }
                    }
                    thread::sleep(Duration::from_millis(200));
                }
            }
            if let Some(started_sender) = self.started_sender.take() {
                if let Err(e) = started_sender.send(()) {
                    panic!("Failed to send to started_sender: {:?}", e);
                }
            }
        }
    }

    fn parse_event(&self, event: DebugInterfaceEvent) -> Option<ValidatorEvent> {
        let json: json::Value =
            serde_json::from_str(&event.json).expect("Failed to parse json from debug interface");

        let e = if event.name == "committed" {
            Self::parse_commit(json)
        } else {
            println!("Unknown event: {} from {}", event.name, self.instance);
            return None;
        };
        Some(ValidatorEvent {
            validator: self.instance.short_hash().clone(),
            timestamp: Duration::from_millis(event.get_timestamp() as u64),
            received_timestamp: unix_timestamp_now(),
            event: e,
        })
    }

    fn parse_commit(json: json::Value) -> Event {
        Event::Commit(Commit {
            commit: json
                .get("block_id")
                .expect("No block_id in commit event")
                .as_str()
                .expect("block_id is not string")
                .to_string(),
            round: json
                .get("round")
                .expect("No round in commit event")
                .as_u64()
                .expect("round is not u64"),
            parent: json
                .get("parent_id")
                .expect("No parent_id in commit event")
                .as_str()
                .expect("parent_id is not string")
                .to_string(),
        })
    }
}
<|endoftext|>


<commit_before>use crate::{
    cluster::Cluster,
    health::{Commit, Event, LogTail, ValidatorEvent},
    instance::Instance,
    util::unix_timestamp_now,
};
use debug_interface::{
    self,
    proto::{
        node_debug_interface::{Event as DebugInterfaceEvent, GetEventsRequest},
        node_debug_interface_grpc::NodeDebugInterfaceClient,
    },
};
use grpcio::{ChannelBuilder, EnvBuilder};
use serde_json::{self, value as json};
use std::{
    env,
    sync::{atomic::AtomicI64, mpsc, Arc},
    thread,
    time::Duration,
};

pub struct DebugPortLogThread {
    instance: Instance,
    client: NodeDebugInterfaceClient,
    event_sender: mpsc::Sender<ValidatorEvent>,
}

impl DebugPortLogThread {
    pub fn spawn_new(cluster: &Cluster) -> LogTail {
        let (event_sender, event_receiver) = mpsc::channel();
        let env = Arc::new(EnvBuilder::new().name_prefix("grpc-log-tail-").build());
        for instance in cluster.instances() {
            let ch =
                ChannelBuilder::new(env.clone()).connect(&format!("{}:{}", instance.ip(), 6191));
            let client = NodeDebugInterfaceClient::new(ch);
            let debug_port_log_thread = DebugPortLogThread {
                instance: instance.clone(),
                client,
                event_sender: event_sender.clone(),
            };
            thread::Builder::new()
                .name(format!("log-tail-{}", instance.short_hash()))
                .spawn(move || debug_port_log_thread.run())
                .expect("Failed to spawn log tail thread");
        }
        LogTail {
            event_receiver,
            pending_messages: Arc::new(AtomicI64::new(0)),
        }
    }
}

impl DebugPortLogThread {
    pub fn run(self) {
        let print_failures = env::var("VERBOSE").is_ok();
        loop {
            match self.client.get_events(&GetEventsRequest::new()) {
                Err(e) => {
                    if print_failures {
                        println!("Failed to get events from {}: {:?}", self.instance, e);
                    }
                    thread::sleep(Duration::from_secs(1));
                }
                Ok(resp) => {
                    for event in resp.events.into_iter() {
                        if let Some(e) = self.parse_event(event) {
                            let _ignore = self.event_sender.send(e);
                        }
                    }
                    thread::sleep(Duration::from_millis(200));
                }
            }
        }
    }

    fn parse_event(&self, event: DebugInterfaceEvent) -> Option<ValidatorEvent> {
        let json: json::Value =
            serde_json::from_str(&event.json).expect("Failed to parse json from debug interface");

        let e = if event.name == "committed" {
            Self::parse_commit(json)
        } else {
            println!("Unknown event: {} from {}", event.name, self.instance);
            return None;
        };
        Some(ValidatorEvent {
            validator: self.instance.short_hash().clone(),
            timestamp: Duration::from_millis(event.get_timestamp() as u64),
            received_timestamp: unix_timestamp_now(),
            event: e,
        })
    }

    fn parse_commit(json: json::Value) -> Event {
        Event::Commit(Commit {
            commit: json
                .get("block_id")
                .expect("No block_id in commit event")
                .as_str()
                .expect("block_id is not string")
                .to_string(),
            round: json
                .get("round")
                .expect("No round in commit event")
                .as_u64()
                .expect("round is not u64"),
            parent: json
                .get("parent_id")
                .expect("No parent_id in commit event")
                .as_str()
                .expect("parent_id is not string")
                .to_string(),
        })
    }
}
<commit_msg>[cluster_test] Set timeout for debug port RPC<commit_after>use crate::{
    cluster::Cluster,
    health::{Commit, Event, LogTail, ValidatorEvent},
    instance::Instance,
    util::unix_timestamp_now,
};
use debug_interface::{
    self,
    proto::{
        node_debug_interface::{Event as DebugInterfaceEvent, GetEventsRequest},
        node_debug_interface_grpc::NodeDebugInterfaceClient,
    },
};
use grpcio::{self, ChannelBuilder, EnvBuilder};
use serde_json::{self, value as json};
use std::{
    env,
    sync::{atomic::AtomicI64, mpsc, Arc},
    thread,
    time::Duration,
};

pub struct DebugPortLogThread {
    instance: Instance,
    client: NodeDebugInterfaceClient,
    event_sender: mpsc::Sender<ValidatorEvent>,
}

impl DebugPortLogThread {
    pub fn spawn_new(cluster: &Cluster) -> LogTail {
        let (event_sender, event_receiver) = mpsc::channel();
        let env = Arc::new(EnvBuilder::new().name_prefix("grpc-log-tail-").build());
        for instance in cluster.instances() {
            let ch =
                ChannelBuilder::new(env.clone()).connect(&format!("{}:{}", instance.ip(), 6191));
            let client = NodeDebugInterfaceClient::new(ch);
            let debug_port_log_thread = DebugPortLogThread {
                instance: instance.clone(),
                client,
                event_sender: event_sender.clone(),
            };
            thread::Builder::new()
                .name(format!("log-tail-{}", instance.short_hash()))
                .spawn(move || debug_port_log_thread.run())
                .expect("Failed to spawn log tail thread");
        }
        LogTail {
            event_receiver,
            pending_messages: Arc::new(AtomicI64::new(0)),
        }
    }
}

impl DebugPortLogThread {
    pub fn run(self) {
        let print_failures = env::var("VERBOSE").is_ok();
        loop {
            let opts = grpcio::CallOption::default().timeout(Duration::from_secs(5));
            match self.client.get_events_opt(&GetEventsRequest::new(), opts) {
                Err(e) => {
                    if print_failures {
                        println!("Failed to get events from {}: {:?}", self.instance, e);
                    }
                    thread::sleep(Duration::from_secs(1));
                }
                Ok(resp) => {
                    for event in resp.events.into_iter() {
                        if let Some(e) = self.parse_event(event) {
                            let _ignore = self.event_sender.send(e);
                        }
                    }
                    thread::sleep(Duration::from_millis(200));
                }
            }
        }
    }

    fn parse_event(&self, event: DebugInterfaceEvent) -> Option<ValidatorEvent> {
        let json: json::Value =
            serde_json::from_str(&event.json).expect("Failed to parse json from debug interface");

        let e = if event.name == "committed" {
            Self::parse_commit(json)
        } else {
            println!("Unknown event: {} from {}", event.name, self.instance);
            return None;
        };
        Some(ValidatorEvent {
            validator: self.instance.short_hash().clone(),
            timestamp: Duration::from_millis(event.get_timestamp() as u64),
            received_timestamp: unix_timestamp_now(),
            event: e,
        })
    }

    fn parse_commit(json: json::Value) -> Event {
        Event::Commit(Commit {
            commit: json
                .get("block_id")
                .expect("No block_id in commit event")
                .as_str()
                .expect("block_id is not string")
                .to_string(),
            round: json
                .get("round")
                .expect("No round in commit event")
                .as_u64()
                .expect("round is not u64"),
            parent: json
                .get("parent_id")
                .expect("No parent_id in commit event")
                .as_str()
                .expect("parent_id is not string")
                .to_string(),
        })
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Example of mutex<commit_after>use std::sync::Mutex;

fn main() {
    let m = Mutex::new(5);

    {
        let mut num = m.lock().unwrap();
        *num = 6;
    }

    println!("m = {:?}", m);
}
<|endoftext|>


<commit_before>use iron::{Handler, Response, Request, IronResult, Url, Error};
use typemap::Assoc;
use trie::Trie;

/// Exposes the original, unmodified path to be stored in `Request::extensions`.
pub struct OriginalUrl;
impl Assoc<Url> for OriginalUrl {}

/// `Mount` is a simple mounting middleware.
///
/// Mounting allows you to install a handler on a route and have it receive requests as if they
/// are relative to that route. For example, a handler mounted on `/foo/` will receive
/// requests like `/foo/bar` as if they are just `/bar`. Iron's mounting middleware allows
/// you to specify multiple mountings using one middleware instance. Requests that pass through
/// the mounting middleware are passed along to the mounted handler that best matches the request's
/// path. `Request::url` is modified so that requests appear to be relative to the mounted handler's route.
///
/// Mounted handlers may also access the *original* URL by requesting the `OriginalUrl` key
/// from `Request::extensions`.
pub struct Mount {
    inner: Trie<String, Match>
}

struct Match {
    handler: Box<Handler + Send + Sync>,
    length: uint
}

/// The error returned by `Mount` when a request doesn't match any mounted handlers.
#[deriving(Show)]
pub struct NoMatch;

impl Error for NoMatch {
    fn name(&self) -> &'static str { "No Match" }
}

impl Mount {
    /// Creates a new instance of `Mount`.
    pub fn new() -> Mount {
        Mount {
            inner: Trie::new()
        }
    }

    /// Mounts a given `Handler` onto a route.
    ///
    /// This method may be called multiple times with different routes.
    /// For a given request, the *most specific* handler will be selected.
    ///
    /// Existing handlers on the same route will be overwritten.
    pub fn mount<H: Handler>(&mut self, route: &str, handler: H) -> &mut Mount {
        // Parse the route into a list of strings. The unwrap is safe because strs are UTF-8.
        let key: Vec<String> = Path::new(route).str_components().map(|s| s.unwrap().to_string()).collect();

        // Insert a match struct into the trie.
        self.inner.insert(key.as_slice(), Match {
            handler: box handler as Box<Handler + Send + Sync>,
            length: key.len()
        });
        self
    }
}

impl Handler for Mount {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        // Find the matching handler.
        let matched = {
            // Extract the request path.
            let path = req.url.path.as_slice();

            // If present, remove the trailing empty string (which represents a trailing slash).
            // If it isn't removed the path will never match anything, because
            // Path::str_components ignores trailing slashes and will never create routes
            // ending in "".
            let key = match path.last() {
                Some(s) if s.is_empty() => path.slice_to(path.len() - 1),
                _ => path
            };

            // Search the Trie for the nearest most specific match.
            match self.inner.find_ancestor(key) {
                Some(matched) => matched,
                None => return Err(box NoMatch as Box<Error>)
            }
        };

        // We have a match, so fire off the child.
        // If another mount middleware hasn't already, insert the unmodified url
        // into the extensions as the "original url".
        let is_outer_mount = !req.extensions.contains::<OriginalUrl, Url>();
        if is_outer_mount {
            req.extensions.insert::<OriginalUrl, Url>(req.url.clone());
        }

        // Remove the prefix from the request's path before passing it to the mounted handler.
        // If the prefix is entirely removed and no trailing slash was present, the new path
        // will be the empty list. For the purposes of redirection, conveying that the path
        // did not include a trailing slash is more important than providing a non-empty list.
        req.url.path = req.url.path.as_slice().slice_from(matched.length).to_vec();

        let res = matched.handler.call(req);

        // Reverse the URL munging, for future middleware.
        req.url = match req.extensions.find::<OriginalUrl, Url>() {
            Some(original) => original.clone(),
            None => fail!("OriginalUrl unexpectedly removed from req.extensions.")
        };

        // If this mount middleware is the outermost mount middleware,
        // remove the original url from the extensions map to prevent leakage.
        if is_outer_mount {
            req.extensions.remove::<OriginalUrl, Url>();
        }

        res
    }
}

<commit_msg>(cleanup) Use Error::abstract.<commit_after>use iron::{Handler, Response, Request, IronResult, Url, Error};
use typemap::Assoc;
use trie::Trie;

/// Exposes the original, unmodified path to be stored in `Request::extensions`.
pub struct OriginalUrl;
impl Assoc<Url> for OriginalUrl {}

/// `Mount` is a simple mounting middleware.
///
/// Mounting allows you to install a handler on a route and have it receive requests as if they
/// are relative to that route. For example, a handler mounted on `/foo/` will receive
/// requests like `/foo/bar` as if they are just `/bar`. Iron's mounting middleware allows
/// you to specify multiple mountings using one middleware instance. Requests that pass through
/// the mounting middleware are passed along to the mounted handler that best matches the request's
/// path. `Request::url` is modified so that requests appear to be relative to the mounted handler's route.
///
/// Mounted handlers may also access the *original* URL by requesting the `OriginalUrl` key
/// from `Request::extensions`.
pub struct Mount {
    inner: Trie<String, Match>
}

struct Match {
    handler: Box<Handler + Send + Sync>,
    length: uint
}

/// The error returned by `Mount` when a request doesn't match any mounted handlers.
#[deriving(Show)]
pub struct NoMatch;

impl Error for NoMatch {
    fn name(&self) -> &'static str { "No Match" }
}

impl Mount {
    /// Creates a new instance of `Mount`.
    pub fn new() -> Mount {
        Mount {
            inner: Trie::new()
        }
    }

    /// Mounts a given `Handler` onto a route.
    ///
    /// This method may be called multiple times with different routes.
    /// For a given request, the *most specific* handler will be selected.
    ///
    /// Existing handlers on the same route will be overwritten.
    pub fn mount<H: Handler>(&mut self, route: &str, handler: H) -> &mut Mount {
        // Parse the route into a list of strings. The unwrap is safe because strs are UTF-8.
        let key: Vec<String> = Path::new(route).str_components().map(|s| s.unwrap().to_string()).collect();

        // Insert a match struct into the trie.
        self.inner.insert(key.as_slice(), Match {
            handler: box handler as Box<Handler + Send + Sync>,
            length: key.len()
        });
        self
    }
}

impl Handler for Mount {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        // Find the matching handler.
        let matched = {
            // Extract the request path.
            let path = req.url.path.as_slice();

            // If present, remove the trailing empty string (which represents a trailing slash).
            // If it isn't removed the path will never match anything, because
            // Path::str_components ignores trailing slashes and will never create routes
            // ending in "".
            let key = match path.last() {
                Some(s) if s.is_empty() => path.slice_to(path.len() - 1),
                _ => path
            };

            // Search the Trie for the nearest most specific match.
            match self.inner.find_ancestor(key) {
                Some(matched) => matched,
                None => return Err(NoMatch.abstract())
            }
        };

        // We have a match, so fire off the child.
        // If another mount middleware hasn't already, insert the unmodified url
        // into the extensions as the "original url".
        let is_outer_mount = !req.extensions.contains::<OriginalUrl, Url>();
        if is_outer_mount {
            req.extensions.insert::<OriginalUrl, Url>(req.url.clone());
        }

        // Remove the prefix from the request's path before passing it to the mounted handler.
        // If the prefix is entirely removed and no trailing slash was present, the new path
        // will be the empty list. For the purposes of redirection, conveying that the path
        // did not include a trailing slash is more important than providing a non-empty list.
        req.url.path = req.url.path.as_slice().slice_from(matched.length).to_vec();

        let res = matched.handler.call(req);

        // Reverse the URL munging, for future middleware.
        req.url = match req.extensions.find::<OriginalUrl, Url>() {
            Some(original) => original.clone(),
            None => fail!("OriginalUrl unexpectedly removed from req.extensions.")
        };

        // If this mount middleware is the outermost mount middleware,
        // remove the original url from the extensions map to prevent leakage.
        if is_outer_mount {
            req.extensions.remove::<OriginalUrl, Url>();
        }

        res
    }
}

<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::fmt::{Debug, Error, Formatter};
use std::sync::atomic::{AtomicUsize, Ordering};

use ffi::futex;
use thread;

pub struct Mutex {
    inner: UnsafeCell<MutexInner>
}

struct MutexInner {
    lock: AtomicUsize,
    futex: i32
}

// TODO: a scoped / RAII lock would be useful.
impl Mutex {
    pub fn new() -> Mutex {
        Mutex { inner: UnsafeCell::new(MutexInner::new()) }
    }

    fn get_inner(&self) -> &mut MutexInner {
        unsafe { &mut *self.inner.get() }
    }

    pub fn try_lock(&mut self) -> bool {
        self.get_inner().try_lock()
    }

    pub fn lock(&mut self) {
        self.get_inner().lock()
    }

    pub fn unlock(&mut self) {
        self.get_inner().unlock()
    }
}

impl Debug for Mutex {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let tid = unsafe {
            let inner = &mut *self.inner.get();
            inner.lock.load(Ordering::Relaxed)
        };

        if tid == LOCK_FREE {
            fmt.write_str("Mutex { unlocked }")
        } else {
            fmt.write_fmt(format_args!("Mutex {{ owned by {} }}", tid))
        }
    }
}

const LOCK_FREE: usize = 0xa5a5a5a5;

/// TODO: handle all let _ = ... error cases.
impl MutexInner {
    pub fn new() -> MutexInner {
        MutexInner {
            lock: AtomicUsize::new(LOCK_FREE),
            futex: 0
        }
    }

    pub fn unlock(&mut self) {
        let old_val = self.lock.load(Ordering::Relaxed);

        if old_val != thread::get_current_thread().tid as usize {
            panic!("trying to unlock a mutex we don't own");
        }

        // mark the lock as free
        self.lock.store(LOCK_FREE, Ordering::Relaxed);

        // wake up 1 thread waiting to lock
        let _ = futex::wake(&mut self.futex, 1);
    }

    pub fn try_lock(&mut self) -> bool {
        let tid = thread::get_current_thread().tid;
        let swap = self.lock.compare_and_swap(LOCK_FREE, tid as usize, Ordering::Relaxed);

        // If compare_and_swap returned LOCK_FREE, we were the first ones
        // to grab the lock, so we currently own the mutex.
        swap == LOCK_FREE
    }

    pub fn lock(&mut self) {
        while !self.try_lock() {
            // We didn't get the lock this time, wait for owner to unlock
            let _ = futex::wait(&mut self.futex, 0);
        }
    }
}
<commit_msg>Mutex should be Sync + Send<commit_after>use std::cell::UnsafeCell;
use std::fmt::{Debug, Error, Formatter};
use std::sync::atomic::{AtomicUsize, Ordering};

use ffi::futex;
use thread;

pub struct Mutex {
    inner: UnsafeCell<MutexInner>
}

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

struct MutexInner {
    lock: AtomicUsize,
    futex: i32
}

// TODO: a scoped / RAII lock would be useful.
impl Mutex {
    pub fn new() -> Mutex {
        Mutex { inner: UnsafeCell::new(MutexInner::new()) }
    }

    fn get_inner(&self) -> &mut MutexInner {
        unsafe { &mut *self.inner.get() }
    }

    pub fn try_lock(&mut self) -> bool {
        self.get_inner().try_lock()
    }

    pub fn lock(&mut self) {
        self.get_inner().lock()
    }

    pub fn unlock(&mut self) {
        self.get_inner().unlock()
    }
}

impl Debug for Mutex {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let tid = unsafe {
            let inner = &mut *self.inner.get();
            inner.lock.load(Ordering::Relaxed)
        };

        if tid == LOCK_FREE {
            fmt.write_str("Mutex { unlocked }")
        } else {
            fmt.write_fmt(format_args!("Mutex {{ owned by {} }}", tid))
        }
    }
}

const LOCK_FREE: usize = 0xa5a5a5a5;

/// TODO: handle all let _ = ... error cases.
impl MutexInner {
    pub fn new() -> MutexInner {
        MutexInner {
            lock: AtomicUsize::new(LOCK_FREE),
            futex: 0
        }
    }

    pub fn unlock(&mut self) {
        let old_val = self.lock.load(Ordering::Relaxed);

        if old_val != thread::get_current_thread().tid as usize {
            panic!("trying to unlock a mutex we don't own");
        }

        // mark the lock as free
        self.lock.store(LOCK_FREE, Ordering::Relaxed);

        // wake up 1 thread waiting to lock
        let _ = futex::wake(&mut self.futex, 1);
    }

    pub fn try_lock(&mut self) -> bool {
        let tid = thread::get_current_thread().tid;
        let swap = self.lock.compare_and_swap(LOCK_FREE, tid as usize, Ordering::Relaxed);

        // If compare_and_swap returned LOCK_FREE, we were the first ones
        // to grab the lock, so we currently own the mutex.
        swap == LOCK_FREE
    }

    pub fn lock(&mut self) {
        while !self.try_lock() {
            // We didn't get the lock this time, wait for owner to unlock
            let _ = futex::wait(&mut self.futex, 0);
        }
    }
}
<|endoftext|>


<commit_before>use regex::Regex;

struct Score;

impl Score {
    pub fn score(choice: &str, query: &str) -> f32 {
        let choice_length = choice.len();
        let query_length = query.len();
        if choice_length == 0 || query_length > choice_length  {
            return 0.0
        }
        if query_length == 0  {
            return 1.0
        }

        if create_regex(query).is_match(choice) {
            return 1.0 / (choice_length as f32)
        }

        0.0
    }
}

fn create_regex(query: &str) -> Regex {
   match Regex::new(expand_regex(query).as_slice()) {
            Ok(re) => re,
            Err(err) => panic!("{}", err),
   }
}

fn expand_regex(query: &str) -> String {
    let mut result = "(?iU).*".to_string();
    for c in query.chars() {
        result.push(c);
        result.push_str(".*");
    }
    result
}

#[cfg(test)]

#[test]
fn scores_zero_when_the_choice_is_emtpy() {
    assert_eq!(Score::score("", "a"), 0.0);
}

#[test]
fn scores_one_when_the_query_is_empty() {
    assert_eq!(Score::score("a", ""), 1.0);
}

#[test]
fn scores_zero_if_query_is_longer_than_the_choice() {
    assert_eq!(Score::score("a", "aaaaa"), 0.0);
}

#[test]
fn scores_zero_if_query_does_not_match_at_all() {
    assert_eq!(Score::score("a", "b"), 0.0);
}

#[test]
fn scores_greater_than_zero_if_query_matches_choice() {
    assert!(Score::score("a", "a") > 0.0);
    assert!(Score::score("ab", "a") > 0.0);
    assert!(Score::score("ba", "a") > 0.0);
    assert!(Score::score("bab", "a") > 0.0);
    assert!(Score::score("babababab", "aaaa") > 0.0);
}

#[test]
fn case_insensitive_matching() {
    assert!(Score::score("a", "A") == 1.0);
    assert!(Score::score("A", "a") == 1.0);
}

#[test]
fn normalizes_score_based_on_length() {
    assert_eq!(Score::score("a", "a") , 1.0);
    assert_eq!(Score::score("ab", "ab") , 0.5);
    assert_eq!(Score::score("a long string", "a long string") , 1.0 / "a long string".len() as f32);
    assert_eq!(Score::score("spec/search_spec.rb", "sear"), 1.0 / "spec/search_spec.rb".len() as f32)
}

//#[test]
fn matches_punctuation() {
    assert!(Score::score("/! symbols $^", "/!$^") > 0.0);
}

#[test]
fn repeated_character_does_not_match() {
    assert_eq!(Score::score("a", "aa") , 0.0);
}

#[test]
fn scores_higher_for_better_matches() {
      assert!(Score::score("selecta.gemspec", "asp") > Score::score("algorithm4_spec.rb", "asp"));
      assert!(Score::score("README.md", "em") > Score::score("benchmark.rb", "em"));
      assert!(Score::score("search.rb", "sear") > Score::score("spec/search_spec.rb", "sear"));
}

#[test]
fn scores_shorter_matches_higher() {
      assert!(Score::score("fbb", "fbb") > Score::score("foo bar baz", "fbb"));
      assert!(Score::score("foo", "foo") > Score::score("longer foo", "foo"));
      assert!(Score::score("foo", "foo") > Score::score("foo longer", "foo"));
      assert!(Score::score("1/2/3/4", "1/2/3") > Score::score("1/9/2/3/4", "1/2/3"));
}

#[test]
fn scores_the_tighter_of_two_matches_regardless_of_order() {
      let beginning = "121padding2";
      let end = "1padding212";
      assert_eq!(Score::score(beginning, "12"), Score::score(end, "12"));
}

<commit_msg>Removes regex and custom functions for searching<commit_after>use std::ascii::AsciiExt;

struct Score;

impl Score {
    pub fn score(choice: &str, query: &str) -> f32 {
        let choice_length = choice.len() as f32;
        let query_length = query.len() as f32;
        let lower_choice = choice.to_ascii_lowercase();
        let lower_query = query.to_ascii_lowercase();

        if choice_length == 0.0 || query_length > choice_length  {
            return 0.0
        }
        if query_length == 0.0  {
            return 1.0
        }

        let possible_match_length = compute_match_length(lower_choice.as_slice(), lower_query.as_slice());
         match possible_match_length {
             Some(match_length) => return normalize_score(query_length, match_length, choice_length),
             None => return 0.0,
         };
    }
}

fn normalize_score(query_length: f32, match_length: uint, choice_length: f32) -> f32 {
    (query_length / match_length as f32) / choice_length
}

fn compute_match_length(choice: &str, query: &str) -> Option<uint> {
    let query_chars = query.chars().collect::<Vec<char>>();
    let first_char = query_chars[0];

    let match_beginnings = find_char_in_choice(first_char, choice);

    let mut shortest_match: Option<uint> = None;

    for beginning in match_beginnings.iter() {
        let possible_end = find_end_of_match(choice, &query_chars, *beginning);
        match possible_end {
            Some(end) => shortest_match = Some(end - *beginning + 1),
            None => continue,
        };
    }
    return shortest_match;
}

fn find_char_in_choice(first_char: char, choice: &str) -> Vec<uint> {
    let mut found: Vec<uint> = Vec::new();
    for  (idx, character) in choice.chars().enumerate() {
        if character == first_char {
            found.push(idx);
        }
    }

    return found;
}

fn find_end_of_match(choice: &str, query_chars: &Vec<char>, beginning: uint) -> Option<uint> {
    let mut last_index = beginning;
    for query_char in query_chars.iter() {
       let found = find_first_after(choice, *query_char, last_index);
       match found {
           Some(n) => last_index = n,
           None => return None,
       };
    }
    return Some(last_index);
}

fn find_first_after(choice: &str, query: char, beginning: uint) -> Option<uint> {
    for (idx, character) in choice.chars().enumerate().skip(beginning) {
        if character == query {
            return Some(idx);
        }
    }
    None
}

#[cfg(test)]

#[test]
fn scores_zero_when_the_choice_is_emtpy() {
    assert_eq!(Score::score("", "a"), 0.0);
}

#[test]
fn scores_one_when_the_query_is_empty() {
    assert_eq!(Score::score("a", ""), 1.0);
}

#[test]
fn scores_zero_if_query_is_longer_than_the_choice() {
    assert_eq!(Score::score("a", "aaaaa"), 0.0);
}

#[test]
fn scores_zero_if_query_does_not_match_at_all() {
    assert_eq!(Score::score("a", "b"), 0.0);
}

#[test]
fn scores_greater_than_zero_if_query_matches_choice() {
    assert!(Score::score("a", "a") > 0.0);
    assert!(Score::score("ab", "a") > 0.0);
    assert!(Score::score("ba", "a") > 0.0);
    assert!(Score::score("bab", "a") > 0.0);
    assert!(Score::score("babababab", "aaaa") > 0.0);
}

#[test]
fn case_insensitive_matching() {
    assert!(Score::score("a", "A") == 1.0);
    assert!(Score::score("A", "a") == 1.0);
}

#[test]
fn normalizes_score_based_on_length() {
    assert_eq!(Score::score("a", "a") , 1.0);
    assert_eq!(Score::score("ab", "ab") , 0.5);
    assert_eq!(Score::score("a long string", "a long string") , 1.0 / "a long string".len() as f32);
    assert_eq!(Score::score("spec/search_spec.rb", "sear"), 1.0 / "spec/search_spec.rb".len() as f32)
}

//#[test]
fn matches_punctuation() {
    assert!(Score::score("/! symbols $^", "/!$^") > 0.0);
}

#[test]
fn repeated_character_does_not_match() {
    assert_eq!(Score::score("a", "aa") , 0.0);
}

#[test]
fn scores_higher_for_better_matches() {
      assert!(Score::score("selecta.gemspec", "asp") > Score::score("algorithm4_spec.rb", "asp"));
      assert!(Score::score("README.md", "em") > Score::score("benchmark.rb", "em"));
      assert!(Score::score("search.rb", "sear") > Score::score("spec/search_spec.rb", "sear"));
}

#[test]
fn scores_shorter_matches_higher() {
      assert!(Score::score("fbb", "fbb") > Score::score("foo bar baz", "fbb"));
      assert!(Score::score("foo", "foo") > Score::score("longer foo", "foo"));
      assert!(Score::score("foo", "foo") > Score::score("foo longer", "foo"));
      assert!(Score::score("1/2/3/4", "1/2/3") > Score::score("1/9/2/3/4", "1/2/3"));
}

//#[test]
fn scores_the_tighter_of_two_matches_regardless_of_order() {
      let beginning = "121padding2";
      let end = "1padding212";
      assert_eq!(Score::score(beginning, "12"), Score::score(end, "12"));
}

<|endoftext|>


<commit_before>use rocket;
use rocket::http::hyper::header::*;
use rocket::http::Status;
use rocket::Response;
use rocket::response::{self, Responder};
use std::cmp;
use std::convert::From;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::str::FromStr;

#[derive(Debug)]
pub enum PartialFileRange {
	AllFrom(u64),
	FromTo(u64, u64),
	Last(u64),
}

impl From<ByteRangeSpec> for PartialFileRange {
	fn from(b: ByteRangeSpec) -> PartialFileRange {
		match b {
			ByteRangeSpec::AllFrom(from) => PartialFileRange::AllFrom(from),
			ByteRangeSpec::FromTo(from, to) => PartialFileRange::FromTo(from, to),
			ByteRangeSpec::Last(last) => PartialFileRange::Last(last),
		}
	}
}

impl From<Vec<ByteRangeSpec>> for PartialFileRange {
	fn from(v: Vec<ByteRangeSpec>) -> PartialFileRange {
		match v.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		}
	}
}

pub struct RangeResponder<R> {
	original: R,
}

impl<'r, R: Responder<'r>> RangeResponder<R> {
	pub fn new(original: R) -> RangeResponder<R> {
		RangeResponder { original }
	}

	fn ignore_range(self, request: &rocket::request::Request, file_length: Option<u64>) -> response::Result<'r> {
		let mut response = self.original.respond_to(request)?;
		if let Some(content_length) = file_length {
			response.set_header(ContentLength(content_length));
		}
		response.set_status(Status::Ok);
		Ok(response)
	}

	fn reject_range(self, file_length: Option<u64>) -> response::Result<'r> {
		let mut response = Response::build()
						.status(Status::RangeNotSatisfiable)
						.finalize();
		if file_length.is_some() {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: None,
				instance_length: file_length,
			});
			response.set_header(content_range);
		}
		response.set_status(Status::RangeNotSatisfiable);
		Ok(response)
	}
}

fn truncate_range(range: &PartialFileRange, file_length: &Option<u64>) -> Option<(u64, u64)> {
	use self::PartialFileRange::*;

	match (range, file_length) {
		(FromTo(from, to), Some(file_length)) => {
			if from <= to && from < file_length {
				Some((*from, cmp::min(*to, file_length - 1)))
			} else {
				None
			}
		}
		(AllFrom(from), Some(file_length)) => {
			if from < file_length {
				Some((*from, file_length - 1))
			} else {
				None
			}
		}
		(Last(last), Some(file_length)) => {
			if last < file_length {
				Some((file_length - last, file_length - 1))
			} else {
				Some((0, file_length - 1))
			}
		}
		(_, None) => None,
	}
}

impl<'r> Responder<'r> for RangeResponder<File> {
	fn respond_to(mut self, request: &rocket::request::Request) -> response::Result<'r> {

		let metadata: Option<_> = self.original.metadata().ok();
		let file_length: Option<u64> = metadata.map(|m| m.len());

		let range_header = request.headers().get_one("Range");
		let range_header = match range_header {
			None => return self.ignore_range(request, file_length),
			Some(h) => h,
		};

		let vec_range = match Range::from_str(range_header) {
			Ok(Range::Bytes(v)) => v,
			_ => {
				warn!("Ignoring range header that could not be parse {:?}, file length is {:?}", range_header, file_length);
				return self.ignore_range(request, file_length);
			},
		};

		let partial_file_range = match vec_range.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		};

		let range: Option<(u64, u64)> = truncate_range(&partial_file_range, &file_length);

		if let Some((from, to)) = range {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: range,
				instance_length: file_length,
			});
			let content_len = to - from + 1;

			match self.original.seek(SeekFrom::Start(from)) {
				Ok(_) => (),
				Err(_) => return Err(rocket::http::Status::InternalServerError),
			}
			let partial_original = self.original.take(content_len).into_inner();
			let mut response = partial_original.respond_to(request)?;
			response.set_header(ContentLength(content_len));
			response.set_header(content_range);
			response.set_status(rocket::http::Status::PartialContent);

			Ok(response)
		} else {
			warn!("Rejecting unsatisfiable range header {:?}, file length is {:?}", &partial_file_range, &file_length);
			self.reject_range(file_length)
		}
	}
}
<commit_msg>Fixed partial content responses<commit_after>use rocket;
use rocket::http::hyper::header::*;
use rocket::http::Status;
use rocket::Response;
use rocket::response::{self, Responder};
use std::cmp;
use std::convert::From;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::str::FromStr;

#[derive(Debug)]
pub enum PartialFileRange {
	AllFrom(u64),
	FromTo(u64, u64),
	Last(u64),
}

impl From<ByteRangeSpec> for PartialFileRange {
	fn from(b: ByteRangeSpec) -> PartialFileRange {
		match b {
			ByteRangeSpec::AllFrom(from) => PartialFileRange::AllFrom(from),
			ByteRangeSpec::FromTo(from, to) => PartialFileRange::FromTo(from, to),
			ByteRangeSpec::Last(last) => PartialFileRange::Last(last),
		}
	}
}

impl From<Vec<ByteRangeSpec>> for PartialFileRange {
	fn from(v: Vec<ByteRangeSpec>) -> PartialFileRange {
		match v.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		}
	}
}

pub struct RangeResponder<R> {
	original: R,
}

impl<'r, R: Responder<'r>> RangeResponder<R> {
	pub fn new(original: R) -> RangeResponder<R> {
		RangeResponder { original }
	}

	fn ignore_range(self, request: &rocket::request::Request, file_length: Option<u64>) -> response::Result<'r> {
		let mut response = self.original.respond_to(request)?;
		if let Some(content_length) = file_length {
			response.set_header(ContentLength(content_length));
		}
		response.set_status(Status::Ok);
		Ok(response)
	}

	fn reject_range(self, file_length: Option<u64>) -> response::Result<'r> {
		let mut response = Response::build()
						.status(Status::RangeNotSatisfiable)
						.finalize();
		if file_length.is_some() {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: None,
				instance_length: file_length,
			});
			response.set_header(content_range);
		}
		response.set_status(Status::RangeNotSatisfiable);
		Ok(response)
	}
}

fn truncate_range(range: &PartialFileRange, file_length: &Option<u64>) -> Option<(u64, u64)> {
	use self::PartialFileRange::*;

	match (range, file_length) {
		(FromTo(from, to), Some(file_length)) => {
			if from <= to && from < file_length {
				Some((*from, cmp::min(*to, file_length - 1)))
			} else {
				None
			}
		}
		(AllFrom(from), Some(file_length)) => {
			if from < file_length {
				Some((*from, file_length - 1))
			} else {
				None
			}
		}
		(Last(last), Some(file_length)) => {
			if last < file_length {
				Some((file_length - last, file_length - 1))
			} else {
				Some((0, file_length - 1))
			}
		}
		(_, None) => None,
	}
}

impl<'r> Responder<'r> for RangeResponder<File> {
	fn respond_to(mut self, request: &rocket::request::Request) -> response::Result<'r> {

		let metadata: Option<_> = self.original.metadata().ok();
		let file_length: Option<u64> = metadata.map(|m| m.len());

		let range_header = request.headers().get_one("Range");
		let range_header = match range_header {
			None => return self.ignore_range(request, file_length),
			Some(h) => h,
		};

		let vec_range = match Range::from_str(range_header) {
			Ok(Range::Bytes(v)) => v,
			_ => {
				warn!("Ignoring range header that could not be parse {:?}, file length is {:?}", range_header, file_length);
				return self.ignore_range(request, file_length);
			},
		};

		let partial_file_range = match vec_range.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		};

		let range: Option<(u64, u64)> = truncate_range(&partial_file_range, &file_length);

		if let Some((from, to)) = range {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: range,
				instance_length: file_length,
			});
			let content_len = to - from + 1;

			match self.original.seek(SeekFrom::Start(from)) {
				Ok(_) => (),
				Err(_) => return Err(rocket::http::Status::InternalServerError),
			}
			let partial_original = self.original.take(content_len);
			let response = Response::build()
									.status(Status::PartialContent)
									.header(ContentLength(content_len))
									.header(content_range)
									.streamed_body(partial_original)
									.finalize();

			Ok(response)
		} else {
			warn!("Rejecting unsatisfiable range header {:?}, file length is {:?}", &partial_file_range, &file_length);
			self.reject_range(file_length)
		}
	}
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::pio::*;

use schemes::KScheme;

/// PS2
pub struct Ps2 {
    /// The data
    data: Pio8,
    /// The command
    cmd: Pio8,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: isize,
    /// Mouse point y
    mouse_y: isize,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio8::new(0x60),
            cmd: Pio8::new(0x64),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
        };

        unsafe {
            module.keyboard_init();
            module.mouse_init();
        }

        module
    }

    unsafe fn wait0(&self) {
        while (self.cmd.read() & 1) == 0 {}
    }

    unsafe fn wait1(&self) {
        while (self.cmd.read() & 2) == 2 {}
    }

    unsafe fn keyboard_init(&mut self) {
        while (self.cmd.read() & 0x1) == 1 {
            self.data.read();
        }

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let flags = (self.data.read() & 0b00110111) | 1 | 0b10000;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(flags);

        // Set Defaults
        self.wait1();
        self.data.write(0xF6);
        self.wait0();
        self.data.read();

        // Set LEDS
        self.wait1();
        self.data.write(0xED);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(0);
        self.wait0();
        self.data.read();

        // Set Scancode Map:
        self.wait1();
        self.data.write(0xF0);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(1);
        self.wait0();
        self.data.read();
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self) -> Option<KeyEvent> {
        let scancode = unsafe { self.data.read() };

        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        }

        let shift;
        if self.caps_lock {
            shift = !(self.lshift || self.rshift);
        } else {
            shift = self.lshift || self.rshift;
        }

        return Some(KeyEvent {
            character: char_for_scancode(scancode & 0x7F, shift),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    unsafe fn mouse_cmd(&mut self, byte: u8) -> u8 {
        self.wait1();
        self.cmd.write(0xD4);
        self.wait1();
        self.data.write(byte);

        self.wait0();
        self.data.read()
    }

    /// Initialize mouse
    pub unsafe fn mouse_init(&mut self) {
        // The Init Dance
        self.wait1();
        self.cmd.write(0xA8);

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let status = self.data.read() | 2;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(status);

        // Set defaults
        self.mouse_cmd(0xF6);

        // Enable Streaming
        self.mouse_cmd(0xF4);
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self) -> Option<MouseEvent> {
        let byte = unsafe { self.data.read() };
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = self.mouse_packet[1] as isize -
                    (((self.mouse_packet[0] as isize) << 4) & 0x100);
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = (((self.mouse_packet[0] as isize) << 3) & 0x100) -
                    self.mouse_packet[2] as isize;
            } else {
                y = 0;
            }

            unsafe {
                self.mouse_x = cmp::max(0,
                                        cmp::min((*::console).display.width as isize,
                                                 self.mouse_x + x));
                self.mouse_y = cmp::max(0,
                                        cmp::min((*::console).display.height as isize,
                                                 self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }
}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0x1 || irq == 0xC {
            self.on_poll();
        }
    }

    fn on_poll(&mut self) {
        loop {
            let status = unsafe { self.cmd.read() };
            if status & 0x21 == 1 {
                if let Some(key_event) = self.keyboard_interrupt() {
                    key_event.trigger();
                }
            } else if status & 0x21 == 0x21 {
                if let Some(mouse_event) = self.mouse_interrupt() {
                    mouse_event.trigger();
                }
            } else {
                break;
            }
        }
    }
}

fn char_for_scancode(scancode: u8, shift: bool) -> char {
    let mut character = '\x00';
    if scancode < 58 {
        if shift {
            character = SCANCODES[scancode as usize][1];
        } else {
            character = SCANCODES[scancode as usize][0];
        }
    }
    character
}

static SCANCODES: [[char; 2]; 58] = [['\0', '\0'],
                                     ['\x1B', '\x1B'],
                                     ['1', '!'],
                                     ['2', '@'],
                                     ['3', '#'],
                                     ['4', '$'],
                                     ['5', '%'],
                                     ['6', '^'],
                                     ['7', '&'],
                                     ['8', '*'],
                                     ['9', '('],
                                     ['0', ')'],
                                     ['-', '_'],
                                     ['=', '+'],
                                     ['\0', '\0'],
                                     ['\t', '\t'],
                                     ['q', 'Q'],
                                     ['w', 'W'],
                                     ['e', 'E'],
                                     ['r', 'R'],
                                     ['t', 'T'],
                                     ['y', 'Y'],
                                     ['u', 'U'],
                                     ['i', 'I'],
                                     ['o', 'O'],
                                     ['p', 'P'],
                                     ['[', '{'],
                                     [']', '}'],
                                     ['\n', '\n'],
                                     ['\0', '\0'],
                                     ['a', 'A'],
                                     ['s', 'S'],
                                     ['d', 'D'],
                                     ['f', 'F'],
                                     ['g', 'G'],
                                     ['h', 'H'],
                                     ['j', 'J'],
                                     ['k', 'K'],
                                     ['l', 'L'],
                                     [';', ':'],
                                     ['\'', '"'],
                                     ['`', '~'],
                                     ['\0', '\0'],
                                     ['\\', '|'],
                                     ['z', 'Z'],
                                     ['x', 'X'],
                                     ['c', 'C'],
                                     ['v', 'V'],
                                     ['b', 'B'],
                                     ['n', 'N'],
                                     ['m', 'M'],
                                     [',', '<'],
                                     ['.', '>'],
                                     ['/', '?'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     [' ', ' ']];

 static SCANCODES_FR: [[char; 2]; 58] = [['\0', '\0'],
                                      ['\x1B', '\x1B'],
                                      ['1', '&'],
                                      ['2', 'é'],
                                      ['3', '"'],
                                      ['4', '\''],
                                      ['5', '('],
                                      ['6', '-'],
                                      ['7', 'è'],
                                      ['8', '_'],
                                      ['9', 'ç'],
                                      ['0', 'à'],
                                      ['-', ')'],
                                      ['=', '='],
                                      ['\0', '\0'],
                                      ['\t', '\t'],
                                      ['a', 'A'],
                                      ['z', 'Z'],
                                      ['e', 'E'],
                                      ['r', 'R'],
                                      ['t', 'T'],
                                      ['y', 'Y'],
                                      ['u', 'U'],
                                      ['i', 'I'],
                                      ['o', 'O'],
                                      ['p', 'P'],
                                      ['^', '¨'],
                                      ['$', '£'],
                                      ['\n', '\n'],
                                      ['\0', '\0'],
                                      ['q', 'Q'],
                                      ['s', 'S'],
                                      ['d', 'D'],
                                      ['f', 'F'],
                                      ['g', 'G'],
                                      ['h', 'H'],
                                      ['j', 'J'],
                                      ['k', 'K'],
                                      ['l', 'L'],
                                      ['m', 'M'],
                                      ['ù', '%'],
                                      ['*', 'µ'],
                                      ['\0', '\0'],
                                      ['<', '>'],
                                      ['w', 'W'],
                                      ['x', 'X'],
                                      ['c', 'C'],
                                      ['v', 'V'],
                                      ['b', 'B'],
                                      ['n', 'N'],
                                      [',', '?'],
                                      [';', '.'],
                                      [':', '/'],
                                      ['!', '§'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      [' ', ' ']];
<commit_msg>New field in Ps2 structure to choose the layout<commit_after>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::pio::*;

use schemes::KScheme;

/// PS2
pub struct Ps2 {
    /// The data
    data: Pio8,
    /// The command
    cmd: Pio8,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: isize,
    /// Mouse point y
    mouse_y: isize,
    /// Layout for keyboard
    layout: usize,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio8::new(0x60),
            cmd: Pio8::new(0x64),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
        };

        unsafe {
            module.keyboard_init();
            module.mouse_init();
        }

        module
    }

    unsafe fn wait0(&self) {
        while (self.cmd.read() & 1) == 0 {}
    }

    unsafe fn wait1(&self) {
        while (self.cmd.read() & 2) == 2 {}
    }

    unsafe fn keyboard_init(&mut self) {
        while (self.cmd.read() & 0x1) == 1 {
            self.data.read();
        }

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let flags = (self.data.read() & 0b00110111) | 1 | 0b10000;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(flags);

        // Set Defaults
        self.wait1();
        self.data.write(0xF6);
        self.wait0();
        self.data.read();

        // Set LEDS
        self.wait1();
        self.data.write(0xED);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(0);
        self.wait0();
        self.data.read();

        // Set Scancode Map:
        self.wait1();
        self.data.write(0xF0);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(1);
        self.wait0();
        self.data.read();
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self) -> Option<KeyEvent> {
        let scancode = unsafe { self.data.read() };

        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        }

        let shift;
        if self.caps_lock {
            shift = !(self.lshift || self.rshift);
        } else {
            shift = self.lshift || self.rshift;
        }

        return Some(KeyEvent {
            character: char_for_scancode(scancode & 0x7F, shift),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    unsafe fn mouse_cmd(&mut self, byte: u8) -> u8 {
        self.wait1();
        self.cmd.write(0xD4);
        self.wait1();
        self.data.write(byte);

        self.wait0();
        self.data.read()
    }

    /// Initialize mouse
    pub unsafe fn mouse_init(&mut self) {
        // The Init Dance
        self.wait1();
        self.cmd.write(0xA8);

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let status = self.data.read() | 2;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(status);

        // Set defaults
        self.mouse_cmd(0xF6);

        // Enable Streaming
        self.mouse_cmd(0xF4);
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self) -> Option<MouseEvent> {
        let byte = unsafe { self.data.read() };
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = self.mouse_packet[1] as isize -
                    (((self.mouse_packet[0] as isize) << 4) & 0x100);
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = (((self.mouse_packet[0] as isize) << 3) & 0x100) -
                    self.mouse_packet[2] as isize;
            } else {
                y = 0;
            }

            unsafe {
                self.mouse_x = cmp::max(0,
                                        cmp::min((*::console).display.width as isize,
                                                 self.mouse_x + x));
                self.mouse_y = cmp::max(0,
                                        cmp::min((*::console).display.height as isize,
                                                 self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }
}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0x1 || irq == 0xC {
            self.on_poll();
        }
    }

    fn on_poll(&mut self) {
        loop {
            let status = unsafe { self.cmd.read() };
            if status & 0x21 == 1 {
                if let Some(key_event) = self.keyboard_interrupt() {
                    key_event.trigger();
                }
            } else if status & 0x21 == 0x21 {
                if let Some(mouse_event) = self.mouse_interrupt() {
                    mouse_event.trigger();
                }
            } else {
                break;
            }
        }
    }
}

fn char_for_scancode(scancode: u8, shift: bool) -> char {
    let mut character = '\x00';
    if scancode < 58 {
        if shift {
            character = SCANCODES[scancode as usize][1];
        } else {
            character = SCANCODES[scancode as usize][0];
        }
    }
    character
}

static SCANCODES: [[char; 2]; 58] = [['\0', '\0'],
                                     ['\x1B', '\x1B'],
                                     ['1', '!'],
                                     ['2', '@'],
                                     ['3', '#'],
                                     ['4', '$'],
                                     ['5', '%'],
                                     ['6', '^'],
                                     ['7', '&'],
                                     ['8', '*'],
                                     ['9', '('],
                                     ['0', ')'],
                                     ['-', '_'],
                                     ['=', '+'],
                                     ['\0', '\0'],
                                     ['\t', '\t'],
                                     ['q', 'Q'],
                                     ['w', 'W'],
                                     ['e', 'E'],
                                     ['r', 'R'],
                                     ['t', 'T'],
                                     ['y', 'Y'],
                                     ['u', 'U'],
                                     ['i', 'I'],
                                     ['o', 'O'],
                                     ['p', 'P'],
                                     ['[', '{'],
                                     [']', '}'],
                                     ['\n', '\n'],
                                     ['\0', '\0'],
                                     ['a', 'A'],
                                     ['s', 'S'],
                                     ['d', 'D'],
                                     ['f', 'F'],
                                     ['g', 'G'],
                                     ['h', 'H'],
                                     ['j', 'J'],
                                     ['k', 'K'],
                                     ['l', 'L'],
                                     [';', ':'],
                                     ['\'', '"'],
                                     ['`', '~'],
                                     ['\0', '\0'],
                                     ['\\', '|'],
                                     ['z', 'Z'],
                                     ['x', 'X'],
                                     ['c', 'C'],
                                     ['v', 'V'],
                                     ['b', 'B'],
                                     ['n', 'N'],
                                     ['m', 'M'],
                                     [',', '<'],
                                     ['.', '>'],
                                     ['/', '?'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     [' ', ' ']];

 static SCANCODES_FR: [[char; 2]; 58] = [['\0', '\0'],
                                      ['\x1B', '\x1B'],
                                      ['1', '&'],
                                      ['2', 'é'],
                                      ['3', '"'],
                                      ['4', '\''],
                                      ['5', '('],
                                      ['6', '-'],
                                      ['7', 'è'],
                                      ['8', '_'],
                                      ['9', 'ç'],
                                      ['0', 'à'],
                                      ['-', ')'],
                                      ['=', '='],
                                      ['\0', '\0'],
                                      ['\t', '\t'],
                                      ['a', 'A'],
                                      ['z', 'Z'],
                                      ['e', 'E'],
                                      ['r', 'R'],
                                      ['t', 'T'],
                                      ['y', 'Y'],
                                      ['u', 'U'],
                                      ['i', 'I'],
                                      ['o', 'O'],
                                      ['p', 'P'],
                                      ['^', '¨'],
                                      ['$', '£'],
                                      ['\n', '\n'],
                                      ['\0', '\0'],
                                      ['q', 'Q'],
                                      ['s', 'S'],
                                      ['d', 'D'],
                                      ['f', 'F'],
                                      ['g', 'G'],
                                      ['h', 'H'],
                                      ['j', 'J'],
                                      ['k', 'K'],
                                      ['l', 'L'],
                                      ['m', 'M'],
                                      ['ù', '%'],
                                      ['*', 'µ'],
                                      ['\0', '\0'],
                                      ['<', '>'],
                                      ['w', 'W'],
                                      ['x', 'X'],
                                      ['c', 'C'],
                                      ['v', 'V'],
                                      ['b', 'B'],
                                      ['n', 'N'],
                                      [',', '?'],
                                      [';', '.'],
                                      [':', '/'],
                                      ['!', '§'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      [' ', ' ']];
<|endoftext|>


<commit_before>use std::process::{Command, Output};
use std::io::Error;
use configuration;
use output;
use file;

pub fn provision(configuration: &configuration::Configuration) -> i32 {

    let mut packages = Vec::new();

    packages.extend(configuration.packages.iter().cloned());

    packages.reverse();

    let mut exit_codes = Vec::new();

    let package_exit_codes = install_packages(&packages);
    exit_codes.extend(&package_exit_codes[..]);

    let results = handle_file_resources(&configuration.files);
    exit_codes.extend(&results[..]);

    exit_codes.sort();

    match exit_codes.last() {
        Some(&0) => return 0,
        None     => return 0,
        _        => return 1
    }
}

fn install_packages(package_list: &Vec<String>) -> Vec<i32> {
    let mut exit_codes = Vec::new();
    let mut packages = package_list.clone();

    while let Some(package) = packages.pop() {
        if is_package_installed(&package) {
            continue;
        }
        let shellout = install_package(&package);
        output::print_shellout::<String>(&package, &shellout);
        let exit_status = shellout.status.clone();
        if exit_status.success() == false {
            exit_codes.push(exit_status.code().unwrap());
        }
    }
    exit_codes
}

fn handle_file_resources(resources: &Vec<file::FileResource>) -> Vec<i32> {
    let mut results = Vec::new();
    for resource in resources {
        let result = resource.write_file();
        match result {
            Ok(_) =>  {
                let msg = format!("==> Wrote file {}", resource.path);
                output::print_message(msg, output::MessageType::Stdout);
                results.push(0);
            },
            Err(err) => {
                let msg = format!("==> Error while writing file {}", resource.path);
                output::print_message(msg, output::MessageType::Stderr);
                output::print_message(format!("==> {}", err), output::MessageType::Stderr);
                results.push(1);
            }
        }
    }
    results
}

fn is_package_installed(package_name: &String) -> bool {
    let command_str = format!("yum list installed {}", package_name);
    let output = Command::new(command_str).output();
    output.is_ok()
}

fn install_package(package: &String) -> Output {
    Command::new("yum")
        .args(&vec!["install", "-y", package])
        .output()
        .unwrap()
}
<commit_msg>Abort provisioning if configuration is invalid<commit_after>use std::process::{Command, Output};
use std::io::Error;
use configuration;
use output;
use file;

pub fn provision(configuration: &configuration::Configuration) -> i32 {
    let mut packages = Vec::new();

    if !configuration.is_valid() {
        output::print_message(format!("==> Configuration invalid! Abort provisioning."), output::MessageType::Stderr);
        return 1;
    }

    packages.extend(configuration.packages.iter().cloned());

    packages.reverse();

    let mut exit_codes = Vec::new();

    let package_exit_codes = install_packages(&packages);
    exit_codes.extend(&package_exit_codes[..]);

    let results = handle_file_resources(&configuration.files);
    exit_codes.extend(&results[..]);

    exit_codes.sort();

    match exit_codes.last() {
        Some(&0) => return 0,
        None     => return 0,
        _        => return 1
    }
}

fn install_packages(package_list: &Vec<String>) -> Vec<i32> {
    let mut exit_codes = Vec::new();
    let mut packages = package_list.clone();

    while let Some(package) = packages.pop() {
        if is_package_installed(&package) {
            continue;
        }
        let shellout = install_package(&package);
        output::print_shellout::<String>(&package, &shellout);
        let exit_status = shellout.status.clone();
        if exit_status.success() == false {
            exit_codes.push(exit_status.code().unwrap());
        }
    }
    exit_codes
}

fn handle_file_resources(resources: &Vec<file::FileResource>) -> Vec<i32> {
    let mut results = Vec::new();
    for resource in resources {
        let result = resource.write_file();
        match result {
            Ok(_) =>  {
                let msg = format!("==> Wrote file {}", resource.path);
                output::print_message(msg, output::MessageType::Stdout);
                results.push(0);
            },
            Err(err) => {
                let msg = format!("==> Error while writing file {}", resource.path);
                output::print_message(msg, output::MessageType::Stderr);
                output::print_message(format!("==> {}", err), output::MessageType::Stderr);
                results.push(1);
            }
        }
    }
    results
}

fn is_package_installed(package_name: &String) -> bool {
    let command_str = format!("yum list installed {}", package_name);
    let output = Command::new(command_str).output();
    output.is_ok()
}

fn install_package(package: &String) -> Output {
    Command::new("yum")
        .args(&vec!["install", "-y", package])
        .output()
        .unwrap()
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;

use stack::Stack;
use super::common::{push, rust_trampoline};

pub const STACK_ALIGN: usize = 16;

#[allow(raw_pointer_derive)]
#[derive(Copy, Clone)]
pub struct Registers {
  rsp: *mut usize
}

impl Registers {
  #[inline]
  pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
    let sp_limit = stack.limit();
    let mut sp = stack.top() as *mut usize;
    let f_ptr = push(&mut sp, f);

    asm!(include_str!("init.s")
          : "={rdi}"(sp)
          : "{rdi}" (sp),
            "{rsi}" (rust_trampoline::<F>),
            "{rdx}" (f_ptr),
            "{rcx}" (sp_limit)
          :
          : "volatile");

    Registers { rsp: sp }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    asm!(include_str!("swap.s")
          :
          : "{rdi}" (&mut self.rsp)
          : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
            "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
            "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
            "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
            "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
            "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
            "cc"
          : "volatile");
  }
}
<commit_msg>there is no point in Registers being Copy + Clone<commit_after>// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;

use stack::Stack;
use super::common::{push, rust_trampoline};

pub const STACK_ALIGN: usize = 16;

pub struct Registers {
  rsp: *mut usize
}

impl Registers {
  #[inline]
  pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
    let sp_limit = stack.limit();
    let mut sp = stack.top() as *mut usize;
    let f_ptr = push(&mut sp, f);

    asm!(include_str!("init.s")
          : "={rdi}"(sp)
          : "{rdi}" (sp),
            "{rsi}" (rust_trampoline::<F>),
            "{rdx}" (f_ptr),
            "{rcx}" (sp_limit)
          :
          : "volatile");

    Registers { rsp: sp }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    asm!(include_str!("swap.s")
          :
          : "{rdi}" (&mut self.rsp)
          : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
            "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
            "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
            "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
            "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
            "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
            "cc"
          : "volatile");
  }
}
<|endoftext|>