<commit_before>//! Contains information for keybindings.

use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...
use std::hash::{Hash, Hasher};

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        let press_s = KeyPress::from_key_names(vec!["Mod4"], vec!["s"]).unwrap();
        map.insert(press_s, Arc::new(Box::new(key_s)));

        let press_f4 = KeyPress::from_key_names(vec!["Alt"],vec!["F4"]).unwrap();
        map.insert(press_f4, Arc::new(Box::new(key_f4)));

        let press_l = KeyPress::from_key_names(vec!["Ctrl"], vec!["l"]).unwrap();
        map.insert(press_l, Arc::new(Box::new(key_lua)));

        let press_k = KeyPress::from_key_names(
            vec!["Ctrl"], vec!["k"]).unwrap();
        map.insert(press_k, Arc::new(Box::new(key_sleep)));

        RwLock::new(map)
    };
}

fn key_sleep() {
    use std::thread;
    use std::time::Duration;

    use super::lua;
    use lua::LuaQuery;

    info!("keyhandler: Beginning thread::sleep keypress!");
    lua::send(LuaQuery::Execute("print('>entering sleep')\
                                 os.execute('sleep 5')\
                                 print('>leaving sleep')".to_string()));
    //thread::sleep(Duration::from_secs(5));
    info!("keyhandler: Finished thread::sleep keypress!");
}

fn key_s() {
    info!("[Key handler] S keypress!");
}

fn key_f4() {
    info!("[Key handler] F4 keypress!");
}

fn key_lua() {
    use super::lua;
    use lua::LuaQuery;
    info!("[Key handler] ctrl+l keypress!");
    lua::send(LuaQuery::Execute("print('Hello world from lua keypress!')".to_string()));
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        match keymod_from_names(mods) {
            Err(message) => Err(message),
            Ok(mods) => {
                let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
                for name in keys {
                    if let Some(sym) = Keysym::from_name(name.to_string(),
                                                         NameFlags::None) {
                            syms.push(sym);
                    }
                    // Else if could not parse
                    else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                        NameFlags::CaseInsensitive) {
                        syms.push(sym);
                    }
                    else {
                        return Err(format!("Invalid key: {}", name));
                    }
                }
                syms.sort_by_key(|s| s.get_code());
                syms.dedup();
                return Ok(KeyPress { modifiers: mods, keys: syms });
            }
        }
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read().unwrap();
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new key mapping
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write().unwrap();
    for value in values {
        bindings.insert(value.0, value.1);
    }
}
<commit_msg>Add ctrl+p to print pointer location from lua<commit_after>//! Contains information for keybindings.

use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...
use std::hash::{Hash, Hasher};

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        let press_s = KeyPress::from_key_names(vec!["Mod4"], vec!["s"]).unwrap();
        map.insert(press_s, Arc::new(Box::new(key_s)));

        let press_f4 = KeyPress::from_key_names(vec!["Alt"],vec!["F4"]).unwrap();
        map.insert(press_f4, Arc::new(Box::new(key_f4)));

        let press_k = KeyPress::from_key_names(
            vec!["Ctrl"], vec!["k"]).unwrap();
        map.insert(press_k, Arc::new(Box::new(key_sleep)));

        let press_p = KeyPress::from_key_names(vec!["Ctrl"], vec!["p"]).unwrap();
        map.insert(press_p, Arc::new(Box::new(key_pointer_pos)));

        RwLock::new(map)
    };
}

fn key_sleep() {
    use std::thread;
    use std::time::Duration;

    use super::lua;
    use lua::LuaQuery;

    info!("keyhandler: Beginning thread::sleep keypress!");
    lua::send(LuaQuery::Execute("print('>entering sleep')\
                                 os.execute('sleep 5')\
                                 print('>leaving sleep')".to_string()));
    info!("keyhandler: Finished thread::sleep keypress!");
}

fn key_pointer_pos() {
    use super::lua;
    use lua::LuaQuery;
    let code = "if wm == nil then print('wm table does not exist')\n\
                elseif wm.pointer == nil then print('wm.pointer table does not exist')\n\
                else\n\
                print('get_position is a func, preparing execution')
                local x, y = wm.pointer.get_position()\n\
                print('The cursor is at ' .. x .. ', ' .. y)\n\
                end".to_string();
    lua::send(LuaQuery::Execute(code));
}

fn key_s() {
    info!("[Key handler] S keypress!");
}

fn key_f4() {
    info!("[Key handler] F4 keypress!");
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        match keymod_from_names(mods) {
            Err(message) => Err(message),
            Ok(mods) => {
                let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
                for name in keys {
                    if let Some(sym) = Keysym::from_name(name.to_string(),
                                                         NameFlags::None) {
                            syms.push(sym);
                    }
                    // Else if could not parse
                    else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                        NameFlags::CaseInsensitive) {
                        syms.push(sym);
                    }
                    else {
                        return Err(format!("Invalid key: {}", name));
                    }
                }
                syms.sort_by_key(|s| s.get_code());
                syms.dedup();
                return Ok(KeyPress { modifiers: mods, keys: syms });
            }
        }
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read().unwrap();
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new key mapping
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write().unwrap();
    for value in values {
        bindings.insert(value.0, value.1);
    }
}
<|endoftext|>


<commit_before>// main.rs
// Main entry point for a Rust version
// of some (micro-) benchmarks
//
// vim: ft=rust sw=4 ts=4
//

extern crate image;
extern crate num;
extern crate num_complex;
extern crate rayon;
extern crate time;

use time::precise_time_ns;

// declare submodules
mod fibonacci;
mod mandelbrot;
mod perfect_number;
mod primes;

// a helper function to time closures
fn time_it<F, T>(fun: F) -> (T, u64)
where
    F: Fn() -> T,
{
    let tic = precise_time_ns();
    let res = fun();
    let toc = precise_time_ns();

    (res, (toc - tic) / 1_000_000)
}

fn main() {
    println!("Rust benchmarks");
    println!("===============");

    println!();

    println!("Fibonacci numbers:");
    println!("------------------");

    let (res, elap) = time_it(|| fibonacci::fib_naive(35));
    println!("fib_naive(35) = {}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| fibonacci::fib(35));
    println!("fib(35) = {}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| fibonacci::fib(1000));
    println!("fib(1000) = {}\tElapsed: {}ms", res, elap);

    println!();

    println!("Prime numbers:");
    println!("--------------");

    let (res, elap) = time_it(|| primes::find_primes(1_000_000));
    println!("find_primes(1_000_000): {:?} primes\tElapsed: {}ms", res.len(), elap);

    let (res, elap) = time_it(|| primes::find_primes_rayon(1_000_000));
    println!("find_primes_rayon(1_000_000): {:?} primes\tElapsed: {}ms", res.len(), elap);

    println!();

    println!("Perfect numbers:");
    println!("----------------");

    let (res, elap) = time_it(|| perfect_number::perfect_numbers(10000));
    println!("pn(10000) = {:?}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| perfect_number::perfect_number_iter(4));
    println!("pn_iter(4) = {:?}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| perfect_number::perfect_numbers_rayon(10000));
    println!("pn_rayon(10000) = {:?}\tElapsed: {}ms", res, elap);

    println!();

    println!("Mandelbrot set:");
    println!("--------------");

    let (res, elap) = time_it(|| mandelbrot::mandelbrot(640, 480, -0.5, 0.0, 4.0 / f64::from(640)));
    println!("mandelbrot(640, 480) done\tElapsed: {}ms", elap);
    let (_, elap) = time_it(|| res.save("./mandelbrot.png").unwrap());
    println!("mandelbrot(640, 480) written to PNG\tElapsed: {}ms", elap);

    let (res, elap) =
        time_it(|| mandelbrot::mandelbrot(1920, 1200, -0.5, 0.0, 4.0 / f64::from(1920)));
    println!("mandelbrot(1920, 1200) done\tElapsed: {}ms", elap);
    let (_, elap) = time_it(|| res.save("./mandelbrot.png").unwrap());
    println!("mandelbrot(1920, 1200) written to PNG\tElapsed: {}ms", elap);

    let _: Vec<()> = vec![1, 2, 4, 8, 16, 30, 60]
        .into_iter()
        .map(|i| {
            let (_res, elap) = time_it(|| {
                mandelbrot::mandelbrot_rayon(1920, 1200, -0.5, 0.0, 4.0 / f64::from(1920), i)
            });
            println!("mandelbrot_rayon(1920, 1200, {}) done\tElapsed: {}ms", i, elap);
        })
        .collect();

    let (_, elap) = time_it(|| res.save("./mandelbrot.png").unwrap());
    println!(
        "mandelbrot_rayon(1920, 1200) written to PNG\tElapsed: {}ms",
        elap
    );
    println!();

    println!("------------------");
    println!("Done!");
}
<commit_msg>format source<commit_after>// main.rs
// Main entry point for a Rust version
// of some (micro-) benchmarks
//
// vim: ft=rust sw=4 ts=4
//

extern crate image;
extern crate num;
extern crate num_complex;
extern crate rayon;
extern crate time;

use time::precise_time_ns;

// declare submodules
mod fibonacci;
mod mandelbrot;
mod perfect_number;
mod primes;

// a helper function to time closures
fn time_it<F, T>(fun: F) -> (T, u64)
where
    F: Fn() -> T,
{
    let tic = precise_time_ns();
    let res = fun();
    let toc = precise_time_ns();

    (res, (toc - tic) / 1_000_000)
}

fn main() {
    println!("Rust benchmarks");
    println!("===============");

    println!();

    println!("Fibonacci numbers:");
    println!("------------------");

    let (res, elap) = time_it(|| fibonacci::fib_naive(35));
    println!("fib_naive(35) = {}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| fibonacci::fib(35));
    println!("fib(35) = {}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| fibonacci::fib(1000));
    println!("fib(1000) = {}\tElapsed: {}ms", res, elap);

    println!();

    println!("Prime numbers:");
    println!("--------------");

    let (res, elap) = time_it(|| primes::find_primes(1_000_000));
    println!(
        "find_primes(1_000_000): {:?} primes\tElapsed: {}ms",
        res.len(),
        elap
    );

    let (res, elap) = time_it(|| primes::find_primes_rayon(1_000_000));
    println!(
        "find_primes_rayon(1_000_000): {:?} primes\tElapsed: {}ms",
        res.len(),
        elap
    );

    println!();

    println!("Perfect numbers:");
    println!("----------------");

    let (res, elap) = time_it(|| perfect_number::perfect_numbers(10000));
    println!("pn(10000) = {:?}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| perfect_number::perfect_number_iter(4));
    println!("pn_iter(4) = {:?}\tElapsed: {}ms", res, elap);

    let (res, elap) = time_it(|| perfect_number::perfect_numbers_rayon(10000));
    println!("pn_rayon(10000) = {:?}\tElapsed: {}ms", res, elap);

    println!();

    println!("Mandelbrot set:");
    println!("--------------");

    let (res, elap) = time_it(|| mandelbrot::mandelbrot(640, 480, -0.5, 0.0, 4.0 / f64::from(640)));
    println!("mandelbrot(640, 480) done\tElapsed: {}ms", elap);
    let (_, elap) = time_it(|| res.save("./mandelbrot.png").unwrap());
    println!("mandelbrot(640, 480) written to PNG\tElapsed: {}ms", elap);

    let (res, elap) =
        time_it(|| mandelbrot::mandelbrot(1920, 1200, -0.5, 0.0, 4.0 / f64::from(1920)));
    println!("mandelbrot(1920, 1200) done\tElapsed: {}ms", elap);
    let (_, elap) = time_it(|| res.save("./mandelbrot.png").unwrap());
    println!("mandelbrot(1920, 1200) written to PNG\tElapsed: {}ms", elap);

    let _: Vec<()> = vec![1, 2, 4, 8, 16, 30, 60]
        .into_iter()
        .map(|i| {
            let (_res, elap) = time_it(|| {
                mandelbrot::mandelbrot_rayon(1920, 1200, -0.5, 0.0, 4.0 / f64::from(1920), i)
            });
            println!(
                "mandelbrot_rayon(1920, 1200, {}) done\tElapsed: {}ms",
                i, elap
            );
        })
        .collect();

    let (_, elap) = time_it(|| res.save("./mandelbrot.png").unwrap());
    println!(
        "mandelbrot_rayon(1920, 1200) written to PNG\tElapsed: {}ms",
        elap
    );
    println!();

    println!("------------------");
    println!("Done!");
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
use std::fmt;

use hab_net::conn::RouteClient;
use rand::{self, Rng};
use time::SteadyTime;
use time::Duration as SteadyDuration;
use threadpool::ThreadPool;

use pool::Pool;
use error::Result;

pub type DispatchKey = String;
pub type EventFunction = fn(Pool, RouteClient) -> Result<EventOutcome>;

pub enum EventOutcome {
    Finished,
    Retry,
}

const BACKOFF_SLOT_TIME_MS: u64 = 100;
const FAILURE_COUNT_UPPER_BOUND: usize = 10;

#[derive(Clone)]
pub struct AsyncServer {
    pool: Pool,
    router_pipe: Arc<String>,
    stop: Arc<AtomicBool>,
    pub dispatch: Arc<RwLock<HashMap<DispatchKey, EventFunction>>>,
    pub failure_count: Arc<RwLock<HashMap<DispatchKey, usize>>>,
    pub retry: Arc<RwLock<HashMap<DispatchKey, (SteadyTime, EventFunction)>>>,
    pub running: Arc<RwLock<HashSet<DispatchKey>>>,
}

impl fmt::Debug for AsyncServer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AsyncServer")
    }
}

impl AsyncServer {
    pub fn new(pool: Pool, router_pipe: Arc<String>) -> AsyncServer {
        AsyncServer {
            pool: pool,
            router_pipe: router_pipe,
            stop: Arc::new(AtomicBool::new(false)),
            dispatch: Arc::new(RwLock::new(HashMap::new())),
            failure_count: Arc::new(RwLock::new(HashMap::new())),
            retry: Arc::new(RwLock::new(HashMap::new())),
            running: Arc::new(RwLock::new(HashSet::new())),
        }
    }

    pub fn schedule(&self, dispatch_key: &str) -> Result<()> {
        let has_key = {
            let d = self.dispatch.read().expect(
                "Async dispatch lock is poisoned",
            );
            d.contains_key(dispatch_key)
        };
        let is_scheduled = {
            let r = self.retry.read().expect("Async retry lock is poisoned");
            r.contains_key(dispatch_key)
        };
        if has_key && !is_scheduled {
            let function = {
                let d = self.dispatch.read().expect(
                    "Async dispatch lock is poisoned",
                );
                // Safe because we checked above
                d.get(dispatch_key).unwrap().clone()
            };
            let mut r = self.retry.write().expect("Async retry lock is poisoned");
            r.insert(dispatch_key.to_string(), (SteadyTime::now(), function));
        }
        Ok(())
    }

    pub fn register(&self, dispatch_key: DispatchKey, callback: EventFunction) {
        {
            let mut d = self.dispatch.write().expect(
                "Async dispatch lock is poisoned",
            );
            d.insert(dispatch_key.clone(), callback.clone());
        }
        {
            let mut r = self.retry.write().expect("Async retry lock is poisoned");
            r.insert(dispatch_key, (SteadyTime::now(), callback));
        }
    }

    fn get_num_events(&self, available_jobs: usize) -> Vec<(DispatchKey, EventFunction)> {
        let r = self.retry.read().expect("Async retry lock is poisoned");
        r.iter()
            .filter(|&(_dispatch_key, &(event_time, _callback))| {
                SteadyTime::now() >= event_time
            })
            .take(available_jobs)
            .map(|(dispatch_key, &(_event_time, callback))| {
                (dispatch_key.to_string(), callback.clone())
            })
            .collect()
    }

    pub fn run_event(&self, key: DispatchKey, event: EventFunction) {
        let remove_key = key.clone();
        let conn = RouteClient::new().expect("failed to create RouteClient");
        conn.connect(&*self.router_pipe).expect(
            "failed to connect RouteClient to inproc pipe",
        );
        match event(self.pool.clone(), conn) {
            Ok(EventOutcome::Finished) => {
                debug!("Event finished {}", key);
                let mut r = self.retry.write().expect("Async retry lock poisoned");
                let mut f = self.failure_count.write().expect(
                    "Async failure count lock poisoned",
                );
                f.remove(&key);
                r.remove(&key);
            }
            Ok(EventOutcome::Retry) => {
                self.retry_failed_event(key, event);
            }
            Err(e) => {
                warn!("Event {} failed, {}", key, e);
                self.retry_failed_event(key, event);
            }
        }
        let mut running = self.running.write().expect("Running lock is poisoned");
        running.remove(&remove_key);
    }

    fn retry_failed_event(&self, key: DispatchKey, event: EventFunction) {
        warn!("Scheduling retry of {:?}", key);
        let failure_count = {
            let mut f = self.failure_count.write().expect(
                "Async failure count lock poisoned",
            );
            let mut value = f.entry(key.clone()).or_insert(0);
            *value += 1;
            if *value >= FAILURE_COUNT_UPPER_BOUND {
                *value
            } else {
                FAILURE_COUNT_UPPER_BOUND
            }
        };
        let mut rng = rand::thread_rng();
        let high_end = 2u64.pow(failure_count as u32);
        let cycles = rng.gen_range(0, high_end);
        let next_event = SteadyTime::now() +
            SteadyDuration::milliseconds((cycles * BACKOFF_SLOT_TIME_MS) as i64);
        info!("Backing off {:?} for {:?}", key, next_event);
        let mut r = self.retry.write().expect("Async retry lock poisoned");
        r.insert(key, (next_event, event));
    }

    pub fn stop(&self) {
        self.stop.store(true, Ordering::SeqCst);
    }

    pub fn start(self, workers: usize) {
        let server = self;

        let _ = thread::Builder::new()
            .name("async-events".to_string())
            .spawn(move || {
                let threadpool =
                    ThreadPool::new_with_name("async-event-worker".to_string(), workers);
                loop {
                    if server.stop.load(Ordering::SeqCst) {
                        return;
                    }
                    let available_jobs = threadpool.max_count() - threadpool.active_count();
                    if available_jobs == 0 {
                        info!("Async Pool is full; delaying all events for 500ms");
                        thread::sleep(Duration::from_millis(500));
                        continue;
                    }
                    let events = server.get_num_events(available_jobs);
                    for (key, event) in events.into_iter() {
                        let is_running = {
                            let running_events =
                                server.running.read().expect("Running events lock poisoned");
                            running_events.contains(&key)
                        };
                        if !is_running {
                            let sa = server.clone();
                            error!("Dispatching {}", key);
                            {
                                let mut running_events = server.running.write().expect(
                                    "Running events lock poisoned",
                                );
                                running_events.insert(key.clone());
                            }
                            {
                                let mut r =
                                    server.retry.write().expect("Async write lock poisoned");
                                r.remove(&key);
                            }
                            threadpool.execute(move || sa.run_event(key, event));
                        }
                    }
                    thread::sleep(Duration::from_millis(200));
                }
            });
    }
}
<commit_msg>Reassign debug output in db::async module from error to debug<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
use std::fmt;

use hab_net::conn::RouteClient;
use rand::{self, Rng};
use time::SteadyTime;
use time::Duration as SteadyDuration;
use threadpool::ThreadPool;

use pool::Pool;
use error::Result;

pub type DispatchKey = String;
pub type EventFunction = fn(Pool, RouteClient) -> Result<EventOutcome>;

pub enum EventOutcome {
    Finished,
    Retry,
}

const BACKOFF_SLOT_TIME_MS: u64 = 100;
const FAILURE_COUNT_UPPER_BOUND: usize = 10;

#[derive(Clone)]
pub struct AsyncServer {
    pool: Pool,
    router_pipe: Arc<String>,
    stop: Arc<AtomicBool>,
    pub dispatch: Arc<RwLock<HashMap<DispatchKey, EventFunction>>>,
    pub failure_count: Arc<RwLock<HashMap<DispatchKey, usize>>>,
    pub retry: Arc<RwLock<HashMap<DispatchKey, (SteadyTime, EventFunction)>>>,
    pub running: Arc<RwLock<HashSet<DispatchKey>>>,
}

impl fmt::Debug for AsyncServer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AsyncServer")
    }
}

impl AsyncServer {
    pub fn new(pool: Pool, router_pipe: Arc<String>) -> AsyncServer {
        AsyncServer {
            pool: pool,
            router_pipe: router_pipe,
            stop: Arc::new(AtomicBool::new(false)),
            dispatch: Arc::new(RwLock::new(HashMap::new())),
            failure_count: Arc::new(RwLock::new(HashMap::new())),
            retry: Arc::new(RwLock::new(HashMap::new())),
            running: Arc::new(RwLock::new(HashSet::new())),
        }
    }

    pub fn schedule(&self, dispatch_key: &str) -> Result<()> {
        let has_key = {
            let d = self.dispatch.read().expect(
                "Async dispatch lock is poisoned",
            );
            d.contains_key(dispatch_key)
        };
        let is_scheduled = {
            let r = self.retry.read().expect("Async retry lock is poisoned");
            r.contains_key(dispatch_key)
        };
        if has_key && !is_scheduled {
            let function = {
                let d = self.dispatch.read().expect(
                    "Async dispatch lock is poisoned",
                );
                // Safe because we checked above
                d.get(dispatch_key).unwrap().clone()
            };
            let mut r = self.retry.write().expect("Async retry lock is poisoned");
            r.insert(dispatch_key.to_string(), (SteadyTime::now(), function));
        }
        Ok(())
    }

    pub fn register(&self, dispatch_key: DispatchKey, callback: EventFunction) {
        {
            let mut d = self.dispatch.write().expect(
                "Async dispatch lock is poisoned",
            );
            d.insert(dispatch_key.clone(), callback.clone());
        }
        {
            let mut r = self.retry.write().expect("Async retry lock is poisoned");
            r.insert(dispatch_key, (SteadyTime::now(), callback));
        }
    }

    fn get_num_events(&self, available_jobs: usize) -> Vec<(DispatchKey, EventFunction)> {
        let r = self.retry.read().expect("Async retry lock is poisoned");
        r.iter()
            .filter(|&(_dispatch_key, &(event_time, _callback))| {
                SteadyTime::now() >= event_time
            })
            .take(available_jobs)
            .map(|(dispatch_key, &(_event_time, callback))| {
                (dispatch_key.to_string(), callback.clone())
            })
            .collect()
    }

    pub fn run_event(&self, key: DispatchKey, event: EventFunction) {
        let remove_key = key.clone();
        let conn = RouteClient::new().expect("failed to create RouteClient");
        conn.connect(&*self.router_pipe).expect(
            "failed to connect RouteClient to inproc pipe",
        );
        match event(self.pool.clone(), conn) {
            Ok(EventOutcome::Finished) => {
                debug!("Event finished {}", key);
                let mut r = self.retry.write().expect("Async retry lock poisoned");
                let mut f = self.failure_count.write().expect(
                    "Async failure count lock poisoned",
                );
                f.remove(&key);
                r.remove(&key);
            }
            Ok(EventOutcome::Retry) => {
                self.retry_failed_event(key, event);
            }
            Err(e) => {
                warn!("Event {} failed, {}", key, e);
                self.retry_failed_event(key, event);
            }
        }
        let mut running = self.running.write().expect("Running lock is poisoned");
        running.remove(&remove_key);
    }

    fn retry_failed_event(&self, key: DispatchKey, event: EventFunction) {
        warn!("Scheduling retry of {:?}", key);
        let failure_count = {
            let mut f = self.failure_count.write().expect(
                "Async failure count lock poisoned",
            );
            let mut value = f.entry(key.clone()).or_insert(0);
            *value += 1;
            if *value >= FAILURE_COUNT_UPPER_BOUND {
                *value
            } else {
                FAILURE_COUNT_UPPER_BOUND
            }
        };
        let mut rng = rand::thread_rng();
        let high_end = 2u64.pow(failure_count as u32);
        let cycles = rng.gen_range(0, high_end);
        let next_event = SteadyTime::now() +
            SteadyDuration::milliseconds((cycles * BACKOFF_SLOT_TIME_MS) as i64);
        info!("Backing off {:?} for {:?}", key, next_event);
        let mut r = self.retry.write().expect("Async retry lock poisoned");
        r.insert(key, (next_event, event));
    }

    pub fn stop(&self) {
        self.stop.store(true, Ordering::SeqCst);
    }

    pub fn start(self, workers: usize) {
        let server = self;

        let _ = thread::Builder::new()
            .name("async-events".to_string())
            .spawn(move || {
                let threadpool =
                    ThreadPool::new_with_name("async-event-worker".to_string(), workers);
                loop {
                    if server.stop.load(Ordering::SeqCst) {
                        return;
                    }
                    let available_jobs = threadpool.max_count() - threadpool.active_count();
                    if available_jobs == 0 {
                        info!("Async Pool is full; delaying all events for 500ms");
                        thread::sleep(Duration::from_millis(500));
                        continue;
                    }
                    let events = server.get_num_events(available_jobs);
                    for (key, event) in events.into_iter() {
                        let is_running = {
                            let running_events =
                                server.running.read().expect("Running events lock poisoned");
                            running_events.contains(&key)
                        };
                        if !is_running {
                            let sa = server.clone();
                            debug!("Dispatching {}", key);
                            {
                                let mut running_events = server.running.write().expect(
                                    "Running events lock poisoned",
                                );
                                running_events.insert(key.clone());
                            }
                            {
                                let mut r =
                                    server.retry.write().expect("Async write lock poisoned");
                                r.remove(&key);
                            }
                            threadpool.execute(move || sa.run_event(key, event));
                        }
                    }
                    thread::sleep(Duration::from_millis(200));
                }
            });
    }
}
<|endoftext|>


<commit_before>#![macro_escape]

//! LVal: The basic object type

use std::fmt;
use parser::ast::{Expr, ExprNode};
use util::print_error;

/// Return an error
macro_rules! err(
    ($msg:expr) => (
        return LVal::err($msg.into_string())
    );

    ($msg:expr, $( $args:expr ),* ) => (
        return LVal::err(format!($msg, $($args),* ))
    );
)

/// A basic object
pub enum LVal {
    Num(f64),
    Err(String),
    Sym(String),
    SExpr(Vec<LVal>)
}

impl LVal {

    // --- Constructors ---------------------------------------------------------

    /// Create a new number lval
    pub fn num(value: f64) -> LVal {
        LVal::Num(value)
    }

    /// Create a new error lval
    pub fn err(msg: String) -> LVal {
        LVal::Err(msg)
    }

    /// Create a new symbol lval
    pub fn sym(symbol: &str) -> LVal {
        LVal::Sym(symbol.into_string())
    }

    /// Create a new sepxr lval
    pub fn sexpr() -> LVal {
        LVal::SExpr(vec![])
    }

    /// Construct a lval from a given AST
    pub fn from_ast(ast: ExprNode) -> LVal {
        match ast.value {
            Expr::Number(i) => LVal::num(i as f64),
            Expr::Symbol(s) => LVal::sym(s[]),
            Expr::SExpr(exprs) => {
                let mut sexpr = LVal::sexpr();
                for child in exprs.into_iter() {
                    sexpr.append(LVal::from_ast(child));
                }

                sexpr
            }
        }
    }

    // --- Public methods -------------------------------------------------------

    /// Delete a lval
    pub fn del(self) {}

    pub fn get_num(&self) -> f64 {
        if let LVal::Num(i) = *self {
            return i
        } else {
            panic!("Cannot get number of non-number: {}", self)
        }
    }

    /// Append a lval to a sexpr
    ///
    /// Panics when `self` is not a SExpr
    pub fn append(&mut self, expr: LVal) {
        if let LVal::SExpr(ref mut values) = *self {
            values.push(expr);
        } else {
            panic!("cannot extend a non-sexpr")
        }
    }
}

impl fmt::Show for LVal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            LVal::Num(i)          => write!(f, "{}", i),
            LVal::Err(ref msg)    => { print_error(msg[]); Ok(()) },
            LVal::Sym(ref symbol) => write!(f, "{}", symbol),
            LVal::SExpr(ref values) => {
                write!(f, "({})", values.iter()
                                        .map(|v| format!("{}", v))
                                        .collect::<Vec<_>>()
                                        .connect(" "))
            }
        }
    }
}<commit_msg>Fix tests after last chapter<commit_after>#![macro_escape]

//! LVal: The basic object type

use std;
use std::fmt;
use parser::ast::{Expr, ExprNode};
use util::print_error;

/// Return an error
macro_rules! err(
    ($msg:expr) => (
        return LVal::err($msg.into_string())
    );

    ($msg:expr, $( $args:expr ),* ) => (
        return LVal::err(format!($msg, $($args),* ))
    );
)

// Tricking the compiler into thinking that floats are Eq...
// Fixme: Better solution?
#[deriving(PartialEq)]
pub struct Float(f64);

impl std::cmp::Eq for Float {
    #[inline]
    fn assert_receiver_is_total_eq(&self) {}
}

impl fmt::Show for Float {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Float(value) = *self;
        write!(f, "{}", value)
    }
}

/// A basic object
#[deriving(Eq, PartialEq)]
pub enum LVal {
    Num(Float),
    Err(String),
    Sym(String),
    SExpr(Vec<LVal>)
}

impl LVal {

    // --- Constructors ---------------------------------------------------------

    /// Create a new number lval
    pub fn num(value: f64) -> LVal {
        LVal::Num(Float(value))
    }

    /// Create a new error lval
    pub fn err(msg: String) -> LVal {
        LVal::Err(msg)
    }

    /// Create a new symbol lval
    pub fn sym(symbol: &str) -> LVal {
        LVal::Sym(symbol.into_string())
    }

    /// Create a new sepxr lval
    pub fn sexpr() -> LVal {
        LVal::SExpr(vec![])
    }

    /// Construct a lval from a given AST
    pub fn from_ast(ast: ExprNode) -> LVal {
        match ast.value {
            Expr::Number(i) => LVal::num(i as f64),
            Expr::Symbol(s) => LVal::sym(s[]),
            Expr::SExpr(exprs) => {
                let mut sexpr = LVal::sexpr();
                for child in exprs.into_iter() {
                    sexpr.append(LVal::from_ast(child));
                }

                sexpr
            }
        }
    }

    // --- Public methods -------------------------------------------------------

    /// Delete a lval
    pub fn del(self) {}

    pub fn get_num(&self) -> f64 {
        if let LVal::Num(i) = *self {
            let Float(i) = i;
            return i
        } else {
            panic!("Cannot get number of non-number: {}", self)
        }
    }

    /// Append a lval to a sexpr
    ///
    /// Panics when `self` is not a SExpr
    pub fn append(&mut self, expr: LVal) {
        if let LVal::SExpr(ref mut values) = *self {
            values.push(expr);
        } else {
            panic!("cannot extend a non-sexpr")
        }
    }
}

impl fmt::Show for LVal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            LVal::Num(i)          => write!(f, "{}", i),
            LVal::Err(ref msg)    => { print_error(msg[]); Ok(()) },
            LVal::Sym(ref symbol) => write!(f, "{}", symbol),
            LVal::SExpr(ref values) => {
                write!(f, "({})", values.iter()
                                        .map(|v| format!("{}", v))
                                        .collect::<Vec<_>>()
                                        .connect(" "))
            }
        }
    }
}<|endoftext|>


<commit_before>extern crate num;
extern crate portaudio;
extern crate rtlsdr;
extern crate dft;
extern crate gnuplot;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;

use gnuplot::*;
use dft::{Operation, Plan};

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8.
const SDR_BUF_SIZE: usize = 262144;

// Separating out the buffer sizes seems to help some.
const BUF_SIZE: usize = 262144;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SAMPLE_RATE: u32 = 2880000;

// Here is the sample rate of the output waveform we'll try to use.
const SAMPLE_RATE_AUDIO: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency (MHz).")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Initialize the PortAudio class.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        SAMPLE_RATE_AUDIO as f64,
        BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;

    // We were decimating way too much. We need to decimate in two stages: one
    // to remove nearby stations and another to match the sound card. For
    // wideband signals, 8 and 3 seems to work well and also hits that sweet
    // spot of no buffer underflows!
    //
    // TODO: need to still calculate this on the fly. In addition, we need to
    // find apporpriate decimation values for narrowband. I'm still confident
    // that the decimation value depends on the bandwitdh, but I need to
    // figure out that appropriate formula.
    //
    let dec_rate_filt = 9;
    let dec_rate_audio = 3;
    let mut sdr =
        RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

    // This holds the previous value for the moving average filter so we can
    // keep track in between iterations of reading from the SDR.
    let mut prev = Complex::new(0.0, 0.0);

    // TODO: the number of taps here really affects the speed of the audio. Is
    // the filter decimating or am I just doing the filter wrong?
    let taps_filt = windowed_sinc(bandwidth as f32, SAMPLE_RATE as f32, 32);
    let taps_audio = windowed_sinc(
        bandwidth as f32 / dec_rate_filt as f32,
        SAMPLE_RATE as f32 / dec_rate_filt as f32,
        32,
    );

    loop {
        // Read the samples and decimate down to match the sample rate of
        // the audio that'll be going out.
        let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
        let mut iq_vec = read_samples(bytes).unwrap();
        iq_vec = filter(&iq_vec, &taps_filt);
        iq_vec = decimate(iq_vec.as_slice(), dec_rate_filt);

        // After decimation, demodulate the signal and send out of the
        // thread to the receiver.
        let res = demod_fm(iq_vec, prev);
        let mut demod_iq = filter_real(&res.0, &taps_audio);
        demod_iq = decimate(demod_iq.as_slice(), dec_rate_audio);
        prev = res.1;

        // Get the write stream and write our samples to the stream.
        let out_frames = match stream.write_available() {
            Ok(available) => {
                match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::OutputUnderflowed => {
                        return Err(Box::new(PAError::OutputUnderflowed))
                    }
                    _ => return Err(Box::new(PAError::NullCallback)),
                }
            }
            Err(e) => return Err(Box::new(e)),
        };

        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let write_frames = std::cmp::min(buffer_frames, out_frames);
        let n_write_samples = write_frames as usize * CHANNELS as usize;

        stream.write(
            write_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = 0.05 * demod_iq[ix];
            },
        )?;
    }
}

fn plot_spectrum<'a>(
    signal: &Vec<Complex<f32>>,
    figure: &'a mut Figure,
) -> &'a mut Figure {
    let mut sig = signal.clone();
    let radix_2: u32 = (sig.len() as f32).log2().ceil() as u32;
    let new_len = 2u32.pow(radix_2) as usize;
    sig.resize(new_len, Complex::zero());
    let plan = Plan::new(Operation::Forward, new_len);
    dft::transform(&mut sig, &plan);

    // Now generate a plot.
    figure.clear_axes();
    figure.axes2d().lines(
        0..new_len,
        sig.iter().map(|x| x.norm()),
        &[],
    );
    figure.show();
    figure
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_agc_mode(true));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn read_samples(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);

    // Write the values to the complex value and normalize from [0, 255] to
    // [-127, 128].
    for iq in bytes.chunks(2) {
        let iq_cmplx =
            Complex::new((iq[0] as f32 - 127.0), (iq[1] as f32 - 127.0));
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(
    iq: Vec<Complex<f32>>,
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    // TODO: calculate an appropriate gain here.
    let gain = SAMPLE_RATE as f32 / (2.0 * PI * 75e3 / 8.0);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

///
/// Filters a Complex vector.
///
fn filter<T: Copy + Num + Zero>(
    samples: &Vec<Complex<T>>,
    taps: &Vec<T>,
) -> Vec<Complex<T>> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Filter a real vector.
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &Vec<T>,
    taps: &Vec<T>,
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Generates taps for a Hamming window.
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

///
/// Generates filter taps for a sinc filter with a Hamming window.
///
fn windowed_sinc(cutoff_freq: f32, sample_rate: f32, ntaps: usize) -> Vec<f32> {
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    let win_taps: Vec<f32> = hamming(ntaps);
    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<commit_msg>Moved reading from the dongle and demodulation into threads<commit_after>extern crate num;
extern crate portaudio;
extern crate rtlsdr;
extern crate dft;
extern crate gnuplot;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

use gnuplot::*;
use dft::{Operation, Plan};

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8.
const SDR_BUF_SIZE: usize = 524288;

// Separating out the buffer sizes seems to help some.
const BUF_SIZE: usize = 262144;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SAMPLE_RATE: u32 = 2400000;

// Here is the sample rate of the output waveform we'll try to use.
const SAMPLE_RATE_AUDIO: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency (MHz).")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Initialize the PortAudio class.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        SAMPLE_RATE_AUDIO as f64,
        BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;

    // We were decimating way too much. We need to decimate in two stages: one
    // to remove nearby stations and another to match the sound card. For
    // wideband signals, 8 and 3 seems to work well and also hits that sweet
    // spot of no buffer underflows!
    //
    // TODO: need to still calculate this on the fly. In addition, we need to
    // find apporpriate decimation values for narrowband. I'm still confident
    // that the decimation value depends on the bandwitdh, but I need to
    // figure out that appropriate formula.
    //
    let dec_rate_filt = 24;
    let dec_rate_audio = 1;
    let mut sdr =
        RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

    // TODO: the number of taps here really affects the speed of the audio. Is
    // the filter decimating or am I just doing the filter wrong?
    let taps_filt = windowed_sinc(bandwidth as f32, SAMPLE_RATE as f32, 64);
    let taps_audio = windowed_sinc(
        bandwidth as f32 / dec_rate_filt as f32,
        SAMPLE_RATE as f32 / dec_rate_filt as f32,
        64,
    );

    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    thread::spawn(move || {
        loop {
            // Read the samples and decimate down to match the sample rate of
            // the audio that'll be going out.
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let mut iq_vec = read_samples(bytes).unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(iq_vec.as_slice(), dec_rate_filt);
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    thread::spawn(move || {
        let mut prev = Complex::zero();
        loop {
            // After decimation, demodulate the signal and send out of the
            // thread to the receiver.
            let iq_vec = dongle_rx.recv().unwrap();
            let res = demod_fm(iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            // demod_iq = decimate(demod_iq.as_slice(), dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        // Get the write stream and write our samples to the stream.
        let out_frames = match stream.write_available() {
            Ok(available) => {
                match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::OutputUnderflowed => {
                        return Err(Box::new(PAError::OutputUnderflowed))
                    }
                    _ => return Err(Box::new(PAError::NullCallback)),
                }
            }
            Err(e) => return Err(Box::new(e)),
        };

        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let write_frames = std::cmp::min(buffer_frames, out_frames);
        let n_write_samples = write_frames as usize * CHANNELS as usize;

        stream.write(
            write_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            },
        )?;
    }
}

fn plot_spectrum<'a>(
    signal: &Vec<Complex<f32>>,
    figure: &'a mut Figure,
) -> &'a mut Figure {
    let mut sig = signal.clone();
    let radix_2: u32 = (sig.len() as f32).log2().ceil() as u32;
    let new_len = 2u32.pow(radix_2) as usize;
    sig.resize(new_len, Complex::zero());
    let plan = Plan::new(Operation::Forward, new_len);
    dft::transform(&mut sig, &plan);

    // Now generate a plot.
    figure.clear_axes();
    figure.axes2d().lines(
        0..new_len,
        sig.iter().map(|x| x.norm()),
        &[],
    );
    figure.show();
    figure
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_agc_mode(true));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn read_samples(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);

    // Write the values to the complex value and normalize from [0, 255] to
    // [-127, 128].
    for iq in bytes.chunks(2) {
        let iq_cmplx =
            Complex::new((iq[0] as f32 - 127.0) / 127.0, (iq[1] as f32 - 127.0) / 127.0);
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(
    iq: Vec<Complex<f32>>,
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SAMPLE_RATE as f32 / (2.0 * PI * 75e3);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

///
/// Filters a Complex vector.
///
fn filter<T: Copy + Num + Zero>(
    samples: &Vec<Complex<T>>,
    taps: &Vec<T>,
) -> Vec<Complex<T>> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Filter a real vector.
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &Vec<T>,
    taps: &Vec<T>,
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Generates taps for a Hamming window.
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

///
/// Generates filter taps for a sinc filter with a Hamming window.
///
fn windowed_sinc(cutoff_freq: f32, sample_rate: f32, ntaps: usize) -> Vec<f32> {
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    let win_taps: Vec<f32> = hamming(ntaps);
    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<|endoftext|>


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

extern crate chrono;
extern crate rocket;

mod file_utils;

use rocket::response::NamedFile;
use std::io;
use std::path::{Path, PathBuf};

#[get("/")]
fn index() -> io::Result<NamedFile> {
    NamedFile::open("static/index.html")
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("static/").join(file)).ok()
}

#[post("/feedback/<fb>")]
fn feedback(fb: &str) -> Result<(), io::Error> {
    use chrono::{DateTime, Local};
    use file_utils::append_line_to_file;
    use std::io::ErrorKind;

    let timestamp: DateTime<Local> = Local::now();
    let fb_int = match fb {
        "bad" => Ok(-1),
        "neutral" => Ok(0),
        "good" => Ok(1),
        _ => Err(io::Error::new(ErrorKind::InvalidInput, "invalid feedback value")),
    }?;

    let line = format!("{},{:>2}", timestamp.to_rfc3339(), fb_int);
    append_line_to_file(&Path::new("./feedback.csv"), line)?;

    Ok(())
}

fn rocket() -> rocket::Rocket {
    rocket::ignite().mount("/", routes![index, files, feedback])
}

fn main() {
    rocket().launch();
}
<commit_msg>Added a draft of button mashing protection<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate chrono;
extern crate rocket;

mod file_utils;

use chrono::Local;
use rocket::response::NamedFile;
use rocket::State;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::atomic::AtomicUsize;

struct Timings {
    timestamp: AtomicUsize,
}
struct Config {
    log_file: PathBuf,
    cooldown: usize, // cooldown in seconds
}

#[get("/")]
fn index() -> io::Result<NamedFile> {
    NamedFile::open("static/index.html")
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("static/").join(file)).ok()
}

#[post("/feedback/<fb>")]
fn feedback(fb: &str, last: State<Timings>, conf: State<Config>) -> Result<(), io::Error> {
    use file_utils::append_line_to_file;
    use std::io::ErrorKind;
    use std::sync::atomic::Ordering;

    let curr_timestamp = Local::now().timestamp() as usize;
    let time_since_last = curr_timestamp - last.timestamp.load(Ordering::Relaxed);
    last.timestamp.store(curr_timestamp, Ordering::Relaxed);

    if time_since_last < conf.cooldown {
        return Err(io::Error::new(ErrorKind::Other, "button mashing detected"));
    }

    let fb_int = match fb {
        "bad" => Ok(-1),
        "neutral" => Ok(0),
        "good" => Ok(1),
        _ => Err(io::Error::new(ErrorKind::InvalidInput, "invalid feedback value")),
    }?;

    let line = format!("{},{:>2}", Local::now().to_rfc3339(), fb_int);
    append_line_to_file(&conf.log_file, line)?;

    Ok(())
}

fn main() {
    let conf = Config {
        log_file: PathBuf::from("./feedback.csv"),
        cooldown: 1, // seconds
    };
    let tmgs = Timings { timestamp: AtomicUsize::new(Local::now().timestamp() as usize) };

    rocket::ignite()
        .mount("/", routes![index, files, feedback])
        .manage(tmgs)
        .manage(conf)
        .launch();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate simplelog;
extern crate num_cpus;

use std::env;
use std::process;
use std::{thread, time};
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use simplelog::{Config, TermLogger, CombinedLogger, LogLevelFilter};

// Sleep interval between temperature checking.
const SLEEP_TIME_MILLI: u64 = 3000;

// File where minimum supported frequency should be colected.
const MIN_FREQ_FILE: &'static str = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq";

// File where maximum supported frequency should be colected.
const MAX_FREQ_FILE: &'static str = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";

// Step size to change cpu frequency.
const STEP_FREQ: u64 = 100000;

// Possible files where current temperature should be collected.
const POSSIBLE_TEMP_FILES: &'static [&'static str] = &[
	"/sys/class/thermal/thermal_zone0/temp",
	"/sys/class/thermal/thermal_zone1/temp",
	"/sys/class/thermal/thermal_zone2/temp",
	"/sys/class/hwmon/hwmon0/temp1_input",
	"/sys/class/hwmon/hwmon1/temp1_input",
	"/sys/class/hwmon/hwmon2/temp1_input",
	"/sys/class/hwmon/hwmon0/device/temp1_input",
	"/sys/class/hwmon/hwmon1/device/temp1_input",
	"/sys/class/hwmon/hwmon2/device/temp1_input",
];

fn parse_int_file(path: String) -> u64 {
	let mut content = String::new();
	let mut fp = File::open(path).unwrap();
	fp.read_to_string(&mut content).unwrap();
	content.trim().parse::<u64>().unwrap()
}

fn min_frequency() -> u64 {
	parse_int_file(MIN_FREQ_FILE.to_string())
}

fn max_frequency() -> u64 {
	parse_int_file(MAX_FREQ_FILE.to_string())
}

fn get_temp() -> u64 {
	for file in POSSIBLE_TEMP_FILES {
		if Path::new(file).exists() {
			return parse_int_file(file.to_string()) / 1000;
		}
	}
	error!("impossible to collect current cpu temperature!");
	process::exit(1);
}

fn set_freq(freq: u64) {
	info!("setting frequency to {}", freq);
	for c in 0..num_cpus::get() {
		let path = format!("/sys/devices/system/cpu/cpu{}/cpufreq/scaling_max_freq", c);
		let mut fp = File::create(path).unwrap();
		fp.write_all(format!("{}\n", freq).as_bytes()).unwrap();
	}
}

fn main() {
	CombinedLogger::init(
		vec![
			TermLogger::new(LogLevelFilter::Info, Config::default()).unwrap(),
		]
	).unwrap();

	let args: Vec<String> = env::args().collect();
	if args.len() != 2 {
		error!("usage: {} <max temp>", args[0]);
		process::exit(1);
	}

	let max_temp: u64;
	match args[1].parse::<u64>() {
		Err(_) => {
			error!("invalid temperature: {}", args[1]);
			process::exit(1);
		},
		Ok(x) => max_temp = x,
	}
	info!("maximum temperature: {}", max_temp);

	info!("cpu count: {}", num_cpus::get());

	let min_freq = min_frequency();
	info!("minimum frequency supported: {}", min_freq);
	let max_freq = max_frequency();
	info!("maximum frequency supported: {}", max_freq);

	let mut cur_freq = max_freq;
	set_freq(cur_freq);
	loop {
		let temp = get_temp();
		if temp > max_temp && cur_freq > min_freq {
			cur_freq -= STEP_FREQ;
			if cur_freq < min_freq {
				cur_freq = min_freq;
			}
			set_freq(cur_freq);
		}
		else if temp < (max_temp-5) && cur_freq < max_freq {
			cur_freq += STEP_FREQ;
			if cur_freq > max_freq {
				cur_freq = max_freq;
			}
			set_freq(cur_freq);
		}
		debug!("current temperature: {}", temp);
		thread::sleep(time::Duration::from_millis(SLEEP_TIME_MILLI));
	}
}
<commit_msg>TermLogger fails under systemd<commit_after>#[macro_use]
extern crate log;
extern crate simplelog;
extern crate num_cpus;

use std::env;
use std::process;
use std::{thread, time};
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use simplelog::{Config, SimpleLogger, CombinedLogger, LogLevelFilter};

// Sleep interval between temperature checking.
const SLEEP_TIME_MILLI: u64 = 3000;

// File where minimum supported frequency should be colected.
const MIN_FREQ_FILE: &'static str = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq";

// File where maximum supported frequency should be colected.
const MAX_FREQ_FILE: &'static str = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";

// Step size to change cpu frequency.
const STEP_FREQ: u64 = 100000;

// Possible files where current temperature should be collected.
const POSSIBLE_TEMP_FILES: &'static [&'static str] = &[
	"/sys/class/thermal/thermal_zone0/temp",
	"/sys/class/thermal/thermal_zone1/temp",
	"/sys/class/thermal/thermal_zone2/temp",
	"/sys/class/hwmon/hwmon0/temp1_input",
	"/sys/class/hwmon/hwmon1/temp1_input",
	"/sys/class/hwmon/hwmon2/temp1_input",
	"/sys/class/hwmon/hwmon0/device/temp1_input",
	"/sys/class/hwmon/hwmon1/device/temp1_input",
	"/sys/class/hwmon/hwmon2/device/temp1_input",
];

fn parse_int_file(path: String) -> u64 {
	let mut content = String::new();
	let mut fp = File::open(path).unwrap();
	fp.read_to_string(&mut content).unwrap();
	content.trim().parse::<u64>().unwrap()
}

fn min_frequency() -> u64 {
	parse_int_file(MIN_FREQ_FILE.to_string())
}

fn max_frequency() -> u64 {
	parse_int_file(MAX_FREQ_FILE.to_string())
}

fn get_temp() -> u64 {
	for file in POSSIBLE_TEMP_FILES {
		if Path::new(file).exists() {
			return parse_int_file(file.to_string()) / 1000;
		}
	}
	error!("impossible to collect current cpu temperature!");
	process::exit(1);
}

fn set_freq(freq: u64) {
	info!("setting frequency to {}", freq);
	for c in 0..num_cpus::get() {
		let path = format!("/sys/devices/system/cpu/cpu{}/cpufreq/scaling_max_freq", c);
		let mut fp = File::create(path).unwrap();
		fp.write_all(format!("{}\n", freq).as_bytes()).unwrap();
	}
}

fn main() {
	CombinedLogger::init(
		vec![
			SimpleLogger::new(LogLevelFilter::Info, Config::default()),
		]
	).unwrap();

	let args: Vec<String> = env::args().collect();
	if args.len() != 2 {
		error!("usage: {} <max temp>", args[0]);
		process::exit(1);
	}

	let max_temp: u64;
	match args[1].parse::<u64>() {
		Err(_) => {
			error!("invalid temperature: {}", args[1]);
			process::exit(1);
		},
		Ok(x) => max_temp = x,
	}
	info!("maximum temperature: {}", max_temp);

	info!("cpu count: {}", num_cpus::get());

	let min_freq = min_frequency();
	info!("minimum frequency supported: {}", min_freq);
	let max_freq = max_frequency();
	info!("maximum frequency supported: {}", max_freq);

	let mut cur_freq = max_freq;
	set_freq(cur_freq);
	loop {
		let temp = get_temp();
		if temp > max_temp && cur_freq > min_freq {
			cur_freq -= STEP_FREQ;
			if cur_freq < min_freq {
				cur_freq = min_freq;
			}
			set_freq(cur_freq);
		}
		else if temp < (max_temp-5) && cur_freq < max_freq {
			cur_freq += STEP_FREQ;
			if cur_freq > max_freq {
				cur_freq = max_freq;
			}
			set_freq(cur_freq);
		}
		debug!("current temperature: {}", temp);
		thread::sleep(time::Duration::from_millis(SLEEP_TIME_MILLI));
	}
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate schemamama;
extern crate schemamama_postgres;
extern crate postgres;
mod schema;

#[macro_use]
extern crate log;
extern crate log4rs;

extern crate iron;
extern crate router;
extern crate logger;

use iron::prelude::*;
use iron::status;
use router::Router;
use logger::Logger;
use std::io::Read;
use iron::modifiers::Redirect;

use std::env;
use std::ops::Deref;

extern crate uuid;
use uuid::Uuid;
extern crate serde_json;
use serde_json::{Map, Value};

extern crate r2d2;
extern crate r2d2_postgres;
extern crate persistent;
use persistent::Read as PRead;
use postgres::rows::{Row, RowIndex};
use postgres::types::FromSql;

#[macro_use]mod db;
#[macro_use]mod server_id;

use std::error::Error;
use std::fmt::{self, Debug};
#[derive(Debug)]
struct StringError(String);

impl Error for StringError {
    fn description(&self) -> &str {
        &*self.0
    }
}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

fn log_status(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("SELECT id, owner from log WHERE next is null").expect("prepare failure");
    let mut logs = Map::new();
    for row in &stmt.query(&[]).expect("last select works") {
        let id: Uuid = row.get("id");
        let owner: Uuid = row.get("owner");
        logs.insert(owner.to_string(), serde_json::to_value(&id.to_string()));
    }
    let value = Value::Object(logs);
    Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
}

fn new_log(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let body_string = {
        let mut body = String::new();
        req.body.read_to_string(&mut body).expect("could read from body");
        body
    };
    let json: Value = match serde_json::de::from_str(&body_string) {
        Ok(val) => val,
        Err(err) => return Err(IronError::new(err, (status::BadRequest, "Bad JSON"))),
    };
    let id = Uuid::new_v4();
    let hyphenated = id.hyphenated().to_string();
    let server_id = get_server_id!(&req).deref();
    let stmt = conn.prepare("SELECT id from log WHERE next is null and owner = $1 LIMIT 1")
        .expect("prepare failure");
    let results = stmt.query(&[server_id]).expect("last select works");
    let previous = if results.is_empty() {
        None
    } else {
        let row = results.get(0);
        let id: Uuid = row.get("id");
        Some(id)
    };
    conn.execute("UPDATE log set next = $1 where owner = $2 and next is null",
                 &[&id, server_id])
        .expect("update worked");
    conn.execute("INSERT INTO log (id, owner, data, prev) VALUES ($1, $2, $3, $4)",
                 &[&id, server_id, &json, &previous])
        .expect("insert worked");
    let new_url = {
        let req_url = req.url.clone();
        let base_url = req_url.into_generic_url();
        base_url.join(&format!("/log/{}", &hyphenated)).expect("join url works")
    };
    Ok(Response::with((status::Found,
                       Redirect(iron::Url::from_generic_url(new_url).expect("URL parsed ok")))))
}

fn get_with_null<I, T>(row: &Row, index: I) -> Option<T>
    where I: RowIndex,
          T: FromSql
{
    match row.get_opt(index) {
        Some(val) => {
            match val {
                Ok(val) => Some(val),
                Err(_) => None,
            }
        }
        None => None,
    }
}

fn get_log(req: &mut Request) -> IronResult<Response> {
    let ref query = req.extensions
        .get::<Router>()
        .unwrap()
        .find("entry_id")
        .unwrap_or("/");
    let query_id = match Uuid::parse_str(&query) {
        Ok(val) => val,
        Err(_) => {
            return Ok(Response::with((status::NotFound, format!("No log {}", query))));
        }
    };
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("SELECT owner, next, prev, data from log where id=$1").expect("prepare failure");
    let results = stmt.query(&[&query_id]).expect("bad query");
    if results.is_empty() {
        Ok(Response::with((status::NotFound, format!("No log {}", query))))
    } else {
        let row = results.get(0);
        let data: Value = row.get("data");
        let mut map = Map::new();
        let owner: Uuid = row.get("owner");
        let next: Option<Uuid> = get_with_null(&row, "next");
        let prev: Option<Uuid> = get_with_null(&row, "prev");
        map.insert(String::from("owner"),
                   serde_json::to_value(&owner.to_string()));
        map.insert(String::from("prev"),
                   serde_json::to_value(&prev.map(|x| x.to_string())));
        map.insert(String::from("next"),
                   serde_json::to_value(&next.map(|x| x.to_string())));
        map.insert(String::from("data"), data);
        let value = Value::Object(map);
        Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
    }
}

fn main() {
    log4rs::init_file("log.yaml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").expect("Needed DATABASE_URL");
    let pool = db::get_pool(db_url);
    let conn = pool.get().unwrap();
    schema::up(&conn).unwrap();
    let (logger_before, logger_after) = Logger::new(None);
    let mut router = Router::new();
    router.get("/log", log_status);
    router.post("/log", new_log);
    router.get("/log/:entry_id", get_log);
    let mut chain = Chain::new(router);
    chain.link_before(logger_before);
    chain.link_after(logger_after);
    chain.link_before(PRead::<server_id::ServerId>::one(server_id::setup()));
    chain.link(PRead::<db::PostgresDB>::both(pool));
    info!("Potboiler booted");
    Iron::new(chain).http("localhost:8000").unwrap();
}
<commit_msg>Add support for "first log items"<commit_after>#[macro_use]
extern crate schemamama;
extern crate schemamama_postgres;
extern crate postgres;
mod schema;

#[macro_use]
extern crate log;
extern crate log4rs;

extern crate iron;
extern crate router;
extern crate logger;

use iron::prelude::*;
use iron::status;
use router::Router;
use logger::Logger;
use std::io::Read;
use iron::modifiers::Redirect;

use std::env;
use std::ops::Deref;

extern crate uuid;
use uuid::Uuid;
extern crate serde_json;
use serde_json::{Map, Value};

extern crate r2d2;
extern crate r2d2_postgres;
extern crate persistent;
use persistent::Read as PRead;
use postgres::rows::{Row, RowIndex};
use postgres::types::FromSql;

#[macro_use]mod db;
#[macro_use]mod server_id;

use std::error::Error;
use std::fmt::{self, Debug};
#[derive(Debug)]
struct StringError(String);

impl Error for StringError {
    fn description(&self) -> &str {
        &*self.0
    }
}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

fn log_status<T: Into<String>>(req: &mut Request, stmt: T) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare(&stmt.into()).expect("prepare failure");
    let mut logs = Map::new();
    for row in &stmt.query(&[]).expect("last select works") {
        let id: Uuid = row.get("id");
        let owner: Uuid = row.get("owner");
        logs.insert(owner.to_string(), serde_json::to_value(&id.to_string()));
    }
    let value = Value::Object(logs);
    Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
}

fn log_lasts(req: &mut Request) -> IronResult<Response> {
    log_status(req, "SELECT id, owner from log WHERE next is null")
}

fn log_firsts(req: &mut Request) -> IronResult<Response> {
    log_status(req, "SELECT id, owner from log WHERE prev is null")
}

fn new_log(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let body_string = {
        let mut body = String::new();
        req.body.read_to_string(&mut body).expect("could read from body");
        body
    };
    let json: Value = match serde_json::de::from_str(&body_string) {
        Ok(val) => val,
        Err(err) => return Err(IronError::new(err, (status::BadRequest, "Bad JSON"))),
    };
    let id = Uuid::new_v4();
    let hyphenated = id.hyphenated().to_string();
    let server_id = get_server_id!(&req).deref();
    let stmt = conn.prepare("SELECT id from log WHERE next is null and owner = $1 LIMIT 1")
        .expect("prepare failure");
    let results = stmt.query(&[server_id]).expect("last select works");
    let previous = if results.is_empty() {
        None
    } else {
        let row = results.get(0);
        let id: Uuid = row.get("id");
        Some(id)
    };
    conn.execute("UPDATE log set next = $1 where owner = $2 and next is null",
                 &[&id, server_id])
        .expect("update worked");
    conn.execute("INSERT INTO log (id, owner, data, prev) VALUES ($1, $2, $3, $4)",
                 &[&id, server_id, &json, &previous])
        .expect("insert worked");
    let new_url = {
        let req_url = req.url.clone();
        let base_url = req_url.into_generic_url();
        base_url.join(&format!("/log/{}", &hyphenated)).expect("join url works")
    };
    Ok(Response::with((status::Found,
                       Redirect(iron::Url::from_generic_url(new_url).expect("URL parsed ok")))))
}

fn get_with_null<I, T>(row: &Row, index: I) -> Option<T>
    where I: RowIndex,
          T: FromSql
{
    match row.get_opt(index) {
        Some(val) => {
            match val {
                Ok(val) => Some(val),
                Err(_) => None,
            }
        }
        None => None,
    }
}

fn get_log(req: &mut Request) -> IronResult<Response> {
    let ref query = req.extensions
        .get::<Router>()
        .unwrap()
        .find("entry_id")
        .unwrap_or("/");
    let query_id = match Uuid::parse_str(&query) {
        Ok(val) => val,
        Err(_) => {
            return Ok(Response::with((status::NotFound, format!("No log {}", query))));
        }
    };
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("SELECT owner, next, prev, data from log where id=$1").expect("prepare failure");
    let results = stmt.query(&[&query_id]).expect("bad query");
    if results.is_empty() {
        Ok(Response::with((status::NotFound, format!("No log {}", query))))
    } else {
        let row = results.get(0);
        let data: Value = row.get("data");
        let mut map = Map::new();
        let owner: Uuid = row.get("owner");
        let next: Option<Uuid> = get_with_null(&row, "next");
        let prev: Option<Uuid> = get_with_null(&row, "prev");
        map.insert(String::from("owner"),
                   serde_json::to_value(&owner.to_string()));
        map.insert(String::from("prev"),
                   serde_json::to_value(&prev.map(|x| x.to_string())));
        map.insert(String::from("next"),
                   serde_json::to_value(&next.map(|x| x.to_string())));
        map.insert(String::from("data"), data);
        let value = Value::Object(map);
        Ok(Response::with((status::Ok, serde_json::ser::to_string(&value).unwrap())))
    }
}

fn main() {
    log4rs::init_file("log.yaml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").expect("Needed DATABASE_URL");
    let pool = db::get_pool(db_url);
    let conn = pool.get().unwrap();
    schema::up(&conn).unwrap();
    let (logger_before, logger_after) = Logger::new(None);
    let mut router = Router::new();
    router.get("/log", log_lasts);
    router.post("/log", new_log);
    router.get("/log/first", log_firsts);
    router.get("/log/:entry_id", get_log);
    let mut chain = Chain::new(router);
    chain.link_before(logger_before);
    chain.link_after(logger_after);
    chain.link_before(PRead::<server_id::ServerId>::one(server_id::setup()));
    chain.link(PRead::<db::PostgresDB>::both(pool));
    info!("Potboiler booted");
    Iron::new(chain).http("localhost:8000").unwrap();
}
<|endoftext|>


<commit_before>#![feature(path_ext)]
#![feature(fs_walk)]
#![feature(convert)]

#![allow(dead_code)] // for debug

extern crate cronparse;

use std::convert::AsRef;
use std::fs::{walk_dir, PathExt};
use std::path::Path;
use std::io;
use std::thread::spawn;

use cronparse::{CrontabFile, CrontabFileError, CrontabFileErrorKind};
use cronparse::crontab::{UserCrontabEntry, SystemCrontabEntry, AnacrontabEntry, EnvVarEntry, CrontabEntry, ToCrontabEntry};

fn generate_systemd_units(path: &Path, entry: CrontabEntry) {
    println!("{} => {:?}", path.display(), entry);
}

static USERS_CRONTAB_DIR: &'static str = "/var/spool/cron";  // UserCrontabEntry
static SYSTEM_CRONTAB_DIR: &'static str = "/etc/cron.d";  // SystemCrontabEntry
static ANACRONTAB_FILE: &'static str = "/etc/anacrontab";  // AnacrontabEntry

fn process_crontab_file<T: ToCrontabEntry, P: AsRef<Path>>(path: P) {
    let crontab: CrontabFile<T> = CrontabFile::new(path.as_ref()).unwrap();
    for entry in crontab {
        match entry {
            Ok(data) => generate_systemd_units(path.as_ref(), data),
            Err(err @ CrontabFileError { kind: CrontabFileErrorKind::Io(_), .. }) => panic!("error parsing file {}: {}", path.as_ref().display(), err),
            Err(err @ CrontabFileError { kind: CrontabFileErrorKind::Parse(_), .. }) => println!("skipping file {} due to parsing error: {}", path.as_ref().display(), err),
        }
    }
}

fn process_crontab_dir<T: ToCrontabEntry>(dir: &str) {
    for fres in walk_dir(dir).unwrap() {
        let path = fres.unwrap().path();
        if !path.is_file() {
            continue;
        }

        process_crontab_file::<T, _>(path);
    }
}

fn main() {
    let user_thread = spawn(|| process_crontab_dir::<UserCrontabEntry>(USERS_CRONTAB_DIR));
    let system_thread = spawn(|| process_crontab_dir::<SystemCrontabEntry>(SYSTEM_CRONTAB_DIR));
    let anacron_thread = spawn(|| process_crontab_file::<AnacrontabEntry, _>(ANACRONTAB_FILE));

    user_thread.join();
    system_thread.join();
    anacron_thread.join();
}
<commit_msg>handle env vars, no warnings, no panic<commit_after>#![feature(path_ext)]
#![feature(fs_walk)]
#![feature(convert)]

#![allow(dead_code)] // for debug

extern crate cronparse;

use std::convert::AsRef;
use std::fs::{walk_dir, PathExt};
use std::path::{Path, PathBuf};
use std::thread::spawn;
use std::collections::BTreeMap;

use cronparse::{CrontabFile, CrontabFileError, CrontabFileErrorKind};
use cronparse::crontab::{UserCrontabEntry, SystemCrontabEntry, AnacrontabEntry, EnvVarEntry, CrontabEntry, ToCrontabEntry};

fn generate_systemd_units(path: &Path, entry: CrontabEntry, env: &BTreeMap<String, String>) {
    println!("{} => {:?}, {:?}", path.display(), entry, env);
}

static USERS_CRONTAB_DIR: &'static str = "/var/spool/cron";  // UserCrontabEntry
static SYSTEM_CRONTAB_DIR: &'static str = "/etc/cron.d";  // SystemCrontabEntry
static ANACRONTAB_FILE: &'static str = "/etc/anacrontab";  // AnacrontabEntry

fn process_crontab_file<T: ToCrontabEntry, P: AsRef<Path>>(path: P) {
    let _ = CrontabFile::<T>::new(path.as_ref()).map(|crontab| {
        let mut env = BTreeMap::new();
        for entry in crontab {
            match entry {
                Ok(CrontabEntry::EnvVar(EnvVarEntry(name, value))) => { env.insert(name, value); },
                Ok(data) => generate_systemd_units(path.as_ref(), data, &env),
                Err(err @ CrontabFileError { kind: CrontabFileErrorKind::Io(_), .. }) => println!("error accessing file {}: {}", path.as_ref().display(), err),
                Err(err @ CrontabFileError { kind: CrontabFileErrorKind::Parse(_), .. }) => println!("skipping file {} due to parsing error: {}", path.as_ref().display(), err),
            }
        }
    });
}

fn process_crontab_dir<T: ToCrontabEntry>(dir: &str) {
    let files = walk_dir(dir).and_then(|fs| fs.map(|r| r.map(|p| p.path()))
                                       .filter(|r| r.as_ref().map(|p| p.is_file()).unwrap_or(true))
                                       .collect::<Result<Vec<PathBuf>, _>>());
    match files {
        Err(err) => println!("Error processing directory {}: {}", dir, err),
        Ok(files) => for file in files {
            process_crontab_file::<T, _>(file);
        }
    }
}

fn main() {
    let user_thread = spawn(|| process_crontab_dir::<UserCrontabEntry>(USERS_CRONTAB_DIR));
    let system_thread = spawn(|| process_crontab_dir::<SystemCrontabEntry>(SYSTEM_CRONTAB_DIR));
    let anacron_thread = spawn(|| process_crontab_file::<AnacrontabEntry, _>(ANACRONTAB_FILE));

    let _ = user_thread.join();
    let _ = system_thread.join();
    let _ = anacron_thread.join();
}
<|endoftext|>


<commit_before>extern crate sfml;
extern crate survive;

use sfml::graphics::*;
use sfml::window::*;
use sfml::system::{Clock, Vector2i, Vector2u};
use survive::*;

fn main() {
    let mut win = GameWindow::new();
    win.rwin.clear(&Color::white());
    win.rwin.display();

    let res = Resources::new();

    'outer: loop {
        let wg = Worldgen::new();
        //let test = Sprite::with_texture(&wg.textures[9]);

        let tilemgr = TileManager::new(wg.textures());

        let mut entitymgr = EntityManager::new();
        //entitymgr.add(entities::deciduous_tree::DeciduousTree::new(&res));
        //entitymgr.add(Box::new(entities::deciduous_tree::DeciduousTree::new(&res)));
        plants::generate_plants(&res, wg.world(), &mut entitymgr);

        let mut player = Player::new(&res);

        let mut stat = stats::Stats::new();

        let mut inv = Inventory::new();

        let mut ui = UiManager::new(&res);
        let Vector2u { x: width, y: height } = win.rwin.size();
        ui.on_resize(width, height);

        let mut dead = stat.dead();
        let mut restart_clock = Clock::start();

        let mut clock = Clock::start();
        'mainl: loop {
            let delta = clock.restart().as_seconds();

            win.rwin.clear(&Color::rgb(180, 215, 255));
            for i in &tilemgr {
                win.rwin.draw(i);
            }
            //win.rwin.draw(&test);
            entitymgr.draw_all(&mut win.rwin);
            win.rwin.draw(&player);
            ui.draw_all(&mut win.rwin);
            win.rwin.display();

            if !dead && stat.dead() {
                dead = true;
                restart_clock.restart();
            }

            while let Some(e) = win.rwin.poll_event() {
                match e {
                    Event::KeyPressed { code: Key::Escape, .. }
                            => break 'outer,
                    Event::MouseButtonPressed { button, x, y }
                        if !dead && button == mouse::Button::Left =>
                            entitymgr.mouse_click(&mut inv, &win.rwin, x, y),
                    Event::Closed => break 'outer,
                    Event::Resized { width, height } => {
                        win.on_resize(width, height);
                        ui.on_resize(width, height);
                    },
                    _ => {},
                }
            }

            if dead {
                ui.set_display_death(true);

                //println!("restart_clock: {}", restart_clock.elapsed_time().as_seconds());
                if restart_clock.elapsed_time().as_milliseconds() > 2000 {
                    continue 'outer;
                }
            } else {
                match player.update(delta, &win) {
                    Some(s) => win.scroll(&s),
                    None => {},
                };

                let Vector2i { x: mx, y: my } = win.rwin.mouse_position();
                player.mouse_pos(&win.rwin, mx, my);

                if player.is_in_water(&wg.world()) {
                    stat.event(delta, &stats::StatEvent::InWater);
                }
                stat.update(delta);
            }

            ui.update(delta, &stat, &inv);

            //println!("{:?}", stat);
            //println!("dead: {}", stat.dead());
            //println!("Wood count: {}", inv.items()[0]);
        }
    }
}
<commit_msg>Make scroll reset after death<commit_after>extern crate sfml;
extern crate survive;

use sfml::graphics::*;
use sfml::window::*;
use sfml::system::{Clock, Vector2i, Vector2u};
use survive::*;

fn main() {
    let mut win = GameWindow::new();
    win.rwin.clear(&Color::white());
    win.rwin.display();

    let res = Resources::new();

    'outer: loop {
        let wg = Worldgen::new();
        //let test = Sprite::with_texture(&wg.textures[9]);

        let tilemgr = TileManager::new(wg.textures());

        let mut entitymgr = EntityManager::new();
        //entitymgr.add(entities::deciduous_tree::DeciduousTree::new(&res));
        //entitymgr.add(Box::new(entities::deciduous_tree::DeciduousTree::new(&res)));
        plants::generate_plants(&res, wg.world(), &mut entitymgr);

        let mut player = Player::new(&res);

        let mut stat = stats::Stats::new();

        let mut inv = Inventory::new();

        let mut ui = UiManager::new(&res);
        let Vector2u { x: width, y: height } = win.rwin.size();
        ui.on_resize(width, height);

        let mut dead = stat.dead();
        let mut restart_clock = Clock::start();

        let mut clock = Clock::start();
        'mainl: loop {
            let delta = clock.restart().as_seconds();

            win.rwin.clear(&Color::rgb(180, 215, 255));
            for i in &tilemgr {
                win.rwin.draw(i);
            }
            //win.rwin.draw(&test);
            entitymgr.draw_all(&mut win.rwin);
            win.rwin.draw(&player);
            ui.draw_all(&mut win.rwin);
            win.rwin.display();

            if !dead && stat.dead() {
                dead = true;
                restart_clock.restart();
            }

            while let Some(e) = win.rwin.poll_event() {
                match e {
                    Event::KeyPressed { code: Key::Escape, .. }
                            => break 'outer,
                    Event::MouseButtonPressed { button, x, y }
                        if !dead && button == mouse::Button::Left =>
                            entitymgr.mouse_click(&mut inv, &win.rwin, x, y),
                    Event::Closed => break 'outer,
                    Event::Resized { width, height } => {
                        win.on_resize(width, height);
                        ui.on_resize(width, height);
                    },
                    _ => {},
                }
            }

            if dead {
                ui.set_display_death(true);

                //println!("restart_clock: {}", restart_clock.elapsed_time().as_seconds());
                if restart_clock.elapsed_time().as_milliseconds() > 2000 {
                    let mut view = win.rwin.view().to_owned();
                    view.set_center2f(0., 0.);
                    win.rwin.set_view(&view);

                    continue 'outer;
                }
            } else {
                match player.update(delta, &win) {
                    Some(s) => win.scroll(&s),
                    None => {},
                };

                let Vector2i { x: mx, y: my } = win.rwin.mouse_position();
                player.mouse_pos(&win.rwin, mx, my);

                if player.is_in_water(&wg.world()) {
                    stat.event(delta, &stats::StatEvent::InWater);
                }
                stat.update(delta);
            }

            ui.update(delta, &stat, &inv);

            //println!("{:?}", stat);
            //println!("dead: {}", stat.dead());
            //println!("Wood count: {}", inv.items()[0]);
        }
    }
}
<|endoftext|>


<commit_before>/*
 * This is a Rust implementation of the Settler starter bot for Halite-II
 * For the most part, the code is organized like the Python version, so see that
 * code for more information.
 */

mod hlt;

use hlt::entity::{Entity, DockingStatus};
use hlt::game::Game;
use hlt::logging::Logger;

fn main() {
    // Initiailize the game
    let game = Game::new("Settler");
    // Initialize logging
    let mut logger = Logger::new(game.my_id);
    logger.log("Starting my Settler bot!");

    // For each turn
    loop {
        // Update the game state
        let game_map = game.update_map();
        let mut command_queue = Vec::new();

        // Loop over all of our player's ships
        for ship in game_map.get_me().all_ships() {
            // Ignore ships that are docked or in the process of docking
            if ship.docking_status != DockingStatus::UNDOCKED {
                continue;
            }

            // Loop over all planets
            for planet in game_map.all_planets() {
                // Ignore unowned planets
                if planet.is_owned() {
                    continue;
                }

                if ship.can_dock(planet) {
                    // If we are close enough to dock, do it!
                    command_queue.push(ship.dock(planet))
                } else {
                    // If not, navigate towards the planet
                    let navigate_command = ship.navigate(&ship.closest_point_to(planet, 3.0), &game_map, 90);
                    if let Some(command) = navigate_command {
                        command_queue.push(command)
                    }

                }
                break;
            }
        }
        // Send our commands to the game
        game.send_command_queue(&command_queue);
    }
}
<commit_msg>clean: Don't recreate a new Vec each time<commit_after>/*
 * This is a Rust implementation of the Settler starter bot for Halite-II
 * For the most part, the code is organized like the Python version, so see that
 * code for more information.
 */

mod hlt;

use hlt::entity::{Entity, DockingStatus};
use hlt::game::Game;
use hlt::logging::Logger;

fn main() {
    let name = "Kevina";
    // Initiailize the game
    let game = Game::new(name);
    // Initialize logging
    let mut logger = Logger::new(game.my_id);
    logger.log(&format!("Starting my {} bot!", name));

    let mut command_queue = Vec::new();

    loop {

        // Update the game state
        let game_map = game.update_map();

        // Loop over all of our player's ships
        for ship in game_map.get_me().all_ships() {
            // Ignore ships that are docked or in the process of docking
            if ship.docking_status != DockingStatus::UNDOCKED {
                continue;
            }

            // Loop over all planets
            for planet in game_map.all_planets() {
                // Ignore unowned planets
                if planet.is_owned() {
                    continue;
                }

                // If we are close enough to dock, do it!
                if ship.can_dock(planet) {
                    command_queue.push(ship.dock(planet))
                } else {
                    // If not, navigate towards the planet
                    let navigate_command = ship.navigate(&ship.closest_point_to(planet, 3.0), &game_map, 90);
                    if let Some(command) = navigate_command {
                        command_queue.push(command)
                    }

                }
                break;
            }
        }
        // Send our commands to the game
        game.send_command_queue(&command_queue);
        command_queue.clear();
    }
}
<|endoftext|>