<commit_before>use sfml::graphics::*;
use sfml::system::Vector2f;
use super::counter::Counter;
use super::death_screen::DeathScreen;
use super::element::*;
use super::meter::Meter;
use resize_handler::ResizeHandler;
use resources::Resources;
use stats::Stats;

pub struct UiManager<'s> {
    hydration: Meter<'s>,
    wood: Counter<'s>,
    death: DeathScreen<'s>,
    display_death: bool,
}

impl<'s> UiManager<'s> {
    pub fn new(res: &'s Resources) -> UiManager<'s> {
        UiManager {
            hydration: Meter::new(res, &Vector2f::new(0.02, 0.02)),
            wood: Counter::new(res, &Vector2f::new(0.02, 0.8)),
            death: DeathScreen::new(res),
            display_death: false,
        }
    }

    pub fn update(&mut self, delta: f32, current_stats: &Stats) {
        self.hydration.set_value(current_stats.hydration_level());
        //self.wood.set_value((current_stats.hydration_level() * 255.) as u8);
        if self.display_death {
            self.death.update(delta);
        }
    }

    pub fn draw_all<T: RenderTarget>(&self, target: &mut T) {
        let old_view = target.view().to_owned();

        let size = target.size();
        let mut view = target.view().to_owned();
        view.move2f(size.x as f32 / 2., size.y as f32 / 2.);
        target.set_view(&view);

        //let default_view = target.default_view().to_owned();
        //target.set_view(&default_view);

        self.hydration.draw(target);
        self.wood.draw(target);
        if self.display_death {
            self.death.draw(target);
        }

        target.set_view(&old_view);
    }

    pub fn set_display_death(&mut self, display_death: bool) {
        self.display_death = display_death;
    }
}

impl<'s> ResizeHandler for UiManager<'s> {
    fn on_resize(&mut self, width: u32, height: u32) {
        self.hydration.on_resize(width, height);
        self.wood.on_resize(width, height);
        self.death.on_resize(width, height);
    }
}
<commit_msg>Make UI remain still<commit_after>use sfml::graphics::*;
use sfml::system::Vector2f;
use super::counter::Counter;
use super::death_screen::DeathScreen;
use super::element::*;
use super::meter::Meter;
use resize_handler::ResizeHandler;
use resources::Resources;
use stats::Stats;

pub struct UiManager<'s> {
    hydration: Meter<'s>,
    wood: Counter<'s>,
    death: DeathScreen<'s>,
    display_death: bool,
}

impl<'s> UiManager<'s> {
    pub fn new(res: &'s Resources) -> UiManager<'s> {
        UiManager {
            hydration: Meter::new(res, &Vector2f::new(0.02, 0.02)),
            wood: Counter::new(res, &Vector2f::new(0.02, 0.8)),
            death: DeathScreen::new(res),
            display_death: false,
        }
    }

    pub fn update(&mut self, delta: f32, current_stats: &Stats) {
        self.hydration.set_value(current_stats.hydration_level());
        //self.wood.set_value((current_stats.hydration_level() * 255.) as u8);
        if self.display_death {
            self.death.update(delta);
        }
    }

    pub fn draw_all<T: RenderTarget>(&self, target: &mut T) {
        let old_view = target.view().to_owned();

        let size = target.size();
        let mut view = target.view().to_owned();
        view.set_center2f(size.x as f32 / 2., size.y as f32 / 2.);
        target.set_view(&view);

        //let default_view = target.default_view().to_owned();
        //target.set_view(&default_view);

        self.hydration.draw(target);
        self.wood.draw(target);
        if self.display_death {
            self.death.draw(target);
        }

        target.set_view(&old_view);
    }

    pub fn set_display_death(&mut self, display_death: bool) {
        self.display_death = display_death;
    }
}

impl<'s> ResizeHandler for UiManager<'s> {
    fn on_resize(&mut self, width: u32, height: u32) {
        self.hydration.on_resize(width, height);
        self.wood.on_resize(width, height);
        self.death.on_resize(width, height);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;

use sysinfo::get_current_pid;
use sysinfo::{DiskExt, SystemExt};

#[bench]
fn bench_new(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new();
    });
}

#[bench]
fn bench_new_all(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new_all();
    });
}

#[bench]
fn bench_refresh_all(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_all();
    });
}

#[bench]
fn bench_refresh_system(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    s.refresh_system();
    b.iter(move || {
        s.refresh_system();
    });
}

#[bench]
fn bench_refresh_processes(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_processes(); // to load the whole processes list a first time.
    b.iter(move || {
        s.refresh_processes();
    });
}

#[bench]
fn bench_refresh_process(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_all();
    // to be sure it'll exist for at least as long as we run
    let pid = get_current_pid().expect("failed to get current pid");
    b.iter(move || {
        s.refresh_process(pid);
    });
}

#[bench]
fn bench_refresh_disk(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    let disks = s.disks_mut();
    let disk = &mut disks[0];
    b.iter(move || {
        disk.refresh();
    });
}

#[bench]
fn bench_refresh_disks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_disks();
    });
}

#[bench]
fn bench_refresh_disks_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disks_list();
    });
}

#[bench]
fn bench_refresh_networks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_networks();
    });
}

#[bench]
fn bench_refresh_networks_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_networks_list();
    });
}

#[bench]
fn bench_refresh_memory(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_memory();
    });
}

#[bench]
fn bench_refresh_cpu(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_cpu();
    });
}

#[bench]
fn bench_refresh_components(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_components();
    });
}

#[bench]
fn bench_refresh_components_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_components_list();
    });
}

#[bench]
fn bench_refresh_users_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_users_list();
    });
}
<commit_msg>Add new benchmark for new ProcessList creation<commit_after>#![feature(test)]

extern crate test;

use sysinfo::get_current_pid;
use sysinfo::{DiskExt, SystemExt};

#[bench]
fn bench_new(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new();
    });
}

#[bench]
fn bench_new_all(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new_all();
    });
}

#[bench]
fn bench_refresh_all(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_all();
    });
}

#[bench]
fn bench_refresh_system(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    s.refresh_system();
    b.iter(move || {
        s.refresh_system();
    });
}

#[bench]
fn bench_refresh_processes(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_processes(); // to load the whole processes list a first time.
    b.iter(move || {
        s.refresh_processes();
    });
}

#[bench]
fn bench_first_refresh_processes(b: &mut test::Bencher) {
    b.iter(move || {
        let mut s = sysinfo::System::new();
        s.refresh_processes();
    });
}

#[bench]
fn bench_refresh_process(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_all();
    // to be sure it'll exist for at least as long as we run
    let pid = get_current_pid().expect("failed to get current pid");
    b.iter(move || {
        s.refresh_process(pid);
    });
}

#[bench]
fn bench_refresh_disk(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    let disks = s.disks_mut();
    let disk = &mut disks[0];
    b.iter(move || {
        disk.refresh();
    });
}

#[bench]
fn bench_refresh_disks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_disks();
    });
}

#[bench]
fn bench_refresh_disks_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disks_list();
    });
}

#[bench]
fn bench_refresh_networks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_networks();
    });
}

#[bench]
fn bench_refresh_networks_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_networks_list();
    });
}

#[bench]
fn bench_refresh_memory(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_memory();
    });
}

#[bench]
fn bench_refresh_cpu(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_cpu();
    });
}

#[bench]
fn bench_refresh_components(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_components();
    });
}

#[bench]
fn bench_refresh_components_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_components_list();
    });
}

#[bench]
fn bench_refresh_users_list(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new_all();

    b.iter(move || {
        s.refresh_users_list();
    });
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate aho_corasick;
extern crate test;

use std::iter;

use aho_corasick::{Automaton, AcAutomaton, Transitions};
use test::Bencher;

const HAYSTACK_RANDOM: &'static str = include_str!("random.txt");

fn bench_aut_no_match<T: Transitions>(
    b: &mut Bencher,
    aut: AcAutomaton<T>,
    haystack: &str,
) {
    b.bytes = haystack.len() as u64;
    b.iter(|| assert!(aut.find(haystack).next().is_none()));
}

fn bench_full_aut_no_match<T: Transitions>(
    b: &mut Bencher,
    aut: AcAutomaton<T>,
    haystack: &str,
) {
    let aut = aut.into_full();
    b.bytes = haystack.len() as u64;
    b.iter(|| assert!(aut.find(haystack).next().is_none()));
}

fn bench_naive_no_match<S>(b: &mut Bencher, needles: Vec<S>, haystack: &str)
        where S: Into<String> {
    b.bytes = haystack.len() as u64;
    let needles: Vec<String> = needles.into_iter().map(Into::into).collect();
    b.iter(|| assert!(!naive_find(&needles, haystack)));
}

fn haystack_same(letter: char) -> String {
    iter::repeat(letter).take(10000).collect()
}

macro_rules! aut_benches {
    ($prefix:ident, $aut:expr, $bench:expr) => { mod $prefix {
#![allow(unused_imports)]
use aho_corasick::{Automaton, AcAutomaton, Sparse};
use test::Bencher;

use super::{
    HAYSTACK_RANDOM, haystack_same,
    bench_aut_no_match, bench_full_aut_no_match,
};

#[bench]
fn ac_one_byte(b: &mut Bencher) {
    let aut = $aut(vec!["a"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_one_prefix_byte_no_match(b: &mut Bencher) {
    let aut = $aut(vec!["zbc"]);
    $bench(b, aut, &haystack_same('y'));
}

#[bench]
fn ac_one_prefix_byte_every_match(b: &mut Bencher) {
    // We lose the benefit of `memchr` because the first byte matches
    // in every position in the haystack.
    let aut = $aut(vec!["zbc"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_one_prefix_byte_random(b: &mut Bencher) {
    let aut = $aut(vec!["zbc\x00"]);
    $bench(b, aut, HAYSTACK_RANDOM);
}

#[bench]
fn ac_two_bytes(b: &mut Bencher) {
    let aut = $aut(vec!["a", "b"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_two_diff_prefix(b: &mut Bencher) {
    let aut = $aut(vec!["abcdef", "bmnopq"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_two_one_prefix_byte_every_match(b: &mut Bencher) {
    let aut = $aut(vec!["zbcdef", "zmnopq"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_two_one_prefix_byte_no_match(b: &mut Bencher) {
    let aut = $aut(vec!["zbcdef", "zmnopq"]);
    $bench(b, aut, &haystack_same('y'));
}

#[bench]
fn ac_two_one_prefix_byte_random(b: &mut Bencher) {
    let aut = $aut(vec!["zbcdef\x00", "zmnopq\x00"]);
    $bench(b, aut, HAYSTACK_RANDOM);
}

#[bench]
fn ac_ten_bytes(b: &mut Bencher) {
    let aut = $aut(vec!["a", "b", "c", "d", "e",
                        "f", "g", "h", "i", "j"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_ten_diff_prefix(b: &mut Bencher) {
    let aut = $aut(vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
                        "ebcdef", "fbcdef", "gbcdef", "hbcdef",
                        "ibcdef", "jbcdef"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_ten_one_prefix_byte_every_match(b: &mut Bencher) {
    let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                        "zecdef", "zfcdef", "zgcdef", "zhcdef",
                        "zicdef", "zjcdef"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_ten_one_prefix_byte_no_match(b: &mut Bencher) {
    let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                        "zecdef", "zfcdef", "zgcdef", "zhcdef",
                        "zicdef", "zjcdef"]);
    $bench(b, aut, &haystack_same('y'));
}

#[bench]
fn ac_ten_one_prefix_byte_random(b: &mut Bencher) {
    let aut = $aut(vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
                        "zdcdef\x00", "zecdef\x00", "zfcdef\x00",
                        "zgcdef\x00", "zhcdef\x00", "zicdef\x00",
                        "zjcdef\x00"]);
    $bench(b, aut, HAYSTACK_RANDOM);
}
}}}

aut_benches!(dense, AcAutomaton::new, bench_aut_no_match);
aut_benches!(sparse, AcAutomaton::<Sparse>::with_transitions,
             bench_aut_no_match);
aut_benches!(full, AcAutomaton::new, bench_full_aut_no_match);

// A naive multi-pattern search.
// We use this to benchmark *throughput*, so it should never match anything.
fn naive_find(needles: &[String], haystack: &str) -> bool {
    for hi in 0..haystack.len() {
        let rest = &haystack.as_bytes()[hi..];
        for needle in needles {
            let needle = needle.as_bytes();
            if needle.len() > rest.len() {
                continue;
            }
            if needle == &rest[..needle.len()] {
                // should never happen in throughput benchmarks.
                return true;
            }
        }
    }
    false
}

#[bench]
fn naive_one_byte(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["a"], &haystack_same('z'));
}

#[bench]
fn naive_one_prefix_byte_no_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbc"], &haystack_same('y'));
}

#[bench]
fn naive_one_prefix_byte_every_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbc"], &haystack_same('z'));
}

#[bench]
fn naive_one_prefix_byte_random(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbc\x00"], HAYSTACK_RANDOM);
}

#[bench]
fn naive_two_bytes(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["a", "b"], &haystack_same('z'));
}

#[bench]
fn naive_two_diff_prefix(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["abcdef", "bmnopq"], &haystack_same('z'));
}

#[bench]
fn naive_two_one_prefix_byte_every_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('z'));
}

#[bench]
fn naive_two_one_prefix_byte_no_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('y'));
}

#[bench]
fn naive_two_one_prefix_byte_random(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbcdef\x00", "zmnopq\x00"], HAYSTACK_RANDOM);
}

#[bench]
fn naive_ten_bytes(b: &mut Bencher) {
    let needles = vec!["a", "b", "c", "d", "e",
                       "f", "g", "h", "i", "j"];
    bench_naive_no_match(b, needles, &haystack_same('z'));
}

#[bench]
fn naive_ten_diff_prefix(b: &mut Bencher) {
    let needles = vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
                       "ebcdef", "fbcdef", "gbcdef", "hbcdef",
                       "ibcdef", "jbcdef"];
    bench_naive_no_match(b, needles, &haystack_same('z'));
}

#[bench]
fn naive_ten_one_prefix_byte_every_match(b: &mut Bencher) {
    let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                       "zecdef", "zfcdef", "zgcdef", "zhcdef",
                       "zicdef", "zjcdef"];
    bench_naive_no_match(b, needles, &haystack_same('z'));
}

#[bench]
fn naive_ten_one_prefix_byte_no_match(b: &mut Bencher) {
    let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                       "zecdef", "zfcdef", "zgcdef", "zhcdef",
                       "zicdef", "zjcdef"];
    bench_naive_no_match(b, needles, &haystack_same('y'));
}

#[bench]
fn naive_ten_one_prefix_byte_random(b: &mut Bencher) {
    let needles = vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
                       "zdcdef\x00", "zecdef\x00", "zfcdef\x00",
                       "zgcdef\x00", "zhcdef\x00", "zicdef\x00",
                       "zjcdef\x00"];
    bench_naive_no_match(b, needles, HAYSTACK_RANDOM);
}
<commit_msg>Fix benchmarks<commit_after>#![feature(test)]

extern crate aho_corasick;
extern crate test;

use std::iter;

use aho_corasick::{Automaton, AcAutomaton, Transitions};
use test::Bencher;

const HAYSTACK_RANDOM: &'static str = include_str!("random.txt");

fn bench_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
    b: &mut Bencher,
    aut: AcAutomaton<P, T>,
    haystack: &str,
) {
    b.bytes = haystack.len() as u64;
    b.iter(|| assert!(aut.find(haystack).next().is_none()));
}

fn bench_full_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
    b: &mut Bencher,
    aut: AcAutomaton<P, T>,
    haystack: &str,
) {
    let aut = aut.into_full();
    b.bytes = haystack.len() as u64;
    b.iter(|| assert!(aut.find(haystack).next().is_none()));
}

fn bench_naive_no_match<S>(b: &mut Bencher, needles: Vec<S>, haystack: &str)
        where S: Into<String> {
    b.bytes = haystack.len() as u64;
    let needles: Vec<String> = needles.into_iter().map(Into::into).collect();
    b.iter(|| assert!(!naive_find(&needles, haystack)));
}

fn haystack_same(letter: char) -> String {
    iter::repeat(letter).take(10000).collect()
}

macro_rules! aut_benches {
    ($prefix:ident, $aut:expr, $bench:expr) => { mod $prefix {
#![allow(unused_imports)]
use aho_corasick::{Automaton, AcAutomaton, Sparse};
use test::Bencher;

use super::{
    HAYSTACK_RANDOM, haystack_same,
    bench_aut_no_match, bench_full_aut_no_match,
};

#[bench]
fn ac_one_byte(b: &mut Bencher) {
    let aut = $aut(vec!["a"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_one_prefix_byte_no_match(b: &mut Bencher) {
    let aut = $aut(vec!["zbc"]);
    $bench(b, aut, &haystack_same('y'));
}

#[bench]
fn ac_one_prefix_byte_every_match(b: &mut Bencher) {
    // We lose the benefit of `memchr` because the first byte matches
    // in every position in the haystack.
    let aut = $aut(vec!["zbc"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_one_prefix_byte_random(b: &mut Bencher) {
    let aut = $aut(vec!["zbc\x00"]);
    $bench(b, aut, HAYSTACK_RANDOM);
}

#[bench]
fn ac_two_bytes(b: &mut Bencher) {
    let aut = $aut(vec!["a", "b"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_two_diff_prefix(b: &mut Bencher) {
    let aut = $aut(vec!["abcdef", "bmnopq"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_two_one_prefix_byte_every_match(b: &mut Bencher) {
    let aut = $aut(vec!["zbcdef", "zmnopq"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_two_one_prefix_byte_no_match(b: &mut Bencher) {
    let aut = $aut(vec!["zbcdef", "zmnopq"]);
    $bench(b, aut, &haystack_same('y'));
}

#[bench]
fn ac_two_one_prefix_byte_random(b: &mut Bencher) {
    let aut = $aut(vec!["zbcdef\x00", "zmnopq\x00"]);
    $bench(b, aut, HAYSTACK_RANDOM);
}

#[bench]
fn ac_ten_bytes(b: &mut Bencher) {
    let aut = $aut(vec!["a", "b", "c", "d", "e",
                        "f", "g", "h", "i", "j"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_ten_diff_prefix(b: &mut Bencher) {
    let aut = $aut(vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
                        "ebcdef", "fbcdef", "gbcdef", "hbcdef",
                        "ibcdef", "jbcdef"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_ten_one_prefix_byte_every_match(b: &mut Bencher) {
    let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                        "zecdef", "zfcdef", "zgcdef", "zhcdef",
                        "zicdef", "zjcdef"]);
    $bench(b, aut, &haystack_same('z'));
}

#[bench]
fn ac_ten_one_prefix_byte_no_match(b: &mut Bencher) {
    let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                        "zecdef", "zfcdef", "zgcdef", "zhcdef",
                        "zicdef", "zjcdef"]);
    $bench(b, aut, &haystack_same('y'));
}

#[bench]
fn ac_ten_one_prefix_byte_random(b: &mut Bencher) {
    let aut = $aut(vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
                        "zdcdef\x00", "zecdef\x00", "zfcdef\x00",
                        "zgcdef\x00", "zhcdef\x00", "zicdef\x00",
                        "zjcdef\x00"]);
    $bench(b, aut, HAYSTACK_RANDOM);
}
}}}

aut_benches!(dense, AcAutomaton::new, bench_aut_no_match);
aut_benches!(sparse, AcAutomaton::<&str, Sparse>::with_transitions,
             bench_aut_no_match);
aut_benches!(full, AcAutomaton::new, bench_full_aut_no_match);

// A naive multi-pattern search.
// We use this to benchmark *throughput*, so it should never match anything.
fn naive_find(needles: &[String], haystack: &str) -> bool {
    for hi in 0..haystack.len() {
        let rest = &haystack.as_bytes()[hi..];
        for needle in needles {
            let needle = needle.as_bytes();
            if needle.len() > rest.len() {
                continue;
            }
            if needle == &rest[..needle.len()] {
                // should never happen in throughput benchmarks.
                return true;
            }
        }
    }
    false
}

#[bench]
fn naive_one_byte(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["a"], &haystack_same('z'));
}

#[bench]
fn naive_one_prefix_byte_no_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbc"], &haystack_same('y'));
}

#[bench]
fn naive_one_prefix_byte_every_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbc"], &haystack_same('z'));
}

#[bench]
fn naive_one_prefix_byte_random(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbc\x00"], HAYSTACK_RANDOM);
}

#[bench]
fn naive_two_bytes(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["a", "b"], &haystack_same('z'));
}

#[bench]
fn naive_two_diff_prefix(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["abcdef", "bmnopq"], &haystack_same('z'));
}

#[bench]
fn naive_two_one_prefix_byte_every_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('z'));
}

#[bench]
fn naive_two_one_prefix_byte_no_match(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('y'));
}

#[bench]
fn naive_two_one_prefix_byte_random(b: &mut Bencher) {
    bench_naive_no_match(b, vec!["zbcdef\x00", "zmnopq\x00"], HAYSTACK_RANDOM);
}

#[bench]
fn naive_ten_bytes(b: &mut Bencher) {
    let needles = vec!["a", "b", "c", "d", "e",
                       "f", "g", "h", "i", "j"];
    bench_naive_no_match(b, needles, &haystack_same('z'));
}

#[bench]
fn naive_ten_diff_prefix(b: &mut Bencher) {
    let needles = vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
                       "ebcdef", "fbcdef", "gbcdef", "hbcdef",
                       "ibcdef", "jbcdef"];
    bench_naive_no_match(b, needles, &haystack_same('z'));
}

#[bench]
fn naive_ten_one_prefix_byte_every_match(b: &mut Bencher) {
    let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                       "zecdef", "zfcdef", "zgcdef", "zhcdef",
                       "zicdef", "zjcdef"];
    bench_naive_no_match(b, needles, &haystack_same('z'));
}

#[bench]
fn naive_ten_one_prefix_byte_no_match(b: &mut Bencher) {
    let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
                       "zecdef", "zfcdef", "zgcdef", "zhcdef",
                       "zicdef", "zjcdef"];
    bench_naive_no_match(b, needles, &haystack_same('y'));
}

#[bench]
fn naive_ten_one_prefix_byte_random(b: &mut Bencher) {
    let needles = vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
                       "zdcdef\x00", "zecdef\x00", "zfcdef\x00",
                       "zgcdef\x00", "zhcdef\x00", "zicdef\x00",
                       "zjcdef\x00"];
    bench_naive_no_match(b, needles, HAYSTACK_RANDOM);
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{DebugAbbrev, DebugInfo, DebugLine, DebugLineOffset, LineNumberProgramHeader,
            LittleEndian};

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into()));
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);
    let unit = debug_info.units()
        .next()
        .expect("Should have at least one compilation unit")
        .expect("And it should parse OK");

    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);
        test::black_box(unit.abbreviations(debug_abbrev)
            .expect("Should parse abbreviations"));
    });
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);

    let debug_info = read_section("debug_info");

    b.iter(|| {
        let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);

        for unit in debug_info.units() {
            let unit = unit.expect("Should parse compilation unit");
            let abbrevs = unit.abbreviations(debug_abbrev)
                .expect("Should parse abbreviations");

            let mut cursor = unit.entries(&abbrevs);
            while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
                let mut attrs = entry.attrs();
                while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                    test::black_box(&attr);
                }
            }
        }
    });
}

#[bench]
fn bench_parsing_line_number_program_opcodes(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    // We happen to know that there is a line number program and header at
    // offset 0 and that address size is 8 bytes. No need to parse DIEs to grab
    // this info off of the compilation units.
    let offset = DebugLineOffset(0);
    let address_size = 8;

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, offset, address_size)
            .expect("Should parse line number program header");

        for opcode in header.opcodes() {
            let opcode = opcode.expect("Should parse opcode");
            test::black_box(opcode);
        }
    });
}
<commit_msg>Add a bench for executing line number programs<commit_after>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{DebugAbbrev, DebugInfo, DebugLine, DebugLineOffset, LineNumberProgramHeader,
            LittleEndian, StateMachine};

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into()));
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);
    let unit = debug_info.units()
        .next()
        .expect("Should have at least one compilation unit")
        .expect("And it should parse OK");

    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);
        test::black_box(unit.abbreviations(debug_abbrev)
            .expect("Should parse abbreviations"));
    });
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);

    let debug_info = read_section("debug_info");

    b.iter(|| {
        let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);

        for unit in debug_info.units() {
            let unit = unit.expect("Should parse compilation unit");
            let abbrevs = unit.abbreviations(debug_abbrev)
                .expect("Should parse abbreviations");

            let mut cursor = unit.entries(&abbrevs);
            while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
                let mut attrs = entry.attrs();
                while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                    test::black_box(&attr);
                }
            }
        }
    });
}

#[bench]
fn bench_parsing_line_number_program_opcodes(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    // We happen to know that there is a line number program and header at
    // offset 0 and that address size is 8 bytes. No need to parse DIEs to grab
    // this info off of the compilation units.
    let offset = DebugLineOffset(0);
    let address_size = 8;

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, offset, address_size)
            .expect("Should parse line number program header");

        for opcode in header.opcodes() {
            let opcode = opcode.expect("Should parse opcode");
            test::black_box(opcode);
        }
    });
}

#[bench]
fn bench_executing_line_number_programs(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    // We happen to know that there is a line number program and header at
    // offset 0 and that address size is 8 bytes. No need to parse DIEs to grab
    // this info off of the compilation units.
    let offset = DebugLineOffset(0);
    let address_size = 8;

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, offset, address_size)
            .expect("Should parse line number program header");

        let state_machine = StateMachine::new(&header);
        for row in state_machine {
            let row = row.expect("Should parse and execute all rows in the line number program");
            test::black_box(row);
        }
    });
}
<|endoftext|>


<commit_before>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug, Eq, PartialEq)]
pub enum ErrorKind {
  IO(io::ErrorKind),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
  // Parser Error
  HeaderParser,
  MetadataHeaderParser,
  StreamInfoParser,
  PaddingParser,
  ApplicationParser,
  SeekTableParser,
  VorbisCommentParser,
  CueSheetParser,
  PictureParser,
  UnknownParser,
  FrameFooterParser,
  // Invalid Error
  InvalidBlockType,
  InvalidCRC8,
  InvalidCRC16,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add `ErrorKind::NotFound`<commit_after>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug, Eq, PartialEq)]
pub enum ErrorKind {
  IO(io::ErrorKind),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
  // Parser Error
  HeaderParser,
  MetadataHeaderParser,
  StreamInfoParser,
  PaddingParser,
  ApplicationParser,
  SeekTableParser,
  VorbisCommentParser,
  CueSheetParser,
  PictureParser,
  UnknownParser,
  FrameFooterParser,
  // Invalid Error
  InvalidBlockType,
  InvalidCRC8,
  InvalidCRC16,
  // Not Found
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

use std::sync::{atomic::AtomicBool, mpsc, Arc};
use std::thread;
use std::time::Duration;

use raft::eraftpb::MessageType;
use tikv_util::HandyRwLock;

use test_raftstore::*;

enum FailureType<'a> {
    Partition(&'a [u64], &'a [u64]),
    Reboot(&'a [u64]),
}

fn attach_prevote_notifiers<T: Simulator>(cluster: &Cluster<T>, peer: u64) -> mpsc::Receiver<()> {
    // Setup a notifier
    let (tx, rx) = mpsc::channel();
    let response_notifier = Box::new(MessageTypeNotifier::new(
        MessageType::MsgRequestPreVoteResponse,
        tx.clone(),
        Arc::from(AtomicBool::new(true)),
    ));
    let request_notifier = Box::new(MessageTypeNotifier::new(
        MessageType::MsgRequestPreVote,
        tx,
        Arc::from(AtomicBool::new(true)),
    ));

    cluster.sim.wl().add_send_filter(peer, response_notifier);
    cluster.sim.wl().add_send_filter(peer, request_notifier);

    rx
}

// Validate that prevote is used in elections after partition or reboot of some nodes.
fn test_prevote<T: Simulator>(
    cluster: &mut Cluster<T>,
    failure_type: FailureType<'_>,
    leader_after_failure_id: impl Into<Option<u64>>,
    detect_during_failure: impl Into<Option<(u64, bool)>>,
    detect_during_recovery: impl Into<Option<(u64, bool)>>,
) {
    cluster.cfg.raft_store.prevote = true;
    // To stable the test, we use a large election timeout to make
    // leader's readiness get handle within an election timeout
    configure_for_lease_read(cluster, Some(20), Some(10));

    let leader_id = 1;
    let detect_during_failure = detect_during_failure.into();
    let detect_during_recovery = detect_during_recovery.into();

    // We must start the cluster before adding send filters, otherwise it panics.
    cluster.run();

    cluster.must_transfer_leader(1, new_peer(leader_id, 1));
    cluster.must_put(b"k1", b"v1");

    // Determine how to fail.
    let rx = if let Some((id, _)) = detect_during_failure {
        let rx = attach_prevote_notifiers(cluster, id);
        debug!("Attached failure prevote notifier.");
        Some(rx)
    } else {
        None
    };

    match failure_type {
        FailureType::Partition(majority, minority) => {
            cluster.partition(majority.to_vec(), minority.to_vec());
        }
        FailureType::Reboot(peers) => {
            peers.iter().for_each(|&peer| cluster.stop_node(peer));
        }
    };

    if let (Some(rx), Some((_, should_detect))) = (rx, detect_during_failure) {
        // Once we see a response on the wire we know a prevote round is happening.
        let received = rx.recv_timeout(Duration::from_secs(5));
        debug!("Done with failure prevote notifier, got {:?}", received);
        assert_eq!(
            received.is_ok(),
            should_detect,
            "Sends a PreVote or PreVoteResponse during failure.",
        );
    }

    // Let the cluster recover.
    match failure_type {
        FailureType::Partition(_, _) => {
            cluster.clear_send_filters();
        }
        FailureType::Reboot(peers) => {
            cluster.clear_send_filters();
            peers.iter().for_each(|&peer| {
                cluster.run_node(peer).unwrap();
            });
        }
    };

    // Prepare to listen.
    let rx = if let Some((id, _)) = detect_during_recovery {
        let rx = attach_prevote_notifiers(cluster, id);
        debug!("Attached recovery prevote notifier.");
        Some(rx)
    } else {
        None
    };

    if let Some(leader_id) = leader_after_failure_id.into() {
        cluster.must_transfer_leader(1, new_peer(leader_id, 1));
    };

    // Once we see a response on the wire we know a prevote round is happening.
    if let (Some(rx), Some((_, should_detect))) = (rx, detect_during_failure) {
        let received = rx.recv_timeout(Duration::from_secs(5));
        debug!("Done with recovery prevote notifier, got {:?}", received);

        assert_eq!(
            received.is_ok(),
            should_detect,
            "Sends a PreVote or PreVoteResponse during recovery.",
        );
    };

    cluster.must_put(b"k3", b"v3");
    assert_eq!(cluster.must_get(b"k1"), Some(b"v1".to_vec()));
}

#[test]
fn test_prevote_partition_leader_in_majority_detect_in_majority() {
    let mut cluster = new_node_cluster(0, 5);
    // Since the leader is in the majority and not rebooted, it sees no prevote.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2, 3], &[4, 5]),
        None,
        (1, false),
        (1, false),
    );
}

// TODO: Enable detect after failure when we can reliably capture the prevote.
#[test]
fn test_prevote_partition_leader_in_majority_detect_in_minority() {
    let mut cluster = new_node_cluster(0, 5);
    // The follower is in the minority and is part of a prevote process. On rejoin it adopts the
    // old leader.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2, 3], &[4, 5]),
        None,
        (4, true),
        None,
    );
}

// TODO: Enable detect after failure when we can reliably capture the prevote.
#[test]
fn test_prevote_partition_leader_in_minority_detect_in_majority() {
    let mut cluster = new_node_cluster(0, 5);
    // The follower is in the minority and is part of a prevote process. On rejoin it adopts the
    // old leader.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2], &[3, 4, 5]),
        None,
        (4, true),
        None,
    );
}

// TODO: Enable detect after failure when we can reliably capture the prevote.
#[test]
fn test_prevote_partition_leader_in_minority_detect_in_minority() {
    let mut cluster = new_node_cluster(0, 5);
    // The follower is in the minority and is part of a prevote process. On rejoin it adopts the
    // old leader.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2, 3], &[3, 4, 5]),
        None,
        (4, true),
        None,
    );
}

#[test]
fn test_prevote_reboot_majority_followers() {
    let mut cluster = new_node_cluster(0, 5);
    // A prevote round will start, but nothing will succeed.
    test_prevote(
        &mut cluster,
        FailureType::Reboot(&[3, 4, 5]),
        1,
        (1, true),
        None,
    );
}

#[test]
fn test_prevote_reboot_minority_followers() {
    let mut cluster = new_node_cluster(0, 5);
    // A prevote round will start, but nothing will succeed until recovery.
    test_prevote(
        &mut cluster,
        FailureType::Reboot(&[4, 5]),
        None,
        (2, false),
        (2, false),
    );
}

// Test isolating a minority of the cluster and make sure that the remove themselves.
#[cfg(feature = "protobuf-codec")]
fn test_pair_isolated<T: Simulator>(cluster: &mut Cluster<T>) {
    let region = 1;
    let pd_client = Arc::clone(&cluster.pd_client);

    // Given some nodes A, B, C, D, E, we partition the cluster such that D, E are isolated from the rest.
    cluster.run();
    // Choose a predictable leader so we don't accidentally partition the leader.
    cluster.must_transfer_leader(region, new_peer(1, 1));
    cluster.partition(vec![1, 2, 3], vec![4, 5]);

    // Then, add a policy to PD that it should ask the Raft leader to remove the peer from the group.
    pd_client.must_remove_peer(region, new_peer(4, 4));
    pd_client.must_remove_peer(region, new_peer(5, 5));

    // Verify the nodes have self removed.
    cluster.must_remove_region(4, region);
    cluster.must_remove_region(5, region);
}

// FIXME(nrc) failing on CI only
#[cfg(feature = "protobuf-codec")]
#[test]
fn test_server_pair_isolated() {
    let mut cluster = new_server_cluster(0, 5);
    test_pair_isolated(&mut cluster);
}

fn test_isolated_follower_leader_does_not_change<T: Simulator>(cluster: &mut Cluster<T>) {
    cluster.run();
    cluster.must_transfer_leader(1, new_peer(1, 1));
    cluster.must_put(b"k1", b"v1");
    let region_status = new_status_request(1, new_peer(1, 1), new_region_leader_cmd());
    let resp = cluster
        .call_command(region_status.clone(), Duration::from_secs(5))
        .unwrap();
    let term = resp.get_header().get_current_term();
    // Isolate peer5.
    cluster.partition(vec![1, 2, 3, 4], vec![5]);
    let election_timeout = cluster.cfg.raft_store.raft_base_tick_interval.0
        * cluster.cfg.raft_store.raft_election_timeout_ticks as u32;
    // Peer5 should not increase its term.
    thread::sleep(election_timeout * 2);
    // Now peer5 can send messages to others
    cluster.clear_send_filters();
    thread::sleep(election_timeout * 2);
    cluster.must_put(b"k1", b"v1");
    // Peer1 is still the leader.
    let leader = cluster.leader_of_region(1);
    assert_eq!(leader, Some(new_peer(1, 1)));
    // And the term is not changed.
    let resp = cluster
        .call_command(region_status, Duration::from_secs(5))
        .unwrap();
    let current_term = resp.get_header().get_current_term();
    assert_eq!(term, current_term);
}

#[test]
fn test_server_isolated_follower_leader_does_not_change() {
    let mut cluster = new_server_cluster(0, 5);
    test_isolated_follower_leader_does_not_change(&mut cluster);
}

fn test_create_peer_from_pre_vote<T: Simulator>(cluster: &mut Cluster<T>) {
    let pd_client = Arc::clone(&cluster.pd_client);
    pd_client.disable_default_operator();

    let r1 = cluster.run_conf_change();
    cluster.must_put(b"k1", b"v1");

    let rx = attach_prevote_notifiers(cluster, 1);
    cluster.add_send_filter(IsolationFilterFactory::new(2));
    pd_client.must_add_peer(r1, new_peer(2, 2));

    if rx.recv_timeout(Duration::from_secs(3)).is_err() {
        panic!("peer 1 should send pre vote");
    }

    // The peer 2 should be created.
    cluster.clear_send_filters();
    must_get_equal(&cluster.get_engine(2), b"k1", b"v1");
}

#[test]
fn test_node_create_peer_from_pre_vote() {
    let mut cluster = new_node_cluster(0, 2);
    cluster.cfg.raft_store.prevote = true;
    test_create_peer_from_pre_vote(&mut cluster);
}
<commit_msg>test: stabilize prevote cases. (#6472)<commit_after>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

use std::sync::{atomic::AtomicBool, mpsc, Arc};
use std::thread;
use std::time::Duration;

use raft::eraftpb::MessageType;
use tikv_util::HandyRwLock;

use test_raftstore::*;

enum FailureType<'a> {
    Partition(&'a [u64], &'a [u64]),
    Reboot(&'a [u64]),
}

fn attach_prevote_notifiers<T: Simulator>(cluster: &Cluster<T>, peer: u64) -> mpsc::Receiver<()> {
    // Setup a notifier
    let (tx, rx) = mpsc::channel();
    let response_notifier = Box::new(MessageTypeNotifier::new(
        MessageType::MsgRequestPreVoteResponse,
        tx.clone(),
        Arc::from(AtomicBool::new(true)),
    ));
    let request_notifier = Box::new(MessageTypeNotifier::new(
        MessageType::MsgRequestPreVote,
        tx,
        Arc::from(AtomicBool::new(true)),
    ));

    cluster.sim.wl().add_send_filter(peer, response_notifier);
    cluster.sim.wl().add_send_filter(peer, request_notifier);

    rx
}

// Validate that prevote is used in elections after partition or reboot of some nodes.
fn test_prevote<T: Simulator>(
    cluster: &mut Cluster<T>,
    failure_type: FailureType<'_>,
    leader_after_failure_id: impl Into<Option<u64>>,
    detect_during_failure: impl Into<Option<(u64, bool)>>,
    detect_during_recovery: impl Into<Option<(u64, bool)>>,
) {
    cluster.cfg.raft_store.prevote = true;
    // Disable this feature because the test could run slow, in which case peers shouldn't
    // hibernate, otherwise it's possible to detect no vote messages.
    cluster.cfg.raft_store.hibernate_regions = false;
    // To stable the test, we use a large election timeout to make
    // leader's readiness get handle within an election timeout
    configure_for_lease_read(cluster, Some(20), Some(10));

    let leader_id = 1;
    let detect_during_failure = detect_during_failure.into();
    let detect_during_recovery = detect_during_recovery.into();

    // We must start the cluster before adding send filters, otherwise it panics.
    cluster.run();

    cluster.must_transfer_leader(1, new_peer(leader_id, 1));
    cluster.must_put(b"k1", b"v1");

    // Determine how to fail.
    let rx = if let Some((id, _)) = detect_during_failure {
        let rx = attach_prevote_notifiers(cluster, id);
        debug!("Attached failure prevote notifier.");
        Some(rx)
    } else {
        None
    };

    match failure_type {
        FailureType::Partition(majority, minority) => {
            cluster.partition(majority.to_vec(), minority.to_vec());
        }
        FailureType::Reboot(peers) => {
            peers.iter().for_each(|&peer| cluster.stop_node(peer));
        }
    };

    if let (Some(rx), Some((_, should_detect))) = (rx, detect_during_failure) {
        // Once we see a response on the wire we know a prevote round is happening.
        let received = rx.recv_timeout(Duration::from_secs(5));
        debug!("Done with failure prevote notifier, got {:?}", received);
        assert_eq!(
            received.is_ok(),
            should_detect,
            "Sends a PreVote or PreVoteResponse during failure.",
        );
    }

    // Let the cluster recover.
    match failure_type {
        FailureType::Partition(_, _) => {
            cluster.clear_send_filters();
        }
        FailureType::Reboot(peers) => {
            cluster.clear_send_filters();
            peers.iter().for_each(|&peer| {
                cluster.run_node(peer).unwrap();
            });
        }
    };

    // Prepare to listen.
    let rx = if let Some((id, _)) = detect_during_recovery {
        let rx = attach_prevote_notifiers(cluster, id);
        debug!("Attached recovery prevote notifier.");
        Some(rx)
    } else {
        None
    };

    if let Some(leader_id) = leader_after_failure_id.into() {
        cluster.must_transfer_leader(1, new_peer(leader_id, 1));
    };

    // Once we see a response on the wire we know a prevote round is happening.
    if let (Some(rx), Some((_, should_detect))) = (rx, detect_during_failure) {
        let received = rx.recv_timeout(Duration::from_secs(5));
        debug!("Done with recovery prevote notifier, got {:?}", received);

        assert_eq!(
            received.is_ok(),
            should_detect,
            "Sends a PreVote or PreVoteResponse during recovery.",
        );
    };

    cluster.must_put(b"k3", b"v3");
    assert_eq!(cluster.must_get(b"k1"), Some(b"v1".to_vec()));
}

#[test]
fn test_prevote_partition_leader_in_majority_detect_in_majority() {
    let mut cluster = new_node_cluster(0, 5);
    // Since the leader is in the majority and not rebooted, it sees no prevote.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2, 3], &[4, 5]),
        None,
        (1, false),
        (1, false),
    );
}

// TODO: Enable detect after failure when we can reliably capture the prevote.
#[test]
fn test_prevote_partition_leader_in_majority_detect_in_minority() {
    let mut cluster = new_node_cluster(0, 5);
    // The follower is in the minority and is part of a prevote process. On rejoin it adopts the
    // old leader.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2, 3], &[4, 5]),
        None,
        (4, true),
        None,
    );
}

// TODO: Enable detect after failure when we can reliably capture the prevote.
#[test]
fn test_prevote_partition_leader_in_minority_detect_in_majority() {
    let mut cluster = new_node_cluster(0, 5);
    // The follower is in the minority and is part of a prevote process. On rejoin it adopts the
    // old leader.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2], &[3, 4, 5]),
        None,
        (4, true),
        None,
    );
}

// TODO: Enable detect after failure when we can reliably capture the prevote.
#[test]
fn test_prevote_partition_leader_in_minority_detect_in_minority() {
    let mut cluster = new_node_cluster(0, 5);
    // The follower is in the minority and is part of a prevote process. On rejoin it adopts the
    // old leader.
    test_prevote(
        &mut cluster,
        FailureType::Partition(&[1, 2, 3], &[3, 4, 5]),
        None,
        (4, true),
        None,
    );
}

#[test]
fn test_prevote_reboot_majority_followers() {
    let mut cluster = new_node_cluster(0, 5);
    // A prevote round will start, but nothing will succeed.
    test_prevote(
        &mut cluster,
        FailureType::Reboot(&[3, 4, 5]),
        1,
        (1, true),
        None,
    );
}

#[test]
fn test_prevote_reboot_minority_followers() {
    let mut cluster = new_node_cluster(0, 5);
    // A prevote round will start, but nothing will succeed until recovery.
    test_prevote(
        &mut cluster,
        FailureType::Reboot(&[4, 5]),
        None,
        (2, false),
        (2, false),
    );
}

// Test isolating a minority of the cluster and make sure that the remove themselves.
#[cfg(feature = "protobuf-codec")]
fn test_pair_isolated<T: Simulator>(cluster: &mut Cluster<T>) {
    let region = 1;
    let pd_client = Arc::clone(&cluster.pd_client);

    // Given some nodes A, B, C, D, E, we partition the cluster such that D, E are isolated from the rest.
    cluster.run();
    // Choose a predictable leader so we don't accidentally partition the leader.
    cluster.must_transfer_leader(region, new_peer(1, 1));
    cluster.partition(vec![1, 2, 3], vec![4, 5]);

    // Then, add a policy to PD that it should ask the Raft leader to remove the peer from the group.
    pd_client.must_remove_peer(region, new_peer(4, 4));
    pd_client.must_remove_peer(region, new_peer(5, 5));

    // Verify the nodes have self removed.
    cluster.must_remove_region(4, region);
    cluster.must_remove_region(5, region);
}

// FIXME(nrc) failing on CI only
#[cfg(feature = "protobuf-codec")]
#[test]
fn test_server_pair_isolated() {
    let mut cluster = new_server_cluster(0, 5);
    test_pair_isolated(&mut cluster);
}

fn test_isolated_follower_leader_does_not_change<T: Simulator>(cluster: &mut Cluster<T>) {
    cluster.run();
    cluster.must_transfer_leader(1, new_peer(1, 1));
    cluster.must_put(b"k1", b"v1");
    let region_status = new_status_request(1, new_peer(1, 1), new_region_leader_cmd());
    let resp = cluster
        .call_command(region_status.clone(), Duration::from_secs(5))
        .unwrap();
    let term = resp.get_header().get_current_term();
    // Isolate peer5.
    cluster.partition(vec![1, 2, 3, 4], vec![5]);
    let election_timeout = cluster.cfg.raft_store.raft_base_tick_interval.0
        * cluster.cfg.raft_store.raft_election_timeout_ticks as u32;
    // Peer5 should not increase its term.
    thread::sleep(election_timeout * 2);
    // Now peer5 can send messages to others
    cluster.clear_send_filters();
    thread::sleep(election_timeout * 2);
    cluster.must_put(b"k1", b"v1");
    // Peer1 is still the leader.
    let leader = cluster.leader_of_region(1);
    assert_eq!(leader, Some(new_peer(1, 1)));
    // And the term is not changed.
    let resp = cluster
        .call_command(region_status, Duration::from_secs(5))
        .unwrap();
    let current_term = resp.get_header().get_current_term();
    assert_eq!(term, current_term);
}

#[test]
fn test_server_isolated_follower_leader_does_not_change() {
    let mut cluster = new_server_cluster(0, 5);
    test_isolated_follower_leader_does_not_change(&mut cluster);
}

fn test_create_peer_from_pre_vote<T: Simulator>(cluster: &mut Cluster<T>) {
    let pd_client = Arc::clone(&cluster.pd_client);
    pd_client.disable_default_operator();

    let r1 = cluster.run_conf_change();
    cluster.must_put(b"k1", b"v1");

    let rx = attach_prevote_notifiers(cluster, 1);
    cluster.add_send_filter(IsolationFilterFactory::new(2));
    pd_client.must_add_peer(r1, new_peer(2, 2));

    if rx.recv_timeout(Duration::from_secs(3)).is_err() {
        panic!("peer 1 should send pre vote");
    }

    // The peer 2 should be created.
    cluster.clear_send_filters();
    must_get_equal(&cluster.get_engine(2), b"k1", b"v1");
}

#[test]
fn test_node_create_peer_from_pre_vote() {
    let mut cluster = new_node_cluster(0, 2);
    cluster.cfg.raft_store.prevote = true;
    test_create_peer_from_pre_vote(&mut cluster);
}
<|endoftext|>


<commit_before>use alloc::arc::Arc;

use collections::string::{String, ToString};
use collections::vec::Vec;

use core::cell::UnsafeCell;
use core::ops::DerefMut;
use core::{mem, ptr};

use common::elf::Elf;
use common::memory;

use scheduler;
use scheduler::context::{CONTEXT_STACK_SIZE, CONTEXT_STACK_ADDR, context_switch,
context_userspace, Context, ContextMemory};

use schemes::Url;

/// Excecute an excecutable
pub fn execute(url: Url, mut args: Vec<String>) {
    unsafe {

        if let Some(current) = Context::current_mut() {

            let reenable = scheduler::start_no_ints();
            let cptr = current.deref_mut();
            scheduler::end_no_ints(reenable);

            Context::spawn("kexec ".to_string() + &url.string, box move || {
                if let Some(mut resource) = url.open() {
                    let mut vec: Vec<u8> = Vec::new();
                    resource.read_to_end(&mut vec);

                    let executable = Elf::from_data(vec.as_ptr() as usize);
                    let entry = executable.entry();
                    let mut memory = Vec::new();
                    for segment in executable.load_segment().iter() {
                        let virtual_address = segment.vaddr as usize;
                        let virtual_size = segment.mem_len as usize;
                        let physical_address = memory::alloc(virtual_size);

                        if physical_address > 0 {
                            // Copy progbits
                            ::memcpy(physical_address as *mut u8,
                                     (executable.data + segment.off as usize) as *const u8,
                                     segment.file_len as usize);
                            // Zero bss
                            ::memset((physical_address + segment.file_len as usize) as *mut u8,
                            0,
                            segment.mem_len as usize - segment.file_len as usize);

                            memory.push(ContextMemory {
                                physical_address: physical_address,
                                virtual_address: virtual_address,
                                virtual_size: virtual_size,
                                writeable: segment.flags & 2 == 2
                            });
                        }
                    }

                    if entry > 0 && ! memory.is_empty() {
                        args.insert(0, url.to_string());

                        let mut context_args: Vec<usize> = Vec::new();
                        context_args.push(0); // ENVP
                        context_args.push(0); // ARGV NULL
                        let mut argc = 0;
                        for i in 0..args.len() {
                            if let Some(arg) = args.get(args.len() - i - 1) {
                                context_args.push(arg.as_ptr() as usize);
                                argc += 1;
                            }
                        }
                        context_args.push(argc);

                        let reenable = scheduler::start_no_ints();

                        let context = cptr;

                        context.name = url.to_string();

                        context.sp = context.kernel_stack + CONTEXT_STACK_SIZE - 128;

                        context.stack = Some(ContextMemory {
                            physical_address: memory::alloc(CONTEXT_STACK_SIZE),
                            virtual_address: CONTEXT_STACK_ADDR,
                            virtual_size: CONTEXT_STACK_SIZE,
                            writeable: true
                        });

                        context.args = Arc::new(UnsafeCell::new(args));
                        context.cwd = Arc::new(UnsafeCell::new((*context.cwd.get()).clone()));
                        context.memory = Arc::new(UnsafeCell::new(memory));

                        let user_sp = if let Some(ref stack) = context.stack {
                            let mut sp = stack.physical_address + stack.virtual_size - 128;
                            for arg in context_args.iter() {
                                sp -= mem::size_of::<usize>();
                                ptr::write(sp as *mut usize, *arg);
                            }
                            sp - stack.physical_address + stack.virtual_address
                        } else {
                            0
                        };

                        context.push(0x20 | 3);
                        context.push(user_sp);
                        context.push(1 << 9);
                        context.push(0x18 | 3);
                        context.push(entry);
                        context.push(context_userspace as usize);

                        scheduler::end_no_ints(reenable);
                    } else {
                        debug!("{}: Invalid memory or entry\n", url.string);
                    }
                } else {
                    debug!("{}: Failed to open\n", url.string);
                }
            });

            loop {
                context_switch(false);
            }
        }
    }
}
<commit_msg>Fix a typo<commit_after>use alloc::arc::Arc;

use collections::string::{String, ToString};
use collections::vec::Vec;

use core::cell::UnsafeCell;
use core::ops::DerefMut;
use core::{mem, ptr};

use common::elf::Elf;
use common::memory;

use scheduler;
use scheduler::context::{CONTEXT_STACK_SIZE, CONTEXT_STACK_ADDR, context_switch,
context_userspace, Context, ContextMemory};

use schemes::Url;

/// Execute an executable
pub fn execute(url: Url, mut args: Vec<String>) {
    unsafe {

        if let Some(current) = Context::current_mut() {

            let reenable = scheduler::start_no_ints();
            let cptr = current.deref_mut();
            scheduler::end_no_ints(reenable);

            Context::spawn("kexec ".to_string() + &url.string, box move || {
                if let Some(mut resource) = url.open() {
                    let mut vec: Vec<u8> = Vec::new();
                    resource.read_to_end(&mut vec);

                    let executable = Elf::from_data(vec.as_ptr() as usize);
                    let entry = executable.entry();
                    let mut memory = Vec::new();
                    for segment in executable.load_segment().iter() {
                        let virtual_address = segment.vaddr as usize;
                        let virtual_size = segment.mem_len as usize;
                        let physical_address = memory::alloc(virtual_size);

                        if physical_address > 0 {
                            // Copy progbits
                            ::memcpy(physical_address as *mut u8,
                                     (executable.data + segment.off as usize) as *const u8,
                                     segment.file_len as usize);
                            // Zero bss
                            ::memset((physical_address + segment.file_len as usize) as *mut u8,
                            0,
                            segment.mem_len as usize - segment.file_len as usize);

                            memory.push(ContextMemory {
                                physical_address: physical_address,
                                virtual_address: virtual_address,
                                virtual_size: virtual_size,
                                writeable: segment.flags & 2 == 2
                            });
                        }
                    }

                    if entry > 0 && ! memory.is_empty() {
                        args.insert(0, url.to_string());

                        let mut context_args: Vec<usize> = Vec::new();
                        context_args.push(0); // ENVP
                        context_args.push(0); // ARGV NULL
                        let mut argc = 0;
                        for i in 0..args.len() {
                            if let Some(arg) = args.get(args.len() - i - 1) {
                                context_args.push(arg.as_ptr() as usize);
                                argc += 1;
                            }
                        }
                        context_args.push(argc);

                        let reenable = scheduler::start_no_ints();

                        let context = cptr;

                        context.name = url.to_string();

                        context.sp = context.kernel_stack + CONTEXT_STACK_SIZE - 128;

                        context.stack = Some(ContextMemory {
                            physical_address: memory::alloc(CONTEXT_STACK_SIZE),
                            virtual_address: CONTEXT_STACK_ADDR,
                            virtual_size: CONTEXT_STACK_SIZE,
                            writeable: true
                        });

                        context.args = Arc::new(UnsafeCell::new(args));
                        context.cwd = Arc::new(UnsafeCell::new((*context.cwd.get()).clone()));
                        context.memory = Arc::new(UnsafeCell::new(memory));

                        let user_sp = if let Some(ref stack) = context.stack {
                            let mut sp = stack.physical_address + stack.virtual_size - 128;
                            for arg in context_args.iter() {
                                sp -= mem::size_of::<usize>();
                                ptr::write(sp as *mut usize, *arg);
                            }
                            sp - stack.physical_address + stack.virtual_address
                        } else {
                            0
                        };

                        context.push(0x20 | 3);
                        context.push(user_sp);
                        context.push(1 << 9);
                        context.push(0x18 | 3);
                        context.push(entry);
                        context.push(context_userspace as usize);

                        scheduler::end_no_ints(reenable);
                    } else {
                        debug!("{}: Invalid memory or entry\n", url.string);
                    }
                } else {
                    debug!("{}: Failed to open\n", url.string);
                }
            });

            loop {
                context_switch(false);
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[get("/")]
fn get() {  }

#[put("/")]
fn put() {  }

#[post("/")]
fn post() {  }

#[delete("/")]
fn delete() {  }

#[head("/")]
fn head() {  }

#[patch("/")]
fn patch() {  }

// TODO: Allow this once Diesel incompatibility is fixed.
// #[options("/")]
// fn options() {  }

fn main() { }
<commit_msg>Test methods via route attribute.<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[get("/")] fn get() {  }
#[route(GET, "/")] fn get_r() {  }

#[put("/")] fn put() {  }
#[route(PUT, "/")] fn put_r() {  }

#[post("/")] fn post() {  }
#[route(POST, "/")] fn post_r() {  }

#[delete("/")] fn delete() {  }
#[route(DELETE, "/")] fn delete_r() {  }

#[head("/")] fn head() {  }
#[route(HEAD, "/")] fn head_r() {  }

#[patch("/")] fn patch() {  }
#[route(PATCH, "/")] fn patch_r() {  }

// TODO: Allow this once Diesel incompatibility is fixed.
// #[options("/")] fn options() {  }
#[route(OPTIONS, "/")] fn options_r() {  }

fn main() { }
<|endoftext|>


<commit_before>// Copyright 2012 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.

// Basic sanity check for `push_unsafe!(EXPR)` and
// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
// positive number of pushes in the stack, or if we are within a
// normal `unsafe` block, but otherwise cannot.

static mut X: i32 = 0;

unsafe fn f() { X += 1; return; }
fn g() { unsafe { X += 1_000; } return; }

fn main() {
    push_unsafe!( {
        f(); pop_unsafe!({
            f() //~ ERROR: call to unsafe function
        })
    } );

    push_unsafe!({
        f();
        pop_unsafe!({
            g();
            f(); //~ ERROR: call to unsafe function
        })
    } );

    push_unsafe!({
        g(); pop_unsafe!({
            unsafe {
                f();
            }
            f(); //~ ERROR: call to unsafe function
        })
    });

    // Note: For implementation simplicity I have chosen to just have
    // the stack do "saturated pop", but perhaps we would prefer to
    // have cases like these two here be errors:

    pop_unsafe!{ g() };

    push_unsafe!({
        pop_unsafe!(pop_unsafe!{ g() })
    });

    // Okay, back to examples that do error, even in the presence of
    // "saturated pop"

    push_unsafe!({
        g();
        pop_unsafe!(pop_unsafe!({
            f() //~ ERROR: call to unsafe function
        }))
    });

    pop_unsafe!({
        f(); //~ ERROR: call to unsafe function
    })

}
<commit_msg>Add necessary feature gate opt-in for the pushpop_unsafe test.<commit_after>// Copyright 2012 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.

// Basic sanity check for `push_unsafe!(EXPR)` and
// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
// positive number of pushes in the stack, or if we are within a
// normal `unsafe` block, but otherwise cannot.

#![feature(pushpop_unsafe)]

static mut X: i32 = 0;

unsafe fn f() { X += 1; return; }
fn g() { unsafe { X += 1_000; } return; }

fn main() {
    push_unsafe!( {
        f(); pop_unsafe!({
            f() //~ ERROR: call to unsafe function
        })
    } );

    push_unsafe!({
        f();
        pop_unsafe!({
            g();
            f(); //~ ERROR: call to unsafe function
        })
    } );

    push_unsafe!({
        g(); pop_unsafe!({
            unsafe {
                f();
            }
            f(); //~ ERROR: call to unsafe function
        })
    });

    // Note: For implementation simplicity I have chosen to just have
    // the stack do "saturated pop", but perhaps we would prefer to
    // have cases like these two here be errors:

    pop_unsafe!{ g() };

    push_unsafe!({
        pop_unsafe!(pop_unsafe!{ g() })
    });

    // Okay, back to examples that do error, even in the presence of
    // "saturated pop"

    push_unsafe!({
        g();
        pop_unsafe!(pop_unsafe!({
            f() //~ ERROR: call to unsafe function
        }))
    });

    pop_unsafe!({
        f(); //~ ERROR: call to unsafe function
    })

}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use diem_logger::json_log::JsonLogEntry;
use reqwest::blocking;
use std::collections::HashMap;

pub mod node_debug_service;

/// Implement default utility client for NodeDebugInterface
pub struct NodeDebugClient {
    client: blocking::Client,
    addr: String,
}

impl NodeDebugClient {
    /// Create NodeDebugInterfaceClient from a valid socket address.
    pub fn new<A: AsRef<str>>(address: A, port: u16) -> Self {
        let client = blocking::Client::new();
        let addr = format!("http://{}:{}", address.as_ref(), port);

        Self { client, addr }
    }

    /// Retrieves the individual node metric.  Requires all sub fields to match in alphabetical order.
    pub fn get_node_metric<S: AsRef<str>>(&mut self, metric: S) -> Result<Option<i64>> {
        let metrics = self.get_node_metrics()?;
        Ok(metrics.get(metric.as_ref()).cloned())
    }

    /// Retrieves all node metrics for a given metric name.  Allows for filtering metrics by fields afterwards.
    pub fn get_node_metric_with_name(
        &mut self,
        metric: &str,
    ) -> Result<Option<HashMap<String, i64>>> {
        let metrics = self.get_node_metrics()?;
        let search_string = format!("{}{{", metric);

        let result: HashMap<_, _> = metrics
            .iter()
            .filter_map(|(key, value)| {
                if key.starts_with(&search_string) {
                    Some((key.clone(), *value))
                } else {
                    None
                }
            })
            .collect();

        if result.is_empty() {
            Ok(None)
        } else {
            Ok(Some(result))
        }
    }

    pub fn get_node_metrics(&mut self) -> Result<HashMap<String, i64>> {
        let response = self.client.get(&format!("{}/metrics", self.addr)).send()?;

        response
            .json::<HashMap<String, String>>()?
            .into_iter()
            .map(|(k, v)| match v.parse::<i64>() {
                Ok(v) => Ok((k, v)),
                Err(_) => Err(anyhow::format_err!(
                    "Failed to parse stat value to i64 {}: {}",
                    &k,
                    &v
                )),
            })
            .collect()
    }

    pub fn get_events(&mut self) -> Result<Vec<JsonLogEntry>> {
        let response = self.client.get(&format!("{}/events", self.addr)).send()?;

        Ok(response.json()?)
    }
}

/// Implement default utility client for AsyncNodeDebugInterface
pub struct AsyncNodeDebugClient {
    client: reqwest::Client,
    addr: String,
}

impl AsyncNodeDebugClient {
    /// Create AsyncNodeDebugInterface from a valid socket address.
    pub fn new<A: AsRef<str>>(client: reqwest::Client, address: A, port: u16) -> Self {
        let addr = format!("http://{}:{}", address.as_ref(), port);

        Self { client, addr }
    }

    pub async fn get_node_metric<S: AsRef<str>>(&mut self, metric: S) -> Result<Option<i64>> {
        let metrics = self.get_node_metrics().await?;
        Ok(metrics.get(metric.as_ref()).cloned())
    }

    pub async fn get_node_metrics(&mut self) -> Result<HashMap<String, i64>> {
        let response = self
            .client
            .get(&format!("{}/metrics", self.addr))
            .send()
            .await?;

        response
            .json::<HashMap<String, String>>()
            .await?
            .into_iter()
            .map(|(k, v)| match v.parse::<i64>() {
                Ok(v) => Ok((k, v)),
                Err(_) => Err(anyhow::format_err!(
                    "Failed to parse stat value to i64 {}: {}",
                    &k,
                    &v
                )),
            })
            .collect()
    }

    pub async fn get_events(&mut self) -> Result<Vec<JsonLogEntry>> {
        let response = self
            .client
            .get(&format!("{}/events", self.addr))
            .send()
            .await?;

        Ok(response.json().await?)
    }
}
<commit_msg>debug-interface: client improvements<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use diem_logger::json_log::JsonLogEntry;
use reqwest::{blocking, Url};
use std::collections::HashMap;

pub mod node_debug_service;

/// Implement default utility client for NodeDebugInterface
pub struct NodeDebugClient {
    client: blocking::Client,
    url: Url,
}

impl NodeDebugClient {
    /// Create NodeDebugInterfaceClient from a valid socket address.
    pub fn new<A: AsRef<str>>(address: A, port: u16) -> Self {
        let url = Url::parse(&format!("http://{}:{}", address.as_ref(), port)).unwrap();

        Self::from_url(url)
    }

    pub fn from_url(url: Url) -> Self {
        let client = blocking::Client::new();

        Self { client, url }
    }

    /// Retrieves the individual node metric.  Requires all sub fields to match in alphabetical order.
    pub fn get_node_metric<S: AsRef<str>>(&self, metric: S) -> Result<Option<i64>> {
        let metrics = self.get_node_metrics()?;
        Ok(metrics.get(metric.as_ref()).cloned())
    }

    /// Retrieves all node metrics for a given metric name.  Allows for filtering metrics by fields afterwards.
    pub fn get_node_metric_with_name(&self, metric: &str) -> Result<Option<HashMap<String, i64>>> {
        let metrics = self.get_node_metrics()?;
        let search_string = format!("{}{{", metric);

        let result: HashMap<_, _> = metrics
            .iter()
            .filter_map(|(key, value)| {
                if key.starts_with(&search_string) {
                    Some((key.clone(), *value))
                } else {
                    None
                }
            })
            .collect();

        if result.is_empty() {
            Ok(None)
        } else {
            Ok(Some(result))
        }
    }

    pub fn get_node_metrics(&self) -> Result<HashMap<String, i64>> {
        let mut url = self.url.clone();
        url.set_path("metrics");
        let response = self.client.get(url).send()?;

        if !response.status().is_success() {
            anyhow::bail!("Error querying metrics: {}", response.status());
        }

        response
            .json::<HashMap<String, String>>()?
            .into_iter()
            .map(|(k, v)| match v.parse::<i64>() {
                Ok(v) => Ok((k, v)),
                Err(_) => Err(anyhow::format_err!(
                    "Failed to parse stat value to i64 {}: {}",
                    &k,
                    &v
                )),
            })
            .collect()
    }

    pub fn get_events(&self) -> Result<Vec<JsonLogEntry>> {
        let mut url = self.url.clone();
        url.set_path("events");
        let response = self.client.get(url).send()?;

        Ok(response.json()?)
    }
}

/// Implement default utility client for AsyncNodeDebugInterface
pub struct AsyncNodeDebugClient {
    client: reqwest::Client,
    addr: String,
}

impl AsyncNodeDebugClient {
    /// Create AsyncNodeDebugInterface from a valid socket address.
    pub fn new<A: AsRef<str>>(client: reqwest::Client, address: A, port: u16) -> Self {
        let addr = format!("http://{}:{}", address.as_ref(), port);

        Self { client, addr }
    }

    pub async fn get_node_metric<S: AsRef<str>>(&mut self, metric: S) -> Result<Option<i64>> {
        let metrics = self.get_node_metrics().await?;
        Ok(metrics.get(metric.as_ref()).cloned())
    }

    pub async fn get_node_metrics(&mut self) -> Result<HashMap<String, i64>> {
        let response = self
            .client
            .get(&format!("{}/metrics", self.addr))
            .send()
            .await?;

        response
            .json::<HashMap<String, String>>()
            .await?
            .into_iter()
            .map(|(k, v)| match v.parse::<i64>() {
                Ok(v) => Ok((k, v)),
                Err(_) => Err(anyhow::format_err!(
                    "Failed to parse stat value to i64 {}: {}",
                    &k,
                    &v
                )),
            })
            .collect()
    }

    pub async fn get_events(&mut self) -> Result<Vec<JsonLogEntry>> {
        let response = self
            .client
            .get(&format!("{}/events", self.addr))
            .send()
            .await?;

        Ok(response.json().await?)
    }
}
<|endoftext|>