<commit_before>extern crate mio;
extern crate bytes;
#[macro_use]
extern crate log;
extern crate serde;
extern crate serde_json;
extern crate spki_sexp;

extern crate etcd;

use mio::tcp::*;
use mio::EventLoop;
use mio::util::Slab;
use std::collections::{VecDeque,BTreeMap};
use std::net::SocketAddr;
use std::cmp;

mod line_conn;
mod downstream_conn;
mod listener;
mod config;
mod event_handler;
mod data;

use line_conn::{SexpPeer,LineConn};
use downstream_conn::Downstream;
use listener::Listener;
use event_handler::EventHandler;

pub use data::*;
pub use config::*;

const REPLICATION_CREDIT : u64 = 10;

pub type PeerMsg = (u64, u64, Operation);

#[derive(Debug)]
enum ChainReplMsg {
    Operation { source: mio::Token, epoch: Option<u64>, seqno: Option<u64>, op: Operation },
    DownstreamResponse(OpResp),
    NewClientConn(Role, TcpStream),
}

#[derive(Debug)]
pub struct ChainRepl {
    connections: Slab<EventHandler>,
    downstream_slot: Option<mio::Token>,
    // "Model" fields
    last_sent_downstream: Option<u64>,
    last_acked_downstream: Option<u64>,
    pending_operations: BTreeMap<u64, mio::Token>,
    log: BTreeMap<u64, Operation>,
    state: String,
    new_view: Option<ConfigurationView<NodeViewConfig>>,
    node_config: NodeViewConfig,
    current_epoch: u64,
}

impl ChainRepl {
    pub fn new() -> ChainRepl {
        ChainRepl {
            connections: Slab::new(1024),
            downstream_slot: None,
            last_sent_downstream: None,
            last_acked_downstream: None,
            log: BTreeMap::new(),
            pending_operations: BTreeMap::new(),
            state: String::new(),
            new_view: None,
            node_config: Default::default(),
            current_epoch: Default::default(),
        }
    }

    pub fn listen(&mut self, event_loop: &mut mio::EventLoop<ChainRepl>, addr: SocketAddr, role: Role) {
        info!("Listen on {:?} for {:?}", addr, role);
        let l = Listener::new(addr, role.clone());
        match role {
            Role::Upstream => self.node_config.peer_addr = Some(format!("{}", l.listen_addr())),
            Role::Client => self.node_config.client_addr = Some(format!("{}", l.listen_addr())),
        }
        let token = self.connections.insert(EventHandler::Listener(l)).expect("insert listener");
        &self.connections[token].initialize(event_loop, token);
    }

    pub fn set_downstream(&mut self, event_loop: &mut mio::EventLoop<ChainRepl>, target: Option<SocketAddr>) {
        match (self.downstream_slot, target) {
            (Some(_), Some(target)) => self.downstream().expect("downstream").reconnect_to(target),
            (None, Some(target)) => {
                let token = self.connections.insert_with(|token| EventHandler::Downstream(Downstream::new(Some(target), token)))
                    .expect("insert downstream");
                &self.connections[token].initialize(event_loop, token);
                self.downstream_slot = Some(token)
            },
            (Some(_), None) => self.downstream().expect("downstream").disconnect(),
            (None, None) => (),
        }
    }

    fn seqno(&self) -> u64 {
        self.log.len() as u64
    }

    fn next_seqno(&self) -> u64 {
        self.seqno()
    }

    fn process_action(&mut self, msg: ChainReplMsg, event_loop: &mut mio::EventLoop<ChainRepl>) {
        trace!("{:p}; got {:?}", self, msg);
        match msg {
            ChainReplMsg::Operation { source, seqno, epoch, op } => {
                let seqno = seqno.unwrap_or_else(|| self.next_seqno());
                // assert!(seqno == 0 || self.log.get(&(seqno-1)).is_some());

                let epoch = epoch.unwrap_or_else(|| self.current_epoch);

               if epoch != self.current_epoch {
                    warn!("Operation epoch ({}) differers from our last observed configuration: ({})",
                        epoch, self.current_epoch);
                    let resp = OpResp::Err(epoch, seqno, format!("BadEpoch: {}; last seen config: {}", epoch, self.current_epoch));
                    self.connections[source].response(resp);
                    return;
                }

                if !(seqno == 0 || self.log.get(&(seqno-1)).is_some()) {
                    warn!("Hole in history: saw {}/{}; have: {:?}", epoch, seqno, self.log.keys().collect::<Vec<_>>());
                    let resp = OpResp::Err(epoch, seqno, format!("Bad sequence number; previous: {:?}, saw: {:?}",
                        self.log.keys().rev().next(), seqno));
                    self.connections[source].response(resp);
                    return;
                }

                let prev = self.log.insert(seqno, op.clone());
                debug!("Log entry {:?}: {:?}", seqno, op);
                if let Some(prev) = prev {
                    panic!("Unexpectedly existing log entry for item {}: {:?}", seqno, prev);
                }

                if let Some(_) = self.downstream_slot {
                    self.pending_operations.insert(seqno, source);
                    // Replication mechanism should handle the push to downstream.
                } else {
                    info!("Terminus! {:?}/{:?}", seqno, op);
                    let resp = match op {
                        Operation::Set(s) => {
                            self.state = s;
                            OpResp::Ok(epoch, seqno, None)
                        },
                        Operation::Get => OpResp::Ok(epoch, seqno, Some(self.state.clone()))
                    };
                    self.connections[source].response(resp)
                }
            },

            ChainReplMsg::DownstreamResponse(reply) => {
                debug!("Downstream response: {:?}", reply);
                match reply {
                    OpResp::Ok(epoch, seqno, _) | OpResp::Err(epoch, seqno, _) => {
                        if let Some(token) = self.pending_operations.remove(&seqno) {
                            info!("Found in-flight op {:?} for client token {:?}", seqno, token);
                            if let Some(ref mut c)  = self.connections.get_mut(token) {
                                c.response(reply)
                            }
                            self.last_acked_downstream = Some(seqno)
                        } else {
                            warn!("Unexpected response for seqno: {:?}", seqno);
                        }
                    },
                    OpResp::HelloIWant(last_sent_downstream) => {
                        info!("Downstream has {:?}", last_sent_downstream);
                        assert!(last_sent_downstream <= self.seqno());
                        self.last_sent_downstream = Some(last_sent_downstream);
                    },
                };
            },

            ChainReplMsg::NewClientConn(role, socket) => {
                let peer = socket.peer_addr().expect("peer address");
                let seqno = self.seqno();
                assert!(self.log.get(&seqno).is_none());
                let token = self.connections
                    .insert_with(|token| match role {
                            Role::Client => EventHandler::Conn(LineConn::client(socket, token)),
                            Role::Upstream => {
                                let mut conn = LineConn::upstream(socket, token);
                                let msg = OpResp::HelloIWant(seqno);
                                info!("Inform upstream about our current version, {:?}!", msg);
                                conn.response(msg);
                                EventHandler::Upstream(conn)
                            },
                    })
                    .expect("token insert");
                debug!("Client connection of {:?}/{:?} from {:?}", role, token, peer);
                &self.connections[token].initialize(event_loop, token);
            }
        }
    }

    fn process_rules(&mut self, event_loop: &mut mio::EventLoop<Self>) -> bool {
        debug!("pre  Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
            self.seqno(), self.last_sent_downstream, self.last_acked_downstream);
        let mut changed = false;
        if let Some(send_next) = self.last_sent_downstream {
            if send_next < self.seqno() {
                let max_to_push_now = cmp::min(self.last_acked_downstream.unwrap_or(0) + REPLICATION_CREDIT, self.seqno());
                debug!("Window push {:?} - {:?}; waiting: {:?}", send_next, max_to_push_now, self.seqno() - max_to_push_now);
                let epoch = self.current_epoch;
                for i in send_next..max_to_push_now {
                    debug!("Log item: {:?}: {:?}", i, self.log.get(&i));
                    let op = self.log[&i].clone();
                    debug!("Queueing epoch:{:?}; seq:{:?}/{:?}; ds/seqno: {:?}", epoch, i, op, self.last_sent_downstream);
                    self.downstream().expect("Downstream").send_to_downstream(epoch, i, op);
                    self.last_sent_downstream = Some(i+1);
                    changed = true
                }
            }
            debug!("post Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
                self.seqno(), self.last_sent_downstream, self.last_acked_downstream);
        }

        // Cases:
        // Head(nextNode)
        // Middle(nextNode)
        // Tail
        if let Some(view) = self.new_view.take() {
            info!("Reconfigure according to: {:?}", view);
            if !view.in_configuration() {
                warn!("I am not in this configuration; shutting down: {:?}", view);
                event_loop.shutdown();
            }

            let listen_for_clients = view.should_listen_for_clients();
            info!("Listen for clients: {:?}", listen_for_clients);
            for p in self.listeners(Role::Client) {
                p.set_active(listen_for_clients);
            }
            let listen_for_upstreamp = view.should_listen_for_upstream();
            info!("Listen for upstreams: {:?}", listen_for_upstreamp);
            for p in self.listeners(Role::Upstream) {
                p.set_active(listen_for_upstreamp);
            }
            if let Some(ds) = view.should_connect_downstream() {
                info!("Push to downstream on {:?}", ds);
                if let Some(peer_addr) = ds.peer_addr {
                    self.set_downstream(event_loop, Some(peer_addr.parse().expect("peer address")));
                } else {
                    panic!("Cannot reconnect to downstream with no peer listener: {:?}", ds);
                }
            } else {
                info!("Tail node!");
                self.set_downstream(event_loop, None);
            }

            self.current_epoch = view.epoch;

            changed = true;
        }

        changed
    }

    fn downstream<'a>(&'a mut self) -> Option<&'a mut Downstream<SexpPeer>> {
        self.downstream_slot.map(move |slot| match &mut self.connections[slot] {
            &mut EventHandler::Downstream(ref mut d) => d,
            other => panic!("Downstream slot not populated with a downstream instance: {:?}", other),
        })
    }

    fn listeners<'a>(&'a mut self, role: Role) -> Vec<&'a mut Listener> {
        self.connections.iter_mut().filter_map(|it| match it {
            &mut EventHandler::Listener(ref mut l) if l.role == role => Some(l),
            _ => None
        }).collect()
    }

    fn converge_state(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        let mut parent_actions = VecDeque::new();
        let mut changed = true;
        let mut iterations = 0;
        debug!("Converge begin");
        while changed {
            trace!("Iter: {:?}", iterations);
            changed = false;
            for conn in self.connections.iter_mut() {
                let changedp = conn.process_rules(event_loop, &mut |item| parent_actions.push_back(item));
                if changedp { debug!("Changed: {:?}", conn); };
                changed |= changedp;
            }

            let changedp = self.process_rules(event_loop);
            if changedp { debug!("Changed: {:?}", "Model"); }
            changed |= changedp;

            for action in parent_actions.drain(..) {
                debug!("Action: {:?}", action);
                self.process_action(action, event_loop);
            }
            iterations += 1;
        }
        debug!("Converged after {:?} iterations", iterations);
    }

    fn io_ready(&mut self, event_loop: &mut mio::EventLoop<Self>, token: mio::Token) {
        self.converge_state(event_loop);
        if self.connections[token].is_closed() && self.pending_operations.values().all(|tok| tok != &token) {
            debug!("Close candidate: {:?}: pending: {:?}",
                token, self.pending_operations.values().filter(|tok| **tok == token).count());
            let it = self.connections.remove(token);
            debug!("Removing; {:?}; {:?}", token, it);
            if Some(token) == self.downstream_slot {
                self.downstream_slot = None;
                self.last_sent_downstream = None
            }
        }
    }

    fn handle_view_changed(&mut self, view: ConfigurationView<NodeViewConfig>) {
        self.new_view = Some(view)
    }

    pub fn get_notifier(&self, event_loop: &mut mio::EventLoop<Self>) -> Notifier {
        Notifier(event_loop.channel())
    }

    pub fn node_config(&self) -> NodeViewConfig {
        self.node_config.clone()
    }
}

pub struct Notifier(mio::Sender<ConfigurationView<NodeViewConfig>>);

impl Notifier {
    pub fn notify(&self, view: ConfigurationView<NodeViewConfig>) {
        use mio::NotifyError::*;
        let mut item = view;
        let mut backoff_ms = 1;
        loop {
            item = match self.0.send(item) {
                Ok(_) => return,
                Err(Full(it)) => it,
                Err(e) => panic!("{:?}", e),
            };
            info!("Backoff: {}ms", backoff_ms);
            std::thread::sleep_ms(backoff_ms);
            backoff_ms *= 2;
        }
    }
}

impl mio::Handler for ChainRepl {
    // This is a bit wierd; we can pass a parent action back to enqueue some action.
    type Timeout = mio::Token;
    type Message = ConfigurationView<NodeViewConfig>;
    fn ready(&mut self, event_loop: &mut mio::EventLoop<Self>, token: mio::Token, events: mio::EventSet) {
        trace!("{:?}: {:?}", token, events);
        self.connections[token].handle_event(event_loop, events);
        self.io_ready(event_loop, token);
    }

    fn timeout(&mut self, event_loop: &mut EventLoop<Self>, token: mio::Token) {
        debug!("Timeout: {:?}", token);
        self.connections[token].handle_timeout();
        self.io_ready(event_loop, token);
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: ConfigurationView<NodeViewConfig>) {
        debug!("Notified: {:?}", msg);
        self.handle_view_changed(msg);
        self.converge_state(event_loop);
    }
}
<commit_msg>Bump replication window.<commit_after>extern crate mio;
extern crate bytes;
#[macro_use]
extern crate log;
extern crate serde;
extern crate serde_json;
extern crate spki_sexp;

extern crate etcd;

use mio::tcp::*;
use mio::EventLoop;
use mio::util::Slab;
use std::collections::{VecDeque,BTreeMap};
use std::net::SocketAddr;
use std::cmp;

mod line_conn;
mod downstream_conn;
mod listener;
mod config;
mod event_handler;
mod data;

use line_conn::{SexpPeer,LineConn};
use downstream_conn::Downstream;
use listener::Listener;
use event_handler::EventHandler;

pub use data::*;
pub use config::*;

const REPLICATION_CREDIT : u64 = 1024;

pub type PeerMsg = (u64, u64, Operation);

#[derive(Debug)]
enum ChainReplMsg {
    Operation { source: mio::Token, epoch: Option<u64>, seqno: Option<u64>, op: Operation },
    DownstreamResponse(OpResp),
    NewClientConn(Role, TcpStream),
}

#[derive(Debug)]
pub struct ChainRepl {
    connections: Slab<EventHandler>,
    downstream_slot: Option<mio::Token>,
    // "Model" fields
    last_sent_downstream: Option<u64>,
    last_acked_downstream: Option<u64>,
    pending_operations: BTreeMap<u64, mio::Token>,
    log: BTreeMap<u64, Operation>,
    state: String,
    new_view: Option<ConfigurationView<NodeViewConfig>>,
    node_config: NodeViewConfig,
    current_epoch: u64,
}

impl ChainRepl {
    pub fn new() -> ChainRepl {
        ChainRepl {
            connections: Slab::new(1024),
            downstream_slot: None,
            last_sent_downstream: None,
            last_acked_downstream: None,
            log: BTreeMap::new(),
            pending_operations: BTreeMap::new(),
            state: String::new(),
            new_view: None,
            node_config: Default::default(),
            current_epoch: Default::default(),
        }
    }

    pub fn listen(&mut self, event_loop: &mut mio::EventLoop<ChainRepl>, addr: SocketAddr, role: Role) {
        info!("Listen on {:?} for {:?}", addr, role);
        let l = Listener::new(addr, role.clone());
        match role {
            Role::Upstream => self.node_config.peer_addr = Some(format!("{}", l.listen_addr())),
            Role::Client => self.node_config.client_addr = Some(format!("{}", l.listen_addr())),
        }
        let token = self.connections.insert(EventHandler::Listener(l)).expect("insert listener");
        &self.connections[token].initialize(event_loop, token);
    }

    pub fn set_downstream(&mut self, event_loop: &mut mio::EventLoop<ChainRepl>, target: Option<SocketAddr>) {
        match (self.downstream_slot, target) {
            (Some(_), Some(target)) => self.downstream().expect("downstream").reconnect_to(target),
            (None, Some(target)) => {
                let token = self.connections.insert_with(|token| EventHandler::Downstream(Downstream::new(Some(target), token)))
                    .expect("insert downstream");
                &self.connections[token].initialize(event_loop, token);
                self.downstream_slot = Some(token)
            },
            (Some(_), None) => self.downstream().expect("downstream").disconnect(),
            (None, None) => (),
        }
    }

    fn seqno(&self) -> u64 {
        self.log.len() as u64
    }

    fn next_seqno(&self) -> u64 {
        self.seqno()
    }

    fn process_action(&mut self, msg: ChainReplMsg, event_loop: &mut mio::EventLoop<ChainRepl>) {
        trace!("{:p}; got {:?}", self, msg);
        match msg {
            ChainReplMsg::Operation { source, seqno, epoch, op } => {
                let seqno = seqno.unwrap_or_else(|| self.next_seqno());
                // assert!(seqno == 0 || self.log.get(&(seqno-1)).is_some());

                let epoch = epoch.unwrap_or_else(|| self.current_epoch);

               if epoch != self.current_epoch {
                    warn!("Operation epoch ({}) differers from our last observed configuration: ({})",
                        epoch, self.current_epoch);
                    let resp = OpResp::Err(epoch, seqno, format!("BadEpoch: {}; last seen config: {}", epoch, self.current_epoch));
                    self.connections[source].response(resp);
                    return;
                }

                if !(seqno == 0 || self.log.get(&(seqno-1)).is_some()) {
                    warn!("Hole in history: saw {}/{}; have: {:?}", epoch, seqno, self.log.keys().collect::<Vec<_>>());
                    let resp = OpResp::Err(epoch, seqno, format!("Bad sequence number; previous: {:?}, saw: {:?}",
                        self.log.keys().rev().next(), seqno));
                    self.connections[source].response(resp);
                    return;
                }

                let prev = self.log.insert(seqno, op.clone());
                debug!("Log entry {:?}: {:?}", seqno, op);
                if let Some(prev) = prev {
                    panic!("Unexpectedly existing log entry for item {}: {:?}", seqno, prev);
                }

                if let Some(_) = self.downstream_slot {
                    self.pending_operations.insert(seqno, source);
                    // Replication mechanism should handle the push to downstream.
                } else {
                    info!("Terminus! {:?}/{:?}", seqno, op);
                    let resp = match op {
                        Operation::Set(s) => {
                            self.state = s;
                            OpResp::Ok(epoch, seqno, None)
                        },
                        Operation::Get => OpResp::Ok(epoch, seqno, Some(self.state.clone()))
                    };
                    self.connections[source].response(resp)
                }
            },

            ChainReplMsg::DownstreamResponse(reply) => {
                debug!("Downstream response: {:?}", reply);
                match reply {
                    OpResp::Ok(epoch, seqno, _) | OpResp::Err(epoch, seqno, _) => {
                        if let Some(token) = self.pending_operations.remove(&seqno) {
                            info!("Found in-flight op {:?} for client token {:?}", seqno, token);
                            if let Some(ref mut c)  = self.connections.get_mut(token) {
                                c.response(reply)
                            }
                            self.last_acked_downstream = Some(seqno)
                        } else {
                            warn!("Unexpected response for seqno: {:?}", seqno);
                        }
                    },
                    OpResp::HelloIWant(last_sent_downstream) => {
                        info!("Downstream has {:?}", last_sent_downstream);
                        assert!(last_sent_downstream <= self.seqno());
                        self.last_sent_downstream = Some(last_sent_downstream);
                    },
                };
            },

            ChainReplMsg::NewClientConn(role, socket) => {
                let peer = socket.peer_addr().expect("peer address");
                let seqno = self.seqno();
                assert!(self.log.get(&seqno).is_none());
                let token = self.connections
                    .insert_with(|token| match role {
                            Role::Client => EventHandler::Conn(LineConn::client(socket, token)),
                            Role::Upstream => {
                                let mut conn = LineConn::upstream(socket, token);
                                let msg = OpResp::HelloIWant(seqno);
                                info!("Inform upstream about our current version, {:?}!", msg);
                                conn.response(msg);
                                EventHandler::Upstream(conn)
                            },
                    })
                    .expect("token insert");
                debug!("Client connection of {:?}/{:?} from {:?}", role, token, peer);
                &self.connections[token].initialize(event_loop, token);
            }
        }
    }

    fn process_rules(&mut self, event_loop: &mut mio::EventLoop<Self>) -> bool {
        debug!("pre  Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
            self.seqno(), self.last_sent_downstream, self.last_acked_downstream);
        let mut changed = false;
        if let Some(send_next) = self.last_sent_downstream {
            if send_next < self.seqno() {
                let max_to_push_now = cmp::min(self.last_acked_downstream.unwrap_or(0) + REPLICATION_CREDIT, self.seqno());
                debug!("Window push {:?} - {:?}; waiting: {:?}", send_next, max_to_push_now, self.seqno() - max_to_push_now);
                let epoch = self.current_epoch;
                for i in send_next..max_to_push_now {
                    debug!("Log item: {:?}: {:?}", i, self.log.get(&i));
                    let op = self.log[&i].clone();
                    debug!("Queueing epoch:{:?}; seq:{:?}/{:?}; ds/seqno: {:?}", epoch, i, op, self.last_sent_downstream);
                    self.downstream().expect("Downstream").send_to_downstream(epoch, i, op);
                    self.last_sent_downstream = Some(i+1);
                    changed = true
                }
            }
            debug!("post Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
                self.seqno(), self.last_sent_downstream, self.last_acked_downstream);
        }

        // Cases:
        // Head(nextNode)
        // Middle(nextNode)
        // Tail
        if let Some(view) = self.new_view.take() {
            info!("Reconfigure according to: {:?}", view);
            if !view.in_configuration() {
                warn!("I am not in this configuration; shutting down: {:?}", view);
                event_loop.shutdown();
            }

            let listen_for_clients = view.should_listen_for_clients();
            info!("Listen for clients: {:?}", listen_for_clients);
            for p in self.listeners(Role::Client) {
                p.set_active(listen_for_clients);
            }
            let listen_for_upstreamp = view.should_listen_for_upstream();
            info!("Listen for upstreams: {:?}", listen_for_upstreamp);
            for p in self.listeners(Role::Upstream) {
                p.set_active(listen_for_upstreamp);
            }
            if let Some(ds) = view.should_connect_downstream() {
                info!("Push to downstream on {:?}", ds);
                if let Some(peer_addr) = ds.peer_addr {
                    self.set_downstream(event_loop, Some(peer_addr.parse().expect("peer address")));
                } else {
                    panic!("Cannot reconnect to downstream with no peer listener: {:?}", ds);
                }
            } else {
                info!("Tail node!");
                self.set_downstream(event_loop, None);
            }

            self.current_epoch = view.epoch;

            changed = true;
        }

        changed
    }

    fn downstream<'a>(&'a mut self) -> Option<&'a mut Downstream<SexpPeer>> {
        self.downstream_slot.map(move |slot| match &mut self.connections[slot] {
            &mut EventHandler::Downstream(ref mut d) => d,
            other => panic!("Downstream slot not populated with a downstream instance: {:?}", other),
        })
    }

    fn listeners<'a>(&'a mut self, role: Role) -> Vec<&'a mut Listener> {
        self.connections.iter_mut().filter_map(|it| match it {
            &mut EventHandler::Listener(ref mut l) if l.role == role => Some(l),
            _ => None
        }).collect()
    }

    fn converge_state(&mut self, event_loop: &mut mio::EventLoop<Self>) {
        let mut parent_actions = VecDeque::new();
        let mut changed = true;
        let mut iterations = 0;
        debug!("Converge begin");
        while changed {
            trace!("Iter: {:?}", iterations);
            changed = false;
            for conn in self.connections.iter_mut() {
                let changedp = conn.process_rules(event_loop, &mut |item| parent_actions.push_back(item));
                if changedp { debug!("Changed: {:?}", conn); };
                changed |= changedp;
            }

            let changedp = self.process_rules(event_loop);
            if changedp { debug!("Changed: {:?}", "Model"); }
            changed |= changedp;

            for action in parent_actions.drain(..) {
                debug!("Action: {:?}", action);
                self.process_action(action, event_loop);
            }
            iterations += 1;
        }
        debug!("Converged after {:?} iterations", iterations);
    }

    fn io_ready(&mut self, event_loop: &mut mio::EventLoop<Self>, token: mio::Token) {
        self.converge_state(event_loop);
        if self.connections[token].is_closed() && self.pending_operations.values().all(|tok| tok != &token) {
            debug!("Close candidate: {:?}: pending: {:?}",
                token, self.pending_operations.values().filter(|tok| **tok == token).count());
            let it = self.connections.remove(token);
            debug!("Removing; {:?}; {:?}", token, it);
            if Some(token) == self.downstream_slot {
                self.downstream_slot = None;
                self.last_sent_downstream = None
            }
        }
    }

    fn handle_view_changed(&mut self, view: ConfigurationView<NodeViewConfig>) {
        self.new_view = Some(view)
    }

    pub fn get_notifier(&self, event_loop: &mut mio::EventLoop<Self>) -> Notifier {
        Notifier(event_loop.channel())
    }

    pub fn node_config(&self) -> NodeViewConfig {
        self.node_config.clone()
    }
}

pub struct Notifier(mio::Sender<ConfigurationView<NodeViewConfig>>);

impl Notifier {
    pub fn notify(&self, view: ConfigurationView<NodeViewConfig>) {
        use mio::NotifyError::*;
        let mut item = view;
        let mut backoff_ms = 1;
        loop {
            item = match self.0.send(item) {
                Ok(_) => return,
                Err(Full(it)) => it,
                Err(e) => panic!("{:?}", e),
            };
            info!("Backoff: {}ms", backoff_ms);
            std::thread::sleep_ms(backoff_ms);
            backoff_ms *= 2;
        }
    }
}

impl mio::Handler for ChainRepl {
    // This is a bit wierd; we can pass a parent action back to enqueue some action.
    type Timeout = mio::Token;
    type Message = ConfigurationView<NodeViewConfig>;
    fn ready(&mut self, event_loop: &mut mio::EventLoop<Self>, token: mio::Token, events: mio::EventSet) {
        trace!("{:?}: {:?}", token, events);
        self.connections[token].handle_event(event_loop, events);
        self.io_ready(event_loop, token);
    }

    fn timeout(&mut self, event_loop: &mut EventLoop<Self>, token: mio::Token) {
        debug!("Timeout: {:?}", token);
        self.connections[token].handle_timeout();
        self.io_ready(event_loop, token);
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: ConfigurationView<NodeViewConfig>) {
        debug!("Notified: {:?}", msg);
        self.handle_view_changed(msg);
        self.converge_state(event_loop);
    }
}
<|endoftext|>


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

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Output<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::handle::FrameBuffer<R>,
    mask: gfx::Mask,
    supports_gamma_convertion: bool,
    gamma: gfx::Gamma,
}

impl<R: gfx::Resources> Output<R> {
    /// Try to set the gamma conversion.
    pub fn set_gamma(&mut self, gamma: gfx::Gamma) -> Result<(), ()> {
        if self.supports_gamma_convertion || gamma == gfx::Gamma::Original {
            self.gamma = gamma;
            Ok(())
        }else {
            Err(())
        }
    }
}

impl<R: gfx::Resources> gfx::Output<R> for Output<R> {
    fn get_handle(&self) -> Option<&gfx::handle::FrameBuffer<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let factor = self.window.hidpi_factor();
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        ((w as f32 * factor) as Size, (h as f32 * factor) as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn get_gamma(&self) -> gfx::Gamma {
        self.gamma
    }
}

impl<R: gfx::Resources> gfx::Window<R> for Output<R> {
    fn swap_buffers(&mut self) {
        self.window.swap_buffers();
    }
}

/// Result of successful context initialization.
pub type Success = (
    Output<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window.
pub fn init(window: glutin::Window) -> Success {
    unsafe { window.make_current() };
    let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
    let format = window.get_pixel_format();
    let out = Output {
        window: window,
        frame: factory.get_main_frame_buffer(),
        mask: if format.color_bits != 0 { gfx::COLOR } else { gfx::Mask::empty() } |
            if format.depth_bits != 0 { gfx::DEPTH } else  { gfx::Mask::empty() } |
            if format.stencil_bits != 0 { gfx::STENCIL } else { gfx::Mask::empty() },
        supports_gamma_convertion: format.srgb,
        gamma: gfx::Gamma::Original,
    };
    (out, device, factory)
}
<commit_msg>Implemented init_stream<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Output<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::handle::FrameBuffer<R>,
    mask: gfx::Mask,
    supports_gamma_convertion: bool,
    gamma: gfx::Gamma,
}

impl<R: gfx::Resources> Output<R> {
    /// Try to set the gamma conversion.
    pub fn set_gamma(&mut self, gamma: gfx::Gamma) -> Result<(), ()> {
        if self.supports_gamma_convertion || gamma == gfx::Gamma::Original {
            self.gamma = gamma;
            Ok(())
        }else {
            Err(())
        }
    }
}

impl<R: gfx::Resources> gfx::Output<R> for Output<R> {
    fn get_handle(&self) -> Option<&gfx::handle::FrameBuffer<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let factor = self.window.hidpi_factor();
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        ((w as f32 * factor) as Size, (h as f32 * factor) as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn get_gamma(&self) -> gfx::Gamma {
        self.gamma
    }
}

impl<R: gfx::Resources> gfx::Window<R> for Output<R> {
    fn swap_buffers(&mut self) {
        self.window.swap_buffers();
    }
}

/// Result of successful context initialization.
pub type Success = (
    Output<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// A streamed version of the success struct.
pub type SuccessStream = (
    gfx::OwnedStream<
        gfx_device_gl::Resources,
        gfx_device_gl::CommandBuffer,
        Output<gfx_device_gl::Resources>,
    >,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window.
pub fn init(window: glutin::Window) -> Success {
    unsafe { window.make_current() };
    let format = window.get_pixel_format();
    let device = gfx_device_gl::Device::new(|s| window.get_proc_address(s));
    let factory = device.spawn_factory();
    let out = Output {
        window: window,
        frame: factory.get_main_frame_buffer(),
        mask: if format.color_bits != 0 { gfx::COLOR } else { gfx::Mask::empty() } |
            if format.depth_bits != 0 { gfx::DEPTH } else  { gfx::Mask::empty() } |
            if format.stencil_bits != 0 { gfx::STENCIL } else { gfx::Mask::empty() },
        supports_gamma_convertion: format.srgb,
        gamma: gfx::Gamma::Original,
    };
    (out, device, factory)
}

/// Initialize with a window, return a `Stream`.
pub fn init_stream(window: glutin::Window) -> SuccessStream {
    use gfx::traits::StreamFactory;
    let (out, device, mut factory) = init(window);
    let stream = factory.create_stream(out);
    (stream, device, factory)
}
<|endoftext|>


<commit_before>//! Jamal provides a bi-directional interface for transformations between json and yaml documents.
extern crate serde_json;
extern crate serde_yaml;

use serde_json::Value as JsonValue;
use serde_yaml::Value as YamlValue;
use std::error::Error as StdError;
use std::num::ParseFloatError;
use std::collections::BTreeMap;

/// represents potential errors that can happen during the transformation process
#[derive(Debug)]
pub enum Error {
    /// Occurs when an attempt to parse a `serde_yaml::Real` as an `f64` fails
    ParseFloat(ParseFloatError),
    /// Occurs when a transformation is requested for an invalid value
    InvalidValue,
    /// Occurs when an unsupported transformation is requested
    UnsupportedValue
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ParseFloat(ref e) => e.description(),
            Error::InvalidValue => "invalid value",
            Error::UnsupportedValue => "supported value",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::ParseFloat(ref e) => Some(e),
            _ => None,
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

/// A result type with a fixed type for `jamal::Errors`
pub type Result<T> = std::result::Result<T, Error>;

impl From<ParseFloatError> for Error {
    fn from(error: ParseFloatError) -> Error {
        Error::ParseFloat(error)
    }
}

/// converts a `serde_json::Value` into a `serde_yaml::Value`
pub fn to_yaml(json: &JsonValue) -> Result<YamlValue> {
    match json {
        &JsonValue::Null => Ok(YamlValue::Null),
        &JsonValue::Bool(ref value) => Ok(YamlValue::Boolean(value.clone())),
        &JsonValue::I64(ref value) => Ok(YamlValue::Integer(value.clone())),
        &JsonValue::U64(ref value) => Ok(YamlValue::Integer(value.clone() as i64)),
        &JsonValue::F64(ref value) => Ok(YamlValue::Real(value.to_string())),
        &JsonValue::String(ref value) => Ok(YamlValue::String(value.clone())),
        &JsonValue::Array(ref values) => {
            let mut yaml_values = vec![];
            for value in values {
                yaml_values.push(try!(to_yaml(&value)));
            }
            Ok(YamlValue::Array(yaml_values))
        }
        &JsonValue::Object(ref value) => {
            let mut yaml_value = BTreeMap::new();
            for (k, v) in value {
                let yaml = try!(to_yaml(&v));
                yaml_value.insert(YamlValue::String(k.clone()), yaml);
            }
            Ok(YamlValue::Hash(yaml_value))
        }
    }
}

/// converts a `serde_yaml::Value` into a `serde_json::Value`
pub fn to_json(yaml: &YamlValue) -> Result<JsonValue> {
    match yaml {
        &YamlValue::Real(ref value) => Ok(JsonValue::F64(try!(value.parse::<f64>()))),
        &YamlValue::Integer(ref value) => Ok(JsonValue::I64(value.clone())),
        &YamlValue::String(ref value) => Ok(JsonValue::String(value.clone())),
        &YamlValue::Boolean(ref value) => Ok(JsonValue::Bool(value.clone())),
        &YamlValue::Array(ref values) => {
            let mut json_values = vec![];
            for value in values {
                let json = try!(to_json(&value));
                json_values.push(json);
            }
            Ok(JsonValue::Array(json_values))
        }
        &YamlValue::Hash(ref value) => {
            let mut json_value = BTreeMap::new();
            for (k, v) in value {
                match k {
                    &YamlValue::String(ref key) => {
                        let json = try!(to_json(&v));
                        json_value.insert(key.clone(), json);
                    }
                    _ => return Err(Error::InvalidValue),
                }
            }
            Ok(JsonValue::Object(json_value))
        }
        &YamlValue::Alias(_) => Err(Error::InvalidValue), // not supported yet
        &YamlValue::Null => Ok(JsonValue::Null),
        &YamlValue::BadValue => Err(Error::InvalidValue),
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use super::serde_json;
    use super::serde_yaml;
    use super::{to_json, to_yaml};

    #[test]
    fn json_to_yaml() {
        let input = serde_json::to_value(&vec!["foo"]);
        let output = serde_yaml::Value::Array(vec![serde_yaml::Value::String("foo".to_owned())]);
        assert_eq!(to_yaml(&input).unwrap(), output);
    }

    #[test]
    fn yaml_to_json() {
        let input = serde_yaml::to_value(&vec!["foo"]);
        let output = serde_json::Value::Array(vec![serde_json::Value::String("foo".to_owned())]);
        assert_eq!(to_json(&input).unwrap(), output);
    }
}
<commit_msg>unsupported vs invalid<commit_after>//! Jamal provides a bi-directional interface for transformations between json and yaml documents.
extern crate serde_json;
extern crate serde_yaml;

use serde_json::Value as JsonValue;
use serde_yaml::Value as YamlValue;
use std::error::Error as StdError;
use std::num::ParseFloatError;
use std::collections::BTreeMap;

/// represents potential errors that can happen during the transformation process
#[derive(Debug)]
pub enum Error {
    /// Occurs when an attempt to parse a `serde_yaml::Real` as an `f64` fails
    ParseFloat(ParseFloatError),
    /// Occurs when a transformation is requested for an invalid value
    InvalidValue,
    /// Occurs when an unsupported transformation is requested
    UnsupportedValue(YamlValue)
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ParseFloat(ref e) => e.description(),
            Error::InvalidValue => "invalid value",
            Error::UnsupportedValue(_) => "supported value",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::ParseFloat(ref e) => Some(e),
            _ => None,
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

/// A result type with a fixed type for `jamal::Errors`
pub type Result<T> = std::result::Result<T, Error>;

impl From<ParseFloatError> for Error {
    fn from(error: ParseFloatError) -> Error {
        Error::ParseFloat(error)
    }
}

/// converts a `serde_json::Value` into a `serde_yaml::Value`
pub fn to_yaml(json: &JsonValue) -> Result<YamlValue> {
    match json {
        &JsonValue::Null => Ok(YamlValue::Null),
        &JsonValue::Bool(ref value) => Ok(YamlValue::Boolean(value.clone())),
        &JsonValue::I64(ref value) => Ok(YamlValue::Integer(value.clone())),
        &JsonValue::U64(ref value) => Ok(YamlValue::Integer(value.clone() as i64)),
        &JsonValue::F64(ref value) => Ok(YamlValue::Real(value.to_string())),
        &JsonValue::String(ref value) => Ok(YamlValue::String(value.clone())),
        &JsonValue::Array(ref values) => {
            let mut yaml_values = vec![];
            for value in values {
                yaml_values.push(try!(to_yaml(&value)));
            }
            Ok(YamlValue::Array(yaml_values))
        }
        &JsonValue::Object(ref value) => {
            let mut yaml_value = BTreeMap::new();
            for (k, v) in value {
                let yaml = try!(to_yaml(&v));
                yaml_value.insert(YamlValue::String(k.clone()), yaml);
            }
            Ok(YamlValue::Hash(yaml_value))
        }
    }
}

/// converts a `serde_yaml::Value` into a `serde_json::Value`
pub fn to_json(yaml: &YamlValue) -> Result<JsonValue> {
    match yaml {
        &YamlValue::Real(ref value) => Ok(JsonValue::F64(try!(value.parse::<f64>()))),
        &YamlValue::Integer(ref value) => Ok(JsonValue::I64(value.clone())),
        &YamlValue::String(ref value) => Ok(JsonValue::String(value.clone())),
        &YamlValue::Boolean(ref value) => Ok(JsonValue::Bool(value.clone())),
        &YamlValue::Array(ref values) => {
            let mut json_values = vec![];
            for value in values {
                let json = try!(to_json(&value));
                json_values.push(json);
            }
            Ok(JsonValue::Array(json_values))
        }
        &YamlValue::Hash(ref value) => {
            let mut json_value = BTreeMap::new();
            for (k, v) in value {
                match k {
                    &YamlValue::String(ref key) => {
                        let json = try!(to_json(&v));
                        json_value.insert(key.clone(), json);
                    }
                    unsupported => return Err(Error::UnsupportedValue(unsupported.clone())),
                }
            }
            Ok(JsonValue::Object(json_value))
        }
        alias @ &YamlValue::Alias(_) => Err(Error::UnsupportedValue(alias.clone())),
        &YamlValue::Null => Ok(JsonValue::Null),
        &YamlValue::BadValue => Err(Error::InvalidValue),
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use super::serde_json;
    use super::serde_yaml;
    use super::{to_json, to_yaml};

    #[test]
    fn json_to_yaml() {
        let input = serde_json::to_value(&vec!["foo"]);
        let output = serde_yaml::Value::Array(vec![serde_yaml::Value::String("foo".to_owned())]);
        assert_eq!(to_yaml(&input).unwrap(), output);
    }

    #[test]
    fn yaml_to_json() {
        let input = serde_yaml::to_value(&vec!["foo"]);
        let output = serde_json::Value::Array(vec![serde_json::Value::String("foo".to_owned())]);
        assert_eq!(to_json(&input).unwrap(), output);
    }
}
<|endoftext|>


<commit_before>extern crate snowflake;
use self::snowflake::ProcessUniqueId;

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
    tree_id: ProcessUniqueId,
    index: usize
}

//todo: add optional string mapping with HashMap<String, NodeId>
// and add convenience methods for getting nodes by String name

pub struct TreeBuilder<T> {
    root: Option<Node<T>>,
    capacity: usize
}

impl<T> TreeBuilder<T> {
    pub fn new() -> TreeBuilder<T> {
        TreeBuilder {
            root: None,
            capacity: 0
        }
    }

    pub fn with_root(&mut self, root: Node<T>) -> TreeBuilder<T> {
        TreeBuilder {
            root: Some(root),
            capacity: self.capacity
        }
    }

    pub fn with_capacity(&mut self, capacity: usize) -> TreeBuilder<T> {
        TreeBuilder {
            root: self.root.take(),
            capacity: capacity
        }
    }

    pub fn build(&mut self) -> Tree<T> {

        let tree_id = ProcessUniqueId::new();

        let mut tree = Tree {
            id: tree_id,
            root: None,
            nodes: Vec::with_capacity(self.capacity),
            free_ids: Vec::new() //todo: should this start with capacity too?
        };

        if self.root.is_some() {

            let node_id = NodeId {
                tree_id: tree_id,
                index: 0
            };

            tree.nodes.push(self.root.take());
            tree.root = Some(node_id);
        }

        tree
    }
}

pub struct Tree<T> {
    id: ProcessUniqueId,
    root: Option<NodeId>,
    nodes: Vec<Option<Node<T>>>,
    free_ids: Vec<NodeId>
}

impl<T> Tree<T> {
    pub fn set_root(&mut self, new_root: Node<T>) -> NodeId {
        let new_root_id = self.insert_new_node(new_root);

        match self.root {
            Some(current_root_node_id) => {
                self.set_as_parent_and_child(new_root_id, current_root_node_id);
            },
            None => ()
        };

        self.root = Some(new_root_id);
        new_root_id
    }

    pub fn add_child(&mut self, parent_id: NodeId, child: Node<T>) -> NodeId {
        if !self.is_valid_node_id(parent_id) {
            //todo: is panic the right tool here?
            // maybe having this return Result would be better.
            panic!("Invalid NodeId given for parent_id");
        }

        let new_child_id = self.insert_new_node(child);
        self.set_as_parent_and_child(parent_id, new_child_id);

        new_child_id
    }

    pub fn get(&self, node_id: NodeId) -> Option<&Node<T>> {
        if self.is_valid_node_id(node_id) {
            return (*self.nodes.get(node_id.index).unwrap()).as_ref();
        }
        None
    }

    pub fn get_mut(&mut self, node_id: NodeId) -> Option<&mut Node<T>> {
        if self.is_valid_node_id(node_id) {
            return (*self.nodes.get_mut(node_id.index).unwrap()).as_mut();
        }
        None
    }

    pub fn root_node_id(&self) -> Option<NodeId> {
        self.root
    }

    fn set_as_parent_and_child(&mut self, parent_id: NodeId, child_id: NodeId) {
        self.get_mut(parent_id)
            .expect("parent_id refers to a None value.")
            .add_child(child_id);

        self.get_mut(child_id)
            .expect("child_id refers to a None value.")
            .set_parent(parent_id);
    }

    fn insert_new_node(&mut self, new_node: Node<T>) -> NodeId {

        if self.free_ids.len() > 0 {
            let new_node_id: NodeId = self.free_ids.pop()
                .expect("Couldn't pop from Vec with len() > 0 while inserting a new node.");

            self.nodes.push(Some(new_node));
            self.nodes.swap_remove(new_node_id.index);
            return new_node_id;

        } else {
            let new_node_index = self.nodes.len();
            self.nodes.push(Some(new_node));

            return self.new_node_id(new_node_index);
        }
    }

    fn new_node_id(&self, node_index: usize) -> NodeId {
        NodeId {
            tree_id: self.id,
            index: node_index
        }
    }

    fn is_valid_node_id(&self, node_id: NodeId) -> bool {
        if node_id.tree_id != self.id {
            //the node_id belongs to a different tree.
            return false;
        }

        if self.nodes.get(node_id.index).is_none() {
            //the index is out of bounds
            return false;
        }

        if self.nodes.get(node_id.index).unwrap().is_none() {
            //the node at that index was removed.
            return false;
        }

        true
    }
}

pub struct Node<T> {
    data: T,
    parent: Option<NodeId>,
    children: Vec<NodeId>
}

impl<T> Node<T> {
    pub fn new(data: T) -> Node<T> {
        Node {
            data: data,
            parent: None,
            children: Vec::new() //todo: should we have the option for specifying capacity here?
        }
    }

    pub fn data(&self) -> &T {
        &self.data
    }

    pub fn data_mut(&mut self) -> &mut T {
        &mut self.data
    }

    pub fn parent(&self) -> Option<NodeId> {
        self.parent
    }

    pub fn children(&self) -> &Vec<NodeId> {
        &self.children
    }

    fn set_parent(&mut self, parent: NodeId) {
        self.parent = Some(parent);
    }

    fn add_child(&mut self, child: NodeId) {
        self.children.push(child);
    }

    fn children_mut(&mut self) -> &mut Vec<NodeId> {
        &mut self.children
    }
}

#[cfg(test)]
mod tree_builder_tests {
    use super::TreeBuilder;
    use super::Node;

    #[test]
    fn test_new() {
        let tb: TreeBuilder<i32> = TreeBuilder::new();
        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_root() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5));

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_capacity(10);

        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 10);
    }

    #[test]
    fn test_with_root_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5))
            .with_capacity(10);

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 10);
    }
}

#[cfg(test)]
mod tree_tests {
    use super::Tree;
    use super::TreeBuilder;
    use super::NodeId;
    use super::Node;

    #[test]
    fn test_get() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);

        let root_node_ref = tree.get(root_id).unwrap();
        assert_eq!(root_node_ref.data(), &5);
    }

    #[test]
    fn test_get_mut() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);

        {
            let root_node_ref: &mut Node<i32> = tree.get_mut(root_id).unwrap();
            assert_eq!(root_node_ref.data(), &5);
        }

        {
            let root_node_ref: &mut Node<i32> = tree.get_mut(root_id).unwrap();
            *root_node_ref.data_mut() = 6;
        }

        let root_node_ref = tree.get_mut(root_id).unwrap();
        assert_eq!(root_node_ref.data(), &6);
    }

    #[test]
    fn test_set_root() {
        let node_a = Node::new(5);
        let node_b = Node::new(6);
        let mut tree = TreeBuilder::new().build();

        let node_a_id = tree.set_root(node_a);
        let root_id = tree.root_node_id().unwrap();
        assert_eq!(node_a_id, root_id);
        {
            let node_a_ref = tree.get(node_a_id).unwrap();
            let root_ref = tree.get(root_id).unwrap();
            assert_eq!(node_a_ref.data(), &5);
            assert_eq!(root_ref.data(), &5);
        }

        let node_b_id = tree.set_root(node_b);
        let root_id = tree.root_node_id().unwrap();
        assert_eq!(node_b_id, root_id);
        {
            let node_b_ref = tree.get(node_b_id).unwrap();
            let root_ref = tree.get(root_id).unwrap();
            assert_eq!(node_b_ref.data(), &6);
            assert_eq!(root_ref.data(), &6);

            let node_b_child_id = node_b_ref.children().get(0).unwrap();
            let node_b_child_ref = tree.get(*node_b_child_id).unwrap();
            assert_eq!(node_b_child_ref.data(), &5);
        }
    }

    #[test]
    fn test_root_node_id() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);
        let root_node_id = tree.root_node_id().unwrap();

        assert_eq!(root_id, root_node_id);
    }

    #[test]
    fn test_add_child() {
        let mut tree = TreeBuilder::new()
            .with_root(Node::new(5))
            .build();

        let node_1 = Node::new(1);
        let node_2 = Node::new(2);

        let root_id = tree.root_node_id().unwrap();
        let node_1_id = tree.add_child(root_id, node_1);
        let node_2_id = tree.add_child(root_id, node_2);

        let node_1_ref = tree.get(node_1_id).unwrap();
        let node_2_ref = tree.get(node_2_id).unwrap();
        assert_eq!(node_1_ref.data(), &1);
        assert_eq!(node_2_ref.data(), &2);

        assert_eq!(node_1_ref.parent().unwrap(), root_id);
        assert_eq!(node_2_ref.parent().unwrap(), root_id);

        let root_node_ref = tree.get(root_id).unwrap();
        let root_children: &Vec<NodeId> = root_node_ref.children();

        let child_1_id = root_children.get(0).unwrap();
        let child_2_id = root_children.get(1).unwrap();

        let child_1_ref = tree.get(*child_1_id).unwrap();
        let child_2_ref = tree.get(*child_2_id).unwrap();

        assert_eq!(child_1_ref.data(), &1);
        assert_eq!(child_2_ref.data(), &2);

//        for (index, child_id) in root_children.into_iter().enumerate() {
//            let child_data = (index + 1) as i32;
//            let child_ref = tree.get(*child_id).unwrap();
//            assert_eq!(child_ref.data(), &child_data);
//        }
    }
}

#[cfg(test)]
mod node_tests {
    use super::Node;
    use super::NodeId;
    use super::snowflake::ProcessUniqueId;

    #[test]
    fn test_new() {
        let _node = Node::new(5);
    }

    #[test]
    fn test_data() {
        let five = 5;
        let node = Node::new(five);
        assert_eq!(node.data(), &five);
    }

    #[test]
    fn test_data_mut() {
        let mut five = 5;
        let mut node = Node::new(five);
        assert_eq!(node.data_mut(), &mut five);
    }

    #[test]
    fn test_parent() {
        let node = Node::new(5);
        assert!(node.parent().is_none());

        let parent_id: NodeId = NodeId {
            tree_id: ProcessUniqueId::new(),
            index: 0
        };
        let mut node = Node::new(5);
        node.set_parent(parent_id);

        assert_eq!(node.parent(), Some(parent_id))
    }

    #[test]
    fn test_children() {
        let node = Node::new(5);
        assert_eq!(node.children().len(), 0);

        let tree_id = ProcessUniqueId::new();

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            index: 2
        };
        node.add_child(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            index: 2
        };
        node.children_mut().push(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);
    }
}
<commit_msg>add remove_node_drop_children function. Warning! Not a functioning commit atm. added some todos for later. added some thought about the current issue with the new remove function.<commit_after>extern crate snowflake;
use self::snowflake::ProcessUniqueId;

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
    tree_id: ProcessUniqueId,
    index: usize
}

//todo: add optional string mapping with HashMap<String, NodeId>
// and add convenience methods for getting nodes by String name
// maybe this should be made into a different type of tree which
// would possibly hide NodeIds from the user?

pub struct TreeBuilder<T> {
    root: Option<Node<T>>,
    capacity: usize
}

impl<T> TreeBuilder<T> {
    pub fn new() -> TreeBuilder<T> {
        TreeBuilder {
            root: None,
            capacity: 0
        }
    }

    pub fn with_root(&mut self, root: Node<T>) -> TreeBuilder<T> {
        TreeBuilder {
            root: Some(root),
            capacity: self.capacity
        }
    }

    pub fn with_capacity(&mut self, capacity: usize) -> TreeBuilder<T> {
        TreeBuilder {
            root: self.root.take(),
            capacity: capacity
        }
    }

    pub fn build(&mut self) -> Tree<T> {

        let tree_id = ProcessUniqueId::new();

        let mut tree = Tree {
            id: tree_id,
            root: None,
            nodes: Vec::with_capacity(self.capacity),
            free_ids: Vec::new() //todo: should this start with capacity too?
        };

        if self.root.is_some() {

            let node_id = NodeId {
                tree_id: tree_id,
                index: 0
            };

            tree.nodes.push(self.root.take());
            tree.root = Some(node_id);
        }

        tree
    }
}

pub struct Tree<T> {
    id: ProcessUniqueId,
    root: Option<NodeId>,
    nodes: Vec<Option<Node<T>>>,
    free_ids: Vec<NodeId>
}

impl<T> Tree<T> {
    pub fn set_root(&mut self, new_root: Node<T>) -> NodeId {
        let new_root_id = self.insert_new_node(new_root);

        match self.root {
            Some(current_root_node_id) => {
                self.set_as_parent_and_child(new_root_id, current_root_node_id);
            },
            None => ()
        };

        self.root = Some(new_root_id);
        new_root_id
    }

    pub fn add_child(&mut self, parent_id: NodeId, child: Node<T>) -> NodeId {
        if !self.is_valid_node_id(parent_id) {
            //todo: is panic the right tool here?
            // maybe having this return Result would be better.
            panic!("Invalid NodeId given for parent_id.");
        }

        let new_child_id = self.insert_new_node(child);
        self.set_as_parent_and_child(parent_id, new_child_id);

        new_child_id
    }

    pub fn remove_node_drop_children(&mut self, node_id: NodeId) -> Node<T> {
        if !self.is_valid_node_id(node_id) {
            //todo: is panic the right tool here?
            // maybe having this return Result would be better.
            panic!("Invalid NodeId given for node_id.");
        }

        println!("processing node_id: {:?}", node_id);

        if self.is_root_node(node_id) {
            self.root = None;
        }

        let node = self.remove_node(node_id);

        for child_id in node.children() {
            //todo: there's some extra processing going on here that doesn't need to be happening.
            // grandchildren (and below) are cleaning up their parent's child references when
            // they don't actually matter because they are all going to be dropped.
            // we need a function that drops all children without cleaning up any references at all.
            println!("processing child");
            self.remove_node_drop_children(*child_id);
        }

        node
    }

    pub fn get(&self, node_id: NodeId) -> Option<&Node<T>> {
        if self.is_valid_node_id(node_id) {
            return (*self.nodes.get(node_id.index).unwrap()).as_ref();
        }
        None
    }

    pub fn get_mut(&mut self, node_id: NodeId) -> Option<&mut Node<T>> {
        if self.is_valid_node_id(node_id) {
            return (*self.nodes.get_mut(node_id.index).unwrap()).as_mut();
        }
        None
    }

    pub fn root_node_id(&self) -> Option<NodeId> {
        self.root
    }

    fn set_as_parent_and_child(&mut self, parent_id: NodeId, child_id: NodeId) {
        self.get_mut(parent_id)
            .expect("parent_id refers to a None value.")
            .add_child(child_id);

        self.get_mut(child_id)
            .expect("child_id refers to a None value.")
            .set_parent(parent_id);
    }

    fn insert_new_node(&mut self, new_node: Node<T>) -> NodeId {

        if self.free_ids.len() > 0 {
            let new_node_id: NodeId = self.free_ids.pop()
                .expect("Couldn't pop from Vec with len() > 0 while inserting a new node.");

            self.nodes.push(Some(new_node));
            self.nodes.swap_remove(new_node_id.index);
            return new_node_id;

        } else {
            let new_node_index = self.nodes.len();
            self.nodes.push(Some(new_node));

            return self.new_node_id(new_node_index);
        }
    }

    fn remove_node(&mut self, node_id: NodeId) -> Node<T> {
        debug_assert!(self.is_valid_node_id(node_id), "Invalid node_id found in what should be a protected function.");

        println!("removing node: {:?}", node_id);

        self.nodes.push(None);
        let mut node = self.nodes.swap_remove(node_id.index).expect("node_id refers to a None value");

        println!("parent: {:?}", node.parent());

        self.free_ids.push(node_id);

        //todo: it seems like I might be missing an edge case here, but I'm not sure what it is
        // found the issue, as we recurse down the tree, the parent has already been removed,
        // this means that we need to find a different way to do this after dealing with the root node
        // that we are removing.
        // the logic for this likely doesn't belong here as this logic is pretty accurate for the
        // concept of removing a single node.
        if let Some(parent_id) = node.parent() {
            if let Some(parent_node) = self.get_mut(parent_id) {
                println!("removing children");
                parent_node.children_mut().retain(|&child_id| child_id != node_id);
            }
        }

        node.parent = None;

        node
    }

    fn new_node_id(&self, node_index: usize) -> NodeId {
        NodeId {
            tree_id: self.id,
            index: node_index
        }
    }

    fn is_valid_node_id(&self, node_id: NodeId) -> bool {
        if node_id.tree_id != self.id {
            //the node_id belongs to a different tree.
            return false;
        }

        if self.nodes.get(node_id.index).is_none() {
            //the index is out of bounds
            return false;
        }

        if self.nodes.get(node_id.index).unwrap().is_none() {
            //the node at that index was removed.
            return false;
        }

        true
    }

    fn is_root_node(&self, node_id: NodeId) -> bool {
        match self.root {
            Some(root_id) => {
                root_id == node_id
            },
            None => false
        }
    }
}

pub struct Node<T> {
    data: T,
    parent: Option<NodeId>,
    children: Vec<NodeId>
}

impl<T> Node<T> {
    pub fn new(data: T) -> Node<T> {
        Node {
            data: data,
            parent: None,
            children: Vec::new() //todo: should we have the option for specifying capacity here?
        }
    }

    pub fn data(&self) -> &T {
        &self.data
    }

    pub fn data_mut(&mut self) -> &mut T {
        &mut self.data
    }

    pub fn parent(&self) -> Option<NodeId> {
        self.parent
    }

    pub fn children(&self) -> &Vec<NodeId> {
        &self.children
    }

    fn set_parent(&mut self, parent: NodeId) {
        self.parent = Some(parent);
    }

    fn add_child(&mut self, child: NodeId) {
        self.children.push(child);
    }

    fn children_mut(&mut self) -> &mut Vec<NodeId> {
        &mut self.children
    }
}

#[cfg(test)]
mod tree_builder_tests {
    use super::TreeBuilder;
    use super::Node;

    #[test]
    fn test_new() {
        let tb: TreeBuilder<i32> = TreeBuilder::new();
        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_root() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5));

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_capacity(10);

        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 10);
    }

    #[test]
    fn test_with_root_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5))
            .with_capacity(10);

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 10);
    }
}

#[cfg(test)]
mod tree_tests {
    use super::Tree;
    use super::TreeBuilder;
    use super::NodeId;
    use super::Node;

    #[test]
    fn test_get() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);

        let root_node_ref = tree.get(root_id).unwrap();
        assert_eq!(root_node_ref.data(), &5);
    }

    #[test]
    fn test_get_mut() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);

        {
            let root_node_ref: &mut Node<i32> = tree.get_mut(root_id).unwrap();
            assert_eq!(root_node_ref.data(), &5);
        }

        {
            let root_node_ref: &mut Node<i32> = tree.get_mut(root_id).unwrap();
            *root_node_ref.data_mut() = 6;
        }

        let root_node_ref = tree.get_mut(root_id).unwrap();
        assert_eq!(root_node_ref.data(), &6);
    }

    #[test]
    fn test_set_root() {
        let node_a = Node::new(5);
        let node_b = Node::new(6);
        let mut tree = TreeBuilder::new().build();

        let node_a_id = tree.set_root(node_a);
        let root_id = tree.root_node_id().unwrap();
        assert_eq!(node_a_id, root_id);
        {
            let node_a_ref = tree.get(node_a_id).unwrap();
            let root_ref = tree.get(root_id).unwrap();
            assert_eq!(node_a_ref.data(), &5);
            assert_eq!(root_ref.data(), &5);
        }

        let node_b_id = tree.set_root(node_b);
        let root_id = tree.root_node_id().unwrap();
        assert_eq!(node_b_id, root_id);
        {
            let node_b_ref = tree.get(node_b_id).unwrap();
            let root_ref = tree.get(root_id).unwrap();
            assert_eq!(node_b_ref.data(), &6);
            assert_eq!(root_ref.data(), &6);

            let node_b_child_id = node_b_ref.children().get(0).unwrap();
            let node_b_child_ref = tree.get(*node_b_child_id).unwrap();
            assert_eq!(node_b_child_ref.data(), &5);
        }
    }

    #[test]
    fn test_root_node_id() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);
        let root_node_id = tree.root_node_id().unwrap();

        assert_eq!(root_id, root_node_id);
    }

    #[test]
    fn test_add_child() {
        let mut tree = TreeBuilder::new()
            .with_root(Node::new(5))
            .build();

        let node_1 = Node::new(1);
        let node_2 = Node::new(2);

        let root_id = tree.root_node_id().unwrap();
        let node_1_id = tree.add_child(root_id, node_1);
        let node_2_id = tree.add_child(root_id, node_2);

        let node_1_ref = tree.get(node_1_id).unwrap();
        let node_2_ref = tree.get(node_2_id).unwrap();
        assert_eq!(node_1_ref.data(), &1);
        assert_eq!(node_2_ref.data(), &2);

        assert_eq!(node_1_ref.parent().unwrap(), root_id);
        assert_eq!(node_2_ref.parent().unwrap(), root_id);

        let root_node_ref = tree.get(root_id).unwrap();
        let root_children: &Vec<NodeId> = root_node_ref.children();

        let child_1_id = root_children.get(0).unwrap();
        let child_2_id = root_children.get(1).unwrap();

        let child_1_ref = tree.get(*child_1_id).unwrap();
        let child_2_ref = tree.get(*child_2_id).unwrap();

        assert_eq!(child_1_ref.data(), &1);
        assert_eq!(child_2_ref.data(), &2);
    }

    #[test]
    fn test_remove_node_drop_children() {

        let mut tree = TreeBuilder::new()
            .with_root(Node::new(5))
            .build();

        let root_node_id = tree.root_node_id().unwrap();

        let node_1_id = tree.add_child(root_node_id, Node::new(1));
        let node_2_id = tree.add_child(node_1_id, Node::new(2));
        let node_3_id = tree.add_child(node_1_id, Node::new(3));

        let node_1 = tree.remove_node_drop_children(node_1_id);

        assert_eq!(node_1.data(), &1);
        assert_eq!(node_1.children().len(), 0);
        assert!(tree.get(node_2_id).is_none());
        assert!(tree.get(node_3_id).is_none());
    }
}

#[cfg(test)]
mod node_tests {
    use super::Node;
    use super::NodeId;
    use super::snowflake::ProcessUniqueId;

    #[test]
    fn test_new() {
        let _node = Node::new(5);
    }

    #[test]
    fn test_data() {
        let five = 5;
        let node = Node::new(five);
        assert_eq!(node.data(), &five);
    }

    #[test]
    fn test_data_mut() {
        let mut five = 5;
        let mut node = Node::new(five);
        assert_eq!(node.data_mut(), &mut five);
    }

    #[test]
    fn test_parent() {
        let node = Node::new(5);
        assert!(node.parent().is_none());

        let parent_id: NodeId = NodeId {
            tree_id: ProcessUniqueId::new(),
            index: 0
        };
        let mut node = Node::new(5);
        node.set_parent(parent_id);

        assert_eq!(node.parent(), Some(parent_id))
    }

    #[test]
    fn test_children() {
        let node = Node::new(5);
        assert_eq!(node.children().len(), 0);

        let tree_id = ProcessUniqueId::new();

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            index: 2
        };
        node.add_child(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            index: 2
        };
        node.children_mut().push(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);
    }
}
<|endoftext|>


<commit_before>//! Setup and control loop devices.
//!
//! Provides rust interface with similar functionalty to the linux utility `losetup`.
//!
//! # Examples
//!
//! ```rust
//! use loopdev::LoopControl;
//! let lc = LoopControl::open().unwrap();
//! let ld = lc.next_free().unwrap();
//!
//! println!("{}", ld.path().unwrap().display());
//!
//! ld.attach_file("test.img").unwrap();
//! // ...
//! ld.detach().unwrap();
//! ```

extern crate libc;

use std::fs::OpenOptions;
use std::fs::File;

use std::os::unix::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use libc::{c_int, ioctl, uint8_t, uint32_t, uint64_t};
use std::default::Default;

// TODO support missing operations
const LOOP_SET_FD: u16 = 0x4C00;
const LOOP_CLR_FD: u16 = 0x4C01;
const LOOP_SET_STATUS64: u16 = 0x4C04;
//const LOOP_GET_STATUS64: u16 = 0x4C05;
const LOOP_SET_CAPACITY: u16 = 0x4C07;
//const LOOP_SET_DIRECT_IO: u16 = 0x4C08;
//const LOOP_SET_BLOCK_SIZE: u16 = 0x4C09;

//const LOOP_CTL_ADD: u16 = 0x4C80;
//const LOOP_CTL_REMOVE: u16 = 0x4C81;
const LOOP_CTL_GET_FREE: u16 = 0x4C82;

const LOOP_CONTROL: &'static str = "/dev/loop-control";
const LOOP_PREFIX: &'static str = "/dev/loop";

/// Interface to the loop control device: `/dev/loop-control`.
#[derive(Debug)]
pub struct LoopControl {
    dev_file: File,
}

impl LoopControl {
    /// Opens the loop control device.
    pub fn open() -> io::Result<LoopControl> {
        Ok(LoopControl {
            dev_file: try!(OpenOptions::new().read(true).write(true).open(LOOP_CONTROL)),
        })
    }

    /// Finds and opens the next available loop device.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use loopdev::LoopControl;
    /// let lc = LoopControl::open().unwrap();
    /// let ld = lc.next_free().unwrap();
    /// println!("{}", ld.path().unwrap().display());
    /// ```
    pub fn next_free(&self) -> io::Result<LoopDevice> {
        let result;
        unsafe {
            result = ioctl(self.dev_file.as_raw_fd() as c_int, LOOP_CTL_GET_FREE.into());
        }
        if result < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(try!(
                LoopDevice::open(&format!("{}{}", LOOP_PREFIX, result))
            ))
        }
    }
}

/// Interface to a loop device ie `/dev/loop0`.
#[derive(Debug)]
pub struct LoopDevice {
    device: File,
}

impl LoopDevice {
    /// Opens a loop device.
    pub fn open<P: AsRef<Path>>(dev: P) -> io::Result<LoopDevice> {
        // TODO create dev if it does not exist and begins with LOOP_PREFIX
        let f = try!(OpenOptions::new().read(true).write(true).open(dev));
        Ok(LoopDevice { device: f })
    }

    /// Attach the loop device to a file starting at offset into the file.
    #[deprecated(since = "0.2.0", note = "use `attach_file` or `attach_with_offset` instead")]
    pub fn attach<P: AsRef<Path>>(&self, backing_file: P, offset: u64) -> io::Result<()> {
        self.attach_with_sizelimit(backing_file, offset, 0)
    }

    /// Attach the loop device to a file that maps to the whole file.
    ///
    /// # Examples
    ///
    /// Attach the device to a file.
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop4").unwrap();
    /// ld.attach_file("test.img").unwrap();
    /// # ld.detach().unwrap();
    /// ```
    pub fn attach_file<P: AsRef<Path>>(&self, backing_file: P) -> io::Result<()> {
        self.attach_with_sizelimit(backing_file, 0, 0)
    }

    /// Attach the loop device to a file starting at offset into the file.
    ///
    /// # Examples
    ///
    /// Attach the device to the start of a file.
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop5").unwrap();
    /// ld.attach_with_offset("test.img", 0).unwrap();
    /// # ld.detach().unwrap();
    /// ```
    pub fn attach_with_offset<P: AsRef<Path>>(
        &self,
        backing_file: P,
        offset: u64,
    ) -> io::Result<()> {
        self.attach_with_sizelimit(backing_file, offset, 0)
    }

    /// Attach the loop device to a file starting at offset into the file and a the given sizelimit.
    ///
    /// # Examples
    ///
    /// Attach the device to the start of a file with a maximum size of 1024 bytes.
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop6").unwrap();
    /// ld.attach_with_sizelimit("test.img", 0, 1024).unwrap();
    /// # ld.detach().unwrap();
    /// ```
    pub fn attach_with_sizelimit<P: AsRef<Path>>(
        &self,
        backing_file: P,
        offset: u64,
        sizelimit: u64,
    ) -> io::Result<()> {
        let bf = try!(OpenOptions::new().read(true).write(true).open(backing_file));

        // Attach the file
        unsafe {
            if ioctl(
                self.device.as_raw_fd() as c_int,
                LOOP_SET_FD.into(),
                bf.as_raw_fd() as c_int,
            ) < 0
            {
                return Err(io::Error::last_os_error());
            }
        }

        // Set offset for backing_file
        let mut info: loop_info64 = Default::default();
        info.lo_offset = offset;
        info.lo_sizelimit = sizelimit;
        unsafe {
            if ioctl(
                self.device.as_raw_fd() as c_int,
                LOOP_SET_STATUS64.into(),
                &mut info,
            ) < 0
            {
                try!(self.detach());
                return Err(io::Error::last_os_error());
            }
        }
        Ok(())
    }

    /// Get the path of the loop device.
    #[deprecated(since = "0.2.0", note = "use `path` instead")]
    pub fn get_path(&self) -> Option<PathBuf> {
        self.path()
    }

    /// Get the path of the loop device.
    pub fn path(&self) -> Option<PathBuf> {
        let mut p = PathBuf::from("/proc/self/fd");
        p.push(self.device.as_raw_fd().to_string());
        std::fs::read_link(&p).ok()
    }

    /// Detach a loop device from its backing file.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop7").unwrap();
    /// # ld.attach_file("test.img").unwrap();
    /// ld.detach().unwrap();
    /// ```
    pub fn detach(&self) -> io::Result<()> {
        unsafe {
            if ioctl(self.device.as_raw_fd() as c_int, LOOP_CLR_FD.into(), 0) < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(())
            }
        }
    }

    /// Resize a live loop device. If the size of the backing file changes this can be called to
    /// inform the loop driver about the new size.
    pub fn set_capacity(&self) -> io::Result<()> {
        println!("running set_capacity");
        unsafe {
            if ioctl(
                self.device.as_raw_fd() as c_int,
                LOOP_SET_CAPACITY.into(),
                0,
            ) < 0
            {
                Err(io::Error::last_os_error())
            } else {
                println!("ok");
                Ok(())
            }
        }
    }
}

#[repr(C)]
struct loop_info64 {
    pub lo_device: uint64_t,
    pub lo_inode: uint64_t,
    pub lo_rdevice: uint64_t,
    pub lo_offset: uint64_t,
    pub lo_sizelimit: uint64_t,
    pub lo_number: uint32_t,
    pub lo_encrypt_type: uint32_t,
    pub lo_encrypt_key_size: uint32_t,
    pub lo_flags: uint32_t,
    pub lo_file_name: [uint8_t; 64],
    pub lo_crypt_name: [uint8_t; 64],
    pub lo_encrypt_key: [uint8_t; 32],
    pub lo_init: [uint64_t; 2],
}

impl Default for loop_info64 {
    fn default() -> loop_info64 {
        loop_info64 {
            lo_device: 0,
            lo_inode: 0,
            lo_rdevice: 0,
            lo_offset: 0,
            lo_sizelimit: 0,
            lo_number: 0,
            lo_encrypt_type: 0,
            lo_encrypt_key_size: 0,
            lo_flags: 0,
            lo_file_name: [0; 64],
            lo_crypt_name: [0; 64],
            lo_encrypt_key: [0; 32],
            lo_init: [0; 2],
        }
    }
}
<commit_msg>fix(clippy): removes 'static lifetime from const<commit_after>//! Setup and control loop devices.
//!
//! Provides rust interface with similar functionalty to the linux utility `losetup`.
//!
//! # Examples
//!
//! ```rust
//! use loopdev::LoopControl;
//! let lc = LoopControl::open().unwrap();
//! let ld = lc.next_free().unwrap();
//!
//! println!("{}", ld.path().unwrap().display());
//!
//! ld.attach_file("test.img").unwrap();
//! // ...
//! ld.detach().unwrap();
//! ```

extern crate libc;

use std::fs::OpenOptions;
use std::fs::File;

use std::os::unix::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use libc::{c_int, ioctl, uint8_t, uint32_t, uint64_t};
use std::default::Default;

// TODO support missing operations
const LOOP_SET_FD: u16 = 0x4C00;
const LOOP_CLR_FD: u16 = 0x4C01;
const LOOP_SET_STATUS64: u16 = 0x4C04;
//const LOOP_GET_STATUS64: u16 = 0x4C05;
const LOOP_SET_CAPACITY: u16 = 0x4C07;
//const LOOP_SET_DIRECT_IO: u16 = 0x4C08;
//const LOOP_SET_BLOCK_SIZE: u16 = 0x4C09;

//const LOOP_CTL_ADD: u16 = 0x4C80;
//const LOOP_CTL_REMOVE: u16 = 0x4C81;
const LOOP_CTL_GET_FREE: u16 = 0x4C82;

const LOOP_CONTROL: &str = "/dev/loop-control";
const LOOP_PREFIX: &str = "/dev/loop";

/// Interface to the loop control device: `/dev/loop-control`.
#[derive(Debug)]
pub struct LoopControl {
    dev_file: File,
}

impl LoopControl {
    /// Opens the loop control device.
    pub fn open() -> io::Result<LoopControl> {
        Ok(LoopControl {
            dev_file: try!(OpenOptions::new().read(true).write(true).open(LOOP_CONTROL)),
        })
    }

    /// Finds and opens the next available loop device.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use loopdev::LoopControl;
    /// let lc = LoopControl::open().unwrap();
    /// let ld = lc.next_free().unwrap();
    /// println!("{}", ld.path().unwrap().display());
    /// ```
    pub fn next_free(&self) -> io::Result<LoopDevice> {
        let result;
        unsafe {
            result = ioctl(self.dev_file.as_raw_fd() as c_int, LOOP_CTL_GET_FREE.into());
        }
        if result < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(try!(
                LoopDevice::open(&format!("{}{}", LOOP_PREFIX, result))
            ))
        }
    }
}

/// Interface to a loop device ie `/dev/loop0`.
#[derive(Debug)]
pub struct LoopDevice {
    device: File,
}

impl LoopDevice {
    /// Opens a loop device.
    pub fn open<P: AsRef<Path>>(dev: P) -> io::Result<LoopDevice> {
        // TODO create dev if it does not exist and begins with LOOP_PREFIX
        let f = try!(OpenOptions::new().read(true).write(true).open(dev));
        Ok(LoopDevice { device: f })
    }

    /// Attach the loop device to a file starting at offset into the file.
    #[deprecated(since = "0.2.0", note = "use `attach_file` or `attach_with_offset` instead")]
    pub fn attach<P: AsRef<Path>>(&self, backing_file: P, offset: u64) -> io::Result<()> {
        self.attach_with_sizelimit(backing_file, offset, 0)
    }

    /// Attach the loop device to a file that maps to the whole file.
    ///
    /// # Examples
    ///
    /// Attach the device to a file.
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop4").unwrap();
    /// ld.attach_file("test.img").unwrap();
    /// # ld.detach().unwrap();
    /// ```
    pub fn attach_file<P: AsRef<Path>>(&self, backing_file: P) -> io::Result<()> {
        self.attach_with_sizelimit(backing_file, 0, 0)
    }

    /// Attach the loop device to a file starting at offset into the file.
    ///
    /// # Examples
    ///
    /// Attach the device to the start of a file.
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop5").unwrap();
    /// ld.attach_with_offset("test.img", 0).unwrap();
    /// # ld.detach().unwrap();
    /// ```
    pub fn attach_with_offset<P: AsRef<Path>>(
        &self,
        backing_file: P,
        offset: u64,
    ) -> io::Result<()> {
        self.attach_with_sizelimit(backing_file, offset, 0)
    }

    /// Attach the loop device to a file starting at offset into the file and a the given sizelimit.
    ///
    /// # Examples
    ///
    /// Attach the device to the start of a file with a maximum size of 1024 bytes.
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop6").unwrap();
    /// ld.attach_with_sizelimit("test.img", 0, 1024).unwrap();
    /// # ld.detach().unwrap();
    /// ```
    pub fn attach_with_sizelimit<P: AsRef<Path>>(
        &self,
        backing_file: P,
        offset: u64,
        sizelimit: u64,
    ) -> io::Result<()> {
        let bf = try!(OpenOptions::new().read(true).write(true).open(backing_file));

        // Attach the file
        unsafe {
            if ioctl(
                self.device.as_raw_fd() as c_int,
                LOOP_SET_FD.into(),
                bf.as_raw_fd() as c_int,
            ) < 0
            {
                return Err(io::Error::last_os_error());
            }
        }

        // Set offset for backing_file
        let mut info: loop_info64 = Default::default();
        info.lo_offset = offset;
        info.lo_sizelimit = sizelimit;
        unsafe {
            if ioctl(
                self.device.as_raw_fd() as c_int,
                LOOP_SET_STATUS64.into(),
                &mut info,
            ) < 0
            {
                try!(self.detach());
                return Err(io::Error::last_os_error());
            }
        }
        Ok(())
    }

    /// Get the path of the loop device.
    #[deprecated(since = "0.2.0", note = "use `path` instead")]
    pub fn get_path(&self) -> Option<PathBuf> {
        self.path()
    }

    /// Get the path of the loop device.
    pub fn path(&self) -> Option<PathBuf> {
        let mut p = PathBuf::from("/proc/self/fd");
        p.push(self.device.as_raw_fd().to_string());
        std::fs::read_link(&p).ok()
    }

    /// Detach a loop device from its backing file.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use loopdev::LoopDevice;
    /// let ld = LoopDevice::open("/dev/loop7").unwrap();
    /// # ld.attach_file("test.img").unwrap();
    /// ld.detach().unwrap();
    /// ```
    pub fn detach(&self) -> io::Result<()> {
        unsafe {
            if ioctl(self.device.as_raw_fd() as c_int, LOOP_CLR_FD.into(), 0) < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(())
            }
        }
    }

    /// Resize a live loop device. If the size of the backing file changes this can be called to
    /// inform the loop driver about the new size.
    pub fn set_capacity(&self) -> io::Result<()> {
        println!("running set_capacity");
        unsafe {
            if ioctl(
                self.device.as_raw_fd() as c_int,
                LOOP_SET_CAPACITY.into(),
                0,
            ) < 0
            {
                Err(io::Error::last_os_error())
            } else {
                println!("ok");
                Ok(())
            }
        }
    }
}

#[repr(C)]
struct loop_info64 {
    pub lo_device: uint64_t,
    pub lo_inode: uint64_t,
    pub lo_rdevice: uint64_t,
    pub lo_offset: uint64_t,
    pub lo_sizelimit: uint64_t,
    pub lo_number: uint32_t,
    pub lo_encrypt_type: uint32_t,
    pub lo_encrypt_key_size: uint32_t,
    pub lo_flags: uint32_t,
    pub lo_file_name: [uint8_t; 64],
    pub lo_crypt_name: [uint8_t; 64],
    pub lo_encrypt_key: [uint8_t; 32],
    pub lo_init: [uint64_t; 2],
}

impl Default for loop_info64 {
    fn default() -> loop_info64 {
        loop_info64 {
            lo_device: 0,
            lo_inode: 0,
            lo_rdevice: 0,
            lo_offset: 0,
            lo_sizelimit: 0,
            lo_number: 0,
            lo_encrypt_type: 0,
            lo_encrypt_key_size: 0,
            lo_flags: 0,
            lo_file_name: [0; 64],
            lo_crypt_name: [0; 64],
            lo_encrypt_key: [0; 32],
            lo_init: [0; 2],
        }
    }
}
<|endoftext|>


<commit_before>pub mod core {

  #[derive(Debug, Copy, Clone)]
  pub struct Twice<N> {
    pub lo: N,
    pub hi: N
  }

  pub trait Half {
    type Half;
  }

  impl<N> Half for Twice<N> {
    type Half = N;
  }

  pub trait ElemTwice {
    type ElemTwice;
  }

  impl ElemTwice for Twice<Twice<i32>> {
    type ElemTwice = Twice<i64>;
  }

  pub trait Multi {
    type Elem;
    type Repr;
    fn wrap(Self::Repr) -> Self;
    fn unwrap(self) -> Self::Repr;
  }

}

use self::core::*;

pub type M2<N> = Twice<N>;
pub type M4<N> = Twice<M2<N>>;
pub type M8<N> = Twice<M4<N>>;
pub type M16<N> = Twice<M8<N>>;
pub type M32<N> = Twice<M16<N>>;

pub trait Set1<M: Multi> {
  fn set1(&self, M::Elem) -> M;
}

pub trait Add<M: Multi> {
  fn add(&self, M, M) -> M;
}

pub trait Shli<M: Multi> {
  fn shli(&self, M, i32) -> M;
}

pub trait Shri<M: Multi> {
  fn shri(&self, M, i32) -> M;
}

pub trait Mullo<M: Multi + ElemTwice> {
  fn mullo(&self, M, M) -> M::ElemTwice;
}

pub mod arch {

  enum Token { Token }

  pub struct X86(Token);

  pub mod x86;

}
<commit_msg>docs: add description to traits<commit_after>pub mod core {

  #[derive(Debug, Copy, Clone)]
  pub struct Twice<N> {
    pub lo: N,
    pub hi: N
  }

  pub trait Half {
    type Half;
  }

  impl<N> Half for Twice<N> {
    type Half = N;
  }

  pub trait ElemTwice {
    type ElemTwice;
  }

  impl ElemTwice for Twice<Twice<i32>> {
    type ElemTwice = Twice<i64>;
  }

  pub trait Multi {
    type Elem;
    type Repr;
    fn wrap(Self::Repr) -> Self;
    fn unwrap(self) -> Self::Repr;
  }

}

use self::core::*;

pub type M2<N> = Twice<N>;
pub type M4<N> = Twice<M2<N>>;
pub type M8<N> = Twice<M4<N>>;
pub type M16<N> = Twice<M8<N>>;
pub type M32<N> = Twice<M16<N>>;

/// The `Set1` trait is used to specify broadcasting functionality.
pub trait Set1<M: Multi> {
/// Broadcasts `e` to all elements of the vector.
  fn set1(&self, e: M::Elem) -> M;
}

/// The `Add` trait is used to specify element-wise addition functionality.
pub trait Add<M: Multi> {
/// Adds elements in a and b.
  fn add(&self, a: M, b: M) -> M;
}

/// The `Shli` trait is used to specify immediate bit-wise left shift functionality.
pub trait Shli<M: Multi> {
/// Shifts all elements in the `m` left by `i` bits.
  fn shli(&self, m: M, i: i32) -> M;
}

/// The `Shri` trait is used to specify immediate bit-wise right shift functionality.
pub trait Shri<M: Multi> {
/// Shifts all elements in the `m` right by `i` bits.
  fn shri(&self, M, i32) -> M;
}

/// The `Mullo` trait is used to specify low element-wise multiplication functionality.
pub trait Mullo<M: Multi + ElemTwice> {
/// Multiplies the elements in `a` and `b` and stores the lower halves of the results.
  fn mullo(&self, a: M, b: M) -> M::ElemTwice;
}

pub mod arch {

  enum Token { Token }

  pub struct X86(Token);

  pub mod x86;

}
<|endoftext|>