<commit_before>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Transaction, Cursor, DUP_SORT, INTEGER_KEY};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    TransactionError,
    PathError,
    NotFoundError,
}

pub type Result<T> = result::Result<T, Error>;

struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

struct RwTransaction<'a> {
    lmdb_txn: lmdb::RwTransaction<'a>,
}

struct Entry<'a> {
    id: u64,
    parent_id: u64,
    name: &'a str,
    objectclass: &'a str,
}

struct Node<'a> {
    id: u64,
    parent_id: u64,
    name: &'a str,
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: 0,
            parent_id: 0,
            name: "/"
        }
    }

    fn from_bytes_and_parent_id(bytes: &[u8], parent_id: u64) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        let name = match std::str::from_utf8(&bytes[8..]) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Node {
            id: LmdbAdapter::bytes_to_id(id),
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&LmdbAdapter::id_to_bytes(self.id));
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new()
                            .set_max_dbs(8)
                            .open_with_permissions(&path, 0o600) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbCreateError),
        };

        let nodes = match env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        let entries = match env.create_db(Some("entries"), INTEGER_KEY) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new().open(&path) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let nodes = match env.open_db(Some("nodes")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let entries = match env.open_db(Some("entries")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    fn id_to_bytes(id: u64) -> [u8; 8] {
        unsafe { std::mem::transmute(id) }
    }

    fn bytes_to_id(bytes: [u8; 8]) -> u64 {
        unsafe { std::mem::transmute(bytes) }
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction { lmdb_txn: txn }),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id(&self, txn: &mut RwTransaction) -> Result<u64> {
        let cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
            Ok(c) => c,
            Err(_) => return Err(Error::TransactionError),
        };

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => {
                let mut id_bytes = [0u8; 8];
                id_bytes.copy_from_slice(id.unwrap()); // TODO: don't panic
                LmdbAdapter::bytes_to_id(id_bytes)
            }
            Err(_) => 0, // 0 is reserved for root
        };

        Ok(last_id + 1)
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &mut RwTransaction,
                            id: u64,
                            parent_id: u64,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let ref mut lmdb_txn = txn.lmdb_txn;
        let id_bytes = LmdbAdapter::id_to_bytes(id);

        let mut path_info = Vec::with_capacity(8 + name.len());
        path_info.extend_from_slice(&id_bytes);
        path_info.extend_from_slice(name.as_bytes());

        match lmdb_txn.put(self.nodes,
                           &LmdbAdapter::id_to_bytes(parent_id),
                           &path_info,
                           lmdb::WriteFlags::empty()) {
            Ok(_) => (),
            Err(_) => return Err(Error::DbWriteError),
        }

        match lmdb_txn.put(self.entries,
                           &id_bytes,
                           &objectclass,
                           lmdb::WriteFlags::empty()) {
            Ok(_) => (),
            Err(_) => return Err(Error::DbWriteError),
        }

        Ok(Entry {
            id: id,
            parent_id: parent_id,
            name: name,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a>(&'a self, txn: &'a mut RwTransaction, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = match txn.lmdb_txn.get(self.entries, &LmdbAdapter::id_to_bytes(node.id)) {
            Ok(bytes) => bytes,
            Err(_) => return Err(Error::DbCorruptError),
        };

        let objectclass = match std::str::from_utf8(&entry_bytes) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Entry {
            id: node.id,
            parent_id: node.parent_id,
            name: node.name,
            objectclass: objectclass,
        })
    }

    fn find_node(&self, txn: &mut RwTransaction, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;
            let parent_id_bytes = LmdbAdapter::id_to_bytes(parent_id);

            let mut cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
                Ok(c) => c,
                Err(_) => return Err(Error::TransactionError),
            };

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id_bytes) {
                if id != parent_id_bytes {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_bytes_and_parent_id(node_bytes, parent_id));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            match child_node {
                Some(node) => Ok(node),
                None => return Err(Error::NotFoundError),
            }
        })
    }
}

impl<'a> RwTransaction<'a> {
    pub fn commit(self) -> Result<()> {
        match self.lmdb_txn.commit() {
            Ok(_) => Ok(()),
            Err(_) => return Err(Error::TransactionError),
        }
    }
}

#[test]
fn test_entry_lookup() {
    let path = Path::new("./tmp");
    let adapter = LmdbAdapter::create(path).unwrap();

    {
        let mut txn = adapter.rw_transaction().unwrap();
        let id = adapter.next_available_id(&mut txn).unwrap();
        let domain = adapter.create_entry(&mut txn, id, 0, "example.com", "domain").unwrap();
        let hosts = adapter.create_entry(&mut txn, id + 1, domain.id, "hosts", "ou").unwrap();
        let host = adapter.create_entry(&mut txn, id + 2, hosts.id, "master.example.com", "host")
                          .unwrap();

        txn.commit().unwrap();
    }

    {
        let mut txn = adapter.rw_transaction().unwrap();
        let entry = adapter.find_entry(&mut txn, "/example.com/hosts/master.example.com").unwrap();

        assert_eq!(entry.name, "master.example.com");
        assert_eq!(entry.objectclass, "host");
    }
}
<commit_msg>Extract Id type<commit_after>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Transaction, Cursor, DUP_SORT, INTEGER_KEY};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

pub type Result<T> = result::Result<T, Error>;

struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

struct RwTransaction<'a> {
    lmdb_txn: lmdb::RwTransaction<'a>,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct Id(u64);

struct Entry<'a> {
    id: Id,
    parent_id: Id,
    name: &'a str,
    objectclass: &'a str,
}

struct Node<'a> {
    id: Id,
    parent_id: Id,
    name: &'a str,
}

impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_bytes_and_parent_id(bytes: &[u8], parent_id: Id) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));

        let name = match std::str::from_utf8(&bytes[8..]) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new()
                            .set_max_dbs(8)
                            .open_with_permissions(&path, 0o600) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbCreateError),
        };

        let nodes = match env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        let entries = match env.create_db(Some("entries"), INTEGER_KEY) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new().open(&path) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let nodes = match env.open_db(Some("nodes")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let entries = match env.open_db(Some("entries")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction { lmdb_txn: txn }),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id(&self, txn: &mut RwTransaction) -> Result<Id> {
        let cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
            Ok(c) => c,
            Err(_) => return Err(Error::TransactionError),
        };

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let ref mut lmdb_txn = txn.lmdb_txn;

        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        match lmdb_txn.put(self.nodes,
                           &parent_id.as_bytes(),
                           &node.to_bytes(),
                           lmdb::WriteFlags::empty()) {
            Ok(_) => (),
            Err(_) => return Err(Error::DbWriteError),
        }

        match lmdb_txn.put(self.entries,
                           &id.as_bytes(),
                           &objectclass,
                           lmdb::WriteFlags::empty()) {
            Ok(_) => (),
            Err(_) => return Err(Error::DbWriteError),
        }

        Ok(Entry {
            id: id,
            parent_id: parent_id,
            name: name,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a>(&'a self, txn: &'a mut RwTransaction, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = match txn.lmdb_txn.get(self.entries, &node.id.as_bytes()) {
            Ok(bytes) => bytes,
            Err(_) => return Err(Error::DbCorruptError),
        };

        let objectclass = match std::str::from_utf8(&entry_bytes) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Entry {
            id: node.id,
            parent_id: node.parent_id,
            name: node.name,
            objectclass: objectclass,
        })
    }

    fn find_node(&self, txn: &mut RwTransaction, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
                Ok(c) => c,
                Err(_) => return Err(Error::TransactionError),
            };

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_bytes_and_parent_id(node_bytes, parent_id));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            match child_node {
                Some(node) => Ok(node),
                None => return Err(Error::NotFoundError),
            }
        })
    }
}

impl<'a> RwTransaction<'a> {
    pub fn commit(self) -> Result<()> {
        match self.lmdb_txn.commit() {
            Ok(_) => Ok(()),
            Err(_) => return Err(Error::TransactionError),
        }
    }
}

#[test]
fn test_entry_lookup() {
    let path = Path::new("./tmp");
    let adapter = LmdbAdapter::create(path).unwrap();

    {
        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&mut txn).unwrap();
        let domain = adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain")
                            .unwrap();

        let hosts_id = domain_id.next();
        let hosts = adapter.create_entry(&mut txn, hosts_id, domain.id, "hosts", "ou").unwrap();

        let host_id = hosts_id.next();
        let host = adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host")
                          .unwrap();

        txn.commit().unwrap();
    }

    {
        let mut txn = adapter.rw_transaction().unwrap();
        let entry = adapter.find_entry(&mut txn, "/example.com/hosts/master.example.com").unwrap();

        assert_eq!(entry.name, "master.example.com");
        assert_eq!(entry.objectclass, "host");
    }
}
<|endoftext|>


<commit_before>#![feature(str_char)]

pub mod atom;
pub mod sexp;
pub mod parser;
pub mod token;

pub use atom::Atom;
pub use sexp::Sexp;

/// Convert self into a S-expression.
pub trait ToSexp {
    fn to_sexp(&self) -> Sexp;
}
<commit_msg>Revert "Add ToSexp trait"<commit_after>#![feature(str_char)]

pub mod atom;
pub mod sexp;
pub mod parser;
pub mod token;

pub use atom::Atom;
pub use sexp::Sexp;
<|endoftext|>


<commit_before>// Copyright 2016 oauth-client-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! Performs topological sorting.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![cfg_attr(feature = "cargo-clippy", warn(if_not_else))]
#![cfg_attr(feature = "cargo-clippy", warn(invalid_upcast_comparisons))]
#![cfg_attr(feature = "cargo-clippy", warn(items_after_statements))]
#![cfg_attr(feature = "cargo-clippy", warn(mut_mut))]
#![cfg_attr(feature = "cargo-clippy", warn(never_loop))]
#![cfg_attr(feature = "cargo-clippy", warn(nonminimal_bool))]
#![cfg_attr(feature = "cargo-clippy", warn(option_map_unwrap_or))]
#![cfg_attr(feature = "cargo-clippy", warn(option_map_unwrap_or_else))]
#![cfg_attr(feature = "cargo-clippy", warn(option_unwrap_used))]
#![cfg_attr(feature = "cargo-clippy", warn(result_unwrap_used))]
#![cfg_attr(feature = "cargo-clippy", warn(used_underscore_binding))]

use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::fmt;
use std::hash::Hash;
use std::iter::FromIterator;

#[derive(Clone)]
struct Dependency<T> {
    num_prec: usize,
    succ: HashSet<T>,
}

impl<T: Hash + Eq> Dependency<T> {
    fn new() -> Dependency<T> {
        Dependency {
            num_prec: 0,
            succ: HashSet::new(),
        }
    }
}

/// Performs topological sorting.
#[derive(Clone)]
pub struct TopologicalSort<T> {
    top: HashMap<T, Dependency<T>>,
}

impl<T: Hash + Eq + Clone> TopologicalSort<T> {
    /// Creates new empty `TopologicalSort`.
    ///
    /// ```rust
    /// # extern crate topological_sort;
    /// # fn main() {
    /// use topological_sort::TopologicalSort;
    /// let mut ts = TopologicalSort::<&str>::new();
    /// ts.add_dependency("hello_world.o", "hello_world");
    /// ts.add_dependency("hello_world.c", "hello_world");
    /// ts.add_dependency("stdio.h", "hello_world.o");
    /// ts.add_dependency("glibc.so", "hello_world");
    /// assert_eq!(vec!["glibc.so", "hello_world.c", "stdio.h"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world.o"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert!(ts.pop_all().is_empty());
    /// # }
    /// ```
    #[inline]
    pub fn new() -> TopologicalSort<T> {
        TopologicalSort {
            top: HashMap::new(),
        }
    }

    /// Returns the number of elements in the `TopologicalSort`.
    #[inline]
    pub fn len(&self) -> usize {
        self.top.len()
    }

    /// Returns true if the `TopologicalSort` contains no elements.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.top.is_empty()
    }

    /// Registers the two elements' dependency.
    ///
    /// # Arguments
    ///
    /// * `prec` - The element appears before `succ`. `prec` is depended on by `succ`.
    /// * `succ` - The element appears after `prec`. `succ` depends on `prec`.
    pub fn add_dependency<P, S>(&mut self, prec: P, succ: S)
    where
        P: Into<T>,
        S: Into<T>,
    {
        self.add_dependency_impl(prec.into(), succ.into())
    }

    fn add_dependency_impl(&mut self, prec: T, succ: T) {
        match self.top.entry(prec) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.succ.insert(succ.clone());
                let _ = e.insert(dep);
            }
            Entry::Occupied(e) => {
                if !e.into_mut().succ.insert(succ.clone()) {
                    // Already registered
                    return;
                }
            }
        }

        match self.top.entry(succ) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.num_prec += 1;
                let _ = e.insert(dep);
            }
            Entry::Occupied(e) => {
                e.into_mut().num_prec += 1;
            }
        }
    }

    /// Registers a dependency link.
    pub fn add_link(&mut self, link: DependencyLink<T>) {
        self.add_dependency(link.prec, link.succ)
    }

    /// Inserts an element, without adding any dependencies from or to it.
    ///
    /// If the `TopologicalSort` did not have this element present, `true` is returned.
    ///
    /// If the `TopologicalSort` already had this element present, `false` is returned.
    pub fn insert<U>(&mut self, elt: U) -> bool
    where
        U: Into<T>,
    {
        match self.top.entry(elt.into()) {
            Entry::Vacant(e) => {
                let dep = Dependency::new();
                let _ = e.insert(dep);
                true
            }
            Entry::Occupied(_) => false,
        }
    }

    /// Removes the item that is not depended on by any other items and returns it, or `None` if
    /// there is no such item.
    ///
    /// If `pop` returns `None` and `len` is not 0, there is cyclic dependencies.
    pub fn pop(&mut self) -> Option<T> {
        self.peek().map(T::clone).map(|key| {
            let _ = self.remove(&key);
            key
        })
    }

    /// Removes all items that are not depended on by any other items and returns it, or empty
    /// vector if there are no such items.
    ///
    /// If `pop_all` returns an empty vector and `len` is not 0, there is cyclic dependencies.
    pub fn pop_all(&mut self) -> Vec<T> {
        let keys = self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k.clone())
            .collect::<Vec<_>>();
        for k in &keys {
            let _ = self.remove(k);
        }
        keys
    }

    /// Return a reference to the first item that does not depend on any other items, or `None` if
    /// there is no such item.
    pub fn peek(&self) -> Option<&T> {
        self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k)
            .next()
    }

    /// Return a vector of references to all items that do not depend on any other items, or an
    /// empty vector if there are no such items.
    pub fn peek_all(&self) -> Vec<&T> {
        self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k)
            .collect::<Vec<_>>()
    }

    fn remove(&mut self, prec: &T) -> Option<Dependency<T>> {
        let result = self.top.remove(prec);
        if let Some(ref p) = result {
            for s in &p.succ {
                if let Some(y) = self.top.get_mut(s) {
                    y.num_prec -= 1;
                }
            }
        }
        result
    }
}

impl<T: PartialOrd + Eq + Hash + Clone> FromIterator<T> for TopologicalSort<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> TopologicalSort<T> {
        let mut top = TopologicalSort::new();
        let mut seen = Vec::<T>::default();
        for item in iter {
            top.insert(item.clone());
            for seen_item in seen.iter().cloned() {
                match seen_item.partial_cmp(&item) {
                    Some(Ordering::Less) => {
                        top.add_dependency(seen_item, item.clone());
                    }
                    Some(Ordering::Greater) => {
                        top.add_dependency(item.clone(), seen_item);
                    }
                    _ => (),
                }
            }
            seen.push(item);
        }
        top
    }
}

/// A link between two items in a sort.
#[derive(Copy, Clone, Debug)]
pub struct DependencyLink<T> {
    /// The element which is depened upon by `succ`.
    pub prec: T,
    /// The element which depends on `prec`.
    pub succ: T,
}

impl<T> From<(T, T)> for DependencyLink<T> {
    fn from(tuple: (T, T)) -> Self {
        DependencyLink {
            succ: tuple.0,
            prec: tuple.1,
        }
    }
}

impl<T: Eq + Hash + Clone> FromIterator<DependencyLink<T>> for TopologicalSort<T> {
    fn from_iter<I: IntoIterator<Item = DependencyLink<T>>>(iter: I) -> TopologicalSort<T> {
        let mut top = TopologicalSort::new();
        for link in iter {
            top.add_link(link);
        }
        top
    }
}

impl<T: Hash + Eq + Clone> Iterator for TopologicalSort<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.pop()
    }
}

impl<T: fmt::Debug + Hash + Eq> fmt::Debug for Dependency<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "prec={}, succ={:?}", self.num_prec, self.succ)
    }
}

impl<T: fmt::Debug + Hash + Eq + Clone> fmt::Debug for TopologicalSort<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.top)
    }
}

#[cfg(test)]
mod test {
    use super::TopologicalSort;
    use std::iter::FromIterator;

    #[test]
    fn from_iter() {
        let t = vec![4, 3, 3, 5, 7, 6, 8];
        let mut ts = TopologicalSort::<i32>::from_iter(t);
        assert_eq!(Some(3), ts.next());
        assert_eq!(Some(4), ts.next());
        assert_eq!(Some(5), ts.next());
        assert_eq!(Some(6), ts.next());
        assert_eq!(Some(7), ts.next());
        assert_eq!(Some(8), ts.next());
        assert_eq!(None, ts.next());
    }

    #[test]
    fn iter() {
        let mut ts = TopologicalSort::<i32>::new();
        ts.add_dependency(1, 2);
        ts.add_dependency(2, 3);
        ts.add_dependency(3, 4);
        assert_eq!(Some(1), ts.next());
        assert_eq!(Some(2), ts.next());
        assert_eq!(Some(3), ts.next());
        assert_eq!(Some(4), ts.next());
        assert_eq!(None, ts.next());
    }

    #[test]
    fn pop_all() {
        fn check(result: &[i32], ts: &mut TopologicalSort<i32>) {
            let l = ts.len();
            let mut v = ts.pop_all();
            v.sort();
            assert_eq!(result, &v[..]);
            assert_eq!(l - result.len(), ts.len());
        }

        let mut ts = TopologicalSort::new();
        ts.add_dependency(7, 11);
        assert_eq!(2, ts.len());
        ts.add_dependency(7, 8);
        assert_eq!(3, ts.len());
        ts.add_dependency(5, 11);
        assert_eq!(4, ts.len());
        ts.add_dependency(3, 8);
        assert_eq!(5, ts.len());
        ts.add_dependency(3, 10);
        assert_eq!(6, ts.len());
        ts.add_dependency(11, 2);
        assert_eq!(7, ts.len());
        ts.add_dependency(11, 9);
        assert_eq!(8, ts.len());
        ts.add_dependency(11, 10);
        assert_eq!(8, ts.len());
        ts.add_dependency(8, 9);
        assert_eq!(8, ts.len());

        check(&[3, 5, 7], &mut ts);
        check(&[8, 11], &mut ts);
        check(&[2, 9, 10], &mut ts);
        check(&[], &mut ts);
    }

    #[test]
    fn cyclic_deadlock() {
        let mut ts = TopologicalSort::new();
        ts.add_dependency("stone", "sharp");

        ts.add_dependency("bucket", "hole");
        ts.add_dependency("hole", "straw");
        ts.add_dependency("straw", "axe");
        ts.add_dependency("axe", "sharp");
        ts.add_dependency("sharp", "water");
        ts.add_dependency("water", "bucket");
        assert_eq!(ts.pop(), Some("stone"));
        assert!(ts.pop().is_none());
        println!("{:?}", ts);
    }
}
<commit_msg>Fix unused result warning<commit_after>// Copyright 2016 oauth-client-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! Performs topological sorting.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![cfg_attr(feature = "cargo-clippy", warn(if_not_else))]
#![cfg_attr(feature = "cargo-clippy", warn(invalid_upcast_comparisons))]
#![cfg_attr(feature = "cargo-clippy", warn(items_after_statements))]
#![cfg_attr(feature = "cargo-clippy", warn(mut_mut))]
#![cfg_attr(feature = "cargo-clippy", warn(never_loop))]
#![cfg_attr(feature = "cargo-clippy", warn(nonminimal_bool))]
#![cfg_attr(feature = "cargo-clippy", warn(option_map_unwrap_or))]
#![cfg_attr(feature = "cargo-clippy", warn(option_map_unwrap_or_else))]
#![cfg_attr(feature = "cargo-clippy", warn(option_unwrap_used))]
#![cfg_attr(feature = "cargo-clippy", warn(result_unwrap_used))]
#![cfg_attr(feature = "cargo-clippy", warn(used_underscore_binding))]

use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::fmt;
use std::hash::Hash;
use std::iter::FromIterator;

#[derive(Clone)]
struct Dependency<T> {
    num_prec: usize,
    succ: HashSet<T>,
}

impl<T: Hash + Eq> Dependency<T> {
    fn new() -> Dependency<T> {
        Dependency {
            num_prec: 0,
            succ: HashSet::new(),
        }
    }
}

/// Performs topological sorting.
#[derive(Clone)]
pub struct TopologicalSort<T> {
    top: HashMap<T, Dependency<T>>,
}

impl<T: Hash + Eq + Clone> TopologicalSort<T> {
    /// Creates new empty `TopologicalSort`.
    ///
    /// ```rust
    /// # extern crate topological_sort;
    /// # fn main() {
    /// use topological_sort::TopologicalSort;
    /// let mut ts = TopologicalSort::<&str>::new();
    /// ts.add_dependency("hello_world.o", "hello_world");
    /// ts.add_dependency("hello_world.c", "hello_world");
    /// ts.add_dependency("stdio.h", "hello_world.o");
    /// ts.add_dependency("glibc.so", "hello_world");
    /// assert_eq!(vec!["glibc.so", "hello_world.c", "stdio.h"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world.o"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert!(ts.pop_all().is_empty());
    /// # }
    /// ```
    #[inline]
    pub fn new() -> TopologicalSort<T> {
        TopologicalSort {
            top: HashMap::new(),
        }
    }

    /// Returns the number of elements in the `TopologicalSort`.
    #[inline]
    pub fn len(&self) -> usize {
        self.top.len()
    }

    /// Returns true if the `TopologicalSort` contains no elements.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.top.is_empty()
    }

    /// Registers the two elements' dependency.
    ///
    /// # Arguments
    ///
    /// * `prec` - The element appears before `succ`. `prec` is depended on by `succ`.
    /// * `succ` - The element appears after `prec`. `succ` depends on `prec`.
    pub fn add_dependency<P, S>(&mut self, prec: P, succ: S)
    where
        P: Into<T>,
        S: Into<T>,
    {
        self.add_dependency_impl(prec.into(), succ.into())
    }

    fn add_dependency_impl(&mut self, prec: T, succ: T) {
        match self.top.entry(prec) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                let _ = dep.succ.insert(succ.clone());
                let _ = e.insert(dep);
            }
            Entry::Occupied(e) => {
                if !e.into_mut().succ.insert(succ.clone()) {
                    // Already registered
                    return;
                }
            }
        }

        match self.top.entry(succ) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.num_prec += 1;
                let _ = e.insert(dep);
            }
            Entry::Occupied(e) => {
                e.into_mut().num_prec += 1;
            }
        }
    }

    /// Registers a dependency link.
    pub fn add_link(&mut self, link: DependencyLink<T>) {
        self.add_dependency(link.prec, link.succ)
    }

    /// Inserts an element, without adding any dependencies from or to it.
    ///
    /// If the `TopologicalSort` did not have this element present, `true` is returned.
    ///
    /// If the `TopologicalSort` already had this element present, `false` is returned.
    pub fn insert<U>(&mut self, elt: U) -> bool
    where
        U: Into<T>,
    {
        match self.top.entry(elt.into()) {
            Entry::Vacant(e) => {
                let dep = Dependency::new();
                let _ = e.insert(dep);
                true
            }
            Entry::Occupied(_) => false,
        }
    }

    /// Removes the item that is not depended on by any other items and returns it, or `None` if
    /// there is no such item.
    ///
    /// If `pop` returns `None` and `len` is not 0, there is cyclic dependencies.
    pub fn pop(&mut self) -> Option<T> {
        self.peek().map(T::clone).map(|key| {
            let _ = self.remove(&key);
            key
        })
    }

    /// Removes all items that are not depended on by any other items and returns it, or empty
    /// vector if there are no such items.
    ///
    /// If `pop_all` returns an empty vector and `len` is not 0, there is cyclic dependencies.
    pub fn pop_all(&mut self) -> Vec<T> {
        let keys = self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k.clone())
            .collect::<Vec<_>>();
        for k in &keys {
            let _ = self.remove(k);
        }
        keys
    }

    /// Return a reference to the first item that does not depend on any other items, or `None` if
    /// there is no such item.
    pub fn peek(&self) -> Option<&T> {
        self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k)
            .next()
    }

    /// Return a vector of references to all items that do not depend on any other items, or an
    /// empty vector if there are no such items.
    pub fn peek_all(&self) -> Vec<&T> {
        self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k)
            .collect::<Vec<_>>()
    }

    fn remove(&mut self, prec: &T) -> Option<Dependency<T>> {
        let result = self.top.remove(prec);
        if let Some(ref p) = result {
            for s in &p.succ {
                if let Some(y) = self.top.get_mut(s) {
                    y.num_prec -= 1;
                }
            }
        }
        result
    }
}

impl<T: PartialOrd + Eq + Hash + Clone> FromIterator<T> for TopologicalSort<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> TopologicalSort<T> {
        let mut top = TopologicalSort::new();
        let mut seen = Vec::<T>::default();
        for item in iter {
            let _ = top.insert(item.clone());
            for seen_item in seen.iter().cloned() {
                match seen_item.partial_cmp(&item) {
                    Some(Ordering::Less) => {
                        top.add_dependency(seen_item, item.clone());
                    }
                    Some(Ordering::Greater) => {
                        top.add_dependency(item.clone(), seen_item);
                    }
                    _ => (),
                }
            }
            seen.push(item);
        }
        top
    }
}

/// A link between two items in a sort.
#[derive(Copy, Clone, Debug)]
pub struct DependencyLink<T> {
    /// The element which is depened upon by `succ`.
    pub prec: T,
    /// The element which depends on `prec`.
    pub succ: T,
}

impl<T> From<(T, T)> for DependencyLink<T> {
    fn from(tuple: (T, T)) -> Self {
        DependencyLink {
            succ: tuple.0,
            prec: tuple.1,
        }
    }
}

impl<T: Eq + Hash + Clone> FromIterator<DependencyLink<T>> for TopologicalSort<T> {
    fn from_iter<I: IntoIterator<Item = DependencyLink<T>>>(iter: I) -> TopologicalSort<T> {
        let mut top = TopologicalSort::new();
        for link in iter {
            top.add_link(link);
        }
        top
    }
}

impl<T: Hash + Eq + Clone> Iterator for TopologicalSort<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.pop()
    }
}

impl<T: fmt::Debug + Hash + Eq> fmt::Debug for Dependency<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "prec={}, succ={:?}", self.num_prec, self.succ)
    }
}

impl<T: fmt::Debug + Hash + Eq + Clone> fmt::Debug for TopologicalSort<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.top)
    }
}

#[cfg(test)]
mod test {
    use super::TopologicalSort;
    use std::iter::FromIterator;

    #[test]
    fn from_iter() {
        let t = vec![4, 3, 3, 5, 7, 6, 8];
        let mut ts = TopologicalSort::<i32>::from_iter(t);
        assert_eq!(Some(3), ts.next());
        assert_eq!(Some(4), ts.next());
        assert_eq!(Some(5), ts.next());
        assert_eq!(Some(6), ts.next());
        assert_eq!(Some(7), ts.next());
        assert_eq!(Some(8), ts.next());
        assert_eq!(None, ts.next());
    }

    #[test]
    fn iter() {
        let mut ts = TopologicalSort::<i32>::new();
        ts.add_dependency(1, 2);
        ts.add_dependency(2, 3);
        ts.add_dependency(3, 4);
        assert_eq!(Some(1), ts.next());
        assert_eq!(Some(2), ts.next());
        assert_eq!(Some(3), ts.next());
        assert_eq!(Some(4), ts.next());
        assert_eq!(None, ts.next());
    }

    #[test]
    fn pop_all() {
        fn check(result: &[i32], ts: &mut TopologicalSort<i32>) {
            let l = ts.len();
            let mut v = ts.pop_all();
            v.sort();
            assert_eq!(result, &v[..]);
            assert_eq!(l - result.len(), ts.len());
        }

        let mut ts = TopologicalSort::new();
        ts.add_dependency(7, 11);
        assert_eq!(2, ts.len());
        ts.add_dependency(7, 8);
        assert_eq!(3, ts.len());
        ts.add_dependency(5, 11);
        assert_eq!(4, ts.len());
        ts.add_dependency(3, 8);
        assert_eq!(5, ts.len());
        ts.add_dependency(3, 10);
        assert_eq!(6, ts.len());
        ts.add_dependency(11, 2);
        assert_eq!(7, ts.len());
        ts.add_dependency(11, 9);
        assert_eq!(8, ts.len());
        ts.add_dependency(11, 10);
        assert_eq!(8, ts.len());
        ts.add_dependency(8, 9);
        assert_eq!(8, ts.len());

        check(&[3, 5, 7], &mut ts);
        check(&[8, 11], &mut ts);
        check(&[2, 9, 10], &mut ts);
        check(&[], &mut ts);
    }

    #[test]
    fn cyclic_deadlock() {
        let mut ts = TopologicalSort::new();
        ts.add_dependency("stone", "sharp");

        ts.add_dependency("bucket", "hole");
        ts.add_dependency("hole", "straw");
        ts.add_dependency("straw", "axe");
        ts.add_dependency("axe", "sharp");
        ts.add_dependency("sharp", "water");
        ts.add_dependency("water", "bucket");
        assert_eq!(ts.pop(), Some("stone"));
        assert!(ts.pop().is_none());
        println!("{:?}", ts);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2019 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

//! A client for Redis using Tokio and Futures.
//!
//! Three interfaces are provided: one low-level, that makes no assumptions about how Redis is used; a high-level client,
//! suitable for the vast majority of use-cases; a PUBSUB client specifically for Redis's PUBSUB functionality.
//!
//! ## Low-level
//!
//! [`client::connect`](client/connect/fn.connect.html) returns a pair of `Sink` and `Stream` (see [futures](https://github.com/alexcrichton/futures-rs)) which
//! both transport [`resp::RespValue`](resp/enum.RespValue.html)s between client and Redis, these work independently of one another
//! to allow pipelining.  It is the responsibility of the caller to match responses to requests.  It is also the
//! responsibility of the client to convert application data into instances of [`resp::RespValue`](resp/enum.RespValue.html) and
//! back (there are conversion traits available for common examples).
//!
//! This is a very low-level API compared to most Redis clients, but is done so intentionally, for two reasons: 1) it is
//! the common demoniator between a functional Redis client (i.e. is able to support all types of requests, including those
//! that block and have streaming responses), and 2) it results in clean `Sink`s and `Stream`s which will be composable
//! with other Tokio-based libraries.
//!
//! For most practical purposes this low-level interface will not be used, the only exception possibly being the
//! [`MONITOR`](https://redis.io/commands/monitor) command.
//!
//! ## High-level
//!
//! [`client::paired_connect`](client/paired/fn.paired_connect.html) is used for most Redis commands (those for which one command
//! returns one response, it's not suitable for PUBSUB, `MONITOR` or other similar commands).  It allows a Redis command to
//! be sent and a Future returned for each command.
//!
//! Commands will be sent in the order that [`send`](client/paired/struct.PairedConnection.html#method.send) is called, regardless
//! of how the future is realised.  This is to allow us to take advantage of Redis's features by implicitly pipelining
//! commands where appropriate.  One side-effect of this is that for many commands, e.g. `SET` we don't need to realise the
//! future at all, it can be assumed to be fire-and-forget; but, the final future of the final command does need to be
//! realised (at least) to ensure that the correct behaviour is observed.
//!
//! ## PUBSUB
//!
//! PUBSUB in Redis works differently.  A connection will subscribe to one or more topics, then receive all messages that
//! are published to that topic.  As such the single-request/single-response model of
//! [`paired_connect`](client/paired/fn.paired_connect.html) will not work.  A specific
//! [`client::pubsub_connect`](client/pubsub/fn.pubsub_connect.html) is provided for this purpose.
//!
//! It returns a future which resolves to a [`PubsubConnection`](client/pubsub/struct.PubsubConnection.html), this provides a
//! [`subscribe`](client/pubsub/struct.PubsubConnection.html#method.subscribe) function that takes a topic as a parameter and
//! returns a future which, once the subscription is confirmed, resolves to a stream that contains all messages published
//! to that topic.
extern crate bytes;

#[macro_use]
pub mod resp;

#[macro_use]
pub mod client;

pub mod error;

pub mod reconnect;
<commit_msg>Remove stray statement<commit_after>/*
 * Copyright 2017-2019 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

//! A client for Redis using Tokio and Futures.
//!
//! Three interfaces are provided: one low-level, that makes no assumptions about how Redis is used; a high-level client,
//! suitable for the vast majority of use-cases; a PUBSUB client specifically for Redis's PUBSUB functionality.
//!
//! ## Low-level
//!
//! [`client::connect`](client/connect/fn.connect.html) returns a pair of `Sink` and `Stream` (see [futures](https://github.com/alexcrichton/futures-rs)) which
//! both transport [`resp::RespValue`](resp/enum.RespValue.html)s between client and Redis, these work independently of one another
//! to allow pipelining.  It is the responsibility of the caller to match responses to requests.  It is also the
//! responsibility of the client to convert application data into instances of [`resp::RespValue`](resp/enum.RespValue.html) and
//! back (there are conversion traits available for common examples).
//!
//! This is a very low-level API compared to most Redis clients, but is done so intentionally, for two reasons: 1) it is
//! the common demoniator between a functional Redis client (i.e. is able to support all types of requests, including those
//! that block and have streaming responses), and 2) it results in clean `Sink`s and `Stream`s which will be composable
//! with other Tokio-based libraries.
//!
//! For most practical purposes this low-level interface will not be used, the only exception possibly being the
//! [`MONITOR`](https://redis.io/commands/monitor) command.
//!
//! ## High-level
//!
//! [`client::paired_connect`](client/paired/fn.paired_connect.html) is used for most Redis commands (those for which one command
//! returns one response, it's not suitable for PUBSUB, `MONITOR` or other similar commands).  It allows a Redis command to
//! be sent and a Future returned for each command.
//!
//! Commands will be sent in the order that [`send`](client/paired/struct.PairedConnection.html#method.send) is called, regardless
//! of how the future is realised.  This is to allow us to take advantage of Redis's features by implicitly pipelining
//! commands where appropriate.  One side-effect of this is that for many commands, e.g. `SET` we don't need to realise the
//! future at all, it can be assumed to be fire-and-forget; but, the final future of the final command does need to be
//! realised (at least) to ensure that the correct behaviour is observed.
//!
//! ## PUBSUB
//!
//! PUBSUB in Redis works differently.  A connection will subscribe to one or more topics, then receive all messages that
//! are published to that topic.  As such the single-request/single-response model of
//! [`paired_connect`](client/paired/fn.paired_connect.html) will not work.  A specific
//! [`client::pubsub_connect`](client/pubsub/fn.pubsub_connect.html) is provided for this purpose.
//!
//! It returns a future which resolves to a [`PubsubConnection`](client/pubsub/struct.PubsubConnection.html), this provides a
//! [`subscribe`](client/pubsub/struct.PubsubConnection.html#method.subscribe) function that takes a topic as a parameter and
//! returns a future which, once the subscription is confirmed, resolves to a stream that contains all messages published
//! to that topic.
#[macro_use]
pub mod resp;

#[macro_use]
pub mod client;

pub mod error;

pub mod reconnect;
<|endoftext|>


<commit_before>// Copyright 2015 The Ramp 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.

#![crate_type="lib"]
#![crate_name="ramp"]

#![allow(dead_code)] // Work in progress

#![feature(core, asm, alloc, associated_consts)]
#![feature(zero_one, step_trait, unique)]

#![cfg_attr(test, feature(test))]

#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;

pub mod ll;
mod mem;

pub mod int;

// Re-exports

pub use int::Int;
<commit_msg>Fix features for nightly<commit_after>// Copyright 2015 The Ramp 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.

#![crate_type="lib"]
#![crate_name="ramp"]

#![allow(dead_code)] // Work in progress

#![feature(core_intrinsics, asm, heap_api, associated_consts)]
#![feature(zero_one, step_trait, unique)]

#![cfg_attr(test, feature(test))]

#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;

pub mod ll;
mod mem;

pub mod int;

// Re-exports

pub use int::Int;
<|endoftext|>


<commit_before>extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate oauthcli;
extern crate serde_json;
extern crate url;

mod util;

use futures::{Async, Future, Poll, Stream};
use hyper::client::Client;
use hyper::status::StatusCode;
use util::{Lines, Timeout};
use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, BufReader};
use std::time::{Duration, Instant};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Token<'a>(pub &'a str, pub &'a str);

pub struct TwitterUserStreamBuilder<'a> {
    consumer: Token<'a>,
    token: Token<'a>,
    client: Option<&'a Client>,
    end_point: Option<&'a str>,
    timeout: Duration,
    user_agent: Option<&'a str>,
}

pub struct TwitterUserStream {
    lines: Lines,
    timeout: Duration,
    timer: Timeout,
}

pub enum Error {
    Url(url::ParseError),
    Hyper(hyper::Error),
    Http(StatusCode),
    Io(io::Error),
    TimedOut,
}

pub type Result<T> = std::result::Result<T, Error>;

impl<'a> TwitterUserStreamBuilder<'a> {
    pub fn new(consumer: Token<'a>, token: Token<'a>) -> Self {
        TwitterUserStreamBuilder {
            consumer: consumer,
            token: token,
            client: None,
            end_point: None,
            timeout: Duration::from_secs(95),
            user_agent: None,
        }
    }

    pub fn client(&mut self, client: Option<&'a Client>) -> &mut Self {
        self.client = client;
        self
    }

    pub fn end_point(&mut self, url: Option<&'a str>) -> &mut Self {
        self.end_point = url;
        self
    }

    pub fn timeout(&mut self, timeout: Duration) -> &mut Self {
        self.timeout = timeout;
        self
    }

    pub fn user_agent(&mut self, user_agent: Option<&'a str>) -> &mut Self {
        self.user_agent = user_agent;
        self
    }

    pub fn login(&self) -> Result<TwitterUserStream> {
        use hyper::header::{Headers, Authorization, UserAgent};
        use hyper::status::StatusCode;
        use oauthcli::{OAuthAuthorizationHeaderBuilder, SignatureMethod};
        use url::Url;

        let end_point = self.end_point.unwrap_or("https://userstream.twitter.com/1.1/user.json?with=user");
        let url = Url::parse(end_point)?;

        let auth = OAuthAuthorizationHeaderBuilder::new(
            "GET", &url, self.consumer.0, self.consumer.1, SignatureMethod::HmacSha1)
            .token(self.token.0, self.token.1)
            .finish_for_twitter();

        let mut headers = Headers::new();
        headers.set(Authorization(auth));
        if let Some(ua) = self.user_agent {
            headers.set(UserAgent(ua.to_owned()));
        }

        let res = if let Some(client) = self.client {
            client
                .get(url)
                .headers(headers)
                .send()?
        } else {
            Client::new()
                .get(url)
                .headers(headers)
                .send()?
        };

        match &res.status {
            &StatusCode::Ok => (),
            _ => return Err(res.status.into()),
        }

        Ok(TwitterUserStream {
            lines: util::lines(BufReader::new(res)),
            timeout: self.timeout,
            timer: Timeout::after(self.timeout),
        })
    }
}

impl TwitterUserStream {
    pub fn login<'a>(consumer: Token<'a>, token: Token<'a>) -> Result<Self> {
        TwitterUserStreamBuilder::new(consumer, token).login()
    }
}

impl Stream for TwitterUserStream {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        use Async::*;

        trace!("TwitterUserStream::poll");

        loop {
            match self.lines.poll()? {
                Ready(line_opt) => {
                    match line_opt {
                        Some(line) => {
                            let now = Instant::now();
                            let mut timer = Timeout::after(self.timeout);
                            timer.park(now);
                            info!("duration since last message: {}", {
                                let elapsed = timer.when() - self.timer.when(); // = (now + timeout) - (last + timeout)
                                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000f64
                            });
                            self.timer = timer;
                            if line.is_empty() {
                                info!("blank line");
                            } else {
                                return Ok(Ready(Some(line)));
                            }
                        },
                        None => return Ok(None.into()),
                    }
                },
                NotReady => {
                    if let Ok(Ready(())) = self.timer.poll() {
                        return Err(Error::TimedOut);
                    } else {
                        debug!("polled before being ready");
                        return Ok(NotReady);
                    }
                },
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Url(ref e) => e.description(),
            &Error::Hyper(ref e) => e.description(),
            &Error::Http(ref status) => status.canonical_reason().unwrap_or("unknown HTTP error"),
            &Error::Io(ref e) => e.description(),
            &Error::TimedOut => "the connection has timed out",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self {
            &Error::Url(ref e) => e.cause(),
            &Error::Hyper(ref e) => e.cause(),
            &Error::Http(_) => None,
            &Error::Io(ref e) => e.cause(),
            &Error::TimedOut => None,
        }
    }
}

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

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

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Url(e)
    }
}

impl From<hyper::Error> for Error {
    fn from(e: hyper::Error) -> Self {
        Error::Hyper(e)
    }
}

impl From<StatusCode> for Error {
    fn from(e: StatusCode) -> Self {
        Error::Http(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<commit_msg>Changed default timeout value<commit_after>extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate oauthcli;
extern crate serde_json;
extern crate url;

mod messages;
mod util;

use futures::{Async, Future, Poll, Stream};
use hyper::client::Client;
use hyper::status::StatusCode;
use util::{Lines, Timeout};
use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, BufReader};
use std::time::{Duration, Instant};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Token<'a>(pub &'a str, pub &'a str);

pub struct TwitterUserStreamBuilder<'a> {
    consumer: Token<'a>,
    token: Token<'a>,
    client: Option<&'a Client>,
    end_point: Option<&'a str>,
    timeout: Duration,
    user_agent: Option<&'a str>,
}

pub struct TwitterUserStream {
    lines: Lines,
    timeout: Duration,
    timer: Timeout,
}

pub enum Error {
    Url(url::ParseError),
    Hyper(hyper::Error),
    Http(StatusCode),
    Io(io::Error),
    TimedOut,
}

pub type Result<T> = std::result::Result<T, Error>;

impl<'a> TwitterUserStreamBuilder<'a> {
    pub fn new(consumer: Token<'a>, token: Token<'a>) -> Self {
        TwitterUserStreamBuilder {
            consumer: consumer,
            token: token,
            client: None,
            end_point: None,
            timeout: Duration::from_secs(90),
            user_agent: None,
        }
    }

    pub fn client(&mut self, client: Option<&'a Client>) -> &mut Self {
        self.client = client;
        self
    }

    pub fn end_point(&mut self, url: Option<&'a str>) -> &mut Self {
        self.end_point = url;
        self
    }

    pub fn timeout(&mut self, timeout: Duration) -> &mut Self {
        self.timeout = timeout;
        self
    }

    pub fn user_agent(&mut self, user_agent: Option<&'a str>) -> &mut Self {
        self.user_agent = user_agent;
        self
    }

    pub fn login(&self) -> Result<TwitterUserStream> {
        use hyper::header::{Headers, Authorization, UserAgent};
        use hyper::status::StatusCode;
        use oauthcli::{OAuthAuthorizationHeaderBuilder, SignatureMethod};
        use url::Url;

        let end_point = self.end_point.unwrap_or("https://userstream.twitter.com/1.1/user.json?with=user");
        let url = Url::parse(end_point)?;

        let auth = OAuthAuthorizationHeaderBuilder::new(
            "GET", &url, self.consumer.0, self.consumer.1, SignatureMethod::HmacSha1)
            .token(self.token.0, self.token.1)
            .finish_for_twitter();

        let mut headers = Headers::new();
        headers.set(Authorization(auth));
        if let Some(ua) = self.user_agent {
            headers.set(UserAgent(ua.to_owned()));
        }

        let res = if let Some(client) = self.client {
            client
                .get(url)
                .headers(headers)
                .send()?
        } else {
            Client::new()
                .get(url)
                .headers(headers)
                .send()?
        };

        match &res.status {
            &StatusCode::Ok => (),
            _ => return Err(res.status.into()),
        }

        Ok(TwitterUserStream {
            lines: util::lines(BufReader::new(res)),
            timeout: self.timeout,
            timer: Timeout::after(self.timeout),
        })
    }
}

impl TwitterUserStream {
    pub fn login<'a>(consumer: Token<'a>, token: Token<'a>) -> Result<Self> {
        TwitterUserStreamBuilder::new(consumer, token).login()
    }
}

impl Stream for TwitterUserStream {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        use Async::*;

        trace!("TwitterUserStream::poll");

        loop {
            match self.lines.poll()? {
                Ready(line_opt) => {
                    match line_opt {
                        Some(line) => {
                            let now = Instant::now();
                            let mut timer = Timeout::after(self.timeout);
                            timer.park(now);
                            info!("duration since last message: {}", {
                                let elapsed = timer.when() - self.timer.when(); // = (now + timeout) - (last + timeout)
                                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000f64
                            });
                            self.timer = timer;
                            if line.is_empty() {
                                info!("blank line");
                            } else {
                                return Ok(Ready(Some(line)));
                            }
                        },
                        None => return Ok(None.into()),
                    }
                },
                NotReady => {
                    if let Ok(Ready(())) = self.timer.poll() {
                        return Err(Error::TimedOut);
                    } else {
                        debug!("polled before being ready");
                        return Ok(NotReady);
                    }
                },
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Url(ref e) => e.description(),
            &Error::Hyper(ref e) => e.description(),
            &Error::Http(ref status) => status.canonical_reason().unwrap_or("unknown HTTP error"),
            &Error::Io(ref e) => e.description(),
            &Error::TimedOut => "the connection has timed out",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self {
            &Error::Url(ref e) => e.cause(),
            &Error::Hyper(ref e) => e.cause(),
            &Error::Http(_) => None,
            &Error::Io(ref e) => e.cause(),
            &Error::TimedOut => None,
        }
    }
}

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

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

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Url(e)
    }
}

impl From<hyper::Error> for Error {
    fn from(e: hyper::Error) -> Self {
        Error::Hyper(e)
    }
}

impl From<StatusCode> for Error {
    fn from(e: StatusCode) -> Self {
        Error::Http(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<|endoftext|>


<commit_before>#![crate_name = "raft"]
#![crate_type="lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/Hoverbear/raft/master/raft.png")]
#![doc(html_root_url = "https://hoverbear.github.io/raft/raft/")]

//! This is the Raft Distributed Consensus Protocol implemented for Rust.
//! [Raft](http://raftconsensus.github.io/) is described as:
//!
//! > Raft is a consensus algorithm that is designed to be easy to understand. It's equivalent to
//! > Paxos in fault-tolerance and performance. The difference is that it's decomposed into
//! > relatively independent subproblems, and it cleanly addresses all major pieces needed for
//! > practical systems.
//!
//! This implementation utilizes [Cap'n Proto](https://kentonv.github.io/capnproto/) for its RPC,
//! [`mio`](https://github.com/carllerche/mio) for it's async event loop.
//!
//! If this package fails to build for you it is possibly because you do not have the
//! [`capnp`](https://capnproto.org/capnp-tool.html) utility installed. You should be able to find
//! appropriate packages for most popular distributions.
//!
//! # Consuming this library
//!
//! Consuming this library works in a few parts:
//!
//! 1. Implement or consume a Persistent Log and a State Machine such that they will hook into
//!    your application desirably.
//! 2. Create a `Server` with those implementations. It will independently fire up and join the
//!    cluster.
//! 3. Interact with the cluster by issuing `.propose()` and `.query()` calls via the `Client`
//! 4. React to calls to `.propose()` and `.query()` from the implemented `StateMachine`
//!
//! ## Peristent Log
//!
//! A `Log` represents the **replicated, persistent log** of your application. It has a
//! strong ordering such that `A → B → C` and should **only** act to store information. Entries
//! placed into the log should not be acted on in any way by the consuming application as they
//! have not been committed to the cluster.
//!
//! Some ideas for a Persistent Log implementation:
//!
//!   * A PostgreSQL / SQLite instance.
//!   * A plain old file.
//!   * A vector in memory *(Note: Log compaction is still pending, so be aware of running out!)*
//!
//! > It is our belief that in many cases the implementation of `Log` will be generic to
//! > application purposes. You are encouraged to submit your own implementations to us!
//!
//! ## State Machine
//!
//! The `StateMachine` represents the **stateful representation** of your application. Events
//! are applied to the `StateMachine` in the correct ordering at the time of commit. This is where
//! your application **should** act on information.
//!
//! In the `StateMachine` there are both mutable (`.apply()`) and immutable (`.query()`) calls.
//! There is a considerable performance difference, as `.query()` calls do not pass through the
//! durablable `Log` while `.apply()` events do.
//!
//! Some ideas for a State Machine implementation:
//!
//!   * A Hashmap or key-value store (Example provided)
//!   * A single register (Example provided)
//!   * Basically anything from `std::collections`
//!
//! ## Client Requests
//!
//! Client requests are the **only** way to interact with the Raft cluster. Calls to `.propose()`
//! and `.query()` are automatically routed to the relevant `Leader` node and behave as blocking
//! calls.
//!
//! This means `.propose()` won't return until the entry is durably replicated into the log of at
//! least the majority of the cluster and has been commited. `.query()` will perform better if
//! you wish to only read data and not have it pass through the persisted log.
//!

#![feature(socket_timeout)]

extern crate bufstream;
extern crate capnp;
extern crate mio;
extern crate rand;
extern crate uuid;
#[macro_use] extern crate log;
#[macro_use] extern crate scoped_log;
#[macro_use] extern crate wrapped_enum;
#[cfg(test)] extern crate env_logger;
#[cfg(feature = "serde")] extern crate serde;

/// Prepares the environment testing. Should be called as the first line of every test with the
/// name of the test as the only argument.
///
/// TODO: Make this an annotation like #[rust_test] instead of a macro.
#[cfg(test)]
macro_rules! setup_test {
    ($test_name:expr) => (
        let _ = env_logger::init();
        push_log_scope!($test_name);
    );
}

pub mod state_machine;
pub mod persistent_log;
pub mod messages_capnp {
    #![allow(dead_code)]
    include!(concat!(env!("OUT_DIR"), "/messages_capnp.rs"));
}

mod backoff;
mod client;
mod connection;
mod messages;
mod consensus;
mod server;
mod state;

pub use server::Server;
pub use state_machine::StateMachine;
pub use persistent_log::Log;
pub use client::Client;

use std::{io, net, ops, fmt};

use uuid::Uuid;

/// A simple convienence type.
pub type Result<T> = std::result::Result<T, Error>;

wrapped_enum!{
    #[doc = "The generic `raft::Error` is composed of one of the errors that can originate from the"]
    #[doc = "various libraries consumed by the library."]
    #[doc = "With the exception of the `Raft` variant these are generated from `try!()` macros invoking"]
    #[doc = "on `io::Error` or `capnp::Error` by using"]
    #[doc = "[`FromError`](https://doc.rust-lang.org/std/error/#the-fromerror-trait)."]
    #[derive(Debug)]
    pub enum Error {
        /// An error originating from the [Cap'n Proto](https://github.com/dwrensha/capnproto-rust) library.
        CapnProto(capnp::Error),
        /// A specific error produced when a bad Cap'n proto message is discovered.
        SchemaError(capnp::NotInSchema),
        /// Errors originating from `std::io`.
        Io(io::Error),
        /// Raft specific errors.
        Raft(RaftError),
        /// Errors related to parsing addresses.
        AddrParse(net::AddrParseError),
    }
}

/// A Raft Error represents a Raft specific error that consuming code is expected to handle
/// gracefully.
#[derive(Debug)]
pub enum RaftError {
    /// The server ran out of slots in the slab for new connections
    ConnectionLimitReached,
    /// A client reported an invalid client id
    InvalidClientId,
    /// A consensus module reported back a leader not in the cluster.
    ClusterViolation,
    /// A remote connection attempted to use an unknown connection type in the connection preamble
    UnknownConnectionType,
    /// An invalid peer in in the peer set. Returned Server::new().
    InvalidPeerSet,
    /// Registering a connection failed
    ConnectionRegisterFailed,
    /// Failed to find a leader in the cluster. Try again later.
    LeaderSearchExhausted,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::CapnProto(ref error) => fmt::Display::fmt(error, f),
            Error::SchemaError(ref error) => fmt::Display::fmt(error, f),
            Error::Io(ref error) => fmt::Display::fmt(error, f),
            Error::Raft(ref error) => fmt::Debug::fmt(error, f),
            Error::AddrParse(ref error) => fmt::Debug::fmt(error, f),
        }
    }
}

/// The term of a log entry.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Term(u64);
impl Term {
    pub fn as_u64(self) -> u64 {
        self.0
    }
}
impl From<u64> for Term {
    fn from(val: u64) -> Term {
        Term(val)
    }
}
impl Into<u64> for Term {
    fn into(self) -> u64 {
        self.0
    }
}
impl ops::Add<u64> for Term {
    type Output = Term;
    fn add(self, rhs: u64) -> Term {
        Term(self.0.checked_add(rhs).expect("overflow while incrementing Term"))
    }
}
impl ops::Sub<u64> for Term {
    type Output = Term;
    fn sub(self, rhs: u64) -> Term {
        Term(self.0.checked_sub(rhs).expect("underflow while decrementing Term"))
    }
}
impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

/// The index of a log entry.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct LogIndex(u64);
impl LogIndex {
    pub fn as_u64(self) -> u64 {
        self.0
    }
}
impl From<u64> for LogIndex {
    fn from(val: u64) -> LogIndex {
        LogIndex(val)
    }
}
impl Into<u64> for LogIndex {
    fn into(self) -> u64 {
        self.0
    }
}
impl ops::Add<u64> for LogIndex {
    type Output = LogIndex;
    fn add(self, rhs: u64) -> LogIndex {
        LogIndex(self.0.checked_add(rhs).expect("overflow while incrementing LogIndex"))
    }
}
impl ops::Sub<u64> for LogIndex {
    type Output = LogIndex;
    fn sub(self, rhs: u64) -> LogIndex {
        LogIndex(self.0.checked_sub(rhs).expect("underflow while decrementing LogIndex"))
    }
}
/// Find the offset between two log indices.
impl ops::Sub for LogIndex {
    type Output=u64;
    fn sub(self, rhs: LogIndex) -> u64 {
        self.0.checked_sub(rhs.0).expect("underflow while subtracting LogIndex")
    }
}
impl fmt::Display for LogIndex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

/// The ID of a Raft server. Must be unique among the participants in a
/// consensus group.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ServerId(u64);
impl ServerId {
    fn as_u64(self) -> u64 {
        self.0
    }
}
impl From<u64> for ServerId {
    fn from(val: u64) -> ServerId {
        ServerId(val)
    }
}
impl Into<u64> for ServerId {
    fn into(self) -> u64 {
        self.0
    }
}
impl fmt::Debug for ServerId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ServerId({})", self.0)
    }
}
impl fmt::Display for ServerId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

/// The ID of a Raft client.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ClientId(Uuid);
impl ClientId {
    fn new() -> ClientId {
        ClientId(Uuid::new_v4())
    }
    fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
    fn from_bytes(bytes: &[u8]) -> Result<ClientId> {
        match Uuid::from_bytes(bytes) {
            Some(uuid) => Ok(ClientId(uuid)),
            None => Err(Error::Raft(RaftError::InvalidClientId)),
        }
    }
}
impl fmt::Debug for ClientId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ClientId({})", self.0)
    }
}
impl fmt::Display for ClientId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}
<commit_msg>Fix a couple spelling errors in the root doc-comment<commit_after>#![crate_name = "raft"]
#![crate_type="lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/Hoverbear/raft/master/raft.png")]
#![doc(html_root_url = "https://hoverbear.github.io/raft/raft/")]

//! This is the Raft Distributed Consensus Protocol implemented for Rust.
//! [Raft](http://raftconsensus.github.io/) is described as:
//!
//! > Raft is a consensus algorithm that is designed to be easy to understand. It's equivalent to
//! > Paxos in fault-tolerance and performance. The difference is that it's decomposed into
//! > relatively independent subproblems, and it cleanly addresses all major pieces needed for
//! > practical systems.
//!
//! This implementation utilizes [Cap'n Proto](https://kentonv.github.io/capnproto/) for its RPC,
//! [`mio`](https://github.com/carllerche/mio) for it's async event loop.
//!
//! If this package fails to build for you it is possibly because you do not have the
//! [`capnp`](https://capnproto.org/capnp-tool.html) utility installed. You should be able to find
//! appropriate packages for most popular distributions.
//!
//! # Consuming this library
//!
//! Consuming this library works in a few parts:
//!
//! 1. Implement or consume a Persistent Log and a State Machine such that they will hook into
//!    your application desirably.
//! 2. Create a `Server` with those implementations. It will independently fire up and join the
//!    cluster.
//! 3. Interact with the cluster by issuing `.propose()` and `.query()` calls via the `Client`
//! 4. React to calls to `.propose()` and `.query()` from the implemented `StateMachine`
//!
//! ## Persistent Log
//!
//! A `Log` represents the **replicated, persistent log** of your application. It has a
//! strong ordering such that `A → B → C` and should **only** act to store information. Entries
//! placed into the log should not be acted on in any way by the consuming application as they
//! have not been committed to the cluster.
//!
//! Some ideas for a Persistent Log implementation:
//!
//!   * A PostgreSQL / SQLite instance.
//!   * A plain old file.
//!   * A vector in memory *(Note: Log compaction is still pending, so be aware of running out!)*
//!
//! > It is our belief that in many cases the implementation of `Log` will be generic to
//! > application purposes. You are encouraged to submit your own implementations to us!
//!
//! ## State Machine
//!
//! The `StateMachine` represents the **stateful representation** of your application. Events
//! are applied to the `StateMachine` in the correct ordering at the time of commit. This is where
//! your application **should** act on information.
//!
//! In the `StateMachine` there are both mutable (`.apply()`) and immutable (`.query()`) calls.
//! There is a considerable performance difference, as `.query()` calls do not pass through the
//! durable `Log` while `.apply()` events do.
//!
//! Some ideas for a State Machine implementation:
//!
//!   * A Hashmap or key-value store (Example provided)
//!   * A single register (Example provided)
//!   * Basically anything from `std::collections`
//!
//! ## Client Requests
//!
//! Client requests are the **only** way to interact with the Raft cluster. Calls to `.propose()`
//! and `.query()` are automatically routed to the relevant `Leader` node and behave as blocking
//! calls.
//!
//! This means `.propose()` won't return until the entry is durably replicated into the log of at
//! least the majority of the cluster and has been commited. `.query()` will perform better if
//! you wish to only read data and not have it pass through the persisted log.
//!

#![feature(socket_timeout)]

extern crate bufstream;
extern crate capnp;
extern crate mio;
extern crate rand;
extern crate uuid;
#[macro_use] extern crate log;
#[macro_use] extern crate scoped_log;
#[macro_use] extern crate wrapped_enum;
#[cfg(test)] extern crate env_logger;
#[cfg(feature = "serde")] extern crate serde;

/// Prepares the environment testing. Should be called as the first line of every test with the
/// name of the test as the only argument.
///
/// TODO: Make this an annotation like #[rust_test] instead of a macro.
#[cfg(test)]
macro_rules! setup_test {
    ($test_name:expr) => (
        let _ = env_logger::init();
        push_log_scope!($test_name);
    );
}

pub mod state_machine;
pub mod persistent_log;
pub mod messages_capnp {
    #![allow(dead_code)]
    include!(concat!(env!("OUT_DIR"), "/messages_capnp.rs"));
}

mod backoff;
mod client;
mod connection;
mod messages;
mod consensus;
mod server;
mod state;

pub use server::Server;
pub use state_machine::StateMachine;
pub use persistent_log::Log;
pub use client::Client;

use std::{io, net, ops, fmt};

use uuid::Uuid;

/// A simple convienence type.
pub type Result<T> = std::result::Result<T, Error>;

wrapped_enum!{
    #[doc = "The generic `raft::Error` is composed of one of the errors that can originate from the"]
    #[doc = "various libraries consumed by the library."]
    #[doc = "With the exception of the `Raft` variant these are generated from `try!()` macros invoking"]
    #[doc = "on `io::Error` or `capnp::Error` by using"]
    #[doc = "[`FromError`](https://doc.rust-lang.org/std/error/#the-fromerror-trait)."]
    #[derive(Debug)]
    pub enum Error {
        /// An error originating from the [Cap'n Proto](https://github.com/dwrensha/capnproto-rust) library.
        CapnProto(capnp::Error),
        /// A specific error produced when a bad Cap'n proto message is discovered.
        SchemaError(capnp::NotInSchema),
        /// Errors originating from `std::io`.
        Io(io::Error),
        /// Raft specific errors.
        Raft(RaftError),
        /// Errors related to parsing addresses.
        AddrParse(net::AddrParseError),
    }
}

/// A Raft Error represents a Raft specific error that consuming code is expected to handle
/// gracefully.
#[derive(Debug)]
pub enum RaftError {
    /// The server ran out of slots in the slab for new connections
    ConnectionLimitReached,
    /// A client reported an invalid client id
    InvalidClientId,
    /// A consensus module reported back a leader not in the cluster.
    ClusterViolation,
    /// A remote connection attempted to use an unknown connection type in the connection preamble
    UnknownConnectionType,
    /// An invalid peer in in the peer set. Returned Server::new().
    InvalidPeerSet,
    /// Registering a connection failed
    ConnectionRegisterFailed,
    /// Failed to find a leader in the cluster. Try again later.
    LeaderSearchExhausted,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::CapnProto(ref error) => fmt::Display::fmt(error, f),
            Error::SchemaError(ref error) => fmt::Display::fmt(error, f),
            Error::Io(ref error) => fmt::Display::fmt(error, f),
            Error::Raft(ref error) => fmt::Debug::fmt(error, f),
            Error::AddrParse(ref error) => fmt::Debug::fmt(error, f),
        }
    }
}

/// The term of a log entry.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Term(u64);
impl Term {
    pub fn as_u64(self) -> u64 {
        self.0
    }
}
impl From<u64> for Term {
    fn from(val: u64) -> Term {
        Term(val)
    }
}
impl Into<u64> for Term {
    fn into(self) -> u64 {
        self.0
    }
}
impl ops::Add<u64> for Term {
    type Output = Term;
    fn add(self, rhs: u64) -> Term {
        Term(self.0.checked_add(rhs).expect("overflow while incrementing Term"))
    }
}
impl ops::Sub<u64> for Term {
    type Output = Term;
    fn sub(self, rhs: u64) -> Term {
        Term(self.0.checked_sub(rhs).expect("underflow while decrementing Term"))
    }
}
impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

/// The index of a log entry.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct LogIndex(u64);
impl LogIndex {
    pub fn as_u64(self) -> u64 {
        self.0
    }
}
impl From<u64> for LogIndex {
    fn from(val: u64) -> LogIndex {
        LogIndex(val)
    }
}
impl Into<u64> for LogIndex {
    fn into(self) -> u64 {
        self.0
    }
}
impl ops::Add<u64> for LogIndex {
    type Output = LogIndex;
    fn add(self, rhs: u64) -> LogIndex {
        LogIndex(self.0.checked_add(rhs).expect("overflow while incrementing LogIndex"))
    }
}
impl ops::Sub<u64> for LogIndex {
    type Output = LogIndex;
    fn sub(self, rhs: u64) -> LogIndex {
        LogIndex(self.0.checked_sub(rhs).expect("underflow while decrementing LogIndex"))
    }
}
/// Find the offset between two log indices.
impl ops::Sub for LogIndex {
    type Output=u64;
    fn sub(self, rhs: LogIndex) -> u64 {
        self.0.checked_sub(rhs.0).expect("underflow while subtracting LogIndex")
    }
}
impl fmt::Display for LogIndex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

/// The ID of a Raft server. Must be unique among the participants in a
/// consensus group.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ServerId(u64);
impl ServerId {
    fn as_u64(self) -> u64 {
        self.0
    }
}
impl From<u64> for ServerId {
    fn from(val: u64) -> ServerId {
        ServerId(val)
    }
}
impl Into<u64> for ServerId {
    fn into(self) -> u64 {
        self.0
    }
}
impl fmt::Debug for ServerId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ServerId({})", self.0)
    }
}
impl fmt::Display for ServerId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

/// The ID of a Raft client.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ClientId(Uuid);
impl ClientId {
    fn new() -> ClientId {
        ClientId(Uuid::new_v4())
    }
    fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
    fn from_bytes(bytes: &[u8]) -> Result<ClientId> {
        match Uuid::from_bytes(bytes) {
            Some(uuid) => Ok(ClientId(uuid)),
            None => Err(Error::Raft(RaftError::InvalidClientId)),
        }
    }
}
impl fmt::Debug for ClientId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ClientId({})", self.0)
    }
}
impl fmt::Display for ClientId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2013-2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "glib-2_0-sys"]
#![crate_type = "lib"]

#![allow(missing_copy_implementations)]
#![allow(unstable)]

extern crate libc;

pub mod types;

use types::{gboolean, gchar, gint, gpointer};

#[repr(C)]
pub struct GError {
    pub domain: GQuark,
    pub code: gint,
    pub message: *const gchar
}

#[repr(C)]
pub struct GMainContext;

#[repr(C)]
pub struct GMainLoop;

pub type GQuark = u32;

extern {
    pub fn g_free(mem: gpointer);
    pub fn g_error_copy(error: *const GError) -> *mut GError;
    pub fn g_error_free(error: *mut GError);
    pub fn g_error_new_literal(domain: GQuark, code: gint, message: *const gchar) -> *mut GError;
    pub fn g_main_context_new() -> *mut GMainContext;
    pub fn g_main_context_ref(context: *mut GMainContext) -> *mut GMainContext;
    pub fn g_main_context_unref(context: *mut GMainContext);
    pub fn g_main_context_default() -> *mut GMainContext;
    pub fn g_main_context_push_thread_default(context: *mut GMainContext);
    pub fn g_main_context_pop_thread_default(context: *mut GMainContext);
    pub fn g_main_loop_new(ctx: *mut GMainContext, is_running: gboolean) -> *mut GMainLoop;
    pub fn g_main_loop_ref(l: *mut GMainLoop) -> *mut GMainLoop;
    pub fn g_main_loop_unref(l: *mut GMainLoop);
    pub fn g_main_loop_get_context(l: *mut GMainLoop) -> *mut GMainContext;
    pub fn g_main_loop_run(l: *mut GMainLoop);
    pub fn g_main_loop_quit(l: *mut GMainLoop);
    pub fn g_quark_from_static_string(string: *const gchar) -> GQuark;
    pub fn g_quark_to_string(quark: GQuark) -> *const gchar;
    pub fn g_strdup(str: *const gchar) -> *mut gchar;
}
<commit_msg>Out with #![allow(unstable)], in with #![feature(libc)]<commit_after>// Copyright (C) 2013-2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "glib-2_0-sys"]
#![crate_type = "lib"]

#![allow(missing_copy_implementations)]

#![feature(libc)]

extern crate libc;

pub mod types;

use types::{gboolean, gchar, gint, gpointer};

#[repr(C)]
pub struct GError {
    pub domain: GQuark,
    pub code: gint,
    pub message: *const gchar
}

#[repr(C)]
pub struct GMainContext;

#[repr(C)]
pub struct GMainLoop;

pub type GQuark = u32;

extern {
    pub fn g_free(mem: gpointer);
    pub fn g_error_copy(error: *const GError) -> *mut GError;
    pub fn g_error_free(error: *mut GError);
    pub fn g_error_new_literal(domain: GQuark, code: gint, message: *const gchar) -> *mut GError;
    pub fn g_main_context_new() -> *mut GMainContext;
    pub fn g_main_context_ref(context: *mut GMainContext) -> *mut GMainContext;
    pub fn g_main_context_unref(context: *mut GMainContext);
    pub fn g_main_context_default() -> *mut GMainContext;
    pub fn g_main_context_push_thread_default(context: *mut GMainContext);
    pub fn g_main_context_pop_thread_default(context: *mut GMainContext);
    pub fn g_main_loop_new(ctx: *mut GMainContext, is_running: gboolean) -> *mut GMainLoop;
    pub fn g_main_loop_ref(l: *mut GMainLoop) -> *mut GMainLoop;
    pub fn g_main_loop_unref(l: *mut GMainLoop);
    pub fn g_main_loop_get_context(l: *mut GMainLoop) -> *mut GMainContext;
    pub fn g_main_loop_run(l: *mut GMainLoop);
    pub fn g_main_loop_quit(l: *mut GMainLoop);
    pub fn g_quark_from_static_string(string: *const gchar) -> GQuark;
    pub fn g_quark_to_string(quark: GQuark) -> *const gchar;
    pub fn g_strdup(str: *const gchar) -> *mut gchar;
}
<|endoftext|>