<commit_before>use std;

pub fn bit_length(number: u32) -> u8 {
    32 - number.leading_zeros() as u8
}

pub fn get_bite_mask(mask: u8) -> u32 {
    !std::u32::MAX.checked_shr(mask as u32).unwrap_or(0)
}

pub fn get_bite_mask_u128(mask: u8) -> u128 {
    !std::u128::MAX.checked_shr(mask as u32).unwrap_or(0)
}

pub fn split_ip_netmask(input: &str) -> Option<(&str, &str)> {
    let delimiter = match input.find('/') {
        Some(pos) => pos,
        None => return None,
    };
    let (ip, mask) = input.split_at(delimiter);
    let mask = &mask[1..];

    if ip.is_empty() || mask.is_empty() {
        None
    } else {
        Some((ip, mask))
    }
}

#[cfg(test)]
mod tests {
    use super::{get_bite_mask, split_ip_netmask};
    use std;

    #[test]
    fn get_bite_mask_32() {
        assert_eq!(std::u32::MAX, get_bite_mask(32));
    }

    #[test]
    fn get_bite_mask_0() {
        assert_eq!(0, get_bite_mask(0));
    }

    #[test]
    fn test_split_ip_netmask() {
        let (ip, netmask) = split_ip_netmask("192.168.1.1/24").unwrap();
        assert_eq!("192.168.1.1", ip);
        assert_eq!("24", netmask);
    }

    #[test]
    fn test_split_ip_netmask_invalid_1() {
        let a = split_ip_netmask("ab");
        assert!(a.is_none());
    }

    #[test]
    fn test_split_ip_netmask_invalid_2() {
        let a = split_ip_netmask("/");
        assert!(a.is_none());
    }

    #[test]
    fn test_split_ip_netmask_invalid_3() {
        let a = split_ip_netmask("192.168.1.1/");
        assert!(a.is_none());
    }
}
<commit_msg>Optimised helpers::{get_bite_mask, get_bite_mask_u128} methods<commit_after>use std;

pub fn bit_length(number: u32) -> u8 {
    32 - number.leading_zeros() as u8
}

pub fn get_bite_mask(mask: u8) -> u32 {
    debug_assert!(mask <= 32);
    match mask {
        0 => 0,
        n => (!0 << (32 - n)),
    }
}

pub fn get_bite_mask_u128(mask: u8) -> u128 {
    debug_assert!(mask <= 128);
    match mask {
        0 => 0,
        n => (!0 << (128 - n)),
    }
}

pub fn split_ip_netmask(input: &str) -> Option<(&str, &str)> {
    let delimiter = match input.find('/') {
        Some(pos) => pos,
        None => return None,
    };
    let (ip, mask) = input.split_at(delimiter);
    let mask = &mask[1..];

    if ip.is_empty() || mask.is_empty() {
        None
    } else {
        Some((ip, mask))
    }
}

#[cfg(test)]
mod tests {
    use super::{get_bite_mask, get_bite_mask_u128, split_ip_netmask};
    use std;

    #[test]
    fn get_bite_mask_32() {
        assert_eq!(std::u32::MAX, get_bite_mask(32));
    }

    #[test]
    fn get_bite_mask_0() {
        assert_eq!(0, get_bite_mask(0));
    }

    #[test]
    fn get_bite_mask_u128_0() {
        assert_eq!(0, get_bite_mask_u128(0));
    }

    #[test]
    fn get_bite_mask_u128_128() {
        assert_eq!(std::u128::MAX, get_bite_mask_u128(128));
    }

    #[test]
    fn test_split_ip_netmask() {
        let (ip, netmask) = split_ip_netmask("192.168.1.1/24").unwrap();
        assert_eq!("192.168.1.1", ip);
        assert_eq!("24", netmask);
    }

    #[test]
    fn test_split_ip_netmask_invalid_1() {
        let a = split_ip_netmask("ab");
        assert!(a.is_none());
    }

    #[test]
    fn test_split_ip_netmask_invalid_2() {
        let a = split_ip_netmask("/");
        assert!(a.is_none());
    }

    #[test]
    fn test_split_ip_netmask_invalid_3() {
        let a = split_ip_netmask("192.168.1.1/");
        assert!(a.is_none());
    }
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use super::ast;

pub use super::ast::ScalarType as ScalarType;
pub use super::ast::DataType as DataType;
pub use super::ast::StructuredType as StructuredType;
pub use super::ast::ObjectType as ObjectType;
pub use super::ast::Type as Type;
pub use super::ast::BinOp as BinOp;
pub use super::ast::UnaryOp as UnaryOp;

#[derive(PartialEq, Debug, Clone)]
pub enum Intrinsic {
    Float4(Box<Expression>, Box<Expression>, Box<Expression>, Box<Expression>),

    BufferLoad(Box<Expression>, Box<Expression>),
    StructuredBufferLoad(Box<Expression>, Box<Expression>),
}

#[derive(PartialEq, Debug, Clone)]
pub enum Expression {
    LiteralInt(u64),
    LiteralUint(u64),
    LiteralLong(u64),
    LiteralHalf(f32),
    LiteralFloat(f32),
    LiteralDouble(f64),
    Variable(String),
    UnaryOperation(UnaryOp, Box<Expression>),
    BinaryOperation(BinOp, Box<Expression>, Box<Expression>),
    ArraySubscript(Box<Expression>, Box<Expression>),
    Member(Box<Expression>, String),
    Call(Box<Expression>, Vec<Expression>),
    Cast(Type, Box<Expression>),
    Intrinsic(Intrinsic),
}

#[derive(PartialEq, Debug, Clone)]
pub struct VarDef {
    pub name: String,
    pub typename: Type,
    pub assignment: Option<Expression>,
}

#[derive(PartialEq, Debug, Clone)]
pub enum Condition {
    Expr(Expression),
    Assignment(VarDef),
}

#[derive(PartialEq, Debug, Clone)]
pub enum Statement {
    Expression(Expression),
    Var(VarDef),
    Block(Vec<Statement>),
    If(Condition, Box<Statement>),
    For(Condition, Condition, Condition, Box<Statement>),
    While(Condition, Box<Statement>),
    Return(Expression),
}

pub use super::ast::StructMember as StructMember;
pub use super::ast::StructDefinition as StructDefinition;

pub use super::ast::PackSubOffset as PackSubOffset;
pub use super::ast::PackOffset as PackOffset;
pub use super::ast::ConstantVariable as ConstantVariable;

#[derive(PartialEq, Debug, Clone)]
pub struct ConstantBuffer {
    pub name: String,
    pub members: Vec<ConstantVariable>,
}

#[derive(PartialEq, Debug, Clone)]
pub struct GlobalVariable {
    pub name: String,
    pub typename: Type,
}

pub use super::ast::FunctionAttribute as FunctionAttribute;
pub use super::ast::FunctionParam as FunctionParam;

#[derive(PartialEq, Debug, Clone)]
pub struct FunctionDefinition {
    pub name: String,
    pub returntype: Type,
    pub params: Vec<FunctionParam>,
    pub body: Vec<Statement>,
    pub attributes: Vec<FunctionAttribute>,
}

#[derive(PartialEq, Debug, Clone)]
pub enum RootDefinition {
    Struct(StructDefinition),
    SamplerState,
    ConstantBuffer(ConstantBuffer),
    GlobalVariable(GlobalVariable),
    Function(FunctionDefinition),
}

#[derive(PartialEq, Debug, Clone)]
pub struct GlobalEntry {
    pub name: String,
    pub typename: ast::Type,
}

#[derive(PartialEq, Debug, Clone)]
pub struct GlobalTable {
    pub r_resources: HashMap<u32, GlobalEntry>,
    pub rw_resources: HashMap<u32, GlobalEntry>,
    pub samplers: HashMap<u32, String>,
    pub constants: HashMap<u32, String>,
}

#[derive(PartialEq, Debug, Clone)]
pub struct Module {
    pub entry_point: String,
    pub global_table: GlobalTable,
    pub root_definitions: Vec<RootDefinition>,
}

impl GlobalTable {

    pub fn new() -> GlobalTable {
        GlobalTable {
            r_resources: HashMap::new(),
            rw_resources: HashMap::new(),
            samplers: HashMap::new(),
            constants: HashMap::new(),
        }
    }

    pub fn generate(module: &ast::Module) -> GlobalTable {
        let mut table = GlobalTable::new();
        for root_def in &module.root_definitions {
            match root_def {
                &ast::RootDefinition::ConstantBuffer(ref cbuffer) => {
                    match cbuffer.slot {
                        Some(ref slot_index) => {
                            table.constants.insert(slot_index.0, cbuffer.name.clone());
                        },
                        None => { },
                    }
                },
                &ast::RootDefinition::GlobalVariable(ref global) => {
                    let entry = GlobalEntry { name: global.name.clone(), typename: global.typename.clone() };
                    match global.slot {
                        Some(ast::GlobalSlot::ReadSlot(ref slot_index)) => {
                            table.r_resources.insert(*slot_index, entry);
                        },
                        Some(ast::GlobalSlot::ReadWriteSlot(ref slot_index)) => {
                            table.rw_resources.insert(*slot_index, entry);
                        },
                        None => { },
                    }
                },
                _ => { }
            }
        };
        table
    }
}

<commit_msg>removed unused function<commit_after>
use std::collections::HashMap;
use super::ast;

pub use super::ast::ScalarType as ScalarType;
pub use super::ast::DataType as DataType;
pub use super::ast::StructuredType as StructuredType;
pub use super::ast::ObjectType as ObjectType;
pub use super::ast::Type as Type;
pub use super::ast::BinOp as BinOp;
pub use super::ast::UnaryOp as UnaryOp;

#[derive(PartialEq, Debug, Clone)]
pub enum Intrinsic {
    Float4(Box<Expression>, Box<Expression>, Box<Expression>, Box<Expression>),

    BufferLoad(Box<Expression>, Box<Expression>),
    StructuredBufferLoad(Box<Expression>, Box<Expression>),
}

#[derive(PartialEq, Debug, Clone)]
pub enum Expression {
    LiteralInt(u64),
    LiteralUint(u64),
    LiteralLong(u64),
    LiteralHalf(f32),
    LiteralFloat(f32),
    LiteralDouble(f64),
    Variable(String),
    UnaryOperation(UnaryOp, Box<Expression>),
    BinaryOperation(BinOp, Box<Expression>, Box<Expression>),
    ArraySubscript(Box<Expression>, Box<Expression>),
    Member(Box<Expression>, String),
    Call(Box<Expression>, Vec<Expression>),
    Cast(Type, Box<Expression>),
    Intrinsic(Intrinsic),
}

#[derive(PartialEq, Debug, Clone)]
pub struct VarDef {
    pub name: String,
    pub typename: Type,
    pub assignment: Option<Expression>,
}

#[derive(PartialEq, Debug, Clone)]
pub enum Condition {
    Expr(Expression),
    Assignment(VarDef),
}

#[derive(PartialEq, Debug, Clone)]
pub enum Statement {
    Expression(Expression),
    Var(VarDef),
    Block(Vec<Statement>),
    If(Condition, Box<Statement>),
    For(Condition, Condition, Condition, Box<Statement>),
    While(Condition, Box<Statement>),
    Return(Expression),
}

pub use super::ast::StructMember as StructMember;
pub use super::ast::StructDefinition as StructDefinition;

pub use super::ast::PackSubOffset as PackSubOffset;
pub use super::ast::PackOffset as PackOffset;
pub use super::ast::ConstantVariable as ConstantVariable;

#[derive(PartialEq, Debug, Clone)]
pub struct ConstantBuffer {
    pub name: String,
    pub members: Vec<ConstantVariable>,
}

#[derive(PartialEq, Debug, Clone)]
pub struct GlobalVariable {
    pub name: String,
    pub typename: Type,
}

pub use super::ast::FunctionAttribute as FunctionAttribute;
pub use super::ast::FunctionParam as FunctionParam;

#[derive(PartialEq, Debug, Clone)]
pub struct FunctionDefinition {
    pub name: String,
    pub returntype: Type,
    pub params: Vec<FunctionParam>,
    pub body: Vec<Statement>,
    pub attributes: Vec<FunctionAttribute>,
}

#[derive(PartialEq, Debug, Clone)]
pub enum RootDefinition {
    Struct(StructDefinition),
    SamplerState,
    ConstantBuffer(ConstantBuffer),
    GlobalVariable(GlobalVariable),
    Function(FunctionDefinition),
}

#[derive(PartialEq, Debug, Clone)]
pub struct GlobalEntry {
    pub name: String,
    pub typename: ast::Type,
}

#[derive(PartialEq, Debug, Clone)]
pub struct GlobalTable {
    pub r_resources: HashMap<u32, GlobalEntry>,
    pub rw_resources: HashMap<u32, GlobalEntry>,
    pub samplers: HashMap<u32, String>,
    pub constants: HashMap<u32, String>,
}

#[derive(PartialEq, Debug, Clone)]
pub struct Module {
    pub entry_point: String,
    pub global_table: GlobalTable,
    pub root_definitions: Vec<RootDefinition>,
}

impl GlobalTable {
    pub fn new() -> GlobalTable {
        GlobalTable {
            r_resources: HashMap::new(),
            rw_resources: HashMap::new(),
            samplers: HashMap::new(),
            constants: HashMap::new(),
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::thread;
use std::sync::{Arc, mpsc};
use std::sync::mpsc::Sender;
use std::time::Duration;
use std::process;

use mio::EventLoop;
use rocksdb::DB;

use pd::{INVALID_ID, PdClient, Error as PdError};
use kvproto::raft_serverpb::StoreIdent;
use kvproto::metapb;
use protobuf::RepeatedField;
use util::transport::SendCh;
use raftstore::store::{self, Msg, SnapshotStatusMsg, StoreChannel, Store, Config as StoreConfig,
                       keys, Peekable, Transport, SnapManager};
use super::Result;
use super::config::Config;
use storage::{Storage, RaftKv};
use super::transport::RaftStoreRouter;

const MAX_CHECK_CLUSTER_BOOTSTRAPPED_RETRY_COUNT: u64 = 60;
const CHECK_CLUSTER_BOOTSTRAPPED_RETRY_SECONDS: u64 = 3;

pub fn create_raft_storage<S>(router: S, db: Arc<DB>, cfg: &Config) -> Result<Storage>
    where S: RaftStoreRouter + 'static
{
    let engine = box RaftKv::new(db, router);
    let store = try!(Storage::from_engine(engine, &cfg.storage));
    Ok(store)
}

fn check_region_epoch(region: &metapb::Region, other: &metapb::Region) -> Result<()> {
    let epoch = region.get_region_epoch();
    let other_epoch = other.get_region_epoch();
    if epoch.get_conf_ver() != other_epoch.get_conf_ver() {
        return Err(box_err!("region conf_ver inconsist: {} with {}",
                            epoch.get_conf_ver(),
                            other_epoch.get_conf_ver()));
    }
    if epoch.get_version() != other_epoch.get_version() {
        return Err(box_err!("region version inconsist: {} with {}",
                            epoch.get_version(),
                            other_epoch.get_version()));
    }
    Ok(())
}

// Node is a wrapper for raft store.
// TODO: we will rename another better name like RaftStore later.
pub struct Node<C: PdClient + 'static> {
    cluster_id: u64,
    store: metapb::Store,
    store_cfg: StoreConfig,
    store_handle: Option<thread::JoinHandle<()>>,
    ch: SendCh<Msg>,
    snapshot_status_sender: Option<Sender<SnapshotStatusMsg>>,

    pd_client: Arc<C>,
}

impl<C> Node<C>
    where C: PdClient
{
    pub fn new<T>(event_loop: &mut EventLoop<Store<T, C>>,
                  cfg: &Config,
                  pd_client: Arc<C>)
                  -> Node<C>
        where T: Transport + 'static
    {
        let mut store = metapb::Store::new();
        store.set_id(INVALID_ID);
        if cfg.advertise_addr.is_empty() {
            store.set_address(cfg.addr.clone());
        } else {
            store.set_address(cfg.advertise_addr.clone())
        }

        let mut labels = Vec::new();
        for (k, v) in &cfg.labels {
            let mut label = metapb::StoreLabel::new();
            label.set_key(k.to_owned());
            label.set_value(v.to_owned());
            labels.push(label);
        }
        store.set_labels(RepeatedField::from_vec(labels));

        let ch = SendCh::new(event_loop.channel(), "raftstore");
        Node {
            cluster_id: cfg.cluster_id,
            store: store,
            store_cfg: cfg.raft_store.clone(),
            store_handle: None,
            pd_client: pd_client,
            ch: ch,
            snapshot_status_sender: None,
        }
    }

    pub fn start<T>(&mut self,
                    event_loop: EventLoop<Store<T, C>>,
                    engine: Arc<DB>,
                    trans: T,
                    snap_mgr: SnapManager)
                    -> Result<()>
        where T: Transport + 'static
    {
        let bootstrapped = try!(self.check_cluster_bootstrapped());
        let mut store_id = try!(self.check_store(&engine));
        if store_id == INVALID_ID {
            store_id = try!(self.bootstrap_store(&engine));
        } else if !bootstrapped {
            // We have saved data before, and the cluster must be bootstrapped.
            return Err(box_err!("store {} is not empty, but cluster {} is not bootstrapped, \
                                 maybe you connected a wrong PD or need to remove the TiKV data \
                                 and start again",
                                store_id,
                                self.cluster_id));
        }

        self.store.set_id(store_id);
        try!(self.check_prepare_bootstrap_cluster(&engine));
        if !bootstrapped {
            // cluster is not bootstrapped, and we choose first store to bootstrap
            // prepare bootstrap.
            let region = try!(self.prepare_bootstrap_cluster(&engine, store_id));
            try!(self.bootstrap_cluster(&engine, region));
        }

        // inform pd.
        try!(self.start_store(event_loop, store_id, engine, trans, snap_mgr));
        try!(self.pd_client
            .put_store(self.store.clone()));
        Ok(())
    }

    pub fn id(&self) -> u64 {
        self.store.get_id()
    }

    pub fn get_sendch(&self) -> SendCh<Msg> {
        self.ch.clone()
    }

    pub fn get_snapshot_status_sender(&self) -> Sender<SnapshotStatusMsg> {
        self.snapshot_status_sender.clone().unwrap()
    }

    // check store, return store id for the engine.
    // If the store is not bootstrapped, use INVALID_ID.
    fn check_store(&self, engine: &DB) -> Result<u64> {
        let res = try!(engine.get_msg::<StoreIdent>(&keys::store_ident_key()));
        if res.is_none() {
            return Ok(INVALID_ID);
        }

        let ident = res.unwrap();
        if ident.get_cluster_id() != self.cluster_id {
            error!("cluster ID mismatch: local_id {} remote_id {}",
                   ident.get_cluster_id(),
                   self.cluster_id);
            process::exit(1);
        }

        let store_id = ident.get_store_id();
        if store_id == INVALID_ID {
            return Err(box_err!("invalid store ident {:?}", ident));
        }

        Ok(store_id)
    }

    fn alloc_id(&self) -> Result<u64> {
        let id = try!(self.pd_client.alloc_id());
        Ok(id)
    }

    fn bootstrap_store(&self, engine: &DB) -> Result<u64> {
        let store_id = try!(self.alloc_id());
        info!("alloc store id {} ", store_id);

        try!(store::bootstrap_store(engine, self.cluster_id, store_id));

        Ok(store_id)
    }

    pub fn prepare_bootstrap_cluster(&self, engine: &DB, store_id: u64) -> Result<metapb::Region> {
        let region_id = try!(self.alloc_id());
        info!("alloc first region id {} for cluster {}, store {}",
              region_id,
              self.cluster_id,
              store_id);
        let peer_id = try!(self.alloc_id());
        info!("alloc first peer id {} for first region {}",
              peer_id,
              region_id);

        let region = try!(store::prepare_bootstrap(engine, store_id, region_id, peer_id));
        Ok(region)
    }

    fn check_prepare_bootstrap_cluster(&self, engine: &DB) -> Result<()> {
        let res = try!(engine.get_msg::<metapb::Region>(&keys::prepare_bootstrap_key()));
        if res.is_none() {
            return Ok(());
        }

        let first_region = res.unwrap();
        for _ in 0..MAX_CHECK_CLUSTER_BOOTSTRAPPED_RETRY_COUNT {
            match self.pd_client.get_region(b"") {
                Ok(region) => {
                    if region.get_id() == first_region.get_id() {
                        try!(check_region_epoch(&region, &first_region));
                        try!(store::clear_prepare_bootstrap_state(engine));
                    } else {
                        try!(store::clear_prepare_bootstrap(engine, region.get_id()));
                    }
                    return Ok(());
                }

                Err(e) => {
                    warn!("check cluster prepare bootstrapped failed: {:?}", e);
                }
            }
            thread::sleep(Duration::from_secs(CHECK_CLUSTER_BOOTSTRAPPED_RETRY_SECONDS));
        }
        Err(box_err!("check cluster prepare bootstrapped failed"))
    }

    fn bootstrap_cluster(&mut self, engine: &DB, region: metapb::Region) -> Result<()> {
        let region_id = region.get_id();
        match self.pd_client.bootstrap_cluster(self.store.clone(), region) {
            Err(PdError::ClusterBootstrapped(_)) => {
                error!("cluster {} is already bootstrapped", self.cluster_id);
                try!(store::clear_prepare_bootstrap(engine, region_id));
                Ok(())
            }
            // TODO: should we clean region for other errors too?
            Err(e) => panic!("bootstrap cluster {} err: {:?}", self.cluster_id, e),
            Ok(_) => {
                try!(store::clear_prepare_bootstrap_state(engine));
                info!("bootstrap cluster {} ok", self.cluster_id);
                Ok(())
            }
        }
    }

    fn check_cluster_bootstrapped(&self) -> Result<bool> {
        for _ in 0..MAX_CHECK_CLUSTER_BOOTSTRAPPED_RETRY_COUNT {
            match self.pd_client.is_cluster_bootstrapped() {
                Ok(b) => return Ok(b),
                Err(e) => {
                    warn!("check cluster bootstrapped failed: {:?}", e);
                }
            }
            thread::sleep(Duration::from_secs(CHECK_CLUSTER_BOOTSTRAPPED_RETRY_SECONDS));
        }
        Err(box_err!("check cluster bootstrapped failed"))
    }

    fn start_store<T>(&mut self,
                      mut event_loop: EventLoop<Store<T, C>>,
                      store_id: u64,
                      db: Arc<DB>,
                      trans: T,
                      snap_mgr: SnapManager)
                      -> Result<()>
        where T: Transport + 'static
    {
        info!("start raft store {} thread", store_id);

        if self.store_handle.is_some() {
            return Err(box_err!("{} is already started", store_id));
        }

        let cfg = self.store_cfg.clone();
        let pd_client = self.pd_client.clone();
        let store = self.store.clone();
        let sender = event_loop.channel();

        let (tx, rx) = mpsc::channel();
        let (snapshot_tx, snapshot_rx) = mpsc::channel();
        self.snapshot_status_sender = Some(snapshot_tx);
        let builder = thread::Builder::new().name(thd_name!(format!("raftstore-{}", store_id)));
        let h = try!(builder.spawn(move || {
            let ch = StoreChannel {
                sender: sender,
                snapshot_status_receiver: snapshot_rx,
            };
            let mut store = match Store::new(ch, store, cfg, db, trans, pd_client, snap_mgr) {
                Err(e) => panic!("construct store {} err {:?}", store_id, e),
                Ok(s) => s,
            };
            tx.send(0).unwrap();
            if let Err(e) = store.run(&mut event_loop) {
                error!("store {} run err {:?}", store_id, e);
            };
        }));
        // wait for store to be initialized
        rx.recv().unwrap();

        self.store_handle = Some(h);
        Ok(())
    }

    fn stop_store(&mut self, store_id: u64) -> Result<()> {
        info!("stop raft store {} thread", store_id);
        let h = match self.store_handle.take() {
            None => return Ok(()),
            Some(h) => h,
        };

        box_try!(self.ch.send(Msg::Quit));
        if let Err(e) = h.join() {
            return Err(box_err!("join store {} thread err {:?}", store_id, e));
        }

        Ok(())
    }

    pub fn stop(&mut self) -> Result<()> {
        let store_id = self.store.get_id();
        self.stop_store(store_id)
    }
}

impl<C> Drop for Node<C>
    where C: PdClient
{
    fn drop(&mut self) {
        self.stop().unwrap();
    }
}
#[cfg(test)]
mod tests {
    use raftstore::store::keys;
    use super::check_region_epoch;
    use kvproto::metapb;

    #[test]
    fn test_check_region_epoch() {
        let mut r1 = metapb::Region::new();
        r1.set_id(1);
        r1.set_start_key(keys::EMPTY_KEY.to_vec());
        r1.set_end_key(keys::EMPTY_KEY.to_vec());
        r1.mut_region_epoch().set_version(1);
        r1.mut_region_epoch().set_conf_ver(1);

        let mut r2 = metapb::Region::new();
        r2.set_id(1);
        r2.set_start_key(keys::EMPTY_KEY.to_vec());
        r2.set_end_key(keys::EMPTY_KEY.to_vec());
        r2.mut_region_epoch().set_version(2);
        r2.mut_region_epoch().set_conf_ver(1);

        let mut r3 = metapb::Region::new();
        r3.set_id(1);
        r3.set_start_key(keys::EMPTY_KEY.to_vec());
        r3.set_end_key(keys::EMPTY_KEY.to_vec());
        r3.mut_region_epoch().set_version(1);
        r3.mut_region_epoch().set_conf_ver(2);

        assert!(check_region_epoch(&r1, &r2).is_err());
        assert!(check_region_epoch(&r1, &r3).is_err());
    }
}
<commit_msg>server/node: add cluster id mismatch reason in error (#1825)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::thread;
use std::sync::{Arc, mpsc};
use std::sync::mpsc::Sender;
use std::time::Duration;
use std::process;

use mio::EventLoop;
use rocksdb::DB;

use pd::{INVALID_ID, PdClient, Error as PdError};
use kvproto::raft_serverpb::StoreIdent;
use kvproto::metapb;
use protobuf::RepeatedField;
use util::transport::SendCh;
use raftstore::store::{self, Msg, SnapshotStatusMsg, StoreChannel, Store, Config as StoreConfig,
                       keys, Peekable, Transport, SnapManager};
use super::Result;
use super::config::Config;
use storage::{Storage, RaftKv};
use super::transport::RaftStoreRouter;

const MAX_CHECK_CLUSTER_BOOTSTRAPPED_RETRY_COUNT: u64 = 60;
const CHECK_CLUSTER_BOOTSTRAPPED_RETRY_SECONDS: u64 = 3;

pub fn create_raft_storage<S>(router: S, db: Arc<DB>, cfg: &Config) -> Result<Storage>
    where S: RaftStoreRouter + 'static
{
    let engine = box RaftKv::new(db, router);
    let store = try!(Storage::from_engine(engine, &cfg.storage));
    Ok(store)
}

fn check_region_epoch(region: &metapb::Region, other: &metapb::Region) -> Result<()> {
    let epoch = region.get_region_epoch();
    let other_epoch = other.get_region_epoch();
    if epoch.get_conf_ver() != other_epoch.get_conf_ver() {
        return Err(box_err!("region conf_ver inconsist: {} with {}",
                            epoch.get_conf_ver(),
                            other_epoch.get_conf_ver()));
    }
    if epoch.get_version() != other_epoch.get_version() {
        return Err(box_err!("region version inconsist: {} with {}",
                            epoch.get_version(),
                            other_epoch.get_version()));
    }
    Ok(())
}

// Node is a wrapper for raft store.
// TODO: we will rename another better name like RaftStore later.
pub struct Node<C: PdClient + 'static> {
    cluster_id: u64,
    store: metapb::Store,
    store_cfg: StoreConfig,
    store_handle: Option<thread::JoinHandle<()>>,
    ch: SendCh<Msg>,
    snapshot_status_sender: Option<Sender<SnapshotStatusMsg>>,

    pd_client: Arc<C>,
}

impl<C> Node<C>
    where C: PdClient
{
    pub fn new<T>(event_loop: &mut EventLoop<Store<T, C>>,
                  cfg: &Config,
                  pd_client: Arc<C>)
                  -> Node<C>
        where T: Transport + 'static
    {
        let mut store = metapb::Store::new();
        store.set_id(INVALID_ID);
        if cfg.advertise_addr.is_empty() {
            store.set_address(cfg.addr.clone());
        } else {
            store.set_address(cfg.advertise_addr.clone())
        }

        let mut labels = Vec::new();
        for (k, v) in &cfg.labels {
            let mut label = metapb::StoreLabel::new();
            label.set_key(k.to_owned());
            label.set_value(v.to_owned());
            labels.push(label);
        }
        store.set_labels(RepeatedField::from_vec(labels));

        let ch = SendCh::new(event_loop.channel(), "raftstore");
        Node {
            cluster_id: cfg.cluster_id,
            store: store,
            store_cfg: cfg.raft_store.clone(),
            store_handle: None,
            pd_client: pd_client,
            ch: ch,
            snapshot_status_sender: None,
        }
    }

    pub fn start<T>(&mut self,
                    event_loop: EventLoop<Store<T, C>>,
                    engine: Arc<DB>,
                    trans: T,
                    snap_mgr: SnapManager)
                    -> Result<()>
        where T: Transport + 'static
    {
        let bootstrapped = try!(self.check_cluster_bootstrapped());
        let mut store_id = try!(self.check_store(&engine));
        if store_id == INVALID_ID {
            store_id = try!(self.bootstrap_store(&engine));
        } else if !bootstrapped {
            // We have saved data before, and the cluster must be bootstrapped.
            return Err(box_err!("store {} is not empty, but cluster {} is not bootstrapped, \
                                 maybe you connected a wrong PD or need to remove the TiKV data \
                                 and start again",
                                store_id,
                                self.cluster_id));
        }

        self.store.set_id(store_id);
        try!(self.check_prepare_bootstrap_cluster(&engine));
        if !bootstrapped {
            // cluster is not bootstrapped, and we choose first store to bootstrap
            // prepare bootstrap.
            let region = try!(self.prepare_bootstrap_cluster(&engine, store_id));
            try!(self.bootstrap_cluster(&engine, region));
        }

        // inform pd.
        try!(self.start_store(event_loop, store_id, engine, trans, snap_mgr));
        try!(self.pd_client
            .put_store(self.store.clone()));
        Ok(())
    }

    pub fn id(&self) -> u64 {
        self.store.get_id()
    }

    pub fn get_sendch(&self) -> SendCh<Msg> {
        self.ch.clone()
    }

    pub fn get_snapshot_status_sender(&self) -> Sender<SnapshotStatusMsg> {
        self.snapshot_status_sender.clone().unwrap()
    }

    // check store, return store id for the engine.
    // If the store is not bootstrapped, use INVALID_ID.
    fn check_store(&self, engine: &DB) -> Result<u64> {
        let res = try!(engine.get_msg::<StoreIdent>(&keys::store_ident_key()));
        if res.is_none() {
            return Ok(INVALID_ID);
        }

        let ident = res.unwrap();
        if ident.get_cluster_id() != self.cluster_id {
            error!("cluster ID mismatch: local_id {} remote_id {}. \
            you are trying to connect to another cluster, please reconnect to the correct PD",
                   ident.get_cluster_id(),
                   self.cluster_id);
            process::exit(1);
        }

        let store_id = ident.get_store_id();
        if store_id == INVALID_ID {
            return Err(box_err!("invalid store ident {:?}", ident));
        }

        Ok(store_id)
    }

    fn alloc_id(&self) -> Result<u64> {
        let id = try!(self.pd_client.alloc_id());
        Ok(id)
    }

    fn bootstrap_store(&self, engine: &DB) -> Result<u64> {
        let store_id = try!(self.alloc_id());
        info!("alloc store id {} ", store_id);

        try!(store::bootstrap_store(engine, self.cluster_id, store_id));

        Ok(store_id)
    }

    pub fn prepare_bootstrap_cluster(&self, engine: &DB, store_id: u64) -> Result<metapb::Region> {
        let region_id = try!(self.alloc_id());
        info!("alloc first region id {} for cluster {}, store {}",
              region_id,
              self.cluster_id,
              store_id);
        let peer_id = try!(self.alloc_id());
        info!("alloc first peer id {} for first region {}",
              peer_id,
              region_id);

        let region = try!(store::prepare_bootstrap(engine, store_id, region_id, peer_id));
        Ok(region)
    }

    fn check_prepare_bootstrap_cluster(&self, engine: &DB) -> Result<()> {
        let res = try!(engine.get_msg::<metapb::Region>(&keys::prepare_bootstrap_key()));
        if res.is_none() {
            return Ok(());
        }

        let first_region = res.unwrap();
        for _ in 0..MAX_CHECK_CLUSTER_BOOTSTRAPPED_RETRY_COUNT {
            match self.pd_client.get_region(b"") {
                Ok(region) => {
                    if region.get_id() == first_region.get_id() {
                        try!(check_region_epoch(&region, &first_region));
                        try!(store::clear_prepare_bootstrap_state(engine));
                    } else {
                        try!(store::clear_prepare_bootstrap(engine, region.get_id()));
                    }
                    return Ok(());
                }

                Err(e) => {
                    warn!("check cluster prepare bootstrapped failed: {:?}", e);
                }
            }
            thread::sleep(Duration::from_secs(CHECK_CLUSTER_BOOTSTRAPPED_RETRY_SECONDS));
        }
        Err(box_err!("check cluster prepare bootstrapped failed"))
    }

    fn bootstrap_cluster(&mut self, engine: &DB, region: metapb::Region) -> Result<()> {
        let region_id = region.get_id();
        match self.pd_client.bootstrap_cluster(self.store.clone(), region) {
            Err(PdError::ClusterBootstrapped(_)) => {
                error!("cluster {} is already bootstrapped", self.cluster_id);
                try!(store::clear_prepare_bootstrap(engine, region_id));
                Ok(())
            }
            // TODO: should we clean region for other errors too?
            Err(e) => panic!("bootstrap cluster {} err: {:?}", self.cluster_id, e),
            Ok(_) => {
                try!(store::clear_prepare_bootstrap_state(engine));
                info!("bootstrap cluster {} ok", self.cluster_id);
                Ok(())
            }
        }
    }

    fn check_cluster_bootstrapped(&self) -> Result<bool> {
        for _ in 0..MAX_CHECK_CLUSTER_BOOTSTRAPPED_RETRY_COUNT {
            match self.pd_client.is_cluster_bootstrapped() {
                Ok(b) => return Ok(b),
                Err(e) => {
                    warn!("check cluster bootstrapped failed: {:?}", e);
                }
            }
            thread::sleep(Duration::from_secs(CHECK_CLUSTER_BOOTSTRAPPED_RETRY_SECONDS));
        }
        Err(box_err!("check cluster bootstrapped failed"))
    }

    fn start_store<T>(&mut self,
                      mut event_loop: EventLoop<Store<T, C>>,
                      store_id: u64,
                      db: Arc<DB>,
                      trans: T,
                      snap_mgr: SnapManager)
                      -> Result<()>
        where T: Transport + 'static
    {
        info!("start raft store {} thread", store_id);

        if self.store_handle.is_some() {
            return Err(box_err!("{} is already started", store_id));
        }

        let cfg = self.store_cfg.clone();
        let pd_client = self.pd_client.clone();
        let store = self.store.clone();
        let sender = event_loop.channel();

        let (tx, rx) = mpsc::channel();
        let (snapshot_tx, snapshot_rx) = mpsc::channel();
        self.snapshot_status_sender = Some(snapshot_tx);
        let builder = thread::Builder::new().name(thd_name!(format!("raftstore-{}", store_id)));
        let h = try!(builder.spawn(move || {
            let ch = StoreChannel {
                sender: sender,
                snapshot_status_receiver: snapshot_rx,
            };
            let mut store = match Store::new(ch, store, cfg, db, trans, pd_client, snap_mgr) {
                Err(e) => panic!("construct store {} err {:?}", store_id, e),
                Ok(s) => s,
            };
            tx.send(0).unwrap();
            if let Err(e) = store.run(&mut event_loop) {
                error!("store {} run err {:?}", store_id, e);
            };
        }));
        // wait for store to be initialized
        rx.recv().unwrap();

        self.store_handle = Some(h);
        Ok(())
    }

    fn stop_store(&mut self, store_id: u64) -> Result<()> {
        info!("stop raft store {} thread", store_id);
        let h = match self.store_handle.take() {
            None => return Ok(()),
            Some(h) => h,
        };

        box_try!(self.ch.send(Msg::Quit));
        if let Err(e) = h.join() {
            return Err(box_err!("join store {} thread err {:?}", store_id, e));
        }

        Ok(())
    }

    pub fn stop(&mut self) -> Result<()> {
        let store_id = self.store.get_id();
        self.stop_store(store_id)
    }
}

impl<C> Drop for Node<C>
    where C: PdClient
{
    fn drop(&mut self) {
        self.stop().unwrap();
    }
}
#[cfg(test)]
mod tests {
    use raftstore::store::keys;
    use super::check_region_epoch;
    use kvproto::metapb;

    #[test]
    fn test_check_region_epoch() {
        let mut r1 = metapb::Region::new();
        r1.set_id(1);
        r1.set_start_key(keys::EMPTY_KEY.to_vec());
        r1.set_end_key(keys::EMPTY_KEY.to_vec());
        r1.mut_region_epoch().set_version(1);
        r1.mut_region_epoch().set_conf_ver(1);

        let mut r2 = metapb::Region::new();
        r2.set_id(1);
        r2.set_start_key(keys::EMPTY_KEY.to_vec());
        r2.set_end_key(keys::EMPTY_KEY.to_vec());
        r2.mut_region_epoch().set_version(2);
        r2.mut_region_epoch().set_conf_ver(1);

        let mut r3 = metapb::Region::new();
        r3.set_id(1);
        r3.set_start_key(keys::EMPTY_KEY.to_vec());
        r3.set_end_key(keys::EMPTY_KEY.to_vec());
        r3.mut_region_epoch().set_version(1);
        r3.mut_region_epoch().set_conf_ver(2);

        assert!(check_region_epoch(&r1, &r2).is_err());
        assert!(check_region_epoch(&r1, &r3).is_err());
    }
}
<|endoftext|>


<commit_before>extern crate dbus;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_timer;

use std::str::FromStr;
use std::time::Duration;
use self::dbus::{Connection, ConnectionItem, Message, Props, BusType, Path, Interface, Member};
use self::dbus::arg::{Dict, Iter, Variant};
use self::futures::Future;
use self::futures_cpupool::CpuPool;
use self::tokio_timer::Timer;

pub const SD_SERVICE_MANAGER: &'static str = "org.freedesktop.systemd1";
pub const SD_SERVICE_PATH: &'static str = "/org/freedesktop/systemd1";
pub const SD_MANAGER_INTERFACE: &'static str = "org.freedesktop.systemd1.Manager";
pub const SD_UNIT_INTERFACE: &'static str = "org.freedesktop.systemd1.Unit";

/// Enables the Network Manager service.
///
/// # Examples
///
/// ```
/// use network_manager::service;
/// let state = service::enable(10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn enable(time_out: u64) -> Result<State, Error> {
    let state = try!(state());
    match state {
        State::Active => Ok(state),
        State::Activating => handler(time_out, State::Active),
        State::Failed => Err(Error::Failed),
        _ => {
            let message = try!(Message::new_method_call(SD_SERVICE_MANAGER,
                                                        SD_SERVICE_PATH,
                                                        SD_MANAGER_INTERFACE,
                                                        "StartUnit")
                    .map_err(Error::Message))
                .append2("NetworkManager.service", "fail");

            let connection = try!(Connection::get_private(BusType::System)
                .map_err(Error::Connection));

            try!(connection.send_with_reply_and_block(message, 2000).map_err(Error::Connection));

            handler(time_out, State::Active)
        }
    }
}

/// Disables the Network Manager service.
///
/// # Examples
///
/// ```
/// use network_manager::service;
/// let state = service::disable(10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn disable(time_out: u64) -> Result<State, Error> {
    let state = try!(state());
    match state {
        State::Inactive => Ok(state),
        State::Deactivating => handler(time_out, State::Inactive),
        State::Failed => Err(Error::Failed),
        _ => {
            let message = try!(Message::new_method_call(SD_SERVICE_MANAGER,
                                                        SD_SERVICE_PATH,
                                                        SD_MANAGER_INTERFACE,
                                                        "StopUnit")
                    .map_err(Error::Message))
                .append2("NetworkManager.service", "fail");

            let connection = try!(Connection::get_private(BusType::System)
                .map_err(Error::Connection));

            try!(connection.send_with_reply_and_block(message, 2000).map_err(Error::Connection));

            handler(time_out, State::Inactive)
        }
    }
}

/// Gets the state of the Network Manager service.
///
/// # Examples
///
/// ```
/// use network_manager::service;
/// let state = service::state().unwrap();
/// println!("{:?}", state);
/// ```
pub fn state() -> Result<State, Error> {
    let message = try!(Message::new_method_call(SD_SERVICE_MANAGER,
                                                SD_SERVICE_PATH,
                                                SD_MANAGER_INTERFACE,
                                                "GetUnit")
            .map_err(Error::Message))
        .append1("NetworkManager.service");

    let connection = try!(Connection::get_private(BusType::System).map_err(Error::Connection));

    let response = try!(connection.send_with_reply_and_block(message, 2000)
        .map_err(Error::Connection));

    let path = try!(response.get1::<Path>().ok_or(Error::NotFound));

    let response = try!(Props::new(&connection,
                                   SD_SERVICE_MANAGER,
                                   path,
                                   SD_UNIT_INTERFACE,
                                   2000)
        .get("ActiveState")
        .map_err(Error::Props));

    try!(response.inner::<&str>().ok().ok_or(Error::NotFound)).parse()
}

fn handler(time_out: u64, target_state: State) -> Result<State, Error> {
    if time_out == 0 {
        return state();
    }

    let timer =
        Timer::default().sleep(Duration::from_secs(time_out)).then(|_| Err(Error::TimedOut));

    let process = CpuPool::new_num_cpus().spawn_fn(|| {
        let connection = try!(Connection::get_private(BusType::System).map_err(Error::Connection));
        try!(connection.add_match("type='signal', sender='org.freedesktop.systemd1', \
                        interface='org.freedesktop.DBus.Properties', \
                        member='PropertiesChanged', \
                        path='/org/freedesktop/systemd1/unit/NetworkManager_2eservice'")
            .map_err(Error::Connection));

        if try!(state()) == target_state {
            return Ok(target_state);
        }

        for item in connection.iter(0) {
            let response = if let ConnectionItem::Signal(ref signal) = item {
                signal
            } else {
                continue;
            };

            if try!(response.interface().ok_or(Error::NotFound)) !=
               Interface::from("org.freedesktop.DBus.Properties") ||
               try!(response.member().ok_or(Error::NotFound)) !=
               Member::from("PropertiesChanged") ||
               try!(response.path().ok_or(Error::NotFound)) !=
               Path::from("/org/freedesktop/systemd1/unit/NetworkManager_2eservice") {
                continue;
            }

            let (interface, dictionary) = response.get2::<&str, Dict<&str, Variant<Iter>, _>>();

            if try!(interface.ok_or(Error::NotFound)) != "org.freedesktop.systemd1.Unit" {
                continue;
            }

            for (k, v) in try!(dictionary.ok_or(Error::NotFound)) {
                match k {
                    "ActiveState" => {
                        let response = try!(v.0.clone().get::<&str>().ok_or(Error::NotFound));
                        let state: State = try!(response.parse());
                        if state == target_state {
                            return Ok(target_state);
                        }
                    }
                    _ => (),
                }
            }
        }
        Err(Error::NotFound)
    });

    match timer.select(process).map(|(result, _)| result).wait() {
        Ok(val) => Ok(val),
        Err(val) => Err(val.0),
    }
}

#[test]
fn test_integration() {
    let s = state().unwrap();

    assert!(s == State::Active || s == State::Inactive);

    match s {
        State::Active => {
            disable(10).unwrap();
            assert_eq!(State::Inactive, state().unwrap());

            enable(10).unwrap();
            assert_eq!(State::Active, state().unwrap());
        }
        State::Inactive => {
            enable(10).unwrap();
            assert_eq!(State::Active, state().unwrap());

            disable(10).unwrap();
            assert_eq!(State::Inactive, state().unwrap());
        }
        _ => (),
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum State {
    Active,
    Reloading,
    Inactive,
    Failed,
    Activating,
    Deactivating,
}

#[derive(Debug)]
pub enum Error {
    Message(String),
    Connection(dbus::Error),
    Props(dbus::Error),
    TimedOut,
    Failed,
    NotFound,
}

impl FromStr for State {
    type Err = Error;
    fn from_str(s: &str) -> Result<State, Error> {
        match s {
            "active" => Ok(State::Active),
            "reloading" => Ok(State::Reloading),
            "inactive" => Ok(State::Inactive),
            "failed" => Ok(State::Failed),
            "activating" => Ok(State::Activating),
            "deactivating" => Ok(State::Deactivating),
            _ => Err(Error::NotFound),
        }
    }
}
<commit_msg>Fixed an error caught by clippy<commit_after>extern crate dbus;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_timer;

use std::str::FromStr;
use std::time::Duration;
use self::dbus::{Connection, ConnectionItem, Message, Props, BusType, Path, Interface, Member};
use self::dbus::arg::{Dict, Iter, Variant};
use self::futures::Future;
use self::futures_cpupool::CpuPool;
use self::tokio_timer::Timer;

pub const SD_SERVICE_MANAGER: &'static str = "org.freedesktop.systemd1";
pub const SD_SERVICE_PATH: &'static str = "/org/freedesktop/systemd1";
pub const SD_MANAGER_INTERFACE: &'static str = "org.freedesktop.systemd1.Manager";
pub const SD_UNIT_INTERFACE: &'static str = "org.freedesktop.systemd1.Unit";

/// Enables the Network Manager service.
///
/// # Examples
///
/// ```
/// use network_manager::service;
/// let state = service::enable(10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn enable(time_out: u64) -> Result<State, Error> {
    let state = try!(state());
    match state {
        State::Active => Ok(state),
        State::Activating => handler(time_out, State::Active),
        State::Failed => Err(Error::Failed),
        _ => {
            let message = try!(Message::new_method_call(SD_SERVICE_MANAGER,
                                                        SD_SERVICE_PATH,
                                                        SD_MANAGER_INTERFACE,
                                                        "StartUnit")
                    .map_err(Error::Message))
                .append2("NetworkManager.service", "fail");

            let connection = try!(Connection::get_private(BusType::System)
                .map_err(Error::Connection));

            try!(connection.send_with_reply_and_block(message, 2000).map_err(Error::Connection));

            handler(time_out, State::Active)
        }
    }
}

/// Disables the Network Manager service.
///
/// # Examples
///
/// ```
/// use network_manager::service;
/// let state = service::disable(10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn disable(time_out: u64) -> Result<State, Error> {
    let state = try!(state());
    match state {
        State::Inactive => Ok(state),
        State::Deactivating => handler(time_out, State::Inactive),
        State::Failed => Err(Error::Failed),
        _ => {
            let message = try!(Message::new_method_call(SD_SERVICE_MANAGER,
                                                        SD_SERVICE_PATH,
                                                        SD_MANAGER_INTERFACE,
                                                        "StopUnit")
                    .map_err(Error::Message))
                .append2("NetworkManager.service", "fail");

            let connection = try!(Connection::get_private(BusType::System)
                .map_err(Error::Connection));

            try!(connection.send_with_reply_and_block(message, 2000).map_err(Error::Connection));

            handler(time_out, State::Inactive)
        }
    }
}

/// Gets the state of the Network Manager service.
///
/// # Examples
///
/// ```
/// use network_manager::service;
/// let state = service::state().unwrap();
/// println!("{:?}", state);
/// ```
pub fn state() -> Result<State, Error> {
    let message = try!(Message::new_method_call(SD_SERVICE_MANAGER,
                                                SD_SERVICE_PATH,
                                                SD_MANAGER_INTERFACE,
                                                "GetUnit")
            .map_err(Error::Message))
        .append1("NetworkManager.service");

    let connection = try!(Connection::get_private(BusType::System).map_err(Error::Connection));

    let response = try!(connection.send_with_reply_and_block(message, 2000)
        .map_err(Error::Connection));

    let path = try!(response.get1::<Path>().ok_or(Error::NotFound));

    let response = try!(Props::new(&connection,
                                   SD_SERVICE_MANAGER,
                                   path,
                                   SD_UNIT_INTERFACE,
                                   2000)
        .get("ActiveState")
        .map_err(Error::Props));

    try!(response.inner::<&str>().ok().ok_or(Error::NotFound)).parse()
}

fn handler(time_out: u64, target_state: State) -> Result<State, Error> {
    if time_out == 0 {
        return state();
    }

    let timer =
        Timer::default().sleep(Duration::from_secs(time_out)).then(|_| Err(Error::TimedOut));

    let process = CpuPool::new_num_cpus().spawn_fn(|| {
        let connection = try!(Connection::get_private(BusType::System).map_err(Error::Connection));
        try!(connection.add_match("type='signal', sender='org.freedesktop.systemd1', \
                        interface='org.freedesktop.DBus.Properties', \
                        member='PropertiesChanged', \
                        path='/org/freedesktop/systemd1/unit/NetworkManager_2eservice'")
            .map_err(Error::Connection));

        if try!(state()) == target_state {
            return Ok(target_state);
        }

        for item in connection.iter(0) {
            let response = if let ConnectionItem::Signal(ref signal) = item {
                signal
            } else {
                continue;
            };

            if try!(response.interface().ok_or(Error::NotFound)) !=
               Interface::from("org.freedesktop.DBus.Properties") ||
               try!(response.member().ok_or(Error::NotFound)) !=
               Member::from("PropertiesChanged") ||
               try!(response.path().ok_or(Error::NotFound)) !=
               Path::from("/org/freedesktop/systemd1/unit/NetworkManager_2eservice") {
                continue;
            }

            let (interface, dictionary) = response.get2::<&str, Dict<&str, Variant<Iter>, _>>();

            if try!(interface.ok_or(Error::NotFound)) != "org.freedesktop.systemd1.Unit" {
                continue;
            }

            for (k, v) in try!(dictionary.ok_or(Error::NotFound)) {
                if k == "ActiveState" {
                    let response = try!(v.0.clone().get::<&str>().ok_or(Error::NotFound));
                    let state: State = try!(response.parse());
                    if state == target_state {
                        return Ok(target_state);
                    }
                }
            }
        }
        Err(Error::NotFound)
    });

    match timer.select(process).map(|(result, _)| result).wait() {
        Ok(val) => Ok(val),
        Err(val) => Err(val.0),
    }
}

#[test]
fn test_integration() {
    let s = state().unwrap();

    assert!(s == State::Active || s == State::Inactive);

    match s {
        State::Active => {
            disable(10).unwrap();
            assert_eq!(State::Inactive, state().unwrap());

            enable(10).unwrap();
            assert_eq!(State::Active, state().unwrap());
        }
        State::Inactive => {
            enable(10).unwrap();
            assert_eq!(State::Active, state().unwrap());

            disable(10).unwrap();
            assert_eq!(State::Inactive, state().unwrap());
        }
        _ => (),
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum State {
    Active,
    Reloading,
    Inactive,
    Failed,
    Activating,
    Deactivating,
}

#[derive(Debug)]
pub enum Error {
    Message(String),
    Connection(dbus::Error),
    Props(dbus::Error),
    TimedOut,
    Failed,
    NotFound,
}

impl FromStr for State {
    type Err = Error;
    fn from_str(s: &str) -> Result<State, Error> {
        match s {
            "active" => Ok(State::Active),
            "reloading" => Ok(State::Reloading),
            "inactive" => Ok(State::Inactive),
            "failed" => Ok(State::Failed),
            "activating" => Ok(State::Activating),
            "deactivating" => Ok(State::Deactivating),
            _ => Err(Error::NotFound),
        }
    }
}
<|endoftext|>


<commit_before>extern crate syscall;

use std::cell::Cell;
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::{env, mem, slice, thread};

use color::Color;
use event::{Event, EVENT_RESIZE};
use renderer::Renderer;
use Mode;
use WindowFlag;

pub fn get_display_size() -> Result<(u32, u32), String> {
    let display_path = env::var("DISPLAY").or(Err("DISPLAY not set"))?;
    match File::open(&display_path) {
        Ok(display) => {
            let mut buf: [u8; 4096] = [0; 4096];
            let count = syscall::fpath(display.as_raw_fd() as usize, &mut buf)
                .map_err(|err| format!("{}", err))?;
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            let res = path.split(":").nth(1).unwrap_or("");
            let width = res
                .split("/")
                .nth(1)
                .unwrap_or("")
                .parse::<u32>()
                .unwrap_or(0);
            let height = res
                .split("/")
                .nth(2)
                .unwrap_or("")
                .parse::<u32>()
                .unwrap_or(0);
            Ok((width, height))
        }
        Err(err) => Err(format!("{}", err)),
    }
}

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// True if the window should not wait for events
    window_async: bool,
    /// True if the window can be resized
    resizable: bool,
    /// Drawing mode
    mode: Cell<Mode>,
    /// The input scheme
    file: File,
    /// Window data
    data: &'static mut [Color],
}

impl Renderer for Window {
    /// Get width
    fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    fn height(&self) -> u32 {
        self.h
    }

    /// Access pixel buffer
    fn data(&self) -> &[Color] {
        &self.data
    }

    /// Access pixel buffer mutably
    fn data_mut(&mut self) -> &mut [Color] {
        &mut self.data
    }

    /// Flip the buffer
    fn sync(&mut self) -> bool {
        self.file.sync_data().is_ok()
    }

    /// Set/get mode
    fn mode(&self) -> &Cell<Mode> {
        &self.mode
    }
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
        Window::new_flags(x, y, w, h, title, &[])
    }

    /// Create a new window with flags
    pub fn new_flags(
        x: i32,
        y: i32,
        w: u32,
        h: u32,
        title: &str,
        flags: &[WindowFlag],
    ) -> Option<Self> {
        let mut flag_str = String::new();

        let mut window_async = false;
        let mut resizable = false;
        for &flag in flags.iter() {
            match flag {
                WindowFlag::Async => {
                    window_async = true;
                    flag_str.push('a');
                }
                WindowFlag::Back => flag_str.push('b'),
                WindowFlag::Front => flag_str.push('f'),
                WindowFlag::Borderless => flag_str.push('l'),
                WindowFlag::Resizable => {
                    resizable = true;
                    flag_str.push('r');
                }
                WindowFlag::Transparent => flag_str.push('t'),
                WindowFlag::Unclosable => flag_str.push('u'),
            }
        }

        if let Ok(file) = File::open(&format!(
            "orbital:{}/{}/{}/{}/{}/{}",
            flag_str, x, y, w, h, title
        )) {
            if let Ok(address) = unsafe {
                syscall::fmap(
                    file.as_raw_fd() as usize,
                    &syscall::Map {
                        offset: 0,
                        size: (w * h * 4) as usize,
                        flags: syscall::PROT_READ | syscall::PROT_WRITE,
                    },
                )
            } {
                Some(Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    window_async,
                    resizable: resizable,
                    mode: Cell::new(Mode::Blend),
                    file: file,
                    data: unsafe {
                        slice::from_raw_parts_mut(address as *mut Color, (w * h) as usize)
                    },
                })
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn clipboard(&self) -> String {
        let mut text = String::new();
        let window_fd = self.file.as_raw_fd();
        if let Ok(clipboard_fd) = syscall::dup(window_fd as usize, b"clipboard") {
            let mut clipboard_file = unsafe { File::from_raw_fd(clipboard_fd as RawFd) };
            let _ = clipboard_file.read_to_string(&mut text);
        }
        text
    }

    pub fn set_clipboard(&mut self, text: &str) {
        let window_fd = self.file.as_raw_fd();
        if let Ok(clipboard_fd) = syscall::dup(window_fd as usize, b"clipboard") {
            let mut clipboard_file = unsafe { File::from_raw_fd(clipboard_fd as RawFd) };
            let _ = clipboard_file.write(text.as_bytes());
        }
    }

    /// Not yet available on Redox OS.
    pub fn pop_drop_content(&self) -> Option<String> {
        None
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        let mut buf: [u8; 4096] = [0; 4096];
        if let Ok(count) = syscall::fpath(self.file.as_raw_fd() as usize, &mut buf) {
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            // orbital:/x/y/w/h/t
            let mut parts = path.split('/').skip(1);
            if let Some(x) = parts.next() {
                self.x = x.parse::<i32>().unwrap_or(0);
            }
            if let Some(y) = parts.next() {
                self.y = y.parse::<i32>().unwrap_or(0);
            }
            if let Some(w) = parts.next() {
                self.w = w.parse::<u32>().unwrap_or(0);
            }
            if let Some(h) = parts.next() {
                self.h = h.parse::<u32>().unwrap_or(0);
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set cursor visibility
    pub fn set_mouse_cursor(&mut self, visible: bool) {
        let _ = self.file.write(if visible { b"M,C,1" } else { b"M,C,0" });
    }

    /// Set mouse grabbing
    pub fn set_mouse_grab(&mut self, grab: bool) {
        let _ = self.file.write(if grab { b"M,G,1" } else { b"M,G,0" });
    }

    /// Set mouse relative mode
    pub fn set_mouse_relative(&mut self, relative: bool) {
        let _ = self.file.write(if relative { b"M,R,1" } else { b"M,R,0" });
    }

    /// Set position
    pub fn set_pos(&mut self, x: i32, y: i32) {
        let _ = self.file.write(&format!("P,{},{}", x, y).as_bytes());
        self.sync_path();
    }

    /// Set size
    pub fn set_size(&mut self, width: u32, height: u32) {
        //TODO: Improve safety and reliability
        unsafe {
            syscall::funmap(self.data.as_ptr() as usize)
                .expect("orbclient: failed to unmap memory in resize");
        }
        let _ = self
            .file
            .write(&format!("S,{},{}", width, height).as_bytes());
        self.sync_path();
        unsafe {
            let address = syscall::fmap(
                self.file.as_raw_fd() as usize,
                &syscall::Map {
                    offset: 0,
                    size: (self.w * self.h * 4) as usize,
                    flags: syscall::PROT_READ | syscall::PROT_WRITE,
                },
            )
            .expect("orbclient: failed to map memory in resize");
            self.data =
                slice::from_raw_parts_mut(address as *mut Color, (self.w * self.h) as usize);
        }
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        let _ = self.file.write(&format!("T,{}", title).as_bytes());
        self.sync_path();
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        let mut iter = EventIter {
            extra: None,
            events: [Event::new(); 16],
            i: 0,
            count: 0,
        };

        'blocking: loop {
            if iter.count == iter.events.len() {
                if iter.extra.is_none() {
                    iter.extra = Some(Vec::with_capacity(32));
                }
                iter.extra.as_mut().unwrap().extend_from_slice(&iter.events);
                iter.count = 0;
            }
            let bytes = unsafe {
                slice::from_raw_parts_mut(
                    iter.events[iter.count..].as_mut_ptr() as *mut u8,
                    iter.events[iter.count..].len() * mem::size_of::<Event>(),
                )
            };
            match self.file.read(bytes) {
                Ok(0) => {
                    if !self.window_async && iter.extra.is_none() && iter.count == 0 {
                        thread::yield_now();
                    } else {
                        break 'blocking;
                    }
                }
                Ok(count) => {
                    let count = count / mem::size_of::<Event>();
                    let events = &iter.events[iter.count..][..count];
                    iter.count += count;

                    if self.resizable {
                        let mut resize = None;
                        for event in events {
                            let event = *event;
                            if event.code == EVENT_RESIZE {
                                resize = Some((event.a as u32, event.b as u32));
                            }
                        }
                        if let Some((w, h)) = resize {
                            self.set_size(w, h);
                        }
                    }
                    if !self.window_async {
                        // Synchronous windows are blocking, can't attempt another read
                        break 'blocking;
                    }
                }
                Err(_) => break 'blocking,
            }
        }

        iter
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        let _ = unsafe { syscall::funmap(self.data.as_ptr() as usize) };
    }
}

impl AsRawFd for Window {
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

/// Event iterator
pub struct EventIter {
    extra: Option<Vec<Event>>,
    events: [Event; 16],
    i: usize,
    count: usize,
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        let mut i = self.i;
        if let Some(ref mut extra) = self.extra {
            if i < extra.len() {
                self.i += 1;
                return Some(extra[i]);
            }
            i -= extra.len();
        }
        if i < self.count {
            self.i += 1;
            return Some(self.events[i]);
        }
        None
    }
}
<commit_msg>fixes to redox syscall 0.2<commit_after>extern crate syscall;

use std::cell::Cell;
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::{env, mem, slice, thread};

use color::Color;
use event::{Event, EVENT_RESIZE};
use renderer::Renderer;
use Mode;
use WindowFlag;

pub fn get_display_size() -> Result<(u32, u32), String> {
    let display_path = env::var("DISPLAY").or(Err("DISPLAY not set"))?;
    match File::open(&display_path) {
        Ok(display) => {
            let mut buf: [u8; 4096] = [0; 4096];
            let count = syscall::fpath(display.as_raw_fd() as usize, &mut buf)
                .map_err(|err| format!("{}", err))?;
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            let res = path.split(":").nth(1).unwrap_or("");
            let width = res
                .split("/")
                .nth(1)
                .unwrap_or("")
                .parse::<u32>()
                .unwrap_or(0);
            let height = res
                .split("/")
                .nth(2)
                .unwrap_or("")
                .parse::<u32>()
                .unwrap_or(0);
            Ok((width, height))
        }
        Err(err) => Err(format!("{}", err)),
    }
}

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// True if the window should not wait for events
    window_async: bool,
    /// True if the window can be resized
    resizable: bool,
    /// Drawing mode
    mode: Cell<Mode>,
    /// The input scheme
    file: File,
    /// Window data
    data: &'static mut [Color],
}

impl Renderer for Window {
    /// Get width
    fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    fn height(&self) -> u32 {
        self.h
    }

    /// Access pixel buffer
    fn data(&self) -> &[Color] {
        &self.data
    }

    /// Access pixel buffer mutably
    fn data_mut(&mut self) -> &mut [Color] {
        &mut self.data
    }

    /// Flip the buffer
    fn sync(&mut self) -> bool {
        self.file.sync_data().is_ok()
    }

    /// Set/get mode
    fn mode(&self) -> &Cell<Mode> {
        &self.mode
    }
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
        Window::new_flags(x, y, w, h, title, &[])
    }

    /// Create a new window with flags
    pub fn new_flags(
        x: i32,
        y: i32,
        w: u32,
        h: u32,
        title: &str,
        flags: &[WindowFlag],
    ) -> Option<Self> {
        let mut flag_str = String::new();

        let mut window_async = false;
        let mut resizable = false;
        for &flag in flags.iter() {
            match flag {
                WindowFlag::Async => {
                    window_async = true;
                    flag_str.push('a');
                }
                WindowFlag::Back => flag_str.push('b'),
                WindowFlag::Front => flag_str.push('f'),
                WindowFlag::Borderless => flag_str.push('l'),
                WindowFlag::Resizable => {
                    resizable = true;
                    flag_str.push('r');
                }
                WindowFlag::Transparent => flag_str.push('t'),
                WindowFlag::Unclosable => flag_str.push('u'),
            }
        }

        if let Ok(file) = File::open(&format!(
            "orbital:{}/{}/{}/{}/{}/{}",
            flag_str, x, y, w, h, title
        )) {
            if let Ok(address) = unsafe {
                syscall::fmap(
                    file.as_raw_fd() as usize,
                    &syscall::Map {
                        offset: 0,
                        size: (w * h * 4) as usize,
                        flags: syscall::PROT_READ | syscall::PROT_WRITE,
                        address: 0
                    },
                )
            } {
                Some(Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    window_async,
                    resizable: resizable,
                    mode: Cell::new(Mode::Blend),
                    file: file,
                    data: unsafe {
                        slice::from_raw_parts_mut(address as *mut Color, (w * h) as usize)
                    },
                })
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn clipboard(&self) -> String {
        let mut text = String::new();
        let window_fd = self.file.as_raw_fd();
        if let Ok(clipboard_fd) = syscall::dup(window_fd as usize, b"clipboard") {
            let mut clipboard_file = unsafe { File::from_raw_fd(clipboard_fd as RawFd) };
            let _ = clipboard_file.read_to_string(&mut text);
        }
        text
    }

    pub fn set_clipboard(&mut self, text: &str) {
        let window_fd = self.file.as_raw_fd();
        if let Ok(clipboard_fd) = syscall::dup(window_fd as usize, b"clipboard") {
            let mut clipboard_file = unsafe { File::from_raw_fd(clipboard_fd as RawFd) };
            let _ = clipboard_file.write(text.as_bytes());
        }
    }

    /// Not yet available on Redox OS.
    pub fn pop_drop_content(&self) -> Option<String> {
        None
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        let mut buf: [u8; 4096] = [0; 4096];
        if let Ok(count) = syscall::fpath(self.file.as_raw_fd() as usize, &mut buf) {
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            // orbital:/x/y/w/h/t
            let mut parts = path.split('/').skip(1);
            if let Some(x) = parts.next() {
                self.x = x.parse::<i32>().unwrap_or(0);
            }
            if let Some(y) = parts.next() {
                self.y = y.parse::<i32>().unwrap_or(0);
            }
            if let Some(w) = parts.next() {
                self.w = w.parse::<u32>().unwrap_or(0);
            }
            if let Some(h) = parts.next() {
                self.h = h.parse::<u32>().unwrap_or(0);
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set cursor visibility
    pub fn set_mouse_cursor(&mut self, visible: bool) {
        let _ = self.file.write(if visible { b"M,C,1" } else { b"M,C,0" });
    }

    /// Set mouse grabbing
    pub fn set_mouse_grab(&mut self, grab: bool) {
        let _ = self.file.write(if grab { b"M,G,1" } else { b"M,G,0" });
    }

    /// Set mouse relative mode
    pub fn set_mouse_relative(&mut self, relative: bool) {
        let _ = self.file.write(if relative { b"M,R,1" } else { b"M,R,0" });
    }

    /// Set position
    pub fn set_pos(&mut self, x: i32, y: i32) {
        let _ = self.file.write(&format!("P,{},{}", x, y).as_bytes());
        self.sync_path();
    }

    /// Set size
    pub fn set_size(&mut self, width: u32, height: u32) {
        //TODO: Improve safety and reliability
        unsafe {
            syscall::funmap(self.data.as_ptr() as usize, self.data.len())
                .expect("orbclient: failed to unmap memory in resize");
        }
        let _ = self
            .file
            .write(&format!("S,{},{}", width, height).as_bytes());
        self.sync_path();
        unsafe {
            let address = syscall::fmap(
                self.file.as_raw_fd() as usize,
                &syscall::Map {
                    offset: 0,
                    size: (self.w * self.h * 4) as usize,
                    flags: syscall::PROT_READ | syscall::PROT_WRITE,
                    address: 0
                },
            )
            .expect("orbclient: failed to map memory in resize");
            self.data =
                slice::from_raw_parts_mut(address as *mut Color, (self.w * self.h) as usize);
        }
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        let _ = self.file.write(&format!("T,{}", title).as_bytes());
        self.sync_path();
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        let mut iter = EventIter {
            extra: None,
            events: [Event::new(); 16],
            i: 0,
            count: 0,
        };

        'blocking: loop {
            if iter.count == iter.events.len() {
                if iter.extra.is_none() {
                    iter.extra = Some(Vec::with_capacity(32));
                }
                iter.extra.as_mut().unwrap().extend_from_slice(&iter.events);
                iter.count = 0;
            }
            let bytes = unsafe {
                slice::from_raw_parts_mut(
                    iter.events[iter.count..].as_mut_ptr() as *mut u8,
                    iter.events[iter.count..].len() * mem::size_of::<Event>(),
                )
            };
            match self.file.read(bytes) {
                Ok(0) => {
                    if !self.window_async && iter.extra.is_none() && iter.count == 0 {
                        thread::yield_now();
                    } else {
                        break 'blocking;
                    }
                }
                Ok(count) => {
                    let count = count / mem::size_of::<Event>();
                    let events = &iter.events[iter.count..][..count];
                    iter.count += count;

                    if self.resizable {
                        let mut resize = None;
                        for event in events {
                            let event = *event;
                            if event.code == EVENT_RESIZE {
                                resize = Some((event.a as u32, event.b as u32));
                            }
                        }
                        if let Some((w, h)) = resize {
                            self.set_size(w, h);
                        }
                    }
                    if !self.window_async {
                        // Synchronous windows are blocking, can't attempt another read
                        break 'blocking;
                    }
                }
                Err(_) => break 'blocking,
            }
        }

        iter
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        let _ = unsafe { syscall::funmap(self.data.as_ptr() as usize, self.data.len()) };
    }
}

impl AsRawFd for Window {
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

/// Event iterator
pub struct EventIter {
    extra: Option<Vec<Event>>,
    events: [Event; 16],
    i: usize,
    count: usize,
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        let mut i = self.i;
        if let Some(ref mut extra) = self.extra {
            if i < extra.len() {
                self.i += 1;
                return Some(extra[i]);
            }
            i -= extra.len();
        }
        if i < self.count {
            self.i += 1;
            return Some(self.events[i]);
        }
        None
    }
}
<|endoftext|>


<commit_before>use {io, poll, Evented, Ready, Poll, PollOpt, Token};
use std::io::{Read, Write};
use std::os::unix::io::{IntoRawFd, AsRawFd, FromRawFd, RawFd};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::fcntl::{fcntl, O_NONBLOCK};

pub fn set_nonblock(s: &AsRawFd) -> io::Result<()> {
    fcntl(s.as_raw_fd(), F_SETFL(O_NONBLOCK)).map_err(super::from_nix_error)
                                             .map(|_| ())
}

/*
 *
 * ===== Basic IO type =====
 *
 */

#[derive(Debug)]
pub struct Io {
    fd: RawFd,
}

impl Io {
    pub fn from_raw_fd(fd: RawFd) -> Io {
        Io { fd: fd }
    }
}

impl From<RawFd> for Io {
    fn from(fd: RawFd) -> Io {
        Io { fd: fd }
    }
}

impl FromRawFd for Io {
    unsafe fn from_raw_fd(fd: RawFd) -> Io {
        From::from(fd)
    }
}

impl IntoRawFd for Io {
    fn into_raw_fd(self) -> RawFd {
        self.fd
    }
}

impl AsRawFd for Io {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Evented for Io {
    fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        poll::selector(poll).register(self.fd, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        poll::selector(poll).reregister(self.fd, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        poll::selector(poll).deregister(self.fd)
    }
}

impl Read for Io {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        <&Io as Read>::read(&mut &*self, dst)
    }
}

impl<'a> Read for &'a Io {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        use nix::unistd::read;

        read(self.as_raw_fd(), dst)
            .map_err(super::from_nix_error)
    }
}

impl Write for Io {
    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
        <&Io as Write>::write(&mut &*self, src)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<'a> Write for &'a Io {
    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
        use nix::unistd::write;

        write(self.as_raw_fd(), src)
            .map_err(super::from_nix_error)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Drop for Io {
    fn drop(&mut self) {
        use nix::unistd::close;
        let _ = close(self.as_raw_fd());
    }
}

<commit_msg>prevent Io::into_raw_fd from dropping self<commit_after>use {io, poll, Evented, Ready, Poll, PollOpt, Token};
use std::io::{Read, Write};
use std::mem;
use std::os::unix::io::{IntoRawFd, AsRawFd, FromRawFd, RawFd};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::fcntl::{fcntl, O_NONBLOCK};

pub fn set_nonblock(s: &AsRawFd) -> io::Result<()> {
    fcntl(s.as_raw_fd(), F_SETFL(O_NONBLOCK)).map_err(super::from_nix_error)
                                             .map(|_| ())
}

/*
 *
 * ===== Basic IO type =====
 *
 */

#[derive(Debug)]
pub struct Io {
    fd: RawFd,
}

impl Io {
    pub fn from_raw_fd(fd: RawFd) -> Io {
        Io { fd: fd }
    }
}

impl From<RawFd> for Io {
    fn from(fd: RawFd) -> Io {
        Io { fd: fd }
    }
}

impl FromRawFd for Io {
    unsafe fn from_raw_fd(fd: RawFd) -> Io {
        From::from(fd)
    }
}

impl IntoRawFd for Io {
    fn into_raw_fd(self) -> RawFd {
        // Forget self to prevent drop() from closing self.fd.
        let fd = self.fd;
        mem::forget(self);
        fd
    }
}

impl AsRawFd for Io {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Evented for Io {
    fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        poll::selector(poll).register(self.fd, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        poll::selector(poll).reregister(self.fd, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        poll::selector(poll).deregister(self.fd)
    }
}

impl Read for Io {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        <&Io as Read>::read(&mut &*self, dst)
    }
}

impl<'a> Read for &'a Io {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        use nix::unistd::read;

        read(self.as_raw_fd(), dst)
            .map_err(super::from_nix_error)
    }
}

impl Write for Io {
    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
        <&Io as Write>::write(&mut &*self, src)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<'a> Write for &'a Io {
    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
        use nix::unistd::write;

        write(self.as_raw_fd(), src)
            .map_err(super::from_nix_error)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Drop for Io {
    fn drop(&mut self) {
        use nix::unistd::close;
        let _ = close(self.as_raw_fd());
    }
}

<|endoftext|>