<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![allow(clippy::doc_markdown)]

#[macro_use]
extern crate log;

use std::{
    cell::RefCell,
    env,
    fs::{File, OpenOptions},
    io::{Read, Write},
    os::unix::io::{AsRawFd, RawFd},
    process::exit,
    rc::Rc,
};

use chrono::Duration;
use clap::{App, Arg, ArgMatches};
use env_logger::Builder;
use log::LevelFilter;
use nix::{
    fcntl::{flock, FlockArg},
    sys::{
        signal::{self, SigSet},
        signalfd::{SfdFlags, SignalFd},
    },
    unistd::getpid,
};
use uuid::Uuid;

#[cfg(feature = "dbus_enabled")]
use libstratis::{
    dbus_api::{DbusConnectionData, EventHandler},
    engine::get_engine_listener_list_mut,
};

use libstratis::{
    engine::{Engine, Pool, SimEngine, StratEngine},
    stratis::{buff_log, StratisError, StratisResult, VERSION},
};

const STRATISD_PID_PATH: &str = "/run/stratisd.pid";

/// Number of minutes to buffer log entries.
const DEFAULT_LOG_HOLD_MINUTES: i64 = 30;

/// If writing a program error to stderr fails, panic.
fn print_err(err: &StratisError) {
    eprintln!("{}", err);
}

/// Configure the env_logger as necessary in order to allow the buffered
/// logger to work correctly. Return a Handle to the underlying env_logger.
pub fn from_env_logger(
    mut builder: env_logger::Builder,
    pass_through: bool,
    hold_time: Option<Duration>,
) -> buff_log::Handle<env_logger::Logger> {
    // Do not have the env_logger set the timestamp. Because the entries are
    // buffered, the timestamp set by the env_logger will correspond to the
    // time at which the entry was dumped, not the time of its origination.
    builder.default_format_timestamp(false);
    buff_log::Logger::new(builder.build(), pass_through, hold_time).init()
}

/// Configure and initialize the logger.
/// If debug is true, log at debug level. Otherwise read log configuration
/// parameters from the environment if RUST_LOG is set. Otherwise, just
/// accept the default configuration.
fn initialize_log(debug: bool) -> buff_log::Handle<env_logger::Logger> {
    let mut builder = Builder::new();
    if debug {
        builder.filter(Some("stratisd"), LevelFilter::Debug);
        builder.filter(Some("libstratis"), LevelFilter::Debug);
        from_env_logger(builder, true, None)
    } else {
        builder.filter_level(LevelFilter::Trace);
        if let Ok(s) = env::var("RUST_LOG") {
            builder.parse(&s);
        }
        from_env_logger(
            builder,
            false,
            Some(Duration::minutes(DEFAULT_LOG_HOLD_MINUTES)),
        )
    }
}

/// To ensure only one instance of stratisd runs at a time, acquire an
/// exclusive lock. Return an error if lock attempt fails.
fn trylock_pid_file() -> StratisResult<File> {
    let mut f = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(STRATISD_PID_PATH)
        .map_err(|err| {
            StratisError::Error(format!(
                "Failed to create or open the stratisd PID file at {}: {}",
                STRATISD_PID_PATH, err
            ))
        })?;
    match flock(f.as_raw_fd(), FlockArg::LockExclusiveNonblock) {
        Ok(_) => {
            f.write_all(getpid().to_string().as_bytes())?;
            Ok(f)
        }
        Err(_) => {
            let mut buf = String::new();
            f.read_to_string(&mut buf)?;

            Err(StratisError::Error(format!(
                "Daemon already running with supposed pid: {}",
                buf
            )))
        }
    }
}

// Conditionally compiled support for a D-Bus interface.
struct MaybeDbusSupport {
    #[cfg(feature = "dbus_enabled")]
    handle: Option<libstratis::dbus_api::DbusConnectionData>,
}

// If D-Bus compiled out, do very little.
#[cfg(not(feature = "dbus_enabled"))]
impl MaybeDbusSupport {
    fn new() -> MaybeDbusSupport {
        MaybeDbusSupport {}
    }

    fn process(
        &mut self,
        _engine: &Rc<RefCell<dyn Engine>>,
        _fds: &mut Vec<libc::pollfd>,
        _dbus_client_index_start: usize,
    ) {
    }

    fn register_pool(&mut self, _pool_uuid: Uuid, _pool: &mut dyn Pool) {}

    fn poll_timeout(&self) -> i32 {
        // Non-DBus timeout is infinite
        -1
    }
}

#[cfg(feature = "dbus_enabled")]
impl MaybeDbusSupport {
    fn new() -> MaybeDbusSupport {
        MaybeDbusSupport { handle: None }
    }

    /// Connect to D-Bus and register pools, if not already connected.
    /// Return the connection, if made or already existing, otherwise, None.
    fn setup_connection(
        &mut self,
        engine: &Rc<RefCell<dyn Engine>>,
    ) -> Option<&mut DbusConnectionData> {
        if self.handle.is_none() {
            match libstratis::dbus_api::DbusConnectionData::connect(Rc::clone(engine)) {
                Err(err) => {
                    warn!("D-Bus API is not available: {}", err);
                }
                Ok(mut handle) => {
                    info!("D-Bus API is available");
                    let event_handler = Box::new(EventHandler::new(Rc::clone(&handle.connection)));
                    get_engine_listener_list_mut().register_listener(event_handler);
                    // Register all the pools with dbus
                    for (_, pool_uuid, pool) in engine.borrow_mut().pools_mut() {
                        handle.register_pool(pool_uuid, pool)
                    }
                    self.handle = Some(handle);
                }
            }
        };
        self.handle.as_mut()
    }

    /// Handle any client dbus requests.
    fn process(
        &mut self,
        engine: &Rc<RefCell<dyn Engine>>,
        fds: &mut Vec<libc::pollfd>,
        dbus_client_index_start: usize,
    ) {
        if let Some(handle) = self.setup_connection(engine) {
            handle.handle(&fds[dbus_client_index_start..]);

            // Refresh list of dbus fds to poll for. This can change as
            // D-Bus clients come and go.
            fds.truncate(dbus_client_index_start);
            fds.extend(
                handle
                    .connection
                    .borrow()
                    .watch_fds()
                    .iter()
                    .map(|w| w.to_pollfd()),
            );
        }
    }

    fn register_pool(&mut self, pool_uuid: Uuid, pool: &mut dyn Pool) {
        if let Some(h) = self.handle.as_mut() {
            h.register_pool(pool_uuid, pool)
        }
    }

    fn poll_timeout(&self) -> i32 {
        // If there is no D-Bus connection set timeout to 1 sec (1000 ms), so
        // that stratisd can periodically attempt to set up a connection.
        // If the connection is up, set the timeout to infinite; there is no
        // need to poll as events will be received.
        self.handle.as_ref().map_or(1000, |_| -1)
    }
}

// A facility for listening for and handling udev events that stratisd
// considers interesting.
struct UdevMonitor<'a> {
    socket: libudev::MonitorSocket<'a>,
}

impl<'a> UdevMonitor<'a> {
    fn create(context: &'a libudev::Context) -> StratisResult<UdevMonitor<'a>> {
        let mut monitor = libudev::Monitor::new(context)?;
        monitor.match_subsystem("block")?;

        Ok(UdevMonitor {
            socket: monitor.listen()?,
        })
    }

    fn as_raw_fd(&mut self) -> RawFd {
        self.socket.as_raw_fd()
    }

    /// Handle udev events.
    /// Check if a pool can be constructed and update engine and D-Bus layer
    /// data structures if so.
    fn handle_events(&mut self, engine: &mut dyn Engine, dbus_support: &mut MaybeDbusSupport) {
        while let Some(event) = self.socket.receive_event() {
            if let Some((pool_uuid, pool)) = engine.handle_event(&event) {
                dbus_support.register_pool(pool_uuid, pool);
            }
        }
    }
}

// Process any pending signals, return true if SIGINT received.
// Return an error if there was an error reading the signal.
fn process_signal(
    sfd: &mut SignalFd,
    buff_log: &buff_log::Handle<env_logger::Logger>,
) -> StratisResult<bool> {
    match sfd.read_signal() {
        // This is an unsafe conversion, but in this context that is
        // mostly harmless. A negative converted value, which is
        // virtually impossible, will not match any of the masked
        // values, and stratisd will panic and exit.
        Ok(Some(sig)) => match sig.ssi_signo as i32 {
            nix::libc::SIGUSR1 => {
                info!(
                    "SIGUSR1 received, dumping {} buffered log entries",
                    buff_log.buffered_count()
                );
                buff_log.dump();
                Ok(false)
            }
            nix::libc::SIGINT => {
                info!("SIGINT received, exiting");
                Ok(true)
            }
            signo => {
                panic!("Caught an impossible signal {:?}", signo);
            }
        },
        // No signals waiting (SFD_NONBLOCK flag is set)
        Ok(None) => Ok(false),

        Err(err) => Err(err.into()),
    }
}

/// Handle blocking the event loop
fn process_poll(poll_timeout: i32, fds: &mut Vec<libc::pollfd>) -> StratisResult<()> {
    let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, poll_timeout) };

    // TODO: refine this behavior.
    // Different behaviors may be indicated, depending on the value of
    // errno when return value is -1.
    if r < 0 {
        return Err(StratisError::Error(format!(
            "poll command failed: number of fds: {}, timeout: {}",
            fds.len(),
            poll_timeout
        )));
    }
    Ok(())
}

/// Set up all sorts of signal and event handling mechanisms.
/// Initialize the engine and keep it running until a signal is received
/// or a fatal error is encountered. Dump log entries on specified signal
/// via buff_log.
fn run(matches: &ArgMatches, buff_log: &buff_log::Handle<env_logger::Logger>) -> StratisResult<()> {
    // Ensure that the debug log is output when we leave this function.
    let _guard = buff_log.to_guard();

    let mut dbus_support = MaybeDbusSupport::new();

    // Setup a udev listener before initializing the engine. A device may
    // appear after the engine has processed the udev db, but before it has
    // completed initialization. Unless the udev event has been recorded, the
    // engine will miss the device.
    // This is especially important since stratisd must run during early boot.
    let context = libudev::Context::new()?;
    let mut udev_monitor = UdevMonitor::create(&context)?;

    let engine: Rc<RefCell<dyn Engine>> = {
        info!("stratis daemon version {} started", VERSION);
        if matches.is_present("sim") {
            info!("Using SimEngine");
            Rc::new(RefCell::new(SimEngine::default()))
        } else {
            info!("Using StratEngine");
            Rc::new(RefCell::new(StratEngine::initialize()?))
        }
    };

    /*
    The file descriptor array indexes are:

    0   == Always udev fd index
    1   == SIGNAL FD index
    2   == engine index if eventable
    2/3 == Start of dbus client file descriptor(s)
            * 2 if engine is not eventable
            * else 3
    */
    const FD_INDEX_UDEV: usize = 0;
    const FD_INDEX_SIGNALFD: usize = 1;
    const FD_INDEX_ENGINE: usize = 2;

    /*
    fds is a Vec of libc::pollfd structs. Ideally, it would be possible
    to use the higher level nix crate to handle polling. If this were possible,
    then the Vec would be one of nix::poll::PollFds and this would be more
    rustic. Unfortunately, the rust D-Bus library requires an explicit file
    descriptor to be passed as an argument to Connection::watch_handle(),
    and the explicit file descriptor can not be extracted from the PollFd
    struct. So, at this time, sticking with libc is less complex than
    converting to using nix, because if using nix, the file descriptor would
    have to be maintained in the Vec as well as the PollFd struct.
    */
    let mut fds = Vec::new();

    fds.push(libc::pollfd {
        fd: udev_monitor.as_raw_fd(),
        revents: 0,
        events: libc::POLLIN,
    });

    // Signals can be queued up on this file descriptor
    let mut sfd = {
        let mut mask = SigSet::empty();
        mask.add(signal::SIGINT);
        mask.add(signal::SIGUSR1);
        mask.thread_block()?;
        SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK)?
    };

    fds.push(libc::pollfd {
        fd: sfd.as_raw_fd(),
        revents: 0,
        events: libc::POLLIN,
    });

    let eventable = engine.borrow().get_eventable();

    if let Some(evt) = eventable {
        fds.push(libc::pollfd {
            fd: evt.get_pollable_fd(),
            revents: 0,
            events: libc::POLLIN,
        });
    };

    let dbus_client_index_start = if eventable.is_some() {
        FD_INDEX_ENGINE + 1
    } else {
        FD_INDEX_ENGINE
    };

    loop {
        if fds[FD_INDEX_UDEV].revents != 0 {
            udev_monitor.handle_events(&mut *engine.borrow_mut(), &mut dbus_support)
        }

        if fds[FD_INDEX_SIGNALFD].revents != 0 {
            match process_signal(&mut sfd, buff_log) {
                Ok(should_exit) => {
                    if should_exit {
                        return Ok(());
                    }
                }
                Err(e) => return Err(e),
            }
        }

        if let Some(evt) = eventable {
            if fds[FD_INDEX_ENGINE].revents != 0 {
                evt.clear_event()?;
                engine.borrow_mut().evented()?;
            }
        }

        dbus_support.process(&engine, &mut fds, dbus_client_index_start);

        process_poll(dbus_support.poll_timeout(), &mut fds)?;
    }
}

fn main() {
    let matches = App::new("stratis")
        .version(VERSION)
        .about("Stratis storage management")
        .arg(
            Arg::with_name("debug")
                .long("debug")
                .help("Print additional output for debugging"),
        )
        .arg(
            Arg::with_name("sim")
                .long("sim")
                .help("Use simulator engine"),
        )
        .get_matches();

    // Using a let-expression here so that the scope of the lock file
    // is the rest of the block.
    let lock_file = trylock_pid_file();

    let result = {
        match lock_file {
            Err(err) => Err(err),
            Ok(_) => {
                let log_handle = initialize_log(matches.is_present("debug"));
                run(&matches, &log_handle)
            }
        }
    };

    if let Err(err) = result {
        print_err(&err);
        exit(1);
    } else {
        exit(0);
    }
}
<commit_msg>Get rid of unnecessary print_err method<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![allow(clippy::doc_markdown)]

#[macro_use]
extern crate log;

use std::{
    cell::RefCell,
    env,
    fs::{File, OpenOptions},
    io::{Read, Write},
    os::unix::io::{AsRawFd, RawFd},
    process::exit,
    rc::Rc,
};

use chrono::Duration;
use clap::{App, Arg, ArgMatches};
use env_logger::Builder;
use log::LevelFilter;
use nix::{
    fcntl::{flock, FlockArg},
    sys::{
        signal::{self, SigSet},
        signalfd::{SfdFlags, SignalFd},
    },
    unistd::getpid,
};
use uuid::Uuid;

#[cfg(feature = "dbus_enabled")]
use libstratis::{
    dbus_api::{DbusConnectionData, EventHandler},
    engine::get_engine_listener_list_mut,
};

use libstratis::{
    engine::{Engine, Pool, SimEngine, StratEngine},
    stratis::{buff_log, StratisError, StratisResult, VERSION},
};

const STRATISD_PID_PATH: &str = "/run/stratisd.pid";

/// Number of minutes to buffer log entries.
const DEFAULT_LOG_HOLD_MINUTES: i64 = 30;

/// Configure the env_logger as necessary in order to allow the buffered
/// logger to work correctly. Return a Handle to the underlying env_logger.
pub fn from_env_logger(
    mut builder: env_logger::Builder,
    pass_through: bool,
    hold_time: Option<Duration>,
) -> buff_log::Handle<env_logger::Logger> {
    // Do not have the env_logger set the timestamp. Because the entries are
    // buffered, the timestamp set by the env_logger will correspond to the
    // time at which the entry was dumped, not the time of its origination.
    builder.default_format_timestamp(false);
    buff_log::Logger::new(builder.build(), pass_through, hold_time).init()
}

/// Configure and initialize the logger.
/// If debug is true, log at debug level. Otherwise read log configuration
/// parameters from the environment if RUST_LOG is set. Otherwise, just
/// accept the default configuration.
fn initialize_log(debug: bool) -> buff_log::Handle<env_logger::Logger> {
    let mut builder = Builder::new();
    if debug {
        builder.filter(Some("stratisd"), LevelFilter::Debug);
        builder.filter(Some("libstratis"), LevelFilter::Debug);
        from_env_logger(builder, true, None)
    } else {
        builder.filter_level(LevelFilter::Trace);
        if let Ok(s) = env::var("RUST_LOG") {
            builder.parse(&s);
        }
        from_env_logger(
            builder,
            false,
            Some(Duration::minutes(DEFAULT_LOG_HOLD_MINUTES)),
        )
    }
}

/// To ensure only one instance of stratisd runs at a time, acquire an
/// exclusive lock. Return an error if lock attempt fails.
fn trylock_pid_file() -> StratisResult<File> {
    let mut f = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(STRATISD_PID_PATH)
        .map_err(|err| {
            StratisError::Error(format!(
                "Failed to create or open the stratisd PID file at {}: {}",
                STRATISD_PID_PATH, err
            ))
        })?;
    match flock(f.as_raw_fd(), FlockArg::LockExclusiveNonblock) {
        Ok(_) => {
            f.write_all(getpid().to_string().as_bytes())?;
            Ok(f)
        }
        Err(_) => {
            let mut buf = String::new();
            f.read_to_string(&mut buf)?;

            Err(StratisError::Error(format!(
                "Daemon already running with supposed pid: {}",
                buf
            )))
        }
    }
}

// Conditionally compiled support for a D-Bus interface.
struct MaybeDbusSupport {
    #[cfg(feature = "dbus_enabled")]
    handle: Option<libstratis::dbus_api::DbusConnectionData>,
}

// If D-Bus compiled out, do very little.
#[cfg(not(feature = "dbus_enabled"))]
impl MaybeDbusSupport {
    fn new() -> MaybeDbusSupport {
        MaybeDbusSupport {}
    }

    fn process(
        &mut self,
        _engine: &Rc<RefCell<dyn Engine>>,
        _fds: &mut Vec<libc::pollfd>,
        _dbus_client_index_start: usize,
    ) {
    }

    fn register_pool(&mut self, _pool_uuid: Uuid, _pool: &mut dyn Pool) {}

    fn poll_timeout(&self) -> i32 {
        // Non-DBus timeout is infinite
        -1
    }
}

#[cfg(feature = "dbus_enabled")]
impl MaybeDbusSupport {
    fn new() -> MaybeDbusSupport {
        MaybeDbusSupport { handle: None }
    }

    /// Connect to D-Bus and register pools, if not already connected.
    /// Return the connection, if made or already existing, otherwise, None.
    fn setup_connection(
        &mut self,
        engine: &Rc<RefCell<dyn Engine>>,
    ) -> Option<&mut DbusConnectionData> {
        if self.handle.is_none() {
            match libstratis::dbus_api::DbusConnectionData::connect(Rc::clone(engine)) {
                Err(err) => {
                    warn!("D-Bus API is not available: {}", err);
                }
                Ok(mut handle) => {
                    info!("D-Bus API is available");
                    let event_handler = Box::new(EventHandler::new(Rc::clone(&handle.connection)));
                    get_engine_listener_list_mut().register_listener(event_handler);
                    // Register all the pools with dbus
                    for (_, pool_uuid, pool) in engine.borrow_mut().pools_mut() {
                        handle.register_pool(pool_uuid, pool)
                    }
                    self.handle = Some(handle);
                }
            }
        };
        self.handle.as_mut()
    }

    /// Handle any client dbus requests.
    fn process(
        &mut self,
        engine: &Rc<RefCell<dyn Engine>>,
        fds: &mut Vec<libc::pollfd>,
        dbus_client_index_start: usize,
    ) {
        if let Some(handle) = self.setup_connection(engine) {
            handle.handle(&fds[dbus_client_index_start..]);

            // Refresh list of dbus fds to poll for. This can change as
            // D-Bus clients come and go.
            fds.truncate(dbus_client_index_start);
            fds.extend(
                handle
                    .connection
                    .borrow()
                    .watch_fds()
                    .iter()
                    .map(|w| w.to_pollfd()),
            );
        }
    }

    fn register_pool(&mut self, pool_uuid: Uuid, pool: &mut dyn Pool) {
        if let Some(h) = self.handle.as_mut() {
            h.register_pool(pool_uuid, pool)
        }
    }

    fn poll_timeout(&self) -> i32 {
        // If there is no D-Bus connection set timeout to 1 sec (1000 ms), so
        // that stratisd can periodically attempt to set up a connection.
        // If the connection is up, set the timeout to infinite; there is no
        // need to poll as events will be received.
        self.handle.as_ref().map_or(1000, |_| -1)
    }
}

// A facility for listening for and handling udev events that stratisd
// considers interesting.
struct UdevMonitor<'a> {
    socket: libudev::MonitorSocket<'a>,
}

impl<'a> UdevMonitor<'a> {
    fn create(context: &'a libudev::Context) -> StratisResult<UdevMonitor<'a>> {
        let mut monitor = libudev::Monitor::new(context)?;
        monitor.match_subsystem("block")?;

        Ok(UdevMonitor {
            socket: monitor.listen()?,
        })
    }

    fn as_raw_fd(&mut self) -> RawFd {
        self.socket.as_raw_fd()
    }

    /// Handle udev events.
    /// Check if a pool can be constructed and update engine and D-Bus layer
    /// data structures if so.
    fn handle_events(&mut self, engine: &mut dyn Engine, dbus_support: &mut MaybeDbusSupport) {
        while let Some(event) = self.socket.receive_event() {
            if let Some((pool_uuid, pool)) = engine.handle_event(&event) {
                dbus_support.register_pool(pool_uuid, pool);
            }
        }
    }
}

// Process any pending signals, return true if SIGINT received.
// Return an error if there was an error reading the signal.
fn process_signal(
    sfd: &mut SignalFd,
    buff_log: &buff_log::Handle<env_logger::Logger>,
) -> StratisResult<bool> {
    match sfd.read_signal() {
        // This is an unsafe conversion, but in this context that is
        // mostly harmless. A negative converted value, which is
        // virtually impossible, will not match any of the masked
        // values, and stratisd will panic and exit.
        Ok(Some(sig)) => match sig.ssi_signo as i32 {
            nix::libc::SIGUSR1 => {
                info!(
                    "SIGUSR1 received, dumping {} buffered log entries",
                    buff_log.buffered_count()
                );
                buff_log.dump();
                Ok(false)
            }
            nix::libc::SIGINT => {
                info!("SIGINT received, exiting");
                Ok(true)
            }
            signo => {
                panic!("Caught an impossible signal {:?}", signo);
            }
        },
        // No signals waiting (SFD_NONBLOCK flag is set)
        Ok(None) => Ok(false),

        Err(err) => Err(err.into()),
    }
}

/// Handle blocking the event loop
fn process_poll(poll_timeout: i32, fds: &mut Vec<libc::pollfd>) -> StratisResult<()> {
    let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, poll_timeout) };

    // TODO: refine this behavior.
    // Different behaviors may be indicated, depending on the value of
    // errno when return value is -1.
    if r < 0 {
        return Err(StratisError::Error(format!(
            "poll command failed: number of fds: {}, timeout: {}",
            fds.len(),
            poll_timeout
        )));
    }
    Ok(())
}

/// Set up all sorts of signal and event handling mechanisms.
/// Initialize the engine and keep it running until a signal is received
/// or a fatal error is encountered. Dump log entries on specified signal
/// via buff_log.
fn run(matches: &ArgMatches, buff_log: &buff_log::Handle<env_logger::Logger>) -> StratisResult<()> {
    // Ensure that the debug log is output when we leave this function.
    let _guard = buff_log.to_guard();

    let mut dbus_support = MaybeDbusSupport::new();

    // Setup a udev listener before initializing the engine. A device may
    // appear after the engine has processed the udev db, but before it has
    // completed initialization. Unless the udev event has been recorded, the
    // engine will miss the device.
    // This is especially important since stratisd must run during early boot.
    let context = libudev::Context::new()?;
    let mut udev_monitor = UdevMonitor::create(&context)?;

    let engine: Rc<RefCell<dyn Engine>> = {
        info!("stratis daemon version {} started", VERSION);
        if matches.is_present("sim") {
            info!("Using SimEngine");
            Rc::new(RefCell::new(SimEngine::default()))
        } else {
            info!("Using StratEngine");
            Rc::new(RefCell::new(StratEngine::initialize()?))
        }
    };

    /*
    The file descriptor array indexes are:

    0   == Always udev fd index
    1   == SIGNAL FD index
    2   == engine index if eventable
    2/3 == Start of dbus client file descriptor(s)
            * 2 if engine is not eventable
            * else 3
    */
    const FD_INDEX_UDEV: usize = 0;
    const FD_INDEX_SIGNALFD: usize = 1;
    const FD_INDEX_ENGINE: usize = 2;

    /*
    fds is a Vec of libc::pollfd structs. Ideally, it would be possible
    to use the higher level nix crate to handle polling. If this were possible,
    then the Vec would be one of nix::poll::PollFds and this would be more
    rustic. Unfortunately, the rust D-Bus library requires an explicit file
    descriptor to be passed as an argument to Connection::watch_handle(),
    and the explicit file descriptor can not be extracted from the PollFd
    struct. So, at this time, sticking with libc is less complex than
    converting to using nix, because if using nix, the file descriptor would
    have to be maintained in the Vec as well as the PollFd struct.
    */
    let mut fds = Vec::new();

    fds.push(libc::pollfd {
        fd: udev_monitor.as_raw_fd(),
        revents: 0,
        events: libc::POLLIN,
    });

    // Signals can be queued up on this file descriptor
    let mut sfd = {
        let mut mask = SigSet::empty();
        mask.add(signal::SIGINT);
        mask.add(signal::SIGUSR1);
        mask.thread_block()?;
        SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK)?
    };

    fds.push(libc::pollfd {
        fd: sfd.as_raw_fd(),
        revents: 0,
        events: libc::POLLIN,
    });

    let eventable = engine.borrow().get_eventable();

    if let Some(evt) = eventable {
        fds.push(libc::pollfd {
            fd: evt.get_pollable_fd(),
            revents: 0,
            events: libc::POLLIN,
        });
    };

    let dbus_client_index_start = if eventable.is_some() {
        FD_INDEX_ENGINE + 1
    } else {
        FD_INDEX_ENGINE
    };

    loop {
        if fds[FD_INDEX_UDEV].revents != 0 {
            udev_monitor.handle_events(&mut *engine.borrow_mut(), &mut dbus_support)
        }

        if fds[FD_INDEX_SIGNALFD].revents != 0 {
            match process_signal(&mut sfd, buff_log) {
                Ok(should_exit) => {
                    if should_exit {
                        return Ok(());
                    }
                }
                Err(e) => return Err(e),
            }
        }

        if let Some(evt) = eventable {
            if fds[FD_INDEX_ENGINE].revents != 0 {
                evt.clear_event()?;
                engine.borrow_mut().evented()?;
            }
        }

        dbus_support.process(&engine, &mut fds, dbus_client_index_start);

        process_poll(dbus_support.poll_timeout(), &mut fds)?;
    }
}

fn main() {
    let matches = App::new("stratis")
        .version(VERSION)
        .about("Stratis storage management")
        .arg(
            Arg::with_name("debug")
                .long("debug")
                .help("Print additional output for debugging"),
        )
        .arg(
            Arg::with_name("sim")
                .long("sim")
                .help("Use simulator engine"),
        )
        .get_matches();

    // Using a let-expression here so that the scope of the lock file
    // is the rest of the block.
    let lock_file = trylock_pid_file();

    let result = {
        match lock_file {
            Err(err) => Err(err),
            Ok(_) => {
                let log_handle = initialize_log(matches.is_present("debug"));
                run(&matches, &log_handle)
            }
        }
    };

    if let Err(err) = result {
        eprintln!("{}", err);
        exit(1);
    } else {
        exit(0);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
use borrow_check::nll::type_check::liveness::liveness_map::{LocalWithRegion, NllLivenessMap};
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::vec_linked_list as vll;
use util::liveness::{categorize, DefUse, LiveVariableMap};

/// A map that cross references each local with the locations where it
/// is defined (assigned), used, or dropped. Used during liveness
/// computation.
crate struct LocalUseMap<'me> {
    liveness_map: &'me NllLivenessMap,

    /// Head of a linked list of **definitions** of each variable --
    /// definition in this context means assignment, e.g. `x` is
    /// defined in `x = y` but not `y`; that first def is the head of
    /// a linked list that lets you enumerate all places the variable
    /// is assigned.
    first_def_at: IndexVec<LocalWithRegion, Option<AppearanceIndex>>,

    /// Head of a linked list of **uses** of each variable -- use in
    /// this context means that the existing value of the variable is
    /// read or modified. e.g., `y` is used in `x = y` but not `x`.
    first_use_at: IndexVec<LocalWithRegion, Option<AppearanceIndex>>,

    /// Head of a linked list of **uses** of each variable -- use in
    /// this context means that the existing value of the variable is
    /// read or modified. e.g., `y` is used in `x = y` but not `x`.
    first_drop_at: IndexVec<LocalWithRegion, Option<AppearanceIndex>>,

    appearances: IndexVec<AppearanceIndex, Appearance>,
}

struct Appearance {
    point_index: PointIndex,
    next: Option<AppearanceIndex>,
}

newtype_index!(AppearanceIndex);

impl vll::LinkElem for Appearance {
    type LinkIndex = AppearanceIndex;

    fn next(elem: &Self) -> Option<AppearanceIndex> {
        elem.next
    }
}

impl LocalUseMap<'me> {
    crate fn build(
        liveness_map: &'me NllLivenessMap,
        elements: &RegionValueElements,
        mir: &Mir<'_>,
    ) -> Self {
        let nones = IndexVec::from_elem_n(None, liveness_map.num_variables());
        let mut local_use_map = LocalUseMap {
            liveness_map,
            first_def_at: nones.clone(),
            first_use_at: nones.clone(),
            first_drop_at: nones,
            appearances: IndexVec::new(),
        };

        LocalUseMapBuild {
            local_use_map: &mut local_use_map,
            elements,
        }.visit_mir(mir);

        local_use_map
    }

    crate fn defs(&self, local: LocalWithRegion) -> impl Iterator<Item = PointIndex> + '_ {
        vll::iter(self.first_def_at[local], &self.appearances)
            .map(move |aa| self.appearances[aa].point_index)
    }

    crate fn uses(&self, local: LocalWithRegion) -> impl Iterator<Item = PointIndex> + '_ {
        vll::iter(self.first_use_at[local], &self.appearances)
            .map(move |aa| self.appearances[aa].point_index)
    }

    crate fn drops(&self, local: LocalWithRegion) -> impl Iterator<Item = PointIndex> + '_ {
        vll::iter(self.first_drop_at[local], &self.appearances)
            .map(move |aa| self.appearances[aa].point_index)
    }
}

struct LocalUseMapBuild<'me, 'map> {
    local_use_map: &'me mut LocalUseMap<'map>,
    elements: &'me RegionValueElements,
}

impl LocalUseMapBuild<'_, '_> {
    fn insert_def(&mut self, local: LocalWithRegion, location: Location) {
        Self::insert(
            self.elements,
            &mut self.local_use_map.first_def_at[local],
            &mut self.local_use_map.appearances,
            location,
        );
    }

    fn insert_use(&mut self, local: LocalWithRegion, location: Location) {
        Self::insert(
            self.elements,
            &mut self.local_use_map.first_use_at[local],
            &mut self.local_use_map.appearances,
            location,
        );
    }

    fn insert_drop(&mut self, local: LocalWithRegion, location: Location) {
        Self::insert(
            self.elements,
            &mut self.local_use_map.first_drop_at[local],
            &mut self.local_use_map.appearances,
            location,
        );
    }

    fn insert(
        elements: &RegionValueElements,
        first_appearance: &mut Option<AppearanceIndex>,
        appearances: &mut IndexVec<AppearanceIndex, Appearance>,
        location: Location,
    ) {
        let point_index = elements.point_from_location(location);
        let appearance_index = appearances.push(Appearance {
            point_index,
            next: *first_appearance,
        });
        *first_appearance = Some(appearance_index);
    }
}

impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> {
    fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) {
        if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) {
            match categorize(context) {
                Some(DefUse::Def) => self.insert_def(local_with_region, location),
                Some(DefUse::Use) => self.insert_use(local_with_region, location),
                Some(DefUse::Drop) => self.insert_drop(local_with_region, location),
                _ => (),
            }
        }
    }
}
<commit_msg>fix comment<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
use borrow_check::nll::type_check::liveness::liveness_map::{LocalWithRegion, NllLivenessMap};
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::vec_linked_list as vll;
use util::liveness::{categorize, DefUse, LiveVariableMap};

/// A map that cross references each local with the locations where it
/// is defined (assigned), used, or dropped. Used during liveness
/// computation.
crate struct LocalUseMap<'me> {
    liveness_map: &'me NllLivenessMap,

    /// Head of a linked list of **definitions** of each variable --
    /// definition in this context means assignment, e.g. `x` is
    /// defined in `x = y` but not `y`; that first def is the head of
    /// a linked list that lets you enumerate all places the variable
    /// is assigned.
    first_def_at: IndexVec<LocalWithRegion, Option<AppearanceIndex>>,

    /// Head of a linked list of **uses** of each variable -- use in
    /// this context means that the existing value of the variable is
    /// read or modified. e.g., `y` is used in `x = y` but not `x`.
    /// Note that `DROP(x)` terminators are excluded from this list.
    first_use_at: IndexVec<LocalWithRegion, Option<AppearanceIndex>>,

    /// Head of a linked list of **drops** of each variable -- these
    /// are a special category of uses corresponding to the drop that
    /// we add for each local variable.
    first_drop_at: IndexVec<LocalWithRegion, Option<AppearanceIndex>>,

    appearances: IndexVec<AppearanceIndex, Appearance>,
}

struct Appearance {
    point_index: PointIndex,
    next: Option<AppearanceIndex>,
}

newtype_index!(AppearanceIndex);

impl vll::LinkElem for Appearance {
    type LinkIndex = AppearanceIndex;

    fn next(elem: &Self) -> Option<AppearanceIndex> {
        elem.next
    }
}

impl LocalUseMap<'me> {
    crate fn build(
        liveness_map: &'me NllLivenessMap,
        elements: &RegionValueElements,
        mir: &Mir<'_>,
    ) -> Self {
        let nones = IndexVec::from_elem_n(None, liveness_map.num_variables());
        let mut local_use_map = LocalUseMap {
            liveness_map,
            first_def_at: nones.clone(),
            first_use_at: nones.clone(),
            first_drop_at: nones,
            appearances: IndexVec::new(),
        };

        LocalUseMapBuild {
            local_use_map: &mut local_use_map,
            elements,
        }.visit_mir(mir);

        local_use_map
    }

    crate fn defs(&self, local: LocalWithRegion) -> impl Iterator<Item = PointIndex> + '_ {
        vll::iter(self.first_def_at[local], &self.appearances)
            .map(move |aa| self.appearances[aa].point_index)
    }

    crate fn uses(&self, local: LocalWithRegion) -> impl Iterator<Item = PointIndex> + '_ {
        vll::iter(self.first_use_at[local], &self.appearances)
            .map(move |aa| self.appearances[aa].point_index)
    }

    crate fn drops(&self, local: LocalWithRegion) -> impl Iterator<Item = PointIndex> + '_ {
        vll::iter(self.first_drop_at[local], &self.appearances)
            .map(move |aa| self.appearances[aa].point_index)
    }
}

struct LocalUseMapBuild<'me, 'map> {
    local_use_map: &'me mut LocalUseMap<'map>,
    elements: &'me RegionValueElements,
}

impl LocalUseMapBuild<'_, '_> {
    fn insert_def(&mut self, local: LocalWithRegion, location: Location) {
        Self::insert(
            self.elements,
            &mut self.local_use_map.first_def_at[local],
            &mut self.local_use_map.appearances,
            location,
        );
    }

    fn insert_use(&mut self, local: LocalWithRegion, location: Location) {
        Self::insert(
            self.elements,
            &mut self.local_use_map.first_use_at[local],
            &mut self.local_use_map.appearances,
            location,
        );
    }

    fn insert_drop(&mut self, local: LocalWithRegion, location: Location) {
        Self::insert(
            self.elements,
            &mut self.local_use_map.first_drop_at[local],
            &mut self.local_use_map.appearances,
            location,
        );
    }

    fn insert(
        elements: &RegionValueElements,
        first_appearance: &mut Option<AppearanceIndex>,
        appearances: &mut IndexVec<AppearanceIndex, Appearance>,
        location: Location,
    ) {
        let point_index = elements.point_from_location(location);
        let appearance_index = appearances.push(Appearance {
            point_index,
            next: *first_appearance,
        });
        *first_appearance = Some(appearance_index);
    }
}

impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> {
    fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) {
        if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) {
            match categorize(context) {
                Some(DefUse::Def) => self.insert_def(local_with_region, location),
                Some(DefUse::Use) => self.insert_use(local_with_region, location),
                Some(DefUse::Drop) => self.insert_drop(local_with_region, location),
                _ => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>use common::{R};
use monomial::Monomial;
use polynomial::{Polynomial, PolyBorrowingMons};
use dense_matrix::DenseMatrix;
use mesh::{Mesh, FENum, OShape, SideFace};
use wg_basis::{WgBasis, FaceMonNum, BasisElNum};
use projection::Projector;
use variational_bilinear_form::VariationalBilinearForm;

use std::hashmap::HashMap;
use vbf_laplace::VBFLaplace;

/* METHOD
 * Let {b_i}_i be a basis for V_h^0(Omega), and vbf the bilinear form for
 * the variational problem.  Then the WG approximate solution u_h satisfies
 *   vbf(u_h, v) = (f, v_0) for all v in V_h^0(Omega)
 * Since the {b_i}_i are a basis for V_H^0, this holds iff
 *   vbf(u_h, b_i) = (f, (b_i)_0) for all basis elements b_i
 *
 * With
 *   u_h = sum_j{eta_j b_j} + Q_b g, where Q_b is L2 projection on each segment of
 * the outside boundary of Omega and 0 elsewhere, this becomes
 *   vbf(sum_j{eta_j b_j} + Q_b g, b_i) = (f, (b_i)_0) for all i,
 * ie.,
 *   (sys)
 *         sum_j{ vbf(b_j, b_i) eta_j } = (f, (b_i)_0) - vbf(Q_b g, b_i) for all i
 *
 * which is a linear system we can solve for the unknown eta_j coefficients defining u_h.
 * Note that the matrix for the system m is given by m_{i,j} = vbf(b_j, b_i), which is
 * the *transpose* of the basis-vs-basis vbf values matrix.
 */

struct WgSolution<'self,Mon,MeshT> {
  basis_coefs: ~[R],
  basis: &'self WgBasis<Mon,MeshT>
}

/*
pub fn solve<'self, Mon: Monomial, MeshT: Mesh<Mon>, VBF: VariationalBilinearForm<'self, Mon, MeshT>>
       (vbf: &'self VBF, f: &fn(&[R])->R, g: &fn(&[R])->R) -> WgSolution<'self,Mon,MeshT> {
*/
fn solve_laplace<'a, Mon:Monomial, MeshT:Mesh<Mon>>
       (basis: &'a WgBasis<Mon,MeshT>, f: &fn(&[R])->R, g: &fn(&[R])->R) -> WgSolution<'a,Mon,MeshT> {

  // TODO: Replace with vbf trait parameter when Rust internal compiler error is fixed. https://github.com/mozilla/rust/issues/10201
  let vbf = &VBFLaplace::new(None, basis);

  let boundary_projs = &boundary_projections(g, basis);

  let sys_matrix = vbf.basis_els_vs_basis_els_transpose();

  let sys_rhs = DenseMatrix::from_fn(basis.num_els(), 1, |i,_|
    ip_on_ints(|x|f(x), BasisElNum(i), basis)
    -
    vbf_boundary_projs_vs_bel(vbf, boundary_projs, BasisElNum(i), basis)
  );

/* TODO: Do sparse solve here.
  const sol_basis_coefs = m \ sys_rhs(f, g_projs, wg_solver.vbf, wg_solver.basis)
  WGSolution(vec(sol_basis_coefs), g_projs, wg_solver.basis)
*/
  WgSolution {
    basis_coefs: ~[], // TODO
    basis: basis,
  }
}

fn ip_on_ints<Mon:Monomial, MeshT: Mesh<Mon>>
   (f: &fn(&[R])->R,
    bel: BasisElNum,
    basis: &WgBasis<Mon,MeshT>) -> R {
  if basis.is_int_supported(bel) { 0 as R }
  else {
    let (bel_fe, bel_mon) = (basis.support_int_fe_num(bel), basis.int_mon(bel));
    basis.mesh().intg_global_fn_x_facerel_mon_on_fe_int(f, bel_mon, bel_fe)
  }
}

// Evaluate the variational bilinear form for the projection of the boundary value function g
// onto outside boundary segments vs. the given basis element. This is the vbf(Q_b g, b_i) term
// of the right hand side of (sys). The implementation uses the Element Summability and Locality
// properties of supported variational forms (see VBF module for a discussion).
fn vbf_boundary_projs_vs_bel<'a, Mon:Monomial, MeshT: Mesh<Mon>>
   (vbf: &VBFLaplace<'a,Mon,MeshT>,
    boundary_projs: &BoundaryProjections<'a,Mon>,
    bel: BasisElNum,
    basis: &WgBasis<Mon,MeshT>) -> R {

  let mesh = basis.mesh();

  if basis.is_int_supported(bel) {
    // Only boundary sides which are included in the bel's supporting fe can contribute.
    let fe = basis.support_int_fe_num(bel);
    let fe_oshape = mesh.oriented_shape_for_fe(fe);
    let bel_monn = basis.int_rel_mon_num(bel);
    // Sum of vbf(p,bel) for all boundary side projections p on the boundary sides of bel's fe.
    range(0, mesh.num_side_faces_for_shape(fe_oshape)).fold(0 as R, |sum, sf| {
        match boundary_projs.find(&(fe, SideFace(sf))) {
          Some(bnd_proj) => {
            bnd_proj.foldl_numbered_terms(sum, |sum, (proj_monn, proj_coef, _)| {
              sum + proj_coef * vbf.side_mon_vs_int_mon(fe_oshape,
                                                        FaceMonNum(proj_monn), SideFace(sf), // bnd proj mon and sf
                                                        bel_monn)                            // int basis el
            })
          }
          None => sum
        }
      })
  }
  else { // Side supported - only projections on boundary sides on one of the two including fe's can contribute.
    let bel_monn = basis.side_rel_mon_num(bel);
    let fe_incls_of_bel_supp = {
      let incls = basis.fe_inclusions_of_side_support(bel);
      [(incls.fe1, incls.side_face_in_fe1),
       (incls.fe2, incls.side_face_in_fe2)]
    };
    // Sum contributions from projections on boundary sides (if any) of both including fe's against the basis element.
    fe_incls_of_bel_supp.iter().fold(0 as R, |sum, &(fe, bel_sf)| {
      let fe_oshape = mesh.oriented_shape_for_fe(fe);
      range(0, mesh.num_side_faces_for_shape(fe_oshape)).fold(sum, |sum, sf| {
        match boundary_projs.find(&(fe, SideFace(sf))) {
          Some(bnd_proj) =>
            bnd_proj.foldl_numbered_terms(sum, |sum, (proj_monn, proj_coef, _)| {
              sum + proj_coef * vbf.side_mon_vs_side_mon_fe_contr(fe_oshape,
                                                                  FaceMonNum(proj_monn), SideFace(sf), // bnd proj mon and side face
                                                                  bel_monn, bel_sf)                    // basis el mon and side face
            }),
          None => sum
        }
      })
    })
  }
}

type BoundaryProjections<'self,Mon> = HashMap<(FENum,SideFace), PolyBorrowingMons<'self,Mon>>;

fn boundary_projections<'a, Mon: Monomial, MeshT: Mesh<Mon>>
   (g: &fn(&[R])->R, basis: &'a WgBasis<Mon,MeshT>) -> BoundaryProjections<'a, Mon> {

  let mut projector = Projector::new(basis);

  let mut projs_by_fe_sf = HashMap::with_capacity(basis.mesh().num_boundary_sides());

  let b_fes_by_oshape_sf = basis.mesh().boundary_fes_by_oshape_side();

  for (fes_oshape, oshape_b_fes_by_sf) in b_fes_by_oshape_sf.iter().enumerate() {
    for (sf, fes) in oshape_b_fes_by_sf.iter().enumerate() {
      let fes_projs = projector.projs_to_span_fes_side_supp_basis_els(|x|g(x), *fes, OShape(fes_oshape), SideFace(sf));
      for (proj_poly, fe) in fes_projs.move_iter().zip(fes.iter()) {
        projs_by_fe_sf.insert((*fe, SideFace(sf)), proj_poly);
      }
    }
  }

  projs_by_fe_sf
}

<commit_msg>Add boundary projections to solution structure.<commit_after>use common::{R};
use monomial::Monomial;
use polynomial::{Polynomial, PolyBorrowingMons};
use dense_matrix::DenseMatrix;
use mesh::{Mesh, FENum, OShape, SideFace};
use wg_basis::{WgBasis, FaceMonNum, BasisElNum};
use projection::Projector;
use variational_bilinear_form::VariationalBilinearForm;
use lapack;

use std::hashmap::HashMap;
use vbf_laplace::VBFLaplace; // TODO: remove when Rust ICE is fixed

/* METHOD
 * Let {b_i}_i be a basis for V_h^0(Omega), and vbf the bilinear form for
 * the variational problem.  Then the WG approximate solution u_h satisfies
 *   vbf(u_h, v) = (f, v_0) for all v in V_h^0(Omega)
 * Since the {b_i}_i are a basis for V_H^0, this holds iff
 *   vbf(u_h, b_i) = (f, (b_i)_0) for all basis elements b_i
 *
 * With
 *   u_h = sum_j{eta_j b_j} + Q_b g, where Q_b is L2 projection on each segment of
 * the outside boundary of Omega and 0 elsewhere, this becomes
 *   vbf(sum_j{eta_j b_j} + Q_b g, b_i) = (f, (b_i)_0) for all i,
 * ie.,
 *   (sys)
 *         sum_j{ vbf(b_j, b_i) eta_j } = (f, (b_i)_0) - vbf(Q_b g, b_i) for all i
 *
 * which is a linear system we can solve for the unknown eta_j coefficients defining u_h.
 * Note that the matrix for the system m is given by m_{i,j} = vbf(b_j, b_i), which is
 * the *transpose* of the basis-vs-basis vbf values matrix.
 */

struct WgSolution<'self,Mon,MeshT> {
  basis_coefs: ~[R],
  basis: &'self WgBasis<Mon,MeshT>,
  bnd_projs: BoundaryProjections<'self,Mon>
}

/*
pub fn solve<'self, Mon: Monomial, MeshT: Mesh<Mon>, VBF: VariationalBilinearForm<'self, Mon, MeshT>>
       (vbf: &'self VBF, f: &fn(&[R])->R, g: &fn(&[R])->R) -> WgSolution<'self,Mon,MeshT> {
*/
fn solve_laplace<'a, Mon:Monomial, MeshT:Mesh<Mon>>
   (basis: &'a WgBasis<Mon,MeshT>, f: &fn(&[R])->R, g: &fn(&[R])->R) -> WgSolution<'a,Mon,MeshT> {

  // TODO: Replace with vbf trait parameter when Rust internal compiler error is fixed. https://github.com/mozilla/rust/issues/10201
  let vbf = &VBFLaplace::new(None, basis);

  let bnd_projs = boundary_projections(g, basis);

  let sys_m = vbf.basis_els_vs_basis_els_transpose();

  let sys_rhs = DenseMatrix::from_fn(basis.num_els(), 1, |i,_|
    ip_on_ints(|x|f(x), BasisElNum(i), basis)
    -
    vbf_bnd_projs_vs_bel(vbf, &bnd_projs, BasisElNum(i), basis)
  );

  let sol = lapack::solve_sparse_structurally_symmetric(&sys_m, &sys_rhs, vbf.is_symmetric());

  WgSolution {
    basis_coefs: sol,
    basis: basis,
    bnd_projs: bnd_projs,
  }
}

fn ip_on_ints<Mon:Monomial, MeshT: Mesh<Mon>>
   (f: &fn(&[R])->R,
    bel: BasisElNum,
    basis: &WgBasis<Mon,MeshT>) -> R {
  if basis.is_int_supported(bel) { 0 as R }
  else {
    let (bel_fe, bel_mon) = (basis.support_int_fe_num(bel), basis.int_mon(bel));
    basis.mesh().intg_global_fn_x_facerel_mon_on_fe_int(f, bel_mon, bel_fe)
  }
}

// Evaluate the variational bilinear form for the projection of the boundary value function g
// onto outside boundary segments vs. the given basis element. This is the vbf(Q_b g, b_i) term
// of the right hand side of (sys). The implementation uses the Element Summability and Locality
// properties of supported variational forms (see VBF module for a discussion).
fn vbf_bnd_projs_vs_bel<'a, Mon:Monomial, MeshT: Mesh<Mon>>
   (vbf: &VBFLaplace<'a,Mon,MeshT>,
    bnd_projs: &BoundaryProjections<'a,Mon>,
    bel: BasisElNum,
    basis: &WgBasis<Mon,MeshT>) -> R {

  let mesh = basis.mesh();

  if basis.is_int_supported(bel) {
    // Only boundary sides which are included in the bel's supporting fe can contribute.
    let fe = basis.support_int_fe_num(bel);
    let fe_oshape = mesh.oriented_shape_for_fe(fe);
    let bel_monn = basis.int_rel_mon_num(bel);
    // Sum of vbf(p,bel) for all boundary side projections p on the boundary sides of bel's fe.
    range(0, mesh.num_side_faces_for_shape(fe_oshape)).fold(0 as R, |sum, sf| {
        match bnd_projs.find(&(fe, SideFace(sf))) {
          Some(bnd_proj) => {
            bnd_proj.foldl_numbered_terms(sum, |sum, (proj_monn, proj_coef, _)| {
              sum + proj_coef * vbf.side_mon_vs_int_mon(fe_oshape,
                                                        FaceMonNum(proj_monn), SideFace(sf), // bnd proj mon and sf
                                                        bel_monn)                            // int basis el
            })
          }
          None => sum
        }
      })
  }
  else { // Side supported - only projections on boundary sides on one of the two including fe's can contribute.
    let bel_monn = basis.side_rel_mon_num(bel);
    let fe_incls_of_bel_supp = {
      let incls = basis.fe_inclusions_of_side_support(bel);
      [(incls.fe1, incls.side_face_in_fe1),
       (incls.fe2, incls.side_face_in_fe2)]
    };
    // Sum contributions from projections on boundary sides (if any) of both including fe's against the basis element.
    fe_incls_of_bel_supp.iter().fold(0 as R, |sum, &(fe, bel_sf)| {
      let fe_oshape = mesh.oriented_shape_for_fe(fe);
      range(0, mesh.num_side_faces_for_shape(fe_oshape)).fold(sum, |sum, sf| {
        match bnd_projs.find(&(fe, SideFace(sf))) {
          Some(bnd_proj) =>
            bnd_proj.foldl_numbered_terms(sum, |sum, (proj_monn, proj_coef, _)| {
              sum + proj_coef * vbf.side_mon_vs_side_mon_fe_contr(fe_oshape,
                                                                  FaceMonNum(proj_monn), SideFace(sf), // bnd proj mon and side face
                                                                  bel_monn, bel_sf)                    // basis el mon and side face
            }),
          None => sum
        }
      })
    })
  }
}

type BoundaryProjections<'self,Mon> = HashMap<(FENum,SideFace), PolyBorrowingMons<'self,Mon>>;

fn boundary_projections<'a, Mon: Monomial, MeshT: Mesh<Mon>>
   (g: &fn(&[R])->R, basis: &'a WgBasis<Mon,MeshT>) -> BoundaryProjections<'a, Mon> {

  let mut projector = Projector::new(basis);

  let mut projs_by_fe_sf = HashMap::with_capacity(basis.mesh().num_boundary_sides());

  let b_fes_by_oshape_sf = basis.mesh().boundary_fes_by_oshape_side();

  for (fes_oshape, oshape_b_fes_by_sf) in b_fes_by_oshape_sf.iter().enumerate() {
    for (sf, fes) in oshape_b_fes_by_sf.iter().enumerate() {
      let fes_projs = projector.projs_to_span_fes_side_supp_basis_els(|x|g(x), *fes, OShape(fes_oshape), SideFace(sf));
      for (proj_poly, fe) in fes_projs.move_iter().zip(fes.iter()) {
        projs_by_fe_sf.insert((*fe, SideFace(sf)), proj_poly);
      }
    }
  }

  projs_by_fe_sf
}

<|endoftext|>


<commit_before>use super::{f32, Lab};

pub struct DE2000;

impl DE2000 {
    /// Returns the difference between two `Lab` colors as calculated by the
    /// [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn new(x1: Lab, x2: Lab) -> f32 {
        let ksub_l = 1.0;
        let ksub_c = 1.0;
        let ksub_h = 1.0;

        let delta_l_prime = x2.l - x1.l;

        let l_bar = (x1.l + x2.l) / 2.0;

        let c1 = (x1.a.powi(2) + x1.b.powi(2)).sqrt();
        let c2 = (x2.a.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar = (c1 + c2) / 2.0;

        let a_prime_1 =
            x1.a + (x1.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());
        let a_prime_2 =
            x2.a + (x2.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());

        let c_prime_1 = (a_prime_1.powi(2) + x1.b.powi(2)).sqrt();
        let c_prime_2 = (a_prime_2.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar_prime = (c_prime_1 + c_prime_2) / 2.0;

        let delta_c_prime = c_prime_2 - c_prime_1;

        let s_sub_l = 1.0 +
                      ((0.015 * (l_bar - 50.0).powi(2)) / (20.0 + (l_bar - 50.0).powi(2)).sqrt());

        let s_sub_c = 1.0 + 0.045 * c_bar_prime;

        let h_prime_1 = get_h_prime_fn(x1.b, a_prime_1);
        let h_prime_2 = get_h_prime_fn(x2.b, a_prime_2);

        let delta_h_prime = get_delta_h_prime(c1, c2, h_prime_1, h_prime_2);

        let delta_upcase_h_prime = 2.0 * (c_prime_1 * c_prime_2).sqrt() *
                                   (degrees_to_radians(delta_h_prime) / 2.0).sin();

        let upcase_h_bar_prime = get_upcase_h_bar_prime(h_prime_1, h_prime_2);

        let upcase_t = get_upcase_t(upcase_h_bar_prime);

        let s_sub_upcase_h = 1.0 + 0.015 * c_bar_prime * upcase_t;

        let r_sub_t = get_r_sub_t(c_bar_prime, upcase_h_bar_prime);

        let lightness: f32 = delta_l_prime / (ksub_l * s_sub_l);

        let chroma: f32 = delta_c_prime / (ksub_c * s_sub_c);

        let hue: f32 = delta_upcase_h_prime / (ksub_h * s_sub_upcase_h);

        (lightness.powi(2) + chroma.powi(2) + hue.powi(2) + r_sub_t * chroma * hue).sqrt()
    }

    /// Returns the difference between two RGB colors as calculated by the
    /// [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn from_rgb(x1: &[u8; 3], x2: &[u8; 3]) -> f32 {
        let l1 = Lab::from_rgb(x1);
        let l2 = Lab::from_rgb(x2);

        DE2000::new(l1, l2)
    }
}

fn get_h_prime_fn(x: f32, y: f32) -> f32 {
    let mut hue_angle;

    if x == 0.0 && y == 0.0 {
        return 0.0;
    }

    hue_angle = radians_to_degrees(x.atan2(y));

    if hue_angle < 0.0 {
        hue_angle += 360.0;
    }

    hue_angle
}

fn get_delta_h_prime(c1: f32, c2: f32, h_prime_1: f32, h_prime_2: f32) -> f32 {
    if 0.0 == c1 || 0.0 == c2 {
        return 0.0;
    }

    if (h_prime_1 - h_prime_2).abs() <= 180.0 {
        return h_prime_2 - h_prime_1;
    }

    if h_prime_2 <= h_prime_1 {
        h_prime_2 - h_prime_1 + 360.0
    } else {
        h_prime_2 - h_prime_1 - 360.0
    }
}

fn get_upcase_h_bar_prime(h_prime_1: f32, h_prime_2: f32) -> f32 {
    if (h_prime_1 - h_prime_2).abs() > 180.0 {
        return (h_prime_1 + h_prime_2 + 360.0) / 2.0;
    }

    (h_prime_1 + h_prime_2) / 2.0
}

fn get_upcase_t(upcase_h_bar_prime: f32) -> f32 {
    1.0 - 0.17 * (degrees_to_radians(upcase_h_bar_prime - 30.0)).cos() +
    0.24 * (degrees_to_radians(2.0 * upcase_h_bar_prime)).cos() +
    0.32 * (degrees_to_radians(3.0 * upcase_h_bar_prime + 6.0)).cos() -
    0.20 * (degrees_to_radians(4.0 * upcase_h_bar_prime - 63.0)).cos()
}

fn get_r_sub_t(c_bar_prime: f32, upcase_h_bar_prime: f32) -> f32 {
    -2.0 * (c_bar_prime.powi(7) / (c_bar_prime.powi(7) + 25f32.powi(7))).sqrt() *
    (degrees_to_radians(60.0 * (-(((upcase_h_bar_prime - 275.0) / 25.0).powi(2))).exp())).sin()
}

fn radians_to_degrees(radians: f32) -> f32 {
    radians * (180.0 / f32::consts::PI)
}

fn degrees_to_radians(degrees: f32) -> f32 {
    degrees * (f32::consts::PI / 180.0)
}

#[cfg(test)]
mod tests {
    use super::{DE2000, Lab};

    #[test]
    fn it_works() {
        let x1 = Lab {
            l: 36.0,
            a: 60.0,
            b: 41.0,
        };

        let x2 = Lab {
            l: 55.0,
            a: 66.0,
            b: 77.0,
        };

        assert_eq!(DE2000::new(x1, x2), 22.394508);
    }
}
<commit_msg>Add extensive tests<commit_after>use super::{f32, Lab};

pub struct DE2000;

impl DE2000 {
    /// Returns the difference between two `Lab` colors as calculated by the
    /// [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn new(x1: Lab, x2: Lab) -> f32 {
        let ksub_l = 1.0;
        let ksub_c = 1.0;
        let ksub_h = 1.0;

        let delta_l_prime = x2.l - x1.l;

        let l_bar = (x1.l + x2.l) / 2.0;

        let c1 = (x1.a.powi(2) + x1.b.powi(2)).sqrt();
        let c2 = (x2.a.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar = (c1 + c2) / 2.0;

        let a_prime_1 =
            x1.a + (x1.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());
        let a_prime_2 =
            x2.a + (x2.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());

        let c_prime_1 = (a_prime_1.powi(2) + x1.b.powi(2)).sqrt();
        let c_prime_2 = (a_prime_2.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar_prime = (c_prime_1 + c_prime_2) / 2.0;

        let delta_c_prime = c_prime_2 - c_prime_1;

        let s_sub_l = 1.0 +
                      ((0.015 * (l_bar - 50.0).powi(2)) / (20.0 + (l_bar - 50.0).powi(2)).sqrt());

        let s_sub_c = 1.0 + 0.045 * c_bar_prime;

        let h_prime_1 = get_h_prime_fn(x1.b, a_prime_1);
        let h_prime_2 = get_h_prime_fn(x2.b, a_prime_2);

        let delta_h_prime = get_delta_h_prime(c1, c2, h_prime_1, h_prime_2);

        let delta_upcase_h_prime = 2.0 * (c_prime_1 * c_prime_2).sqrt() *
                                   (degrees_to_radians(delta_h_prime) / 2.0).sin();

        let upcase_h_bar_prime = get_upcase_h_bar_prime(h_prime_1, h_prime_2);

        let upcase_t = get_upcase_t(upcase_h_bar_prime);

        let s_sub_upcase_h = 1.0 + 0.015 * c_bar_prime * upcase_t;

        let r_sub_t = get_r_sub_t(c_bar_prime, upcase_h_bar_prime);

        let lightness: f32 = delta_l_prime / (ksub_l * s_sub_l);

        let chroma: f32 = delta_c_prime / (ksub_c * s_sub_c);

        let hue: f32 = delta_upcase_h_prime / (ksub_h * s_sub_upcase_h);

        (lightness.powi(2) + chroma.powi(2) + hue.powi(2) + r_sub_t * chroma * hue).sqrt()
    }

    /// Returns the difference between two RGB colors as calculated by the
    /// [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn from_rgb(x1: &[u8; 3], x2: &[u8; 3]) -> f32 {
        let l1 = Lab::from_rgb(x1);
        let l2 = Lab::from_rgb(x2);

        DE2000::new(l1, l2)
    }
}

fn get_h_prime_fn(x: f32, y: f32) -> f32 {
    let mut hue_angle;

    if x == 0.0 && y == 0.0 {
        return 0.0;
    }

    hue_angle = radians_to_degrees(x.atan2(y));

    if hue_angle < 0.0 {
        hue_angle += 360.0;
    }

    hue_angle
}

fn get_delta_h_prime(c1: f32, c2: f32, h_prime_1: f32, h_prime_2: f32) -> f32 {
    if 0.0 == c1 || 0.0 == c2 {
        return 0.0;
    }

    if (h_prime_1 - h_prime_2).abs() <= 180.0 {
        return h_prime_2 - h_prime_1;
    }

    if h_prime_2 <= h_prime_1 {
        h_prime_2 - h_prime_1 + 360.0
    } else {
        h_prime_2 - h_prime_1 - 360.0
    }
}

fn get_upcase_h_bar_prime(h_prime_1: f32, h_prime_2: f32) -> f32 {
    if (h_prime_1 - h_prime_2).abs() > 180.0 {
        return (h_prime_1 + h_prime_2 + 360.0) / 2.0;
    }

    (h_prime_1 + h_prime_2) / 2.0
}

fn get_upcase_t(upcase_h_bar_prime: f32) -> f32 {
    1.0 - 0.17 * (degrees_to_radians(upcase_h_bar_prime - 30.0)).cos() +
    0.24 * (degrees_to_radians(2.0 * upcase_h_bar_prime)).cos() +
    0.32 * (degrees_to_radians(3.0 * upcase_h_bar_prime + 6.0)).cos() -
    0.20 * (degrees_to_radians(4.0 * upcase_h_bar_prime - 63.0)).cos()
}

fn get_r_sub_t(c_bar_prime: f32, upcase_h_bar_prime: f32) -> f32 {
    -2.0 * (c_bar_prime.powi(7) / (c_bar_prime.powi(7) + 25f32.powi(7))).sqrt() *
    (degrees_to_radians(60.0 * (-(((upcase_h_bar_prime - 275.0) / 25.0).powi(2))).exp())).sin()
}

fn radians_to_degrees(radians: f32) -> f32 {
    radians * (180.0 / f32::consts::PI)
}

fn degrees_to_radians(degrees: f32) -> f32 {
    degrees * (f32::consts::PI / 180.0)
}

#[cfg(test)]
mod tests {
    use super::{DE2000, Lab};

    fn round(val: f32) -> f32 {
        let rounded = val * 10000 as f32;
        rounded.round() / 10000 as f32
    }

    fn assert_delta_e(expected: f32, lab1: &[f32; 3], lab2: &[f32; 3]) {
        let x1 = Lab {
            l: lab1[0],
            a: lab1[1],
            b: lab1[2],
        };

        let x2 = Lab {
            l: lab2[0],
            a: lab2[1],
            b: lab2[2],
        };

        assert_eq!(round(DE2000::new(x1, x2)), expected);
    }

    // Tests taken from Table 1: "CIEDE2000 total color difference test data" of
    // "The CIEDE2000 Color-Difference Formula: Implementation Notes,
    // Supplementary Test Data, and Mathematical Observations" by Gaurav Sharma,
    // Wencheng Wu and Edul N. Dalal.
    //
    // http://www.ece.rochester.edu/~gsharma/papers/CIEDE2000CRNAFeb05.pdf

    #[test]
    fn tests() {
        assert_delta_e(0.0, &[0.0, 0.0, 0.0], &[0.0, 0.0, 0.0]);
        assert_delta_e(0.0, &[99.5, 0.005, -0.010], &[99.5, 0.005, -0.010]);
        assert_delta_e(100.0, &[100.0, 0.005, -0.010], &[0.0, 0.0, 0.0]);
        assert_delta_e(2.0425, &[50.0000, 2.6772, -79.7751], &[50.0000, 0.0000, -82.7485]);
        assert_delta_e(2.8615, &[50.0000, 3.1571, -77.2803], &[50.0000, 0.0000, -82.7485]);
        assert_delta_e(3.4412, &[50.0000, 2.8361, -74.0200], &[50.0000, 0.0000, -82.7485]);
        assert_delta_e(1.0000, &[50.0000, -1.3802, -84.2814], &[50.0000, 0.0000, -82.7485]);
        assert_delta_e(1.0000, &[50.0000, -1.1848, -84.8006], &[50.0000, 0.0000, -82.7485]);
        assert_delta_e(1.0000, &[50.0000, -0.9009, -85.5211], &[50.0000, 0.0000, -82.7485]);
        assert_delta_e(2.3669, &[50.0000, 0.0000, 0.0000], &[50.0000, -1.0000, 2.0000]);
        assert_delta_e(2.3669, &[50.0000, -1.0000, 2.0000], &[50.0000, 0.0000, 0.0000]);
        assert_delta_e(7.1792, &[50.0000, 2.4900, -0.0010], &[50.0000, -2.4900, 0.0009]);
        assert_delta_e(7.1792, &[50.0000, 2.4900, -0.0010], &[50.0000, -2.4900, 0.0010]);
        assert_delta_e(7.2195, &[50.0000, 2.4900, -0.0010], &[50.0000, -2.4900, 0.0011]);
        assert_delta_e(7.2195, &[50.0000, 2.4900, -0.0010], &[50.0000, -2.4900, 0.0012]);
        assert_delta_e(4.8045, &[50.0000, -0.0010, 2.4900], &[50.0000, 0.0009, -2.4900]);
        assert_delta_e(4.7461, &[50.0000, -0.0010, 2.4900], &[50.0000, 0.0011, -2.4900]);
        assert_delta_e(4.3065, &[50.0000, 2.5000, 0.0000], &[50.0000, 0.0000, -2.5000]);
        assert_delta_e(27.1492, &[50.0000, 2.5000, 0.0000], &[73.0000, 25.0000, -18.0000]);
        assert_delta_e(22.8977, &[50.0000, 2.5000, 0.0000], &[61.0000, -5.0000, 29.0000]);
        assert_delta_e(31.9030, &[50.0000, 2.5000, 0.0000], &[56.0000, -27.0000, -3.0000]);
        assert_delta_e(19.4535, &[50.0000, 2.5000, 0.0000], &[58.0000, 24.0000, 15.0000]);
        assert_delta_e(1.0000, &[50.0000, 2.5000, 0.0000], &[50.0000, 3.1736, 0.5854]);
        assert_delta_e(1.0000, &[50.0000, 2.5000, 0.0000], &[50.0000, 3.2972, 0.0000]);
        assert_delta_e(1.0000, &[50.0000, 2.5000, 0.0000], &[50.0000, 1.8634, 0.5757]);
        assert_delta_e(1.0000, &[50.0000, 2.5000, 0.0000], &[50.0000, 3.2592, 0.3350]);
        assert_delta_e(1.2644, &[60.2574, -34.0099, 36.2677], &[60.4626, -34.1751, 39.4387]);
        assert_delta_e(1.2630, &[63.0109, -31.0961, -5.8663], &[62.8187, -29.7946, -4.0864]);
        assert_delta_e(1.8731, &[61.2901, 3.7196, -5.3901], &[61.4292, 2.2480, -4.9620]);
        assert_delta_e(1.8645, &[35.0831, -44.1164, 3.7933], &[35.0232, -40.0716, 1.5901]);
        assert_delta_e(2.0373, &[22.7233, 20.0904, -46.6940], &[23.0331, 14.9730, -42.5619]);
        assert_delta_e(1.4146, &[36.4612, 47.8580, 18.3852], &[36.2715, 50.5065, 21.2231]);
        assert_delta_e(1.4441, &[90.8027, -2.0831, 1.4410], &[91.1528, -1.6435, 0.0447]);
        assert_delta_e(1.5381, &[90.9257, -0.5406, -0.9208], &[88.6381, -0.8985, -0.7239]);
        assert_delta_e(0.6377, &[6.7747, -0.2908, -2.4247], &[5.8714, -0.0985, -2.2286]);
        assert_delta_e(0.9082, &[2.0776, 0.0795, -1.1350], &[0.9033, -0.0636, -0.5514]);
    }
}
<|endoftext|>


<commit_before>use super::selector::SockState;
use super::InternalState;
use super::{inaddr_any, new_socket, socket_addr};
use crate::poll;
use crate::sys::windows::init;
use crate::{event, Interests, Registry, Token};

use std::fmt;
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::{self, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
use std::sync::{Arc, Mutex};
use winapi::um::winsock2::{bind, closesocket, connect, listen, SOCKET_ERROR, SOCK_STREAM};

pub struct TcpStream {
    internal: Arc<Mutex<Option<InternalState>>>,
    inner: net::TcpStream,
}

pub struct TcpListener {
    internal: Arc<Mutex<Option<InternalState>>>,
    inner: net::TcpListener,
}

impl TcpStream {
    pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
        init();
        new_socket(addr, SOCK_STREAM)
            .and_then(|socket| {
                // Required for a future `connect_overlapped` operation to be
                // executed successfully.
                let any_addr = inaddr_any(addr);
                let (raw_addr, raw_addr_length) = socket_addr(&any_addr);
                syscall!(
                    bind(socket, raw_addr, raw_addr_length),
                    PartialEq::eq,
                    SOCKET_ERROR
                )
                .and_then(|_| {
                    let (raw_addr, raw_addr_length) = socket_addr(&addr);
                    syscall!(
                        connect(socket, raw_addr, raw_addr_length),
                        PartialEq::eq,
                        SOCKET_ERROR
                    )
                    .or_else(|err| match err {
                        ref err if err.kind() == io::ErrorKind::WouldBlock => Ok(0),
                        err => Err(err),
                    })
                })
                .map(|_| socket)
                .map_err(|err| {
                    // Close the socket if we hit an error, ignoring the error
                    // from closing since we can't pass back two errors.
                    let _ = unsafe { closesocket(socket) };
                    err
                })
            })
            .map(|socket| TcpStream {
                internal: Arc::new(Mutex::new(None)),
                inner: unsafe { net::TcpStream::from_raw_socket(socket as StdSocket) },
            })
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.inner.peer_addr()
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<TcpStream> {
        self.inner.try_clone().map(|s| TcpStream {
            internal: Arc::new(Mutex::new(None)),
            inner: s,
        })
    }

    pub fn shutdown(&self, how: net::Shutdown) -> io::Result<()> {
        self.inner.shutdown(how)
    }

    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        self.inner.set_nodelay(nodelay)
    }

    pub fn nodelay(&self) -> io::Result<bool> {
        self.inner.nodelay()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.peek(buf)
    }

    // Used by `try_io` to register after an I/O operation blocked.
    fn io_blocked_reregister(&self) -> io::Result<()> {
        let internal = self.internal.lock().unwrap();
        if internal.is_some() {
            let selector = internal.as_ref().unwrap().selector.clone();
            let token = internal.as_ref().unwrap().token;
            let interests = internal.as_ref().unwrap().interests;
            drop(internal);
            selector.reregister(self, token, interests)
        } else {
            Ok(())
        }
    }
}

impl super::SocketState for TcpStream {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl<'a> super::SocketState for &'a TcpStream {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl Read for TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, read, buf)
    }

    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        try_io!(self, read_vectored, bufs)
    }
}

impl<'a> Read for &'a TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, read, buf)
    }

    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        try_io!(self, read_vectored, bufs)
    }
}

impl Write for TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        try_io!(self, write, buf)
    }

    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        try_io!(self, write_vectored, bufs)
    }

    fn flush(&mut self) -> io::Result<()> {
        try_io!(self, flush)
    }
}

impl<'a> Write for &'a TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        try_io!(self, write, buf)
    }

    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        try_io!(self, write_vectored, bufs)
    }

    fn flush(&mut self) -> io::Result<()> {
        try_io!(self, flush)
    }
}

impl event::Source for TcpStream {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

impl fmt::Debug for TcpStream {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}

impl FromRawSocket for TcpStream {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> TcpStream {
        TcpStream {
            internal: Arc::new(Mutex::new(None)),
            inner: net::TcpStream::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for TcpStream {
    fn into_raw_socket(self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl AsRawSocket for TcpStream {
    fn as_raw_socket(&self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl TcpListener {
    pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
        init();
        new_socket(addr, SOCK_STREAM).and_then(|socket| {
            let (raw_addr, raw_addr_length) = socket_addr(&addr);
            syscall!(
                bind(socket, raw_addr, raw_addr_length,),
                PartialEq::eq,
                SOCKET_ERROR
            )
            .and_then(|_| syscall!(listen(socket, 1024), PartialEq::eq, SOCKET_ERROR))
            .map_err(|err| {
                // Close the socket if we hit an error, ignoring the error
                // from closing since we can't pass back two errors.
                let _ = unsafe { closesocket(socket) };
                err
            })
            .map(|_| TcpListener {
                internal: Arc::new(Mutex::new(None)),
                inner: unsafe { net::TcpListener::from_raw_socket(socket as StdSocket) },
            })
        })
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<TcpListener> {
        self.inner.try_clone().map(|s| TcpListener {
            internal: Arc::new(Mutex::new(None)),
            inner: s,
        })
    }

    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
        try_io!(self, accept).and_then(|(inner, addr)| {
            inner.set_nonblocking(true).map(|()| {
                (
                    TcpStream {
                        internal: Arc::new(Mutex::new(None)),
                        inner,
                    },
                    addr,
                )
            })
        })
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    // Used by `try_io` to register after an I/O operation blocked.
    fn io_blocked_reregister(&self) -> io::Result<()> {
        let internal = self.internal.lock().unwrap();
        if internal.is_some() {
            let selector = internal.as_ref().unwrap().selector.clone();
            let token = internal.as_ref().unwrap().token;
            let interests = internal.as_ref().unwrap().interests;
            drop(internal);
            selector.reregister(self, token, interests)
        } else {
            Ok(())
        }
    }
}

impl super::SocketState for TcpListener {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl event::Source for TcpListener {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

impl fmt::Debug for TcpListener {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}

impl FromRawSocket for TcpListener {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> TcpListener {
        TcpListener {
            internal: Arc::new(Mutex::new(None)),
            inner: net::TcpListener::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for TcpListener {
    fn into_raw_socket(self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl AsRawSocket for TcpListener {
    fn as_raw_socket(&self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}
<commit_msg>Remove Arc from TcpStream and TcpListener internal state<commit_after>use super::selector::SockState;
use super::InternalState;
use super::{inaddr_any, new_socket, socket_addr};
use crate::poll;
use crate::sys::windows::init;
use crate::{event, Interests, Registry, Token};

use std::fmt;
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::{self, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
use std::sync::{Arc, Mutex};
use winapi::um::winsock2::{bind, closesocket, connect, listen, SOCKET_ERROR, SOCK_STREAM};

pub struct TcpStream {
    internal: Mutex<Option<InternalState>>,
    inner: net::TcpStream,
}

pub struct TcpListener {
    internal: Mutex<Option<InternalState>>,
    inner: net::TcpListener,
}

impl TcpStream {
    pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
        init();
        new_socket(addr, SOCK_STREAM)
            .and_then(|socket| {
                // Required for a future `connect_overlapped` operation to be
                // executed successfully.
                let any_addr = inaddr_any(addr);
                let (raw_addr, raw_addr_length) = socket_addr(&any_addr);
                syscall!(
                    bind(socket, raw_addr, raw_addr_length),
                    PartialEq::eq,
                    SOCKET_ERROR
                )
                .and_then(|_| {
                    let (raw_addr, raw_addr_length) = socket_addr(&addr);
                    syscall!(
                        connect(socket, raw_addr, raw_addr_length),
                        PartialEq::eq,
                        SOCKET_ERROR
                    )
                    .or_else(|err| match err {
                        ref err if err.kind() == io::ErrorKind::WouldBlock => Ok(0),
                        err => Err(err),
                    })
                })
                .map(|_| socket)
                .map_err(|err| {
                    // Close the socket if we hit an error, ignoring the error
                    // from closing since we can't pass back two errors.
                    let _ = unsafe { closesocket(socket) };
                    err
                })
            })
            .map(|socket| TcpStream {
                internal: Mutex::new(None),
                inner: unsafe { net::TcpStream::from_raw_socket(socket as StdSocket) },
            })
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.inner.peer_addr()
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<TcpStream> {
        self.inner.try_clone().map(|s| TcpStream {
            internal: Mutex::new(None),
            inner: s,
        })
    }

    pub fn shutdown(&self, how: net::Shutdown) -> io::Result<()> {
        self.inner.shutdown(how)
    }

    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        self.inner.set_nodelay(nodelay)
    }

    pub fn nodelay(&self) -> io::Result<bool> {
        self.inner.nodelay()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.peek(buf)
    }

    // Used by `try_io` to register after an I/O operation blocked.
    fn io_blocked_reregister(&self) -> io::Result<()> {
        let internal = self.internal.lock().unwrap();
        if internal.is_some() {
            let selector = internal.as_ref().unwrap().selector.clone();
            let token = internal.as_ref().unwrap().token;
            let interests = internal.as_ref().unwrap().interests;
            drop(internal);
            selector.reregister(self, token, interests)
        } else {
            Ok(())
        }
    }
}

impl super::SocketState for TcpStream {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl<'a> super::SocketState for &'a TcpStream {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl Read for TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, read, buf)
    }

    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        try_io!(self, read_vectored, bufs)
    }
}

impl<'a> Read for &'a TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, read, buf)
    }

    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        try_io!(self, read_vectored, bufs)
    }
}

impl Write for TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        try_io!(self, write, buf)
    }

    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        try_io!(self, write_vectored, bufs)
    }

    fn flush(&mut self) -> io::Result<()> {
        try_io!(self, flush)
    }
}

impl<'a> Write for &'a TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        try_io!(self, write, buf)
    }

    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        try_io!(self, write_vectored, bufs)
    }

    fn flush(&mut self) -> io::Result<()> {
        try_io!(self, flush)
    }
}

impl event::Source for TcpStream {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

impl fmt::Debug for TcpStream {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}

impl FromRawSocket for TcpStream {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> TcpStream {
        TcpStream {
            internal: Mutex::new(None),
            inner: net::TcpStream::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for TcpStream {
    fn into_raw_socket(self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl AsRawSocket for TcpStream {
    fn as_raw_socket(&self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl TcpListener {
    pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
        init();
        new_socket(addr, SOCK_STREAM).and_then(|socket| {
            let (raw_addr, raw_addr_length) = socket_addr(&addr);
            syscall!(
                bind(socket, raw_addr, raw_addr_length,),
                PartialEq::eq,
                SOCKET_ERROR
            )
            .and_then(|_| syscall!(listen(socket, 1024), PartialEq::eq, SOCKET_ERROR))
            .map_err(|err| {
                // Close the socket if we hit an error, ignoring the error
                // from closing since we can't pass back two errors.
                let _ = unsafe { closesocket(socket) };
                err
            })
            .map(|_| TcpListener {
                internal: Mutex::new(None),
                inner: unsafe { net::TcpListener::from_raw_socket(socket as StdSocket) },
            })
        })
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<TcpListener> {
        self.inner.try_clone().map(|s| TcpListener {
            internal: Mutex::new(None),
            inner: s,
        })
    }

    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
        try_io!(self, accept).and_then(|(inner, addr)| {
            inner.set_nonblocking(true).map(|()| {
                (
                    TcpStream {
                        internal: Mutex::new(None),
                        inner,
                    },
                    addr,
                )
            })
        })
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    // Used by `try_io` to register after an I/O operation blocked.
    fn io_blocked_reregister(&self) -> io::Result<()> {
        let internal = self.internal.lock().unwrap();
        if internal.is_some() {
            let selector = internal.as_ref().unwrap().selector.clone();
            let token = internal.as_ref().unwrap().token;
            let interests = internal.as_ref().unwrap().interests;
            drop(internal);
            selector.reregister(self, token, interests)
        } else {
            Ok(())
        }
    }
}

impl super::SocketState for TcpListener {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl event::Source for TcpListener {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

impl fmt::Debug for TcpListener {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}

impl FromRawSocket for TcpListener {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> TcpListener {
        TcpListener {
            internal: Mutex::new(None),
            inner: net::TcpListener::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for TcpListener {
    fn into_raw_socket(self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl AsRawSocket for TcpListener {
    fn as_raw_socket(&self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}
<|endoftext|>