<commit_before>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender};
use std::collections::HashMap;
use consts::{WatchedEventType, ZkError, ZkState};
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;
use listeners::{Subscription};

pub type Data = HashMap<String, Arc<Vec<u8>>>;

#[derive(Debug)]
pub struct ChildData;

#[derive(Debug)]
pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(ChildData),
    ChildAdded(ChildData),
    ChildUpdated(ChildData),
}

#[derive(Debug)]
pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

pub enum Operation {
    Shutdown(Option<Sender<ZkResult<bool>>>),
    Refresh(RefreshMode, Option<Sender<ZkResult<()>>>),
    Event(PathChildrenCacheEvent, Option<Sender<ZkResult<bool>>>),
    GetData(String /* path */, Option<Sender<ZkResult<Vec<u8>>>>),
}

use std::fmt;
impl fmt::Debug for Operation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Operation::Shutdown(ref _sender) => {
                write!(f, "Operation::Shutdown")
            },
            Operation::Refresh(ref mode, ref _sender) => {
                write!(f, "Operation::Refresh({:?})", mode)
            },
            Operation::Event(ref ev, ref _sender) => {
                write!(f, "Operation::Event({:?})", ev)
            },
            Operation::GetData(ref path, ref _sender) => {
                write!(f, "Operation::GetData({})", path)
            }
        }
    }
}

pub struct PathChildrenCache {
    path: Arc<String>,
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<Operation>>,
    listener_subscription: Option<Subscription>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<()> {
        let ops_chan1 = ops_chan.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let _path = event.path.as_ref().expect("Path absent");

                    // Subscribe to new changes recursively
                    match ops_chan1.send(Operation::Refresh(RefreshMode::Standard, None)) {
                        Err(err) => {
                            warn!("error sending Refresh operation to ops channel: {:?}", err);
                        },
                        _ => {}
                    };
                },
                _ => error!("Unexpected: {:?}", event)
            };
            // Send change event
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = join_path(path, child);

            if !data_locked.contains_key(&child_path) {

                let child_data = try!(Self::get_data(zk.clone(), &child_path, data.clone(), ops_chan.clone()));

                data_locked.insert(child_path, Arc::new(child_data));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<Vec<u8>> {
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    match ops_chan.send(Operation::GetData(path1, None)) {
                        Err(err) => {
                            warn!("error sending GetData to op channel: {:?}", err);
                        },
                        _ => {}
                    }
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);

            //TODO Send change event
        };

        zk.get_data_w(path, data_watcher).map(|stuff| { stuff.0 })
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        Ok(PathChildrenCache{
            path: Arc::new(path.to_string()),
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
            listener_subscription: None,
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    pub fn start(&mut self) -> ZkResult<()> {
        let (ops_chan_tx, ops_chan_rx) = mpsc::channel();
        let (listener_chan_tx, listener_chan_rx) = mpsc::channel();

        let sub = self.zk.add_listener(listener_chan_tx.clone());
        self.listener_subscription = Some(sub);

        let zk = self.zk.clone();
        let path = self.path.clone();
        let data = self.data.clone();
        self.channel = Some(ops_chan_tx.clone());

        self.worker_thread = Some(thread::spawn(move || {
            let mut done = false;

            while !done {
                select! (
                    state = listener_chan_rx.recv() => {
                        match state {
                            Ok(state) => {
                                info!("zk state change {:?}", state);
                                match state {
                                    ZkState::Connected => {
                                        match ops_chan_tx.send(Operation::Refresh(RefreshMode::ForceGetDataAndStat, None)) {
                                            Err(err) => {
                                                warn!("error sending Refresh to op channel: {:?}", err);
                                                done = true;
                                            },
                                            _ => {}
                                        }
                                    },
                                    _ => {
                                    }
                                }
                            },
                            Err(err) => {
                                info!("zk state chan err. shutting down. {:?}", err);
                                done = true;
                            }
                        }
                    },
                    op = ops_chan_rx.recv() => {

                        debug!("handling op {:?}", op);
                        match op {
                            Ok(Operation::Shutdown(_maybe_chan)) => {
                                info!("shutting down worker thread");
                                done = true;
                            },
                            Ok(Operation::Refresh(_mode, maybe_chan)) => {
                                debug!("getting children");
                                let result = Self::get_children(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                                info!("got children {:?}", result);

                                maybe_chan.map_or((), |chan| {
                                    match chan.send(result) {
                                        Err(err) => {
                                            warn!("error returning Refresh result to channel: {:?}", err);
                                        },
                                        _ => {}
                                    }
                                });
                            },
                            Ok(Operation::GetData(path, maybe_chan)) => {
                                debug!("getting data");
                                let result = Self::get_data(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                                info!("got data {:?}", result);

                                maybe_chan.map_or((), |chan| {
                                    match chan.send(result) {
                                        Err(err) => {
                                            warn!("error returning GetData result to channel: {:?}", err);
                                        },
                                        _ => {}
                                    }
                                });
                            },
                            Ok(Operation::Event(event, _maybe_chan)) => {
                                info!("received event {:?}", event);
                            },
                            Err(err) => {
                                info!("error receiving from operations channel ({:?}). shutting down worker thread", err);
                                done = true;
                            }
                        }

                    });
            }
        }));

        self.offer_operation(Operation::Refresh(RefreshMode::ForceGetDataAndStat, None))
    }

    fn offer_operation(&self, op: Operation) -> ZkResult<()> {
        match self.channel {
            Some(ref chan) => {
                chan.send(op).map_err(|err| {
                    warn!("error submitting op to channel: {:?}", err);
                    ZkError::APIError
                })
            },
            None => Err(ZkError::APIError)
        }
    }

}

pub fn join_path(dir: &str, child: &str) -> String {
    let dir_bytes = dir.as_bytes();
    let mut result = dir.to_string();
    if dir_bytes[dir_bytes.len() - 1] != ('/' as u8) {
        result.push_str("/");
    }
    result.push_str(child);
    result
}
<commit_msg>refactor work thread loop into separate match branch methods<commit_after>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender};
use std::collections::HashMap;
use consts::{WatchedEventType, ZkError, ZkState};
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;
use listeners::{Subscription};

pub type Data = HashMap<String, Arc<Vec<u8>>>;

#[derive(Debug)]
pub struct ChildData;

#[derive(Debug)]
pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(ChildData),
    ChildAdded(ChildData),
    ChildUpdated(ChildData),
}

#[derive(Debug)]
pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

pub enum Operation {
    Shutdown(Option<Sender<ZkResult<bool>>>),
    Refresh(RefreshMode, Option<Sender<ZkResult<()>>>),
    Event(PathChildrenCacheEvent, Option<Sender<ZkResult<bool>>>),
    GetData(String /* path */, Option<Sender<ZkResult<Vec<u8>>>>),
}

use std::fmt;
impl fmt::Debug for Operation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Operation::Shutdown(ref _sender) => {
                write!(f, "Operation::Shutdown")
            },
            Operation::Refresh(ref mode, ref _sender) => {
                write!(f, "Operation::Refresh({:?})", mode)
            },
            Operation::Event(ref ev, ref _sender) => {
                write!(f, "Operation::Event({:?})", ev)
            },
            Operation::GetData(ref path, ref _sender) => {
                write!(f, "Operation::GetData({})", path)
            }
        }
    }
}

pub struct PathChildrenCache {
    path: Arc<String>,
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<Operation>>,
    listener_subscription: Option<Subscription>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<()> {
        let ops_chan1 = ops_chan.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let _path = event.path.as_ref().expect("Path absent");

                    // Subscribe to new changes recursively
                    match ops_chan1.send(Operation::Refresh(RefreshMode::Standard, None)) {
                        Err(err) => {
                            warn!("error sending Refresh operation to ops channel: {:?}", err);
                        },
                        _ => {}
                    };
                },
                _ => error!("Unexpected: {:?}", event)
            };
            // Send change event
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = join_path(path, child);

            if !data_locked.contains_key(&child_path) {

                let child_data = try!(Self::get_data(zk.clone(), &child_path, data.clone(), ops_chan.clone()));

                data_locked.insert(child_path, Arc::new(child_data));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<Vec<u8>> {
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    match ops_chan.send(Operation::GetData(path1, None)) {
                        Err(err) => {
                            warn!("error sending GetData to op channel: {:?}", err);
                        },
                        _ => {}
                    }
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);

            //TODO Send change event
        };

        zk.get_data_w(path, data_watcher).map(|stuff| { stuff.0 })
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        Ok(PathChildrenCache{
            path: Arc::new(path.to_string()),
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
            listener_subscription: None,
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    fn handle_state_change(state: ZkState, ops_chan_tx: Sender<Operation>) -> bool {
        let mut done = false;

        match state {
            state => {
                info!("zk state change {:?}", state);
                match state {
                    ZkState::Connected => {
                        match ops_chan_tx.send(Operation::Refresh(RefreshMode::ForceGetDataAndStat, None)) {
                            Err(err) => {
                                warn!("error sending Refresh to op channel: {:?}", err);
                                done = true;
                            },
                            _ => {}
                        }
                    },
                    _ => {
                    }
                }
            },
        }

        done
    }

    fn handle_operation(op: Operation, zk: Arc<ZooKeeper>, path: Arc<String>, data: Arc<Mutex<Data>>, ops_chan_tx: Sender<Operation>) -> bool {
        let mut done = false;

        debug!("handling op {:?}", op);
        match op {
            Operation::Shutdown(_maybe_chan) => {
                info!("shutting down worker thread");
                done = true;
            },
            Operation::Refresh(_mode, maybe_chan) => {
                debug!("getting children");
                let result = Self::get_children(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                info!("got children {:?}", result);

                maybe_chan.map_or((), |chan| {
                    match chan.send(result) {
                        Err(err) => {
                            warn!("error returning Refresh result to channel: {:?}", err);
                        },
                        _ => {}
                    }
                });
            },
            Operation::GetData(path, maybe_chan) => {
                debug!("getting data");
                let result = Self::get_data(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                info!("got data {:?}", result);

                maybe_chan.map_or((), |chan| {
                    match chan.send(result) {
                        Err(err) => {
                            warn!("error returning GetData result to channel: {:?}", err);
                        },
                        _ => {}
                    }
                });
            },
            Operation::Event(event, _maybe_chan) => {
                info!("received event {:?}", event);
            },
        }

        done
    }

    pub fn start(&mut self) -> ZkResult<()> {
        let (ops_chan_tx, ops_chan_rx) = mpsc::channel();
        let (listener_chan_tx, listener_chan_rx) = mpsc::channel();

        let sub = self.zk.add_listener(listener_chan_tx.clone());
        self.listener_subscription = Some(sub);

        let zk = self.zk.clone();
        let path = self.path.clone();
        let data = self.data.clone();
        self.channel = Some(ops_chan_tx.clone());

        self.worker_thread = Some(thread::spawn(move || {
            let mut done = false;

            while !done {
                select! (
                    state_result = listener_chan_rx.recv() => {
                        match state_result {
                            Ok(state) => {
                                done = Self::handle_state_change(state, ops_chan_tx.clone());
                            },
                            Err(err) => {
                                info!("zk state chan err. shutting down. {:?}", err);
                                done = true;
                            }
                        }
                    },
                    op_result = ops_chan_rx.recv() => {
                        match op_result {
                            Ok(operation) => {
                                done = Self::handle_operation(operation, zk.clone(), path.clone(), data.clone(), ops_chan_tx.clone());
                            },
                            Err(err) => {
                                info!("error receiving from operations channel ({:?}). shutting down worker thread", err);
                                done = true;
                            }
                        }
                    });
            }
        }));

        self.offer_operation(Operation::Refresh(RefreshMode::ForceGetDataAndStat, None))
    }

    fn offer_operation(&self, op: Operation) -> ZkResult<()> {
        match self.channel {
            Some(ref chan) => {
                chan.send(op).map_err(|err| {
                    warn!("error submitting op to channel: {:?}", err);
                    ZkError::APIError
                })
            },
            None => Err(ZkError::APIError)
        }
    }

}

pub fn join_path(dir: &str, child: &str) -> String {
    let dir_bytes = dir.as_bytes();
    let mut result = dir.to_string();
    if dir_bytes[dir_bytes.len() - 1] != ('/' as u8) {
        result.push_str("/");
    }
    result.push_str(child);
    result
}
<|endoftext|>


<commit_before>use node_bucket;
use node_bucket::NodeBucket;
use address::{Address, Addressable, LENGTH};
use node::Node;

#[derive(Debug, PartialEq)]
pub enum InsertOutcome {
    Ignored,    // Currently just for ignoring self-node
    Inserted,   // Inserted new node
    Updated,    // Updated existing node
    Discarded   // Bucket is full
}

pub type InsertionResult = Result<InsertOutcome, String>;

#[derive(Debug)]
pub struct RoutingTable {
    k: usize,
    self_address: Address,
    routers: Vec<Box<Node>>,
    buckets: Vec<NodeBucket>
}

impl RoutingTable {
    pub fn new(k: usize, self_address: Address, routers: Vec<Box<Node>>) -> RoutingTable {
        let bucket = NodeBucket::new(k);
        RoutingTable {
            k: k,
            self_address: self_address,
            routers: routers,
            buckets: vec![bucket]
        }
    }

    pub fn insert(&mut self, node: Box<Node>) -> InsertionResult {
        if node.get_address() == self.self_address {
            return Ok(InsertOutcome::Ignored);
        }

        let index = self.bucket_for(&node.get_address());
        let mut bucket = self.buckets.remove(index);
        let self_address = self.self_address;

        if !self.buckets_maxed() && bucket.is_full() && bucket.covers(&self_address) {
            let (a, b) = bucket.split();
            self.buckets.insert(index, a);
            self.buckets.insert(index + 1, b);
            self.insert(node)
        } else {
            let status = bucket.insert(node);
            self.buckets.insert(index, bucket);
            match status {
                Ok(node_bucket::InsertOutcome::Inserted) => Ok(InsertOutcome::Inserted),
                Ok(node_bucket::InsertOutcome::Updated) => Ok(InsertOutcome::Updated),
                Ok(node_bucket::InsertOutcome::Discarded) => Ok(InsertOutcome::Discarded),
                Err(error) => Err(error)
            }
        }
    }

    pub fn nearest(&self) -> Vec<&Box<Node>> {
        self.nearest_to(&self.self_address)
    }

    pub fn nearest_to(&self, address: &Address) -> Vec<&Box<Node>> {
        // TODO: this should walk buckets much more efficiently

        let mut candidates: Vec<&Box<Node>> = self.buckets
            .iter()
            .flat_map(|b| b.get_nodes())
            .collect();

        candidates.sort_by_key(|n| n.get_address().distance_from(address));

        // chain on routers in case we don't have enough nodes yet
        candidates.into_iter().chain(self.routers.iter()).take(self.k).collect()
    }

    fn bucket_for(&self, address: &Address) -> usize {
        let (index, _) = self.buckets
            .iter()
            .enumerate()
            .find(|&(_, ref b)| b.covers(address))
            .unwrap();
        index
    }

    fn buckets_maxed(&self) -> bool {
        self.buckets.len() >= LENGTH
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use messages;
    use node::{Node, Serialize};
    use super::{InsertOutcome, RoutingTable};

    #[derive(Debug)]
    struct TestNode {
        pub address: Address
    }

    impl TestNode {
        fn new(address: Address) -> TestNode {
            TestNode { address: address }
        }
    }

    impl Addressable for TestNode {
        fn get_address(&self) -> Address {
            self.address
        }
    }

    impl Node for TestNode {
        fn update(&mut self) { }
        fn send(&self, _: Vec<u8>) { }
    }

    impl Serialize for TestNode {
        fn serialize(&self) -> messages::protobufs::Node {
            messages::protobufs::Node::new()
        }
    }

    #[test]
    fn test_insert() {
        let self_node = Address::from_str("0000000000000000000000000000000000000000");
        let router = Box::new(TestNode::new(Address::null()));
        let mut table: RoutingTable = RoutingTable::new(2, self_node, vec![router]);
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff")))).unwrap();
        assert_eq!(table.buckets.len(), 1);

        // Splits buckets upon adding a k+1th node in the same space as self node
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffe")))).unwrap();
        assert_eq!(table.buckets.len(), 2);
        table.insert(Box::new(TestNode::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("7ffffffffffffffffffffffffffffffffffffffe")))).unwrap();
        assert_eq!(table.buckets.len(), 3);

        // Replaces instead of duplicates existing nodes
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        assert_eq!(table.buckets.len(), 3);

        // Disregards new nodes for full, non-self space buckets
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffd")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffc")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffb")))).unwrap();
        assert_eq!(table.buckets.len(), 3);

        // Ignores self-node
        assert_eq!(table.insert(Box::new(TestNode::new(self_node))).unwrap(), InsertOutcome::Ignored);
        assert_eq!(table.buckets.len(), 3);
    }

    #[test]
    fn test_nearest_to() {
        let self_node = Address::from_str("0000000000000000000000000000000000000000");
        let router = Box::new(TestNode::new(Address::null()));
        let mut table: RoutingTable = RoutingTable::new(2, self_node, vec![router]);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000001");
        let addr_2 = Address::from_str("7ffffffffffffffffffffffffffffffffffffffe");
        let addr_3 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        table.insert(node_1).unwrap();
        table.insert(node_2).unwrap();
        table.insert(node_3).unwrap();

        let nearest = table.nearest_to(&Address::from_str("fffffffffffffffffffffffffffffffffffffffd"));
        assert_eq!(nearest[0].get_address(), addr_3);
        assert_eq!(nearest[1].get_address(), addr_2);
        let nearest = table.nearest_to(&Address::from_str("0000000000000000000000000000000000000002"));
        assert_eq!(nearest[0].get_address(), addr_1);
        assert_eq!(nearest[1].get_address(), addr_2);
    }
}
<commit_msg>Get nearest nodes mutably<commit_after>use node_bucket;
use node_bucket::NodeBucket;
use address::{Address, Addressable, LENGTH};
use node::Node;

#[derive(Debug, PartialEq)]
pub enum InsertOutcome {
    Ignored,    // Currently just for ignoring self-node
    Inserted,   // Inserted new node
    Updated,    // Updated existing node
    Discarded   // Bucket is full
}

pub type InsertionResult = Result<InsertOutcome, String>;

#[derive(Debug)]
pub struct RoutingTable {
    k: usize,
    self_address: Address,
    routers: Vec<Box<Node>>,
    buckets: Vec<NodeBucket>
}

impl RoutingTable {
    pub fn new(k: usize, self_address: Address, routers: Vec<Box<Node>>) -> RoutingTable {
        let bucket = NodeBucket::new(k);
        RoutingTable {
            k: k,
            self_address: self_address,
            routers: routers,
            buckets: vec![bucket]
        }
    }

    pub fn insert(&mut self, node: Box<Node>) -> InsertionResult {
        if node.get_address() == self.self_address {
            return Ok(InsertOutcome::Ignored);
        }

        let index = self.bucket_for(&node.get_address());
        let mut bucket = self.buckets.remove(index);
        let self_address = self.self_address;

        if !self.buckets_maxed() && bucket.is_full() && bucket.covers(&self_address) {
            let (a, b) = bucket.split();
            self.buckets.insert(index, a);
            self.buckets.insert(index + 1, b);
            self.insert(node)
        } else {
            let status = bucket.insert(node);
            self.buckets.insert(index, bucket);
            match status {
                Ok(node_bucket::InsertOutcome::Inserted) => Ok(InsertOutcome::Inserted),
                Ok(node_bucket::InsertOutcome::Updated) => Ok(InsertOutcome::Updated),
                Ok(node_bucket::InsertOutcome::Discarded) => Ok(InsertOutcome::Discarded),
                Err(error) => Err(error)
            }
        }
    }

        self.nearest_to(&self.self_address)
    pub fn nearest(&mut self) -> Vec<&mut Box<Node>> {
    }

    pub fn nearest_to(&mut self, address: &Address) -> Vec<&mut Box<Node>> {
        // TODO: this should walk buckets much more efficiently

        let mut candidates: Vec<&mut Box<Node>> = self.buckets
            .iter_mut()
            .flat_map(|b| b.get_nodes())
            .collect();

        candidates.sort_by_key(|n| n.get_address().distance_from(address));

        // chain on routers in case we don't have enough nodes yet
        candidates.into_iter().chain(self.routers.iter()).take(self.k).collect()
    }

    fn bucket_for(&self, address: &Address) -> usize {
        let (index, _) = self.buckets
            .iter()
            .enumerate()
            .find(|&(_, ref b)| b.covers(address))
            .unwrap();
        index
    }

    fn buckets_maxed(&self) -> bool {
        self.buckets.len() >= LENGTH
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use messages;
    use node::{Node, Serialize};
    use super::{InsertOutcome, RoutingTable};

    #[derive(Debug)]
    struct TestNode {
        pub address: Address
    }

    impl TestNode {
        fn new(address: Address) -> TestNode {
            TestNode { address: address }
        }
    }

    impl Addressable for TestNode {
        fn get_address(&self) -> Address {
            self.address
        }
    }

    impl Node for TestNode {
        fn update(&mut self) { }
        fn send(&self, _: Vec<u8>) { }
    }

    impl Serialize for TestNode {
        fn serialize(&self) -> messages::protobufs::Node {
            messages::protobufs::Node::new()
        }
    }

    #[test]
    fn test_insert() {
        let self_node = Address::from_str("0000000000000000000000000000000000000000");
        let router = Box::new(TestNode::new(Address::null()));
        let mut table: RoutingTable = RoutingTable::new(2, self_node, vec![router]);
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff")))).unwrap();
        assert_eq!(table.buckets.len(), 1);

        // Splits buckets upon adding a k+1th node in the same space as self node
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffe")))).unwrap();
        assert_eq!(table.buckets.len(), 2);
        table.insert(Box::new(TestNode::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("7ffffffffffffffffffffffffffffffffffffffe")))).unwrap();
        assert_eq!(table.buckets.len(), 3);

        // Replaces instead of duplicates existing nodes
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("0000000000000000000000000000000000000001")))).unwrap();
        assert_eq!(table.buckets.len(), 3);

        // Disregards new nodes for full, non-self space buckets
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffd")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffc")))).unwrap();
        table.insert(Box::new(TestNode::new(Address::from_str("fffffffffffffffffffffffffffffffffffffffb")))).unwrap();
        assert_eq!(table.buckets.len(), 3);

        // Ignores self-node
        assert_eq!(table.insert(Box::new(TestNode::new(self_node))).unwrap(), InsertOutcome::Ignored);
        assert_eq!(table.buckets.len(), 3);
    }

    #[test]
    fn test_nearest_to() {
        let self_node = Address::from_str("0000000000000000000000000000000000000000");
        let router = Box::new(TestNode::new(Address::null()));
        let mut table: RoutingTable = RoutingTable::new(2, self_node, vec![router]);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000001");
        let addr_2 = Address::from_str("7ffffffffffffffffffffffffffffffffffffffe");
        let addr_3 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        table.insert(node_1).unwrap();
        table.insert(node_2).unwrap();
        table.insert(node_3).unwrap();

        let nearest = table.nearest_to(&Address::from_str("fffffffffffffffffffffffffffffffffffffffd"));
        assert_eq!(nearest[0].get_address(), addr_3);
        assert_eq!(nearest[1].get_address(), addr_2);
        let nearest = table.nearest_to(&Address::from_str("0000000000000000000000000000000000000002"));
        assert_eq!(nearest[0].get_address(), addr_1);
        assert_eq!(nearest[1].get_address(), addr_2);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;
use std::net::{SocketAddr};
use std::io;

use mio::deprecated::{EventLoop, Handler, TryWrite};
use mio::*;
use mio::tcp::*;
use bytes::buf::{Buf, ByteBuf};

use packet::{Packet, EofError};
use queues::*;
use worker::*;

struct GearmanRemote {
    socket: TcpStream,
    addr: SocketAddr,
    packet: Packet,
    queues: JobQueues,
    worker: Worker,
    workers: SharedWorkers,
    sendqueue: Vec<ByteBuf>,
    interest: Ready,
    token: Token,
}

pub struct GearmanServer {
    pub socket: TcpListener,
    remotes: HashMap<Token, GearmanRemote>,
    token_counter: usize,
    queues: JobQueues,
    workers: SharedWorkers,
}

const SERVER_TOKEN: Token = Token(0);

impl GearmanRemote {
    pub fn new(socket: TcpStream, addr: SocketAddr, queues: JobQueues, token: Token, workers: SharedWorkers) -> GearmanRemote {
        GearmanRemote {
            socket: socket,
            addr: addr,
            packet: Packet::new(token),
            queues: queues,
            worker: Worker::new(),
            workers: workers,
            sendqueue: Vec::with_capacity(2), // Don't need many bufs
            interest: Ready::readable(),
            token: token,
        }
    }

    pub fn queue_packet(&mut self, packet: &Packet) {
        info!("{} Queueing {:?}", self, &packet);
        self.sendqueue.push(ByteBuf::from_slice(&packet.to_byteslice()));
        self.interest.remove(Ready::readable());
        self.interest.insert(Ready::writable());
    }

    pub fn read(&mut self) -> Result<Option<Packet>, EofError> {
        let mut ret = Ok(None);
        info!("{} readable", self);
        match self.packet.from_socket(&mut self.socket, &mut self.worker, self.workers.clone(), self.queues.clone(), self.token)? {
            None => debug!("{} Done reading", self),
            Some(p) => {
                ret = Ok(Some(p));
            }
        }
        // Non-text packets are consumed, reset
        if self.packet.consumed {
            self.packet = Packet::new(self.token);
        }
        ret
    }

    pub fn write(&mut self) -> Result<(), io::Error> {
        while !self.sendqueue.is_empty() {
            if !self.sendqueue.first().unwrap().has_remaining() {
                self.sendqueue.pop();
                continue;
            }
            let buf = self.sendqueue.first_mut().unwrap();
            match self.socket.try_write(buf.bytes())? {
                None => break,
                Some(n) => {
                    buf.advance(n);
                    continue
                }
            };
        }
        if self.sendqueue.is_empty() {
            self.interest.remove(Ready::writable());
            self.interest.insert(Ready::readable());
        };
        Ok(())
    }

    pub fn shutdown(self) {
        match self.worker.job {
            Some(mut j) => {
                j.remove_remote(&self.token);
                self.queues.clone().add_job(j) // XXX Maybe this should cut in front of the line?
            },
            None => {},
        }
        match self.socket.shutdown(Shutdown::Both) {
            Err(e) => warn!("{:?} fail on shutdown ({:?})", self.addr, e),
            Ok(_) => {},
        }
    }
}

impl fmt::Display for GearmanRemote {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Remote {{ addr: {:?} }}", self.addr)
    }
}

impl GearmanServer {
    pub fn new(server_socket: TcpListener, queues: JobQueues, workers: SharedWorkers) -> GearmanServer {
        GearmanServer {
            token_counter: 1,
            remotes: HashMap::new(),
            socket: server_socket,
            queues: queues,
            workers: workers,
        }
    }

}

impl Handler for GearmanServer {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<GearmanServer>,
             token: Token, events: Ready)
    {
        if events.is_readable() {
            match token {
                SERVER_TOKEN => {
                    let (remote_socket, remote_addr) = match self.socket.accept() {
                        Err(e) => {
                            error!("Accept error: {}", e);
                            return;
                        },
                        Ok((sock, addr)) => (sock, addr),
                    };

                    self.token_counter += 1;
                    let new_token = Token(self.token_counter);

                    self.remotes.insert(new_token, GearmanRemote::new(remote_socket, remote_addr, self.queues.clone(), new_token, self.workers.clone()));

                    event_loop.register(&self.remotes[&new_token].socket,
                                        new_token, Ready::readable(),
                                        PollOpt::edge() | PollOpt::oneshot()).unwrap();
                },
                token => {
                    let mut shutdown = false;
                    {
                        let mut other_packets = Vec::new();
                        {
                            let mut remote = self.remotes.get_mut(&token).unwrap();
                            match remote.read() {
                                Ok(sp) => {
                                    match sp {
                                        Some(p) => {
                                            match p.remote {
                                                None => remote.queue_packet(&p), // Packet is for us
                                                Some(t) => {
                                                    if t == token {
                                                        // Packet is also meant for us
                                                        remote.queue_packet(&p);
                                                    } else {
                                                        // Packet is for a different remote
                                                        other_packets.push(p);
                                                    }
                                                },
                                            };
                                        },
                                        None => {},
                                    }
                                    other_packets.extend(self.workers.do_wakes());
                                    event_loop.reregister(&remote.socket, token, remote.interest,
                                                      PollOpt::edge() | PollOpt::oneshot()).unwrap();
                                },
                                Err(e) => {
                                    info!("remote({}) hung up: {:?}", &remote, e);
                                    shutdown = true;
                                }
                            }
                        }
                        for p in other_packets {
                            let t = p.remote.unwrap();
                            match self.remotes.get_mut(&t) {
                                None => warn!("No remote for packet, dropping: {:?}", &p),
                                Some(mut remote) => {
                                    remote.queue_packet(&p);
                                    event_loop.reregister(&remote.socket, t, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap();
                                },
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }

        if events.is_writable() {
            match token {
                SERVER_TOKEN => panic!("Received writable event for server socket."),
                token => {
                    let mut shutdown = false;
                    {
                        let mut remote = self.remotes.get_mut(&token).unwrap();
                        match remote.write() {
                            Ok(_) => event_loop.reregister(&remote.socket, token, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap(),
                            Err(e) => {
                                info!("remote({}) hung up: {}", &remote, e);
                                shutdown = true;
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }
    }
}
<commit_msg>Cleaning up info logging<commit_after>use std::collections::HashMap;
use std::fmt;
use std::net::{SocketAddr};
use std::io;

use mio::deprecated::{EventLoop, Handler, TryWrite};
use mio::*;
use mio::tcp::*;
use bytes::buf::{Buf, ByteBuf};

use packet::{Packet, EofError};
use queues::*;
use worker::*;

struct GearmanRemote {
    socket: TcpStream,
    addr: SocketAddr,
    packet: Packet,
    queues: JobQueues,
    worker: Worker,
    workers: SharedWorkers,
    sendqueue: Vec<ByteBuf>,
    interest: Ready,
    token: Token,
}

pub struct GearmanServer {
    pub socket: TcpListener,
    remotes: HashMap<Token, GearmanRemote>,
    token_counter: usize,
    queues: JobQueues,
    workers: SharedWorkers,
}

const SERVER_TOKEN: Token = Token(0);

impl GearmanRemote {
    pub fn new(socket: TcpStream, addr: SocketAddr, queues: JobQueues, token: Token, workers: SharedWorkers) -> GearmanRemote {
        GearmanRemote {
            socket: socket,
            addr: addr,
            packet: Packet::new(token),
            queues: queues,
            worker: Worker::new(),
            workers: workers,
            sendqueue: Vec::with_capacity(2), // Don't need many bufs
            interest: Ready::readable(),
            token: token,
        }
    }

    pub fn queue_packet(&mut self, packet: &Packet) {
        info!("{} Queueing {:?}", self, &packet);
        self.sendqueue.push(ByteBuf::from_slice(&packet.to_byteslice()));
        self.interest.remove(Ready::readable());
        self.interest.insert(Ready::writable());
    }

    pub fn read(&mut self) -> Result<Option<Packet>, EofError> {
        let mut ret = Ok(None);
        debug!("{} readable", self);
        match self.packet.from_socket(&mut self.socket, &mut self.worker, self.workers.clone(), self.queues.clone(), self.token)? {
            None => debug!("{} Done reading", self),
            Some(p) => {
                ret = Ok(Some(p));
            }
        }
        info!("{} Processed {:?}", &self, &self.packet);
        // Non-text packets are consumed, reset
        if self.packet.consumed {
            self.packet = Packet::new(self.token);
        }
        ret
    }

    pub fn write(&mut self) -> Result<(), io::Error> {
        while !self.sendqueue.is_empty() {
            if !self.sendqueue.first().unwrap().has_remaining() {
                self.sendqueue.pop();
                continue;
            }
            let buf = self.sendqueue.first_mut().unwrap();
            match self.socket.try_write(buf.bytes())? {
                None => break,
                Some(n) => {
                    buf.advance(n);
                    continue
                }
            };
        }
        if self.sendqueue.is_empty() {
            self.interest.remove(Ready::writable());
            self.interest.insert(Ready::readable());
        };
        Ok(())
    }

    pub fn shutdown(self) {
        match self.worker.job {
            Some(mut j) => {
                j.remove_remote(&self.token);
                self.queues.clone().add_job(j) // XXX Maybe this should cut in front of the line?
            },
            None => {},
        }
        match self.socket.shutdown(Shutdown::Both) {
            Err(e) => warn!("{:?} fail on shutdown ({:?})", self.addr, e),
            Ok(_) => {},
        }
    }
}

impl fmt::Display for GearmanRemote {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Remote {{ addr: {:?} }}", self.addr)
    }
}

impl GearmanServer {
    pub fn new(server_socket: TcpListener, queues: JobQueues, workers: SharedWorkers) -> GearmanServer {
        GearmanServer {
            token_counter: 1,
            remotes: HashMap::new(),
            socket: server_socket,
            queues: queues,
            workers: workers,
        }
    }

}

impl Handler for GearmanServer {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<GearmanServer>,
             token: Token, events: Ready)
    {
        if events.is_readable() {
            match token {
                SERVER_TOKEN => {
                    let (remote_socket, remote_addr) = match self.socket.accept() {
                        Err(e) => {
                            error!("Accept error: {}", e);
                            return;
                        },
                        Ok((sock, addr)) => (sock, addr),
                    };

                    self.token_counter += 1;
                    let new_token = Token(self.token_counter);

                    self.remotes.insert(new_token, GearmanRemote::new(remote_socket, remote_addr, self.queues.clone(), new_token, self.workers.clone()));

                    event_loop.register(&self.remotes[&new_token].socket,
                                        new_token, Ready::readable(),
                                        PollOpt::edge() | PollOpt::oneshot()).unwrap();
                },
                token => {
                    let mut shutdown = false;
                    {
                        let mut other_packets = Vec::new();
                        {
                            let mut remote = self.remotes.get_mut(&token).unwrap();
                            match remote.read() {
                                Ok(sp) => {
                                    match sp {
                                        Some(p) => {
                                            match p.remote {
                                                None => remote.queue_packet(&p), // Packet is for us
                                                Some(t) => {
                                                    if t == token {
                                                        // Packet is also meant for us
                                                        remote.queue_packet(&p);
                                                    } else {
                                                        // Packet is for a different remote
                                                        other_packets.push(p);
                                                    }
                                                },
                                            };
                                        },
                                        None => {},
                                    }
                                    other_packets.extend(self.workers.do_wakes());
                                    event_loop.reregister(&remote.socket, token, remote.interest,
                                                      PollOpt::edge() | PollOpt::oneshot()).unwrap();
                                },
                                Err(e) => {
                                    info!("{} hung up: {:?}", &remote, &e);
                                    shutdown = true;
                                }
                            }
                        }
                        for p in other_packets {
                            let t = p.remote.unwrap();
                            match self.remotes.get_mut(&t) {
                                None => warn!("No remote for packet, dropping: {:?}", &p),
                                Some(mut remote) => {
                                    remote.queue_packet(&p);
                                    event_loop.reregister(&remote.socket, t, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap();
                                },
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }

        if events.is_writable() {
            match token {
                SERVER_TOKEN => panic!("Received writable event for server socket."),
                token => {
                    let mut shutdown = false;
                    {
                        let mut remote = self.remotes.get_mut(&token).unwrap();
                        match remote.write() {
                            Ok(_) => event_loop.reregister(&remote.socket, token, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap(),
                            Err(e) => {
                                info!("remote({}) hung up: {}", &remote, e);
                                shutdown = true;
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
use serde_json;
use rs_es::Client;

use iron::prelude::*;
use iron::{status, Handler, Headers};
use iron::mime::Mime;

use logger::Logger;

use router::Router;

use params::*;

use oath::*;

use config::*;
use resource::Resource;

use std::collections::HashMap;
use std::env;
use std::io::Read;
use std::marker::PhantomData;

macro_rules! try_or_422 {
  ($expr:expr) => (match $expr {
    Ok(val)  => val,
    Err(err) => {
      let mut error = HashMap::new();
      error.insert("error", format!("{}", err));

      let content_type = "application/json".parse::<Mime>().unwrap();
      return Ok(Response::with(
        (content_type, status::UnprocessableEntity, serde_json::to_string(&error).unwrap())
      ))
    }
  })
}

macro_rules! unauthorized {
  () => ({
    return Ok(Response::with(
      (status::Unauthorized)
    ))
  })
}

macro_rules! authorization {
  ($trait_name:ident, $mode:ident) => {
    trait $trait_name {
      fn is_authorized(&self, auth_config: AuthConfig, headers: &Headers) -> bool {
        if auth_config.enabled == false {
          return true;
        }

        match headers.get_raw("Authorization") {
          Some(header) => match String::from_utf8(header[0].to_owned()) {
            Ok(header) => {
              match header.split("token ").collect::<Vec<&str>>().last() {
                Some(token) => {
                  match token.parse::<u64>() {
                    Ok(token) => totp_raw(auth_config.$mode.as_bytes(), 6, 0, 30) == token,
                    Err(_)    => false,
                  }
                },
                None => false
              }
            },
            Err(_) => false
          },
          None => false
        }
      }
    }
  }
}

/// Struct for containing the search results
#[derive(Serialize, Deserialize)]
pub struct SearchResult {
  pub results: Vec<u32>
}

#[derive(Clone)]
pub struct Server<R: Resource> {
  config:   Config,
  endpoint: String,
  resource: PhantomData<R>
}

authorization!(ReadableEndpoint, read);
authorization!(WritableEndpoint, write);

pub struct SearchableHandler<R> {
  config:   Config,
  resource: PhantomData<R>
}

impl<R: Resource> SearchableHandler<R> {
  fn new(config: Config) -> Self {
    SearchableHandler::<R> { resource: PhantomData, config: config }
  }
}

impl<R: Resource> ReadableEndpoint for SearchableHandler<R> {}

impl<R: Resource> Handler for SearchableHandler<R> {
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    if !self.is_authorized(self.config.auth.to_owned(), &req.headers) {
      unauthorized!();
    }

    let mut client = Client::new(&*self.config.es.host, self.config.es.port);

    let params = try_or_422!(req.get_ref::<Params>());

    let response = SearchResult {
      results: R::search(&mut client, &*self.config.es.index, params)
    };

    let content_type = "application/json".parse::<Mime>().unwrap();
    Ok(Response::with(
      (content_type, status::Ok, try_or_422!(serde_json::to_string(&response)))
    ))
  }
}

pub struct IndexableHandler<R> {
  config:   Config,
  resource: PhantomData<R>
}

impl<R: Resource> IndexableHandler<R> {
  fn new(config: Config) -> Self {
    IndexableHandler::<R> { resource: PhantomData, config: config }
  }
}

impl<R: Resource> WritableEndpoint for IndexableHandler<R> {}

impl<R: Resource> Handler for IndexableHandler<R> {
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    if !self.is_authorized(self.config.auth.to_owned(), &req.headers) {
      unauthorized!();
    }

    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let mut client = Client::new(&*self.config.es.host, self.config.es.port);

    let resource: R = try_or_422!(serde_json::from_str(&payload));
    try_or_422!(resource.index(&mut client, &*self.config.es.index));

    Ok(Response::with(status::Created))
  }
}

pub struct ResettableHandler<R> {
  config:   Config,
  resource: PhantomData<R>
}

impl<R: Resource> ResettableHandler<R> {
  fn new(config: Config) -> Self {
    ResettableHandler::<R> { resource: PhantomData, config: config }
  }
}

impl<R: Resource> WritableEndpoint for ResettableHandler<R> {}

impl<R: Resource> Handler for ResettableHandler<R> {
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    if !self.is_authorized(self.config.auth.to_owned(), &req.headers) {
      unauthorized!();
    }

    let mut client = Client::new(&*self.config.es.host, self.config.es.port);
    match R::reset_index(&mut client, &*self.config.es.index) {
      Ok(_)  => Ok(Response::with(status::NoContent)),
      Err(_) => Ok(Response::with(status::UnprocessableEntity))
    }
  }
}

impl<R: Resource> Server<R> {
  pub fn new(endpoint: &str) -> Self {
    let config = match env::args().nth(1) {
      Some(file) => Config::from_file(file),
      None       => Config::from_env()
    };

    Server {
      config:   config,
      endpoint: endpoint.to_owned(),
      resource: PhantomData
    }
  }

  pub fn start(&self) {
    let host = format!("{}:{}", self.config.http.host, self.config.http.port);

    println!("Searchspot v{}\n{}\n{}\n", env!("CARGO_PKG_VERSION"),
                                         self.config.es,
                                         self.config.http);

    let mut router = Router::new();
    router.get(&self.endpoint,    SearchableHandler::<R>::new(self.config.to_owned()));
    router.post(&self.endpoint,   IndexableHandler::<R>::new(self.config.to_owned()));
    router.delete(&self.endpoint, ResettableHandler::<R>::new(self.config.to_owned()));

    match env::var("DYNO") { // for some reasons, chain::link makes heroku crash
      Ok(_)  => Iron::new(router).http(&*host),
      Err(_) => {
        let mut chain = Chain::new(router);
        chain.link(Logger::new(None));
        Iron::new(chain).http(&*host)
      }
    }.unwrap();
  }
}

#[cfg(test)]
mod tests {
  use server::SearchResult;
  use serde_json;

  #[test]
  fn test_search_result_to_json() {
    {
      let response = SearchResult {
        results: vec![]
      };

      let json_response = serde_json::to_string(&response).unwrap();
      assert_eq!(json_response, "{\"results\":[]}");
    }
  }
}

<commit_msg>server: remove empty lines from the end of the page<commit_after>#![allow(non_upper_case_globals)]
use serde_json;
use rs_es::Client;

use iron::prelude::*;
use iron::{status, Handler, Headers};
use iron::mime::Mime;

use logger::Logger;

use router::Router;

use params::*;

use oath::*;

use config::*;
use resource::Resource;

use std::collections::HashMap;
use std::env;
use std::io::Read;
use std::marker::PhantomData;

macro_rules! try_or_422 {
  ($expr:expr) => (match $expr {
    Ok(val)  => val,
    Err(err) => {
      let mut error = HashMap::new();
      error.insert("error", format!("{}", err));

      let content_type = "application/json".parse::<Mime>().unwrap();
      return Ok(Response::with(
        (content_type, status::UnprocessableEntity, serde_json::to_string(&error).unwrap())
      ))
    }
  })
}

macro_rules! unauthorized {
  () => ({
    return Ok(Response::with(
      (status::Unauthorized)
    ))
  })
}

macro_rules! authorization {
  ($trait_name:ident, $mode:ident) => {
    trait $trait_name {
      fn is_authorized(&self, auth_config: AuthConfig, headers: &Headers) -> bool {
        if auth_config.enabled == false {
          return true;
        }

        match headers.get_raw("Authorization") {
          Some(header) => match String::from_utf8(header[0].to_owned()) {
            Ok(header) => {
              match header.split("token ").collect::<Vec<&str>>().last() {
                Some(token) => {
                  match token.parse::<u64>() {
                    Ok(token) => totp_raw(auth_config.$mode.as_bytes(), 6, 0, 30) == token,
                    Err(_)    => false,
                  }
                },
                None => false
              }
            },
            Err(_) => false
          },
          None => false
        }
      }
    }
  }
}

/// Struct for containing the search results
#[derive(Serialize, Deserialize)]
pub struct SearchResult {
  pub results: Vec<u32>
}

#[derive(Clone)]
pub struct Server<R: Resource> {
  config:   Config,
  endpoint: String,
  resource: PhantomData<R>
}

authorization!(ReadableEndpoint, read);
authorization!(WritableEndpoint, write);

pub struct SearchableHandler<R> {
  config:   Config,
  resource: PhantomData<R>
}

impl<R: Resource> SearchableHandler<R> {
  fn new(config: Config) -> Self {
    SearchableHandler::<R> { resource: PhantomData, config: config }
  }
}

impl<R: Resource> ReadableEndpoint for SearchableHandler<R> {}

impl<R: Resource> Handler for SearchableHandler<R> {
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    if !self.is_authorized(self.config.auth.to_owned(), &req.headers) {
      unauthorized!();
    }

    let mut client = Client::new(&*self.config.es.host, self.config.es.port);

    let params = try_or_422!(req.get_ref::<Params>());

    let response = SearchResult {
      results: R::search(&mut client, &*self.config.es.index, params)
    };

    let content_type = "application/json".parse::<Mime>().unwrap();
    Ok(Response::with(
      (content_type, status::Ok, try_or_422!(serde_json::to_string(&response)))
    ))
  }
}

pub struct IndexableHandler<R> {
  config:   Config,
  resource: PhantomData<R>
}

impl<R: Resource> IndexableHandler<R> {
  fn new(config: Config) -> Self {
    IndexableHandler::<R> { resource: PhantomData, config: config }
  }
}

impl<R: Resource> WritableEndpoint for IndexableHandler<R> {}

impl<R: Resource> Handler for IndexableHandler<R> {
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    if !self.is_authorized(self.config.auth.to_owned(), &req.headers) {
      unauthorized!();
    }

    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let mut client = Client::new(&*self.config.es.host, self.config.es.port);

    let resource: R = try_or_422!(serde_json::from_str(&payload));
    try_or_422!(resource.index(&mut client, &*self.config.es.index));

    Ok(Response::with(status::Created))
  }
}

pub struct ResettableHandler<R> {
  config:   Config,
  resource: PhantomData<R>
}

impl<R: Resource> ResettableHandler<R> {
  fn new(config: Config) -> Self {
    ResettableHandler::<R> { resource: PhantomData, config: config }
  }
}

impl<R: Resource> WritableEndpoint for ResettableHandler<R> {}

impl<R: Resource> Handler for ResettableHandler<R> {
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    if !self.is_authorized(self.config.auth.to_owned(), &req.headers) {
      unauthorized!();
    }

    let mut client = Client::new(&*self.config.es.host, self.config.es.port);
    match R::reset_index(&mut client, &*self.config.es.index) {
      Ok(_)  => Ok(Response::with(status::NoContent)),
      Err(_) => Ok(Response::with(status::UnprocessableEntity))
    }
  }
}

impl<R: Resource> Server<R> {
  pub fn new(endpoint: &str) -> Self {
    let config = match env::args().nth(1) {
      Some(file) => Config::from_file(file),
      None       => Config::from_env()
    };

    Server {
      config:   config,
      endpoint: endpoint.to_owned(),
      resource: PhantomData
    }
  }

  pub fn start(&self) {
    let host = format!("{}:{}", self.config.http.host, self.config.http.port);

    println!("Searchspot v{}\n{}\n{}\n", env!("CARGO_PKG_VERSION"),
                                         self.config.es,
                                         self.config.http);

    let mut router = Router::new();
    router.get(&self.endpoint,    SearchableHandler::<R>::new(self.config.to_owned()));
    router.post(&self.endpoint,   IndexableHandler::<R>::new(self.config.to_owned()));
    router.delete(&self.endpoint, ResettableHandler::<R>::new(self.config.to_owned()));

    match env::var("DYNO") { // for some reasons, chain::link makes heroku crash
      Ok(_)  => Iron::new(router).http(&*host),
      Err(_) => {
        let mut chain = Chain::new(router);
        chain.link(Logger::new(None));
        Iron::new(chain).http(&*host)
      }
    }.unwrap();
  }
}

#[cfg(test)]
mod tests {
  use server::SearchResult;
  use serde_json;

  #[test]
  fn test_search_result_to_json() {
    {
      let response = SearchResult {
        results: vec![]
      };

      let json_response = serde_json::to_string(&response).unwrap();
      assert_eq!(json_response, "{\"results\":[]}");
    }
  }
}
<|endoftext|>


<commit_before>use traits::*;

pub enum Method {
    RK2,
    RK4,
}

/**
```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t])
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);

// run the solver
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /**
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            &Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(initial_conditions: &Vec<T>, function: F) -> Solver<T, F> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
            function:           function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn change_weight(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        assert!(self.validate());

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&vec![0., 0.],
                            |t: &f32, _: &Vec<f32>| -> Vec<f32> {
                                vec![2.*t]
                            });
    }
}
<commit_msg>Break change: change_weight -> weights<commit_after>use traits::*;

pub enum Method {
    RK2,
    RK4,
}

/**

# Default values

- [method](struct.Solver.html#method.method): `Method::RK4`

- [weights](struct.Solver.html#method.weights) for the intermediate points:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

(Note that each internal value of the vector will be converted to `T` via
[T::from_str_radix()](../num_traits/trait.Num.html#tymethod.from_str_radix).)

# Example

```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t])
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);

// run the solver
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /*
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            &Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(initial_conditions: &Vec<T>, function: F) -> Solver<T, F> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
            function:           function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn weights(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        assert!(self.validate());

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&vec![0., 0.],
                            |t: &f32, _: &Vec<f32>| -> Vec<f32> {
                                vec![2.*t]
                            });
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::cell::RefCell;
use std::mem::transmute;
use std::process;
use std::thread;
use ffi as glib_ffi;
use ffi::{gboolean, gpointer};
use translate::{from_glib, from_glib_full, FromGlib, ToGlib, ToGlibPtr};
use libc;

use Source;

/// The id of a source that is returned by `idle_add` and `timeout_add`.
///
/// A value of 0 is a good default as it is never a valid source ID.
#[derive(Debug, Default, Eq, PartialEq)]
pub struct SourceId(u32);

impl ToGlib for SourceId {
    type GlibType = u32;

    #[inline]
    fn to_glib(&self) -> u32 {
        self.0
    }
}

impl FromGlib<u32> for SourceId {
    #[inline]
    fn from_glib(val: u32) -> SourceId {
        SourceId(val)
    }
}

/// Continue calling the closure in the future iterations or drop it.
///
/// This is the return type of `idle_add` and `timeout_add` closures.
///
/// `Continue(true)` keeps the closure assigned, to be rerun when appropriate.
///
/// `Continue(false)` disconnects and drops it.
pub struct Continue(pub bool);

impl ToGlib for Continue {
    type GlibType = gboolean;

    #[inline]
    fn to_glib(&self) -> gboolean {
        self.0.to_glib()
    }
}

/// Unwinding propagation guard. Aborts the process if destroyed while
/// panicking.
pub struct CallbackGuard(());

impl CallbackGuard {
    pub fn new() -> CallbackGuard {
        CallbackGuard(())
    }
}

impl Default for CallbackGuard {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for CallbackGuard {
    fn drop(&mut self) {
        use std::io::stderr;
        use std::io::Write;

        if thread::panicking() {
            let _ = stderr().write(b"Uncaught panic, exiting\n");
            process::abort();
        }
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline(func: gpointer) -> gboolean {
    let _guard = CallbackGuard::new();
    let func: &RefCell<Box<FnMut() -> Continue + 'static>> = transmute(func);
    (&mut *func.borrow_mut())().to_glib()
}

unsafe extern "C" fn destroy_closure(ptr: gpointer) {
    let _guard = CallbackGuard::new();
    Box::<RefCell<Box<FnMut() -> Continue + 'static>>>::from_raw(ptr as *mut _);
}

fn into_raw<F: FnMut() -> Continue + Send + 'static>(func: F) -> gpointer {
    let func: Box<RefCell<Box<FnMut() -> Continue + Send + 'static>>> =
        Box::new(RefCell::new(Box::new(func)));
    Box::into_raw(func) as gpointer
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline_child_watch(pid: u32, status: i32, func: gpointer) {
    let _guard = CallbackGuard::new();
    let func: &RefCell<Box<FnMut(u32, i32) + 'static>> = transmute(func);
    (&mut *func.borrow_mut())(pid, status)
}

unsafe extern "C" fn destroy_closure_child_watch(ptr: gpointer) {
    let _guard = CallbackGuard::new();
    Box::<RefCell<Box<FnMut(u32, i32) + 'static>>>::from_raw(ptr as *mut _);
}

fn into_raw_child_watch<F: FnMut(u32, i32) + Send + 'static>(func: F) -> gpointer {
    let func: Box<RefCell<Box<FnMut(u32, i32) + Send + 'static>>> =
        Box::new(RefCell::new(Box::new(func)));
    Box::into_raw(func) as gpointer
}

/// Adds a closure to be called by the default main loop when it's idle.
///
/// `func` will be called repeatedly until it returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn idle_add<F>(func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_idle_add_full(glib_ffi::G_PRIORITY_DEFAULT_IDLE, Some(trampoline),
            into_raw(func), Some(destroy_closure)))
    }
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with millisecond granularity.
///
/// `func` will be called repeatedly every `interval` milliseconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events. Prefer `timeout_add_seconds` when millisecond
/// precision is not necessary.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn timeout_add<F>(interval: u32, func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_timeout_add_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
            Some(trampoline), into_raw(func), Some(destroy_closure)))
    }
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with second granularity.
///
/// `func` will be called repeatedly every `interval` seconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn timeout_add_seconds<F>(interval: u32, func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_timeout_add_seconds_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
            Some(trampoline), into_raw(func), Some(destroy_closure)))
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
/// process exits.
///
/// `func` will be called when `pid` exits
pub fn child_watch_add<'a, N: Into<Option<&'a str>>, F>(pid: u32, func: F) -> SourceId
where F: FnMut(u32, i32) + Send + 'static {
    unsafe {
        let trampoline = trampoline_child_watch as *mut libc::c_void;
        from_glib(glib_ffi::g_child_watch_add_full(glib_ffi::G_PRIORITY_DEFAULT, pid as i32,
            Some(transmute(trampoline)), into_raw_child_watch(func), Some(destroy_closure_child_watch)))
    }
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the default main loop whenever a UNIX signal is raised.
///
/// `func` will be called repeatedly every time `signum` is raised until it
/// returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn unix_signal_add<F>(signum: i32, func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_unix_signal_add_full(glib_ffi::G_PRIORITY_DEFAULT, signum,
            Some(trampoline), into_raw(func), Some(destroy_closure)))
    }
}

/// Removes the source with the given id `source_id` from the default main context.
///
/// It is a programmer error to attempt to remove a non-existent source.
/// Note: source id are reused.
///
/// For historical reasons, the native function always returns true, so we
/// ignore it here.
pub fn source_remove(source_id: SourceId) {
    unsafe {
        glib_ffi::g_source_remove(source_id.to_glib());
    }
}

/// The priority of sources
///
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Priority(i32);

impl ToGlib for Priority {
    type GlibType = i32;

    #[inline]
    fn to_glib(&self) -> i32 {
        self.0
    }
}

impl FromGlib<i32> for Priority {
    #[inline]
    fn from_glib(val: i32) -> Priority {
        Priority(val)
    }
}

pub const PRIORITY_HIGH: Priority = Priority(glib_ffi::G_PRIORITY_HIGH);
pub const PRIORITY_DEFAULT: Priority = Priority(glib_ffi::G_PRIORITY_DEFAULT);
pub const PRIORITY_HIGH_IDLE: Priority = Priority(glib_ffi::G_PRIORITY_HIGH_IDLE);
pub const PRIORITY_DEFAULT_IDLE: Priority = Priority(glib_ffi::G_PRIORITY_DEFAULT_IDLE);
pub const PRIORITY_LOW: Priority = Priority(glib_ffi::G_PRIORITY_LOW);

/// Adds a closure to be called by the main loop the return `Source` is attached to when it's idle.
///
/// `func` will be called repeatedly until it returns `Continue(false)`.
pub fn idle_source_new<'a, N: Into<Option<&'a str>>, F>(name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_idle_source_new();
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to at regular
/// intervals with millisecond granularity.
///
/// `func` will be called repeatedly every `interval` milliseconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events. Prefer `timeout_add_seconds` when millisecond
/// precision is not necessary.
pub fn timeout_source_new<'a, N: Into<Option<&'a str>>, F>(interval: u32, name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_timeout_source_new(interval);
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to at regular
/// intervals with second granularity.
///
/// `func` will be called repeatedly every `interval` seconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events.
pub fn timeout_source_new_seconds<'a, N: Into<Option<&'a str>>, F>(interval: u32, name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_timeout_source_new_seconds(interval);
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
/// process exits.
///
/// `func` will be called when `pid` exits
pub fn child_watch_source_new<'a, N: Into<Option<&'a str>>, F>(pid: u32, name: N, priority: Priority, func: F) -> Source
where F: FnMut(u32, i32) + Send + 'static {
    unsafe {
        let source = glib_ffi::g_child_watch_source_new(pid as glib_ffi::GPid);
        let trampoline = trampoline_child_watch as *mut libc::c_void;
        glib_ffi::g_source_set_callback(source, Some(transmute(trampoline)), into_raw_child_watch(func), Some(destroy_closure_child_watch));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a
/// UNIX signal is raised.
///
/// `func` will be called repeatedly every time `signum` is raised until it
/// returns `Continue(false)`.
pub fn unix_signal_source_new<'a, N: Into<Option<&'a str>>, F>(signum: i32, name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_unix_signal_source_new(signum);
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}
<commit_msg>Remove Default impl for SourceId<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::cell::RefCell;
use std::mem::transmute;
use std::process;
use std::thread;
use ffi as glib_ffi;
use ffi::{gboolean, gpointer};
use translate::{from_glib, from_glib_full, FromGlib, ToGlib, ToGlibPtr};
use libc;

use Source;

/// The id of a source that is returned by `idle_add` and `timeout_add`.
#[derive(Debug, Eq, PartialEq)]
pub struct SourceId(u32);

impl ToGlib for SourceId {
    type GlibType = u32;

    #[inline]
    fn to_glib(&self) -> u32 {
        self.0
    }
}

impl FromGlib<u32> for SourceId {
    #[inline]
    fn from_glib(val: u32) -> SourceId {
        SourceId(val)
    }
}

/// Continue calling the closure in the future iterations or drop it.
///
/// This is the return type of `idle_add` and `timeout_add` closures.
///
/// `Continue(true)` keeps the closure assigned, to be rerun when appropriate.
///
/// `Continue(false)` disconnects and drops it.
pub struct Continue(pub bool);

impl ToGlib for Continue {
    type GlibType = gboolean;

    #[inline]
    fn to_glib(&self) -> gboolean {
        self.0.to_glib()
    }
}

/// Unwinding propagation guard. Aborts the process if destroyed while
/// panicking.
pub struct CallbackGuard(());

impl CallbackGuard {
    pub fn new() -> CallbackGuard {
        CallbackGuard(())
    }
}

impl Default for CallbackGuard {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for CallbackGuard {
    fn drop(&mut self) {
        use std::io::stderr;
        use std::io::Write;

        if thread::panicking() {
            let _ = stderr().write(b"Uncaught panic, exiting\n");
            process::abort();
        }
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline(func: gpointer) -> gboolean {
    let _guard = CallbackGuard::new();
    let func: &RefCell<Box<FnMut() -> Continue + 'static>> = transmute(func);
    (&mut *func.borrow_mut())().to_glib()
}

unsafe extern "C" fn destroy_closure(ptr: gpointer) {
    let _guard = CallbackGuard::new();
    Box::<RefCell<Box<FnMut() -> Continue + 'static>>>::from_raw(ptr as *mut _);
}

fn into_raw<F: FnMut() -> Continue + Send + 'static>(func: F) -> gpointer {
    let func: Box<RefCell<Box<FnMut() -> Continue + Send + 'static>>> =
        Box::new(RefCell::new(Box::new(func)));
    Box::into_raw(func) as gpointer
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline_child_watch(pid: u32, status: i32, func: gpointer) {
    let _guard = CallbackGuard::new();
    let func: &RefCell<Box<FnMut(u32, i32) + 'static>> = transmute(func);
    (&mut *func.borrow_mut())(pid, status)
}

unsafe extern "C" fn destroy_closure_child_watch(ptr: gpointer) {
    let _guard = CallbackGuard::new();
    Box::<RefCell<Box<FnMut(u32, i32) + 'static>>>::from_raw(ptr as *mut _);
}

fn into_raw_child_watch<F: FnMut(u32, i32) + Send + 'static>(func: F) -> gpointer {
    let func: Box<RefCell<Box<FnMut(u32, i32) + Send + 'static>>> =
        Box::new(RefCell::new(Box::new(func)));
    Box::into_raw(func) as gpointer
}

/// Adds a closure to be called by the default main loop when it's idle.
///
/// `func` will be called repeatedly until it returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn idle_add<F>(func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_idle_add_full(glib_ffi::G_PRIORITY_DEFAULT_IDLE, Some(trampoline),
            into_raw(func), Some(destroy_closure)))
    }
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with millisecond granularity.
///
/// `func` will be called repeatedly every `interval` milliseconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events. Prefer `timeout_add_seconds` when millisecond
/// precision is not necessary.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn timeout_add<F>(interval: u32, func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_timeout_add_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
            Some(trampoline), into_raw(func), Some(destroy_closure)))
    }
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with second granularity.
///
/// `func` will be called repeatedly every `interval` seconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn timeout_add_seconds<F>(interval: u32, func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_timeout_add_seconds_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
            Some(trampoline), into_raw(func), Some(destroy_closure)))
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
/// process exits.
///
/// `func` will be called when `pid` exits
pub fn child_watch_add<'a, N: Into<Option<&'a str>>, F>(pid: u32, func: F) -> SourceId
where F: FnMut(u32, i32) + Send + 'static {
    unsafe {
        let trampoline = trampoline_child_watch as *mut libc::c_void;
        from_glib(glib_ffi::g_child_watch_add_full(glib_ffi::G_PRIORITY_DEFAULT, pid as i32,
            Some(transmute(trampoline)), into_raw_child_watch(func), Some(destroy_closure_child_watch)))
    }
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the default main loop whenever a UNIX signal is raised.
///
/// `func` will be called repeatedly every time `signum` is raised until it
/// returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
pub fn unix_signal_add<F>(signum: i32, func: F) -> SourceId
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        from_glib(glib_ffi::g_unix_signal_add_full(glib_ffi::G_PRIORITY_DEFAULT, signum,
            Some(trampoline), into_raw(func), Some(destroy_closure)))
    }
}

/// Removes the source with the given id `source_id` from the default main context.
///
/// It is a programmer error to attempt to remove a non-existent source.
/// Note: source id are reused.
///
/// For historical reasons, the native function always returns true, so we
/// ignore it here.
pub fn source_remove(source_id: SourceId) {
    unsafe {
        glib_ffi::g_source_remove(source_id.to_glib());
    }
}

/// The priority of sources
///
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Priority(i32);

impl ToGlib for Priority {
    type GlibType = i32;

    #[inline]
    fn to_glib(&self) -> i32 {
        self.0
    }
}

impl FromGlib<i32> for Priority {
    #[inline]
    fn from_glib(val: i32) -> Priority {
        Priority(val)
    }
}

pub const PRIORITY_HIGH: Priority = Priority(glib_ffi::G_PRIORITY_HIGH);
pub const PRIORITY_DEFAULT: Priority = Priority(glib_ffi::G_PRIORITY_DEFAULT);
pub const PRIORITY_HIGH_IDLE: Priority = Priority(glib_ffi::G_PRIORITY_HIGH_IDLE);
pub const PRIORITY_DEFAULT_IDLE: Priority = Priority(glib_ffi::G_PRIORITY_DEFAULT_IDLE);
pub const PRIORITY_LOW: Priority = Priority(glib_ffi::G_PRIORITY_LOW);

/// Adds a closure to be called by the main loop the return `Source` is attached to when it's idle.
///
/// `func` will be called repeatedly until it returns `Continue(false)`.
pub fn idle_source_new<'a, N: Into<Option<&'a str>>, F>(name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_idle_source_new();
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to at regular
/// intervals with millisecond granularity.
///
/// `func` will be called repeatedly every `interval` milliseconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events. Prefer `timeout_add_seconds` when millisecond
/// precision is not necessary.
pub fn timeout_source_new<'a, N: Into<Option<&'a str>>, F>(interval: u32, name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_timeout_source_new(interval);
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to at regular
/// intervals with second granularity.
///
/// `func` will be called repeatedly every `interval` seconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events.
pub fn timeout_source_new_seconds<'a, N: Into<Option<&'a str>>, F>(interval: u32, name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_timeout_source_new_seconds(interval);
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
/// process exits.
///
/// `func` will be called when `pid` exits
pub fn child_watch_source_new<'a, N: Into<Option<&'a str>>, F>(pid: u32, name: N, priority: Priority, func: F) -> Source
where F: FnMut(u32, i32) + Send + 'static {
    unsafe {
        let source = glib_ffi::g_child_watch_source_new(pid as glib_ffi::GPid);
        let trampoline = trampoline_child_watch as *mut libc::c_void;
        glib_ffi::g_source_set_callback(source, Some(transmute(trampoline)), into_raw_child_watch(func), Some(destroy_closure_child_watch));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a
/// UNIX signal is raised.
///
/// `func` will be called repeatedly every time `signum` is raised until it
/// returns `Continue(false)`.
pub fn unix_signal_source_new<'a, N: Into<Option<&'a str>>, F>(signum: i32, name: N, priority: Priority, func: F) -> Source
where F: FnMut() -> Continue + Send + 'static {
    unsafe {
        let source = glib_ffi::g_unix_signal_source_new(signum);
        glib_ffi::g_source_set_callback(source, Some(trampoline), into_raw(func), Some(destroy_closure));
        glib_ffi::g_source_set_priority(source, priority.to_glib());

        let name = name.into();
        if let Some(name) = name {
            glib_ffi::g_source_set_name(source, name.to_glib_none().0);
        }

        from_glib_full(source)
    }
}
<|endoftext|>