<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

pub mod cache;
pub mod filecache;

#[cfg(test)]
mod test_filecache;

pub use self::cache::Cache;
pub use self::cache::Nocache;
pub use self::filecache::Filecache;
use std::io::Read;
use std::io;
use core::Config;
use toml;

pub enum Tilecache {
    Nocache(Nocache),
    Filecache(Filecache),
}

impl Cache for Tilecache {
    fn read<F>(&self, path: &str, read: F) -> bool
        where F: FnMut(&mut Read)
    {
        match self {
            &Tilecache::Nocache(ref cache) => cache.read(path, read),
            &Tilecache::Filecache(ref cache) => cache.read(path, read),
        }
    }
    fn write(&self, path: &str, obj: &[u8]) -> Result<(), io::Error> {
        match self {
            &Tilecache::Nocache(ref cache) => cache.write(path, obj),
            &Tilecache::Filecache(ref cache) => cache.write(path, obj),
        }
    }
    fn exists(&self, path: &str) -> bool {
        match self {
            &Tilecache::Nocache(ref cache) => cache.exists(path),
            &Tilecache::Filecache(ref cache) => cache.exists(path),
        }
    }
}

impl Config<Tilecache> for Tilecache {
    fn from_config(config: &toml::Value) -> Result<Self, String> {
        config
            .get("cache.file.base")
            .and_then(|val| val.as_str().or(None))
            .and_then(|basedir| {
                          Some(Tilecache::Filecache(Filecache { basepath: basedir.to_string() }))
                      })
            .or(Some(Tilecache::Nocache(Nocache)))
            .ok_or("config error".to_string())
    }
    fn gen_config() -> String {
        let toml = r#"
#[cache.file]
#base = "/tmp/mvtcache"
"#;
        toml.to_string()
    }
}
<commit_msg>Fix reading cache path config<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

pub mod cache;
pub mod filecache;

#[cfg(test)]
mod test_filecache;

pub use self::cache::Cache;
pub use self::cache::Nocache;
pub use self::filecache::Filecache;
use std::io::Read;
use std::io;
use core::Config;
use toml;

pub enum Tilecache {
    Nocache(Nocache),
    Filecache(Filecache),
}

impl Cache for Tilecache {
    fn read<F>(&self, path: &str, read: F) -> bool
        where F: FnMut(&mut Read)
    {
        match self {
            &Tilecache::Nocache(ref cache) => cache.read(path, read),
            &Tilecache::Filecache(ref cache) => cache.read(path, read),
        }
    }
    fn write(&self, path: &str, obj: &[u8]) -> Result<(), io::Error> {
        match self {
            &Tilecache::Nocache(ref cache) => cache.write(path, obj),
            &Tilecache::Filecache(ref cache) => cache.write(path, obj),
        }
    }
    fn exists(&self, path: &str) -> bool {
        match self {
            &Tilecache::Nocache(ref cache) => cache.exists(path),
            &Tilecache::Filecache(ref cache) => cache.exists(path),
        }
    }
}

impl Config<Tilecache> for Tilecache {
    fn from_config(config: &toml::Value) -> Result<Self, String> {
        config
            .get("cache")
            .and_then(|c| c.get("file"))
            .and_then(|c| c.get("base"))
            .and_then(|val| val.as_str().or(None))
            .and_then(|basedir| {
                          Some(Tilecache::Filecache(Filecache { basepath: basedir.to_string() }))
                      })
            .or(Some(Tilecache::Nocache(Nocache)))
            .ok_or("config error".to_string())
    }
    fn gen_config() -> String {
        let toml = r#"
#[cache.file]
#base = "/tmp/mvtcache"
"#;
        toml.to_string()
    }
}
<|endoftext|>


<commit_before>//! Implementations of the callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
#![allow(deprecated)] // keysyms

use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::{ButtonState, KeyboardModifiers, KeyState, KeyboardLed, ScrollAxis, Size, Point, Geometry,
                     ResizeEdge, ViewState, VIEW_ACTIVATED, VIEW_FULLSCREEN, VIEW_MAXIMIZED, VIEW_RESIZING,
                     MOD_NONE, MOD_CTRL, RESIZE_LEFT, RESIZE_RIGHT, RESIZE_TOP, RESIZE_BOTTOM};
use rustwlc::input::{pointer, keyboard};

use super::keys::{self, KeyPress, KeyEvent};
use super::layout::{try_lock_tree, try_lock_action, Action, ContainerType, MovementError, TreeError};
use super::layout::commands::set_performing_action;
use super::lua::{self, LuaQuery};

/// If the event is handled by way-cooler
const EVENT_BLOCKED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

const LEFT_CLICK: u32 = 0x110;
const RIGHT_CLICK: u32 = 0x111;

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_output(output).and_then(|_|{
            tree.switch_to_workspace(&"1")
        }).is_ok()
    } else {
        false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
}

pub extern fn output_resolution(output: WlcOutput,
                                old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
           output, *old_size_ptr, *new_size_ptr);
    // Update the resolution of the output and its children
    let scale = 1;
    output.set_resolution(*new_size_ptr, scale);
    if let Ok(mut tree) = try_lock_tree() {
        tree.layout_active_of(ContainerType::Output)
            .expect("Could not layout active output");
    }
}

pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    if view.get_class().as_str() == "Background" {
        info!("Setting background: {}", view.get_title());
        view.send_to_back();
        view.set_mask(1);
        let output = view.get_output();
        let resolution = output.get_resolution()
            .expect("Couldn't get output resolution");
        let fullscreen = Geometry {
            origin: Point { x: 0, y: 0 },
            size: resolution
        };
        view.set_geometry(ResizeEdge::empty(), fullscreen);
        return true
    }
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_view(view).and_then(|_| {
            if view.get_class() == "Background" {
                return Ok(())
            }
            view.set_state(VIEW_MAXIMIZED, true);
            tree.set_active_view(view).or_else(|_| {
                // We still want to focus on the window that appeared
                // Might need to change later, in case this focus grabbing
                // gets annoying / becomes a security issue.
                view.focus();
                Ok(())
            })
        }).is_ok()
    } else {
        false
    }
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    if let Ok(mut tree) = try_lock_tree() {
        tree.remove_view(view).unwrap_or_else(|err| {
            match err {
                TreeError::ViewNotFound(_) => {},
                _ => {
                    error!("Error in view_destroyed: {:?}", err);
                }
            }
        });
    } else {
        error!("Could not delete view {:?}", view);
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
    if let Ok(mut tree) = try_lock_tree() {
        match tree.set_active_view(current) {
            Ok(_) => {},
            Err(err) => {
                error!("Could not set {:?} to be active view: {:?}", current, err);
            }
        }
    }
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, toggle: bool) {
    trace!("Setting {:?} to state {:?}", view, state);
    if state == VIEW_FULLSCREEN {
            view.set_state(state, toggle);
            if toggle {
                if let Ok(mut tree) = try_lock_tree() {
                    if let Some(id) = tree.lookup_view(view) {
                        match tree.container_in_active_workspace(id) {
                            Ok(true) => {
                                tree.layout_active_of(ContainerType::Workspace)
                                    .unwrap_or_else(|err| {
                                        error!("Could not layout active workspace for view {:?}: {:?}",
                                               view, err)
                                    });
                            },
                            Ok(false) => {},
                            Err(err) => error!("Could not set {:?} fullscreen: {:?}", view, err)
                        }
                    } else {
                        warn!("Could not find view {:?} in tree", view);
                    }
                }
            }
    }
}

pub extern fn view_request_move(view: WlcView, _dest: &Point) {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.set_active_view(view) {
            error!("view_request_move error: {:?}", err);
        }
    }
}

pub extern fn view_request_resize(view: WlcView, edge: ResizeEdge, point: &Point) {
    if let Ok(mut tree) = try_lock_tree() {
        match try_lock_action() {
            Ok(guard) => {
                if guard.is_some() {
                    if let Some(id) = tree.lookup_view(view) {
                        if let Err(err) = tree.resize_container(id, edge, *point) {
                            error!("Problem: Command returned error: {:#?}", err);
                        }
                    }
                }
            },
            _ => {}
        }
    }
}

pub extern fn keyboard_key(_view: WlcView, _time: u32, mods: &KeyboardModifiers,
                           key: u32, state: KeyState) -> bool {
    let empty_mods: KeyboardModifiers = KeyboardModifiers {
            mods: MOD_NONE,
            leds: KeyboardLed::empty()
    };
    let sym = keyboard::get_keysym_for_key(key, empty_mods);
    let press = KeyPress::new(mods.mods, sym);

    if state == KeyState::Pressed {
        if let Some(action) = keys::get(&press) {
            debug!("[key] Found an action for {}", press);
            match action {
                KeyEvent::Command(func) => {
                    func();
                },
                KeyEvent::Lua => {
                    match lua::send(LuaQuery::HandleKey(press)) {
                        Ok(_) => {},
                        Err(err) => {
                            // We may want to wait for Lua's reply from
                            // keypresses; for example if the table is tampered
                            // with or Lua is restarted or Lua has an error.
                            // ATM Lua asynchronously logs this but in the future
                            // an error popup/etc is a good idea.
                            error!("Error sending keypress: {:?}", err);
                        }
                    }
                }
            }
            return EVENT_BLOCKED
        }
    }

    return EVENT_PASS_THROUGH
}

pub extern fn view_request_geometry(_view: WlcView, _geometry: &Geometry) {
}

pub extern fn pointer_button(view: WlcView, _time: u32,
                         mods: &KeyboardModifiers, button: u32,
                             state: ButtonState, point: &Point) -> bool {
    if state == ButtonState::Pressed {
        if button == LEFT_CLICK && !view.is_root() {
            if let Ok(mut tree) = try_lock_tree() {
                tree.set_active_view(view).unwrap_or_else(|_| {
                    // still focus on view, even if not in tree.
                    view.focus();
                });
                if mods.mods.contains(MOD_CTRL) {
                    let action = Action {
                        view: view,
                        grab: *point,
                        edges: ResizeEdge::empty()
                    };
                    set_performing_action(Some(action));
                }
            }
        } else if button == RIGHT_CLICK && !view.is_root() {
            if let Ok(mut tree) = try_lock_tree() {
                tree.set_active_view(view).ok();
            }
            // TODO Make this set in the config file and read here.
            if mods.mods.contains(MOD_CTRL) {
                let action = Action {
                    view: view,
                    grab: *point,
                    edges: ResizeEdge::empty()
                };
                set_performing_action(Some(action));
                let geometry = view.get_geometry()
                    .expect("Could not get geometry of the view");
                let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
                let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

                {
                    let mut action: Action = try_lock_action().ok().and_then(|guard| *guard)
                        .unwrap_or(Action {
                            view: view,
                            grab: *point,
                            edges: ResizeEdge::empty()
                        });
                    let flag_x = if point.x < halfw {
                        RESIZE_LEFT
                    } else if point.x > halfw {
                        RESIZE_RIGHT
                    } else {
                        ResizeEdge::empty()
                    };

                    let flag_y = if point.y < halfh {
                        RESIZE_TOP
                    } else if point.y > halfh {
                        RESIZE_BOTTOM
                    } else {
                        ResizeEdge::empty()
                    };

                    action.edges = flag_x | flag_y;
                    set_performing_action(Some(action));
                }
                view.set_state(VIEW_RESIZING, true);
                return EVENT_BLOCKED
            }
        }
    } else {
        if let Ok(lock) = try_lock_action() {
            match *lock {
                Some(action) => {
                    let view = action.view;
                    if view.get_state().contains(VIEW_RESIZING) {
                        view.set_state(VIEW_RESIZING, false);
                    }
                },
                _ => {}
            }
        }
        set_performing_action(None);
    }
    EVENT_PASS_THROUGH
}

pub extern fn pointer_scroll(_view: WlcView, _time: u32,
                         _mods_ptr: &KeyboardModifiers, _axis: ScrollAxis,
                         _heights: [f64; 2]) -> bool {
    EVENT_PASS_THROUGH
}

pub extern fn pointer_motion(view: WlcView, _time: u32, point: &Point) -> bool {
    let mut result = EVENT_PASS_THROUGH;
    let mut maybe_action = None;
    {
        if let Ok(action_lock) = try_lock_action() {
            maybe_action = action_lock.clone();
        }
    }
    match maybe_action {
        None => result = EVENT_PASS_THROUGH,
        Some(action) => {
            if action.edges.bits() != 0 {
                if let Ok(mut tree) = try_lock_tree() {
                    // TODO Change to id of _view
                    // Need to implement a map of view to uuid first though...
                    if let Some(active_id) = tree.lookup_view(view) {
                        match tree.resize_container(active_id, action.edges, *point) {
                            // Return early here to not set the pointer
                            Ok(_) => return EVENT_BLOCKED,
                            Err(err) => error!("Error: {:#?}", err)
                        }
                    }
                }
            } else {
                if let Ok(mut tree) = try_lock_tree() {
                    match tree.try_drag_active(*point) {
                        Ok(_) => result = EVENT_BLOCKED,
                        Err(TreeError::PerformingAction(_)) |
                        Err(TreeError::Movement(MovementError::NotFloating(_))) => result = EVENT_PASS_THROUGH,
                        Err(err) => {
                            error!("Error: {:#?}", err);
                            result = EVENT_PASS_THROUGH
                        }
                    }
                }
            }
        }
    }
    pointer::set_position(*point);
    result
}

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
    keys::init();
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
    if let Ok(mut tree) = try_lock_tree() {
        if tree.destroy_tree().is_err() {
            error!("Could not destroy tree");
        }
    }

}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    trace!("Registered wlc callbacks");
}
<commit_msg>Always retile when fullscreen bit toggles<commit_after>//! Implementations of the callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
#![allow(deprecated)] // keysyms

use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::{ButtonState, KeyboardModifiers, KeyState, KeyboardLed, ScrollAxis, Size, Point, Geometry,
                     ResizeEdge, ViewState, VIEW_ACTIVATED, VIEW_FULLSCREEN, VIEW_MAXIMIZED, VIEW_RESIZING,
                     MOD_NONE, MOD_CTRL, RESIZE_LEFT, RESIZE_RIGHT, RESIZE_TOP, RESIZE_BOTTOM};
use rustwlc::input::{pointer, keyboard};

use super::keys::{self, KeyPress, KeyEvent};
use super::layout::{try_lock_tree, try_lock_action, Action, ContainerType, MovementError, TreeError};
use super::layout::commands::set_performing_action;
use super::lua::{self, LuaQuery};

/// If the event is handled by way-cooler
const EVENT_BLOCKED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

const LEFT_CLICK: u32 = 0x110;
const RIGHT_CLICK: u32 = 0x111;

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_output(output).and_then(|_|{
            tree.switch_to_workspace(&"1")
        }).is_ok()
    } else {
        false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
}

pub extern fn output_resolution(output: WlcOutput,
                                old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
           output, *old_size_ptr, *new_size_ptr);
    // Update the resolution of the output and its children
    let scale = 1;
    output.set_resolution(*new_size_ptr, scale);
    if let Ok(mut tree) = try_lock_tree() {
        tree.layout_active_of(ContainerType::Output)
            .expect("Could not layout active output");
    }
}

pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    if view.get_class().as_str() == "Background" {
        info!("Setting background: {}", view.get_title());
        view.send_to_back();
        view.set_mask(1);
        let output = view.get_output();
        let resolution = output.get_resolution()
            .expect("Couldn't get output resolution");
        let fullscreen = Geometry {
            origin: Point { x: 0, y: 0 },
            size: resolution
        };
        view.set_geometry(ResizeEdge::empty(), fullscreen);
        return true
    }
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_view(view).and_then(|_| {
            if view.get_class() == "Background" {
                return Ok(())
            }
            view.set_state(VIEW_MAXIMIZED, true);
            tree.set_active_view(view).or_else(|_| {
                // We still want to focus on the window that appeared
                // Might need to change later, in case this focus grabbing
                // gets annoying / becomes a security issue.
                view.focus();
                Ok(())
            })
        }).is_ok()
    } else {
        false
    }
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    if let Ok(mut tree) = try_lock_tree() {
        tree.remove_view(view).unwrap_or_else(|err| {
            match err {
                TreeError::ViewNotFound(_) => {},
                _ => {
                    error!("Error in view_destroyed: {:?}", err);
                }
            }
        });
    } else {
        error!("Could not delete view {:?}", view);
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
    if let Ok(mut tree) = try_lock_tree() {
        match tree.set_active_view(current) {
            Ok(_) => {},
            Err(err) => {
                error!("Could not set {:?} to be active view: {:?}", current, err);
            }
        }
    }
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, toggle: bool) {
    trace!("Setting {:?} to state {:?}", view, state);
    if state == VIEW_FULLSCREEN {
            view.set_state(state, toggle);
            if let Ok(mut tree) = try_lock_tree() {
                if let Some(id) = tree.lookup_view(view) {
                    match tree.container_in_active_workspace(id) {
                        Ok(true) => {
                            tree.layout_active_of(ContainerType::Workspace)
                                .unwrap_or_else(|err| {
                                    error!("Could not layout active workspace for view {:?}: {:?}",
                                            view, err)
                                });
                        },
                        Ok(false) => {},
                        Err(err) => error!("Could not set {:?} fullscreen: {:?}", view, err)
                    }
                } else {
                    warn!("Could not find view {:?} in tree", view);
                }
            }
    }
}

pub extern fn view_request_move(view: WlcView, _dest: &Point) {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.set_active_view(view) {
            error!("view_request_move error: {:?}", err);
        }
    }
}

pub extern fn view_request_resize(view: WlcView, edge: ResizeEdge, point: &Point) {
    if let Ok(mut tree) = try_lock_tree() {
        match try_lock_action() {
            Ok(guard) => {
                if guard.is_some() {
                    if let Some(id) = tree.lookup_view(view) {
                        if let Err(err) = tree.resize_container(id, edge, *point) {
                            error!("Problem: Command returned error: {:#?}", err);
                        }
                    }
                }
            },
            _ => {}
        }
    }
}

pub extern fn keyboard_key(_view: WlcView, _time: u32, mods: &KeyboardModifiers,
                           key: u32, state: KeyState) -> bool {
    let empty_mods: KeyboardModifiers = KeyboardModifiers {
            mods: MOD_NONE,
            leds: KeyboardLed::empty()
    };
    let sym = keyboard::get_keysym_for_key(key, empty_mods);
    let press = KeyPress::new(mods.mods, sym);

    if state == KeyState::Pressed {
        if let Some(action) = keys::get(&press) {
            debug!("[key] Found an action for {}", press);
            match action {
                KeyEvent::Command(func) => {
                    func();
                },
                KeyEvent::Lua => {
                    match lua::send(LuaQuery::HandleKey(press)) {
                        Ok(_) => {},
                        Err(err) => {
                            // We may want to wait for Lua's reply from
                            // keypresses; for example if the table is tampered
                            // with or Lua is restarted or Lua has an error.
                            // ATM Lua asynchronously logs this but in the future
                            // an error popup/etc is a good idea.
                            error!("Error sending keypress: {:?}", err);
                        }
                    }
                }
            }
            return EVENT_BLOCKED
        }
    }

    return EVENT_PASS_THROUGH
}

pub extern fn view_request_geometry(_view: WlcView, _geometry: &Geometry) {
}

pub extern fn pointer_button(view: WlcView, _time: u32,
                         mods: &KeyboardModifiers, button: u32,
                             state: ButtonState, point: &Point) -> bool {
    if state == ButtonState::Pressed {
        if button == LEFT_CLICK && !view.is_root() {
            if let Ok(mut tree) = try_lock_tree() {
                tree.set_active_view(view).unwrap_or_else(|_| {
                    // still focus on view, even if not in tree.
                    view.focus();
                });
                if mods.mods.contains(MOD_CTRL) {
                    let action = Action {
                        view: view,
                        grab: *point,
                        edges: ResizeEdge::empty()
                    };
                    set_performing_action(Some(action));
                }
            }
        } else if button == RIGHT_CLICK && !view.is_root() {
            if let Ok(mut tree) = try_lock_tree() {
                tree.set_active_view(view).ok();
            }
            // TODO Make this set in the config file and read here.
            if mods.mods.contains(MOD_CTRL) {
                let action = Action {
                    view: view,
                    grab: *point,
                    edges: ResizeEdge::empty()
                };
                set_performing_action(Some(action));
                let geometry = view.get_geometry()
                    .expect("Could not get geometry of the view");
                let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
                let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

                {
                    let mut action: Action = try_lock_action().ok().and_then(|guard| *guard)
                        .unwrap_or(Action {
                            view: view,
                            grab: *point,
                            edges: ResizeEdge::empty()
                        });
                    let flag_x = if point.x < halfw {
                        RESIZE_LEFT
                    } else if point.x > halfw {
                        RESIZE_RIGHT
                    } else {
                        ResizeEdge::empty()
                    };

                    let flag_y = if point.y < halfh {
                        RESIZE_TOP
                    } else if point.y > halfh {
                        RESIZE_BOTTOM
                    } else {
                        ResizeEdge::empty()
                    };

                    action.edges = flag_x | flag_y;
                    set_performing_action(Some(action));
                }
                view.set_state(VIEW_RESIZING, true);
                return EVENT_BLOCKED
            }
        }
    } else {
        if let Ok(lock) = try_lock_action() {
            match *lock {
                Some(action) => {
                    let view = action.view;
                    if view.get_state().contains(VIEW_RESIZING) {
                        view.set_state(VIEW_RESIZING, false);
                    }
                },
                _ => {}
            }
        }
        set_performing_action(None);
    }
    EVENT_PASS_THROUGH
}

pub extern fn pointer_scroll(_view: WlcView, _time: u32,
                         _mods_ptr: &KeyboardModifiers, _axis: ScrollAxis,
                         _heights: [f64; 2]) -> bool {
    EVENT_PASS_THROUGH
}

pub extern fn pointer_motion(view: WlcView, _time: u32, point: &Point) -> bool {
    let mut result = EVENT_PASS_THROUGH;
    let mut maybe_action = None;
    {
        if let Ok(action_lock) = try_lock_action() {
            maybe_action = action_lock.clone();
        }
    }
    match maybe_action {
        None => result = EVENT_PASS_THROUGH,
        Some(action) => {
            if action.edges.bits() != 0 {
                if let Ok(mut tree) = try_lock_tree() {
                    // TODO Change to id of _view
                    // Need to implement a map of view to uuid first though...
                    if let Some(active_id) = tree.lookup_view(view) {
                        match tree.resize_container(active_id, action.edges, *point) {
                            // Return early here to not set the pointer
                            Ok(_) => return EVENT_BLOCKED,
                            Err(err) => error!("Error: {:#?}", err)
                        }
                    }
                }
            } else {
                if let Ok(mut tree) = try_lock_tree() {
                    match tree.try_drag_active(*point) {
                        Ok(_) => result = EVENT_BLOCKED,
                        Err(TreeError::PerformingAction(_)) |
                        Err(TreeError::Movement(MovementError::NotFloating(_))) => result = EVENT_PASS_THROUGH,
                        Err(err) => {
                            error!("Error: {:#?}", err);
                            result = EVENT_PASS_THROUGH
                        }
                    }
                }
            }
        }
    }
    pointer::set_position(*point);
    result
}

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
    keys::init();
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
    if let Ok(mut tree) = try_lock_tree() {
        if tree.destroy_tree().is_err() {
            error!("Could not destroy tree");
        }
    }

}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    trace!("Registered wlc callbacks");
}
<|endoftext|>


<commit_before>//! Add, remove, or modify a collation
use std::cmp::Ordering;
use std::os::raw::{c_int, c_void};
use std::panic::{catch_unwind, UnwindSafe};
use std::ptr;
use std::slice;

use crate::ffi;
use crate::{str_to_cstring, Connection, InnerConnection, Result};

// TODO sqlite3_collation_needed https://sqlite.org/c3ref/collation_needed.html

// FIXME copy/paste from function.rs
unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) {
    drop(Box::from_raw(p as *mut T));
}

impl Connection {
    /// Add or modify a collation.
    pub fn create_collation<C>(&self, collation_name: &str, x_compare: C) -> Result<()>
    where
        C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
    {
        self.db
            .borrow_mut()
            .create_collation(collation_name, x_compare)
    }

    /// Remove collation.
    pub fn remove_collation(&self, collation_name: &str) -> Result<()> {
        self.db.borrow_mut().remove_collation(collation_name)
    }
}

impl InnerConnection {
    fn create_collation<C>(&mut self, collation_name: &str, x_compare: C) -> Result<()>
    where
        C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
    {
        unsafe extern "C" fn call_boxed_closure<F>(
            arg1: *mut c_void,
            arg2: c_int,
            arg3: *const c_void,
            arg4: c_int,
            arg5: *const c_void,
        ) -> c_int
        where
            F: Fn(&str, &str) -> Ordering,
        {
            use std::str;

            let r = catch_unwind(|| {
                let boxed_f: *mut F = arg1 as *mut F;
                assert!(!boxed_f.is_null(), "Internal error - null function pointer");
                let s1 = {
                    let c_slice = slice::from_raw_parts(arg3 as *const u8, arg2 as usize);
                    str::from_utf8_unchecked(c_slice)
                };
                let s2 = {
                    let c_slice = slice::from_raw_parts(arg5 as *const u8, arg4 as usize);
                    str::from_utf8_unchecked(c_slice)
                };
                (*boxed_f)(s1, s2)
            });
            let t = match r {
                Err(_) => {
                    return -1; // FIXME How ?
                }
                Ok(r) => r,
            };

            match t {
                Ordering::Less => -1,
                Ordering::Equal => 0,
                Ordering::Greater => 1,
            }
        }

        let boxed_f: *mut C = Box::into_raw(Box::new(x_compare));
        let c_name = str_to_cstring(collation_name)?;
        let flags = ffi::SQLITE_UTF8;
        let r = unsafe {
            ffi::sqlite3_create_collation_v2(
                self.db(),
                c_name.as_ptr(),
                flags,
                boxed_f as *mut c_void,
                Some(call_boxed_closure::<C>),
                Some(free_boxed_value::<C>),
            )
        };
        self.decode_result(r)
    }

    fn remove_collation(&mut self, collation_name: &str) -> Result<()> {
        let c_name = str_to_cstring(collation_name)?;
        let r = unsafe {
            ffi::sqlite3_create_collation_v2(
                self.db(),
                c_name.as_ptr(),
                ffi::SQLITE_UTF8,
                ptr::null_mut(),
                None,
                None,
            )
        };
        self.decode_result(r)
    }
}

#[cfg(test)]
mod test {
    use crate::{Connection, NO_PARAMS};
    use fallible_streaming_iterator::FallibleStreamingIterator;
    use std::cmp::Ordering;
    use unicase::UniCase;

    fn unicase_compare(s1: &str, s2: &str) -> Ordering {
        UniCase::new(s1).cmp(&UniCase::new(s2))
    }

    #[test]
    fn test_unicase() {
        let db = Connection::open_in_memory().unwrap();

        db.create_collation("unicase", unicase_compare).unwrap();

        db.execute_batch(
            "CREATE TABLE foo (bar);
             INSERT INTO foo (bar) VALUES ('Maße');
             INSERT INTO foo (bar) VALUES ('MASSE');",
        )
        .unwrap();
        let mut stmt = db
            .prepare("SELECT DISTINCT bar COLLATE unicase FROM foo ORDER BY 1")
            .unwrap();
        let rows = stmt.query(NO_PARAMS).unwrap();
        assert_eq!(rows.count().unwrap(), 1);
    }
}
<commit_msg>Add binding to `sqlite3_collation_needed`<commit_after>//! Add, remove, or modify a collation
use std::cmp::Ordering;
use std::os::raw::{c_char, c_int, c_void};
use std::panic::{catch_unwind, UnwindSafe};
use std::ptr;
use std::slice;

use crate::ffi;
use crate::{str_to_cstring, Connection, InnerConnection, Result};

// FIXME copy/paste from function.rs
unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) {
    drop(Box::from_raw(p as *mut T));
}

impl Connection {
    /// Add or modify a collation.
    pub fn create_collation<C>(&self, collation_name: &str, x_compare: C) -> Result<()>
    where
        C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
    {
        self.db
            .borrow_mut()
            .create_collation(collation_name, x_compare)
    }

    /// Collation needed callback
    pub fn collation_needed(
        &self,
        x_coll_needed: fn(&Connection, &str) -> Result<()>,
    ) -> Result<()> {
        self.db.borrow_mut().collation_needed(x_coll_needed)
    }

    /// Remove collation.
    pub fn remove_collation(&self, collation_name: &str) -> Result<()> {
        self.db.borrow_mut().remove_collation(collation_name)
    }
}

impl InnerConnection {
    fn create_collation<C>(&mut self, collation_name: &str, x_compare: C) -> Result<()>
    where
        C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
    {
        unsafe extern "C" fn call_boxed_closure<C>(
            arg1: *mut c_void,
            arg2: c_int,
            arg3: *const c_void,
            arg4: c_int,
            arg5: *const c_void,
        ) -> c_int
        where
            C: Fn(&str, &str) -> Ordering,
        {
            use std::str;

            let r = catch_unwind(|| {
                let boxed_f: *mut C = arg1 as *mut C;
                assert!(!boxed_f.is_null(), "Internal error - null function pointer");
                let s1 = {
                    let c_slice = slice::from_raw_parts(arg3 as *const u8, arg2 as usize);
                    str::from_utf8_unchecked(c_slice)
                };
                let s2 = {
                    let c_slice = slice::from_raw_parts(arg5 as *const u8, arg4 as usize);
                    str::from_utf8_unchecked(c_slice)
                };
                (*boxed_f)(s1, s2)
            });
            let t = match r {
                Err(_) => {
                    return -1; // FIXME How ?
                }
                Ok(r) => r,
            };

            match t {
                Ordering::Less => -1,
                Ordering::Equal => 0,
                Ordering::Greater => 1,
            }
        }

        let boxed_f: *mut C = Box::into_raw(Box::new(x_compare));
        let c_name = str_to_cstring(collation_name)?;
        let flags = ffi::SQLITE_UTF8;
        let r = unsafe {
            ffi::sqlite3_create_collation_v2(
                self.db(),
                c_name.as_ptr(),
                flags,
                boxed_f as *mut c_void,
                Some(call_boxed_closure::<C>),
                Some(free_boxed_value::<C>),
            )
        };
        self.decode_result(r)
    }

    fn collation_needed(
        &mut self,
        x_coll_needed: fn(&Connection, &str) -> Result<()>,
    ) -> Result<()> {
        use std::mem;
        unsafe extern "C" fn collation_needed_callback(
            arg1: *mut c_void,
            arg2: *mut ffi::sqlite3,
            e_text_rep: c_int,
            arg3: *const c_char,
        ) {
            use std::ffi::CStr;
            use std::str;

            if e_text_rep != ffi::SQLITE_UTF8 {
                // TODO: validate
                return;
            }

            let callback: fn(&Connection, &str) -> Result<()> = mem::transmute(arg1);
            if let Err(_) = catch_unwind(|| {
                let conn = Connection::from_handle(arg2).unwrap();
                let collation_name = {
                    let c_slice = CStr::from_ptr(arg3).to_bytes();
                    str::from_utf8_unchecked(c_slice)
                };
                callback(&conn, collation_name)
            }) {
                return; // FIXME How ?
            }
        }

        let r = unsafe {
            ffi::sqlite3_collation_needed(
                self.db(),
                mem::transmute(x_coll_needed),
                Some(collation_needed_callback),
            )
        };
        self.decode_result(r)
    }

    fn remove_collation(&mut self, collation_name: &str) -> Result<()> {
        let c_name = str_to_cstring(collation_name)?;
        let r = unsafe {
            ffi::sqlite3_create_collation_v2(
                self.db(),
                c_name.as_ptr(),
                ffi::SQLITE_UTF8,
                ptr::null_mut(),
                None,
                None,
            )
        };
        self.decode_result(r)
    }
}

#[cfg(test)]
mod test {
    use crate::{Connection, Result, NO_PARAMS};
    use fallible_streaming_iterator::FallibleStreamingIterator;
    use std::cmp::Ordering;
    use unicase::UniCase;

    fn unicase_compare(s1: &str, s2: &str) -> Ordering {
        UniCase::new(s1).cmp(&UniCase::new(s2))
    }

    #[test]
    fn test_unicase() {
        let db = Connection::open_in_memory().unwrap();

        db.create_collation("unicase", unicase_compare).unwrap();

        collate(db);
    }

    fn collate(db: Connection) {
        db.execute_batch(
            "CREATE TABLE foo (bar);
             INSERT INTO foo (bar) VALUES ('Maße');
             INSERT INTO foo (bar) VALUES ('MASSE');",
        )
        .unwrap();
        let mut stmt = db
            .prepare("SELECT DISTINCT bar COLLATE unicase FROM foo ORDER BY 1")
            .unwrap();
        let rows = stmt.query(NO_PARAMS).unwrap();
        assert_eq!(rows.count().unwrap(), 1);
    }

    fn collation_needed(db: &Connection, collation_name: &str) -> Result<()> {
        if "unicase" == collation_name {
            db.create_collation(collation_name, unicase_compare)
        } else {
            Ok(())
        }
    }

    #[test]
    fn test_collation_needed() {
        let db = Connection::open_in_memory().unwrap();
        db.collation_needed(collation_needed).unwrap();
        collate(db);
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;

#[derive(Clone, Debug)]
pub struct Condition(Rc<RefCell<bool>>);

impl Condition {
    pub fn new(state: bool) -> Condition {
        Condition(Rc::new(RefCell::new(state)))
    }

    pub fn is_active(&self) -> bool {
        *self.0.borrow()
    }

    pub fn activate(&mut self) {
        *self.0.borrow_mut() = true;
    }

    pub fn deactivate(&mut self) {
        *self.0.borrow_mut() = false;
    }
}
<commit_msg>Condition: use Cell instead of RefCell<commit_after>use std::cell::Cell;
use std::rc::Rc;

#[derive(Clone, Debug)]
pub struct Condition(Rc<Cell<bool>>);

impl Condition {
    pub fn new(state: bool) -> Condition {
        Condition(Rc::new(Cell::new(state)))
    }

    pub fn is_active(&self) -> bool {
        self.0.get()
    }

    pub fn activate(&mut self) {
        self.0.set(true);
    }

    pub fn deactivate(&mut self) {
        self.0.set(false);
    }
}
<|endoftext|>


<commit_before>use std::marker::Send;
use std::thread;
use std::sync::mpsc::{Sender, channel};
use std::sync::Arc;

use eew::EEW;
use eew_buffer::EEWBuffer;

pub struct Connector {
	tx: Sender<Arc<EEW>>
}

impl Connector {

	pub fn new<F, A>(main_func: F, init_arg: A) -> Connector
		where F: Fn(&[EEW], &EEW, &mut A) + Send + 'static,
			A: Send + 'static
	{
		let (tx, rx) = channel::<Arc<EEW>>();

		thread::spawn(move || {

			let mut buffer = EEWBuffer::new();
			let mut a = init_arg;

			loop {
				let latest = rx.recv().unwrap();
				if let Some(ref eews) = buffer.append(&latest) {
					main_func(&eews, &latest, &mut a);
				}
			}
		});

		let con = Connector { tx: tx };

		return con;
	}

	pub fn emit(&self, eew: Arc<EEW>)
	{
		self.tx.send(eew);
	}
}
<commit_msg>Limit memory usage of channels in Connector<commit_after>use std::marker::Send;
use std::thread;
use std::sync::mpsc::{SyncSender, sync_channel};
use std::sync::Arc;

use eew::EEW;
use eew_buffer::EEWBuffer;

const DEFAULT_MAX_CHANNEL_SIZE: usize = 32;

pub struct Connector {
	tx: SyncSender<Arc<EEW>>
}

impl Connector {

	pub fn new<F, A>(main_func: F, init_arg: A) -> Connector
		where F: Fn(&[EEW], &EEW, &mut A) + Send + 'static,
			A: Send + 'static
	{
		let (tx, rx) = sync_channel::<Arc<EEW>>(DEFAULT_MAX_CHANNEL_SIZE);

		thread::spawn(move || {

			let mut buffer = EEWBuffer::new();
			let mut a = init_arg;

			loop {
				let latest = rx.recv().unwrap();
				if let Some(ref eews) = buffer.append(&latest) {
					main_func(&eews, &latest, &mut a);
				}
			}
		});

		let con = Connector { tx: tx };

		return con;
	}

	pub fn emit(&self, eew: Arc<EEW>)
	{
		self.tx.try_send(eew);
	}
}
<|endoftext|>


<commit_before>use rand::Rng;

#[inline]
fn sbx_beta(u: f32, eta: f32) -> f32 {
    assert!(u >= 0.0 && u < 1.0);

    if u <= 0.5 {
        2.0 * u
    } else {
        1.0 / (2.0 * (1.0 - u))
    }
    .powf(1.0 / (eta + 1.0))
}

#[inline]
fn sbx_beta_bounded(u: f32, eta: f32, gamma: f32) -> f32 {
    assert!(u >= 0.0 && u < 1.0);

    let g = 1.0 - gamma;
    let ug = u * g;

    if u <= 0.5 / g {
        2.0 * ug
    } else {
        1.0 / (2.0 * (1.0 - ug))
    }
    .powf(1.0 / (eta + 1.0))
}

#[inline]
pub fn sbx_single_var<R: Rng>(rng: &mut R, p: (f32, f32), eta: f32) -> (f32, f32) {
    let u = rng.gen::<f32>();
    let beta = sbx_beta(u, eta);

    (0.5 * (((1.0 + beta) * p.0) + ((1.0 - beta) * p.1)),
     0.5 * (((1.0 - beta) * p.0) + ((1.0 + beta) * p.1)))
}

#[inline]
fn _sbx_single_var_bounded<R: Rng>(rng: &mut R,
                                   p: (f32, f32),
                                   bounds: (f32, f32),
                                   eta: f32)
                                   -> (f32, f32) {
    let (a, b) = bounds;
    let p_diff = p.1 - p.0;

    assert!(a <= b);
    assert!(p_diff > 0.0);
    assert!(p.0 >= a && p.0 <= b);
    assert!(p.1 >= a && p.1 <= b);

    let beta_a = 1.0 + (p.0 - a) / p_diff;
    let beta_b = 1.0 + (b - p.1) / p_diff;

    fn gamma(beta: f32, eta: f32) -> f32 {
        1.0 / (2.0 * beta.powf(eta + 1.0))
    }

    let gamma_a = gamma(beta_a, eta);
    let gamma_b = gamma(beta_b, eta);

    let u = rng.gen::<f32>();
    let beta_ua = sbx_beta_bounded(u, eta, gamma_a);
    let beta_ub = sbx_beta_bounded(u, eta, gamma_b);

    let c = (0.5 * (((1.0 + beta_ua) * p.0) + ((1.0 - beta_ua) * p.1)),
             0.5 * (((1.0 - beta_ub) * p.0) + ((1.0 + beta_ub) * p.1)));

    assert!(c.0 >= a && c.0 <= b);
    assert!(c.1 >= a && c.1 <= b);

    return c;
}

#[inline]
pub fn sbx_single_var_bounded<R: Rng>(rng: &mut R,
                                      p: (f32, f32),
                                      bounds: (f32, f32),
                                      eta: f32)
                                      -> (f32, f32) {
    if p.0 < p.1 {
        _sbx_single_var_bounded(rng, (p.0, p.1), bounds, eta)
    } else if p.0 > p.1 {
        let r = _sbx_single_var_bounded(rng, (p.1, p.0), bounds, eta);
        (r.1, r.0)
    } else {
        debug_assert!(p.0 == p.1);
        (p.0, p.1)
    }
}

/// Modifies ind1 and ind2 in-place.
/// Reference: http://www.iitk.ac.in/kangal/papers/k2011017.pdf
pub fn simulated_binary_crossover<R: Rng>(rng: &mut R,
                                          ind1: &mut [f32],
                                          ind2: &mut [f32],
                                          eta: f32) {
    assert!(ind1.len() == ind2.len());

    let mut iter = ind1.iter_mut().zip(ind2.iter_mut());
    for (x1, x2) in iter {
        let (c1, c2) = sbx_single_var(rng, (*x1, *x2), eta);
        *x1 = c1;
        *x2 = c2;
    }
}

#[test]
fn test_sbx() {
    let mut rng = ::rand::isaac::Isaac64Rng::new_unseeded();

    let parent1 = vec![1.0, 2.0];
    let parent2 = vec![100.0, 1.0];

    let mut child1 = parent1.clone();
    let mut child2 = parent2.clone();

    simulated_binary_crossover(&mut rng, &mut child1[..], &mut child2[..], 2.0);

    let beta: Vec<_> = (0..2)
                           .map(|i| (child2[i] - child1[i]) / (parent2[i] - parent1[i]))
                           .collect();

    println!("({:?}, {:?}) => ({:?}, {:?})",
             parent1,
             parent2,
             child1,
             child2);
    println!("beta: {:?}", beta);
}

pub fn linear_2point_crossover<T:Clone>(p1: &[T], p2: &[T], cut_pt1: (usize, usize), cut_pt2: (usize, usize)) -> Vec<T> {
    assert!(cut_pt1.0 <= cut_pt1.1);
    assert!(cut_pt2.0 <= cut_pt2.1);
    assert!(cut_pt1.0 <= p1.len());
    assert!(cut_pt1.1 <= p1.len());
    assert!(cut_pt2.0 <= p2.len());
    assert!(cut_pt2.1 <= p2.len());

    let len1 = cut_pt1.1 - cut_pt1.0;
    let len2 = cut_pt2.1 - cut_pt2.0;

    let len = p1.len() - /* cut out */ len1 + /* insert */ len2;

    let mut res = Vec::with_capacity(len);
    for e in &p1[..cut_pt1.0] { res.push(e.clone()); }
    for e in &p2[cut_pt2.0..cut_pt2.1] { res.push(e.clone()); }
    for e in &p1[cut_pt1.1..] { res.push(e.clone()); }

    assert!(res.len() == len);
    return res;
}

#[test]
fn test_linear_2point_crossover() {
    let p1 = vec![1,2,3,4];
    //             ^ ^
    let p2 = vec![5,6,7,8,9];
    //             ^     ^

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,2), (1, 4));
    assert_eq!(&[1, 6,7,8, 3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,2), (1, 5));
    assert_eq!(&[1, 6,7,8,9, 3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,2), (0, 5));
    assert_eq!(&[1, 5,6,7,8,9, 3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,1), (0, 5));
    assert_eq!(&[1, 5,6,7,8,9, 2,3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (0,4), (0, 5));
    assert_eq!(&[5,6,7,8,9], &c[..]);
}
<commit_msg>Remove unused `mut`<commit_after>use rand::Rng;

#[inline]
fn sbx_beta(u: f32, eta: f32) -> f32 {
    assert!(u >= 0.0 && u < 1.0);

    if u <= 0.5 {
        2.0 * u
    } else {
        1.0 / (2.0 * (1.0 - u))
    }
    .powf(1.0 / (eta + 1.0))
}

#[inline]
fn sbx_beta_bounded(u: f32, eta: f32, gamma: f32) -> f32 {
    assert!(u >= 0.0 && u < 1.0);

    let g = 1.0 - gamma;
    let ug = u * g;

    if u <= 0.5 / g {
        2.0 * ug
    } else {
        1.0 / (2.0 * (1.0 - ug))
    }
    .powf(1.0 / (eta + 1.0))
}

#[inline]
pub fn sbx_single_var<R: Rng>(rng: &mut R, p: (f32, f32), eta: f32) -> (f32, f32) {
    let u = rng.gen::<f32>();
    let beta = sbx_beta(u, eta);

    (0.5 * (((1.0 + beta) * p.0) + ((1.0 - beta) * p.1)),
     0.5 * (((1.0 - beta) * p.0) + ((1.0 + beta) * p.1)))
}

#[inline]
fn _sbx_single_var_bounded<R: Rng>(rng: &mut R,
                                   p: (f32, f32),
                                   bounds: (f32, f32),
                                   eta: f32)
                                   -> (f32, f32) {
    let (a, b) = bounds;
    let p_diff = p.1 - p.0;

    assert!(a <= b);
    assert!(p_diff > 0.0);
    assert!(p.0 >= a && p.0 <= b);
    assert!(p.1 >= a && p.1 <= b);

    let beta_a = 1.0 + (p.0 - a) / p_diff;
    let beta_b = 1.0 + (b - p.1) / p_diff;

    fn gamma(beta: f32, eta: f32) -> f32 {
        1.0 / (2.0 * beta.powf(eta + 1.0))
    }

    let gamma_a = gamma(beta_a, eta);
    let gamma_b = gamma(beta_b, eta);

    let u = rng.gen::<f32>();
    let beta_ua = sbx_beta_bounded(u, eta, gamma_a);
    let beta_ub = sbx_beta_bounded(u, eta, gamma_b);

    let c = (0.5 * (((1.0 + beta_ua) * p.0) + ((1.0 - beta_ua) * p.1)),
             0.5 * (((1.0 - beta_ub) * p.0) + ((1.0 + beta_ub) * p.1)));

    assert!(c.0 >= a && c.0 <= b);
    assert!(c.1 >= a && c.1 <= b);

    return c;
}

#[inline]
pub fn sbx_single_var_bounded<R: Rng>(rng: &mut R,
                                      p: (f32, f32),
                                      bounds: (f32, f32),
                                      eta: f32)
                                      -> (f32, f32) {
    if p.0 < p.1 {
        _sbx_single_var_bounded(rng, (p.0, p.1), bounds, eta)
    } else if p.0 > p.1 {
        let r = _sbx_single_var_bounded(rng, (p.1, p.0), bounds, eta);
        (r.1, r.0)
    } else {
        debug_assert!(p.0 == p.1);
        (p.0, p.1)
    }
}

/// Modifies ind1 and ind2 in-place.
/// Reference: http://www.iitk.ac.in/kangal/papers/k2011017.pdf
pub fn simulated_binary_crossover<R: Rng>(rng: &mut R,
                                          ind1: &mut [f32],
                                          ind2: &mut [f32],
                                          eta: f32) {
    assert!(ind1.len() == ind2.len());

    let iter = ind1.iter_mut().zip(ind2.iter_mut());
    for (x1, x2) in iter {
        let (c1, c2) = sbx_single_var(rng, (*x1, *x2), eta);
        *x1 = c1;
        *x2 = c2;
    }
}

#[test]
fn test_sbx() {
    let mut rng = ::rand::isaac::Isaac64Rng::new_unseeded();

    let parent1 = vec![1.0, 2.0];
    let parent2 = vec![100.0, 1.0];

    let mut child1 = parent1.clone();
    let mut child2 = parent2.clone();

    simulated_binary_crossover(&mut rng, &mut child1[..], &mut child2[..], 2.0);

    let beta: Vec<_> = (0..2)
                           .map(|i| (child2[i] - child1[i]) / (parent2[i] - parent1[i]))
                           .collect();

    println!("({:?}, {:?}) => ({:?}, {:?})",
             parent1,
             parent2,
             child1,
             child2);
    println!("beta: {:?}", beta);
}

pub fn linear_2point_crossover<T:Clone>(p1: &[T], p2: &[T], cut_pt1: (usize, usize), cut_pt2: (usize, usize)) -> Vec<T> {
    assert!(cut_pt1.0 <= cut_pt1.1);
    assert!(cut_pt2.0 <= cut_pt2.1);
    assert!(cut_pt1.0 <= p1.len());
    assert!(cut_pt1.1 <= p1.len());
    assert!(cut_pt2.0 <= p2.len());
    assert!(cut_pt2.1 <= p2.len());

    let len1 = cut_pt1.1 - cut_pt1.0;
    let len2 = cut_pt2.1 - cut_pt2.0;

    let len = p1.len() - /* cut out */ len1 + /* insert */ len2;

    let mut res = Vec::with_capacity(len);
    for e in &p1[..cut_pt1.0] { res.push(e.clone()); }
    for e in &p2[cut_pt2.0..cut_pt2.1] { res.push(e.clone()); }
    for e in &p1[cut_pt1.1..] { res.push(e.clone()); }

    assert!(res.len() == len);
    return res;
}

#[test]
fn test_linear_2point_crossover() {
    let p1 = vec![1,2,3,4];
    //             ^ ^
    let p2 = vec![5,6,7,8,9];
    //             ^     ^

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,2), (1, 4));
    assert_eq!(&[1, 6,7,8, 3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,2), (1, 5));
    assert_eq!(&[1, 6,7,8,9, 3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,2), (0, 5));
    assert_eq!(&[1, 5,6,7,8,9, 3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (1,1), (0, 5));
    assert_eq!(&[1, 5,6,7,8,9, 2,3,4], &c[..]);

    let c = linear_2point_crossover(&p1[..], &p2[..], (0,4), (0, 5));
    assert_eq!(&[5,6,7,8,9], &c[..]);
}
<|endoftext|>


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

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use std::path::Path;
use libc::{c_uint,c_ulong};

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod enums {
    use super::ffi as ffi;

    include!(concat!(env!("OUT_DIR"), "/demux-enums.rs"));
}

pub use self::enums::{Input,Output,PesType};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Demux> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self, buffer_size: u32) -> DeviceResult<()> {
        let mut ffi_size = buffer_size as c_ulong;
        self.device.ioctl_pointer(ffi::DMX_SET_BUFFER_SIZE as c_ulong, &mut ffi_size)
    }

    pub fn get_system_time_counter(&self, num: u32) -> DeviceResult<SystemTimeCounter> {
        let mut ffi_stc = ffi::Struct_dmx_stc { num: num as c_uint, base: 0, stc: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_STC as c_ulong, &mut ffi_stc));
        Ok(SystemTimeCounter { base: ffi_stc.base, counter: ffi_stc.stc })
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        let mut ffi_pids = [0u16; 5];
        try!(self.device.ioctl_pointer(ffi::DMX_GET_PES_PIDS as c_ulong, ffi_pids.as_mut_ptr()));
        Ok(ffi_pids)
    }

    /// This function is undocumented in the official, and doesn't seem to be actually in use.
    /// It is still nevertheless included here, if it is used by out-of-tree DVB drivers.
    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        let mut ffi_caps = ffi::Struct_dmx_caps { caps: 0, num_decoders: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_CAPS as c_ulong, &mut ffi_caps));
        Ok(DemuxCaps { caps: ffi_caps.caps, num_decoders: ffi_caps.num_decoders as i32 })
    }

    pub fn set_source(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_ADD_PID as c_ulong, &mut ffi_pid)
    }

    pub fn remove_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_REMOVE_PID as c_ulong, &mut ffi_pid)
    }
}

pub struct DemuxCaps {
    pub caps: u32,
    pub num_decoders: i32
}

pub struct SystemTimeCounter {
    pub base: u32,
    pub counter: u64
}

pub struct DemuxFilter {
    pub filter: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mask: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mode: [u8; ffi::DMX_FILTER_SIZE as usize],
}

pub struct SectionFilterParams {
    pub pid: u16,
    pub filter: DemuxFilter,
    pub timeout: u32,
    // pub flags: flags::SectionFilterFlags
}

pub struct PesFilterParams {
    pub pid: u16,
    pub input: Input,
    pub output: Output,
    pub pes_type: PesType,
    pub flags: u32
}<commit_msg>Implement set_source() for Demux.<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use std::path::Path;
use libc::{c_uint,c_ulong};

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod enums {
    use super::ffi as ffi;

    include!(concat!(env!("OUT_DIR"), "/demux-enums.rs"));
}

pub use self::enums::{Input,Output,PesType};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Demux> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self, buffer_size: u32) -> DeviceResult<()> {
        let mut ffi_size = buffer_size as c_ulong;
        self.device.ioctl_pointer(ffi::DMX_SET_BUFFER_SIZE as c_ulong, &mut ffi_size)
    }

    pub fn get_system_time_counter(&self, num: u32) -> DeviceResult<SystemTimeCounter> {
        let mut ffi_stc = ffi::Struct_dmx_stc { num: num as c_uint, base: 0, stc: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_STC as c_ulong, &mut ffi_stc));
        Ok(SystemTimeCounter { base: ffi_stc.base, counter: ffi_stc.stc })
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        let mut ffi_pids = [0u16; 5];
        try!(self.device.ioctl_pointer(ffi::DMX_GET_PES_PIDS as c_ulong, ffi_pids.as_mut_ptr()));
        Ok(ffi_pids)
    }

    /// This function is undocumented in the official, and doesn't seem to be actually in use.
    /// It is still nevertheless included here, if it is used by out-of-tree DVB drivers.
    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        let mut ffi_caps = ffi::Struct_dmx_caps { caps: 0, num_decoders: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_CAPS as c_ulong, &mut ffi_caps));
        Ok(DemuxCaps { caps: ffi_caps.caps, num_decoders: ffi_caps.num_decoders as i32 })
    }

    pub fn set_source(&self, source: enums::DemuxSource) -> DeviceResult<()> {
        let mut ffi_source: ffi::dmx_source_t =  source.into();
        self.device.ioctl_pointer(ffi::DMX_SET_SOURCE as c_ulong, &mut ffi_source)
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_ADD_PID as c_ulong, &mut ffi_pid)
    }

    pub fn remove_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_REMOVE_PID as c_ulong, &mut ffi_pid)
    }
}

pub struct DemuxCaps {
    pub caps: u32,
    pub num_decoders: i32
}

pub struct SystemTimeCounter {
    pub base: u32,
    pub counter: u64
}

pub struct DemuxFilter {
    pub filter: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mask: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mode: [u8; ffi::DMX_FILTER_SIZE as usize],
}

pub struct SectionFilterParams {
    pub pid: u16,
    pub filter: DemuxFilter,
    pub timeout: u32,
    // pub flags: flags::SectionFilterFlags
}

pub struct PesFilterParams {
    pub pid: u16,
    pub input: Input,
    pub output: Output,
    pub pes_type: PesType,
    pub flags: u32
}<|endoftext|>


<commit_before>use libc::{c_int, c_double, c_char, c_void};
use std::mem;

/// Typedef for initialization function.
pub type EnergyMonInitFn = unsafe extern fn(em: *mut EnergyMon) -> c_int;
/// Typedef for read function.
pub type EnergyMonReadTotalFn = unsafe extern fn(em: *mut EnergyMon) -> c_double;
/// Typedef for cleanup function.
pub type EnergyMonFinishFn = unsafe extern fn(em: *mut EnergyMon) -> c_int;
/// Typedef for function to get human-readable name.
pub type EnergyMonGetSourceFn = unsafe extern fn(*mut c_char) -> *mut c_char;

#[repr(C)]
/// Representation of native C struct `em_impl`.
pub struct EnergyMon {
    /// Native C function type signature that initializes the `EnergyMon`.
    pub finit: EnergyMonInitFn,
    /// Native C function type signature that reads energy data from the `EnergyMon`.
    pub fread: EnergyMonReadTotalFn,
    /// Native C function type signature that cleans up the `EnergyMon`.
    pub ffinish: EnergyMonFinishFn,
    /// Native C function type signature that gets the `EnergyMon`'s human-readable name.
    pub fsource: EnergyMonGetSourceFn,
    /// Native C pointer used by the underlying `EnergyMon` implementation for storing state.
    pub state: *mut c_void,
}

extern {
    /// Native C function that fills in the EnergyMon struct values and may allocate other
    /// resources.
    fn em_impl_get(em: *mut EnergyMon) -> c_int;
}

impl EnergyMon {
    /// Create an `EnergyMon` which represents a C struct.
    pub fn new() -> Result<EnergyMon, &'static str> {
        unsafe {
            let mut em: EnergyMon = mem::uninitialized();
            let result: i32 = em_impl_get(&mut em);
            if result != 0 {
                return Err("Failed to create energymon");
            }
            Ok(em)
        }
    }

    /// Initialize the `EnergyMon` - may allocate more resources and/or start threads.
    pub fn init(&mut self) -> Result<(), &'static str> {
        let result: i32 = unsafe {
            (self.finit)(self)
        };
        if result != 0 {
            return Err("Failed to initialize energymon");
        }
        Ok(())
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&mut self) -> f64 {
        unsafe {
            (self.fread)(self)
        }

    }

    /// Cleanup the `EnergyMon` - may deallocate associated resources and/or stop threads.
    pub fn finish(&mut self) -> Result<(), &'static str> {
        let result: i32 = unsafe {
            (self.ffinish)(self)
        };
        if result != 0 {
            return Err("Failed to cleanup energymon");
        }
        Ok(())
    }

    /// Utility function to get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> Result<String, &'static str> {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        unsafe {
            let ret: *mut c_char = (self.fsource)(buf.as_mut_ptr());
            if ret.is_null() {
                return Err("Failed to get energymon source");
            }
            let buf: &[u8] = mem::transmute::<&[c_char], &[u8]>(&buf);
            Ok(String::from_utf8_lossy(buf).into_owned())
        }
    }
}

#[cfg(test)]
mod test {
    use super::EnergyMon;

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        em.init().unwrap();
        let val = em.read();
        assert!(val >= 0.0);
        let source = em.source().unwrap();
        em.finish().unwrap();
        println!("Read {} from {}", val, source);
    }

}
<commit_msg>Reduce amount of unsafe<commit_after>use libc::{c_int, c_double, c_char, c_void};
use std::mem;

/// Typedef for initialization function.
pub type EnergyMonInitFn = extern fn(*mut EnergyMon) -> c_int;
/// Typedef for read function.
pub type EnergyMonReadTotalFn = extern fn(*mut EnergyMon) -> c_double;
/// Typedef for cleanup function.
pub type EnergyMonFinishFn = extern fn(*mut EnergyMon) -> c_int;
/// Typedef for function to get human-readable name.
pub type EnergyMonGetSourceFn = extern fn(*mut c_char) -> *mut c_char;

#[repr(C)]
/// Representation of native C struct `em_impl`.
pub struct EnergyMon {
    /// Native C function type signature that initializes the `EnergyMon`.
    pub finit: EnergyMonInitFn,
    /// Native C function type signature that reads energy data from the `EnergyMon`.
    pub fread: EnergyMonReadTotalFn,
    /// Native C function type signature that cleans up the `EnergyMon`.
    pub ffinish: EnergyMonFinishFn,
    /// Native C function type signature that gets the `EnergyMon`'s human-readable name.
    pub fsource: EnergyMonGetSourceFn,
    /// Native C pointer used by the underlying `EnergyMon` implementation for storing state.
    pub state: *mut c_void,
}

extern {
    /// Native C function that fills in the EnergyMon struct values and may allocate other
    /// resources.
    fn em_impl_get(em: *mut EnergyMon) -> c_int;
}

impl EnergyMon {
    /// Create an `EnergyMon` which represents a C struct.
    pub fn new() -> Result<EnergyMon, &'static str> {
        unsafe {
            let mut em: EnergyMon = mem::uninitialized();
            let result: i32 = em_impl_get(&mut em);
            if result != 0 {
                return Err("Failed to create energymon");
            }
            Ok(em)
        }
    }

    /// Initialize the `EnergyMon` - may allocate more resources and/or start threads.
    pub fn init(&mut self) -> Result<(), &'static str> {
        let result: i32 = (self.finit)(self);
        if result != 0 {
            return Err("Failed to initialize energymon");
        }
        Ok(())
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&mut self) -> f64 {
        (self.fread)(self)
    }

    /// Cleanup the `EnergyMon` - may deallocate associated resources and/or stop threads.
    pub fn finish(&mut self) -> Result<(), &'static str> {
        let result: i32 = (self.ffinish)(self);
        if result != 0 {
            return Err("Failed to cleanup energymon");
        }
        Ok(())
    }

    /// Utility function to get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> Result<String, &'static str> {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return Err("Failed to get energymon source");
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        Ok(String::from_utf8_lossy(buf).into_owned())
    }
}

#[cfg(test)]
mod test {
    use super::EnergyMon;

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        em.init().unwrap();
        let val = em.read();
        assert!(val >= 0.0);
        let source = em.source().unwrap();
        em.finish().unwrap();
        println!("Read {} from {}", val, source);
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// 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/.

use std::thread;
use std::net::{TcpListener, ToSocketAddrs};
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver
};

use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use simple_stream::nbetstream::NbetStream;
use stats;
use types::*;
use socket::Socket;
use resources::ResourcePool;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLIN      - Available for read
// EPOLLRDHUP   - Connection has been closed
// EPOLLONESHOT - After an event has been received, and reported, do not track
//                further changes until explicitly told to do so.
const EVENTS: u32 = (
    event_type::EPOLLET | // Set fd to EdgeTrigger mode
    event_type::EPOLLIN |
    event_type::EPOLLRDHUP |
    event_type::EPOLLONESHOT);

pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // EpollEvent handler thread
    let epfd1 = epfd.clone();
    let sockets1 = sockets.clone();
    let (tx_ep_event, rx_ep_event): (Sender<EpollEvent>, Receiver<EpollEvent>) = channel();
    let safe_handler = Arc::new(Mutex::new(*handler));
    thread::Builder::new()
        .name("EpollEvent Handler".to_string())
        .spawn(move || {
            epoll_event_handler(epfd1, rx_ep_event, sockets1, safe_handler);
        }).unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            epoll_wait_loop(epfd2, tx_ep_event);
        }).unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let sockets2 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
            listen(address, epfd3, sockets2);
        }).unwrap();

    // Stay alive forever
    let _ = prox.join();
}

fn listen<T: ToSocketAddrs>(address: T, epfd: RawFd, sockets: SocketList) {
    let listener = TcpListener::bind(address).unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                trace!("New connection received");
                // Create new socket
                match NbetStream::new(stream) {
                    Ok(nb_stream) => {
                        let socket = Socket::new(nb_stream);
                        let socket_ptr;
                        // Add to master list
                        { // Begin Mutex lock
                            let mut guard = match sockets.lock() {
                                Ok(guard) => guard,
                                Err(poisoned) => {
                                    warn!("SocketList Mutex failed, using anyway...");
                                    poisoned.into_inner()
                                }
                            };
                            let socket_list = guard.deref_mut();
                            socket_list.push_back(socket.clone());
                            socket_ptr = socket_list.back_mut().unwrap() as *mut Socket;
                        } // End Mutex lock

                        // Add to epoll
                        let sfd = socket.raw_fd();
                        let mut event = EpollEvent {
                            data: socket_ptr as u64,
                            events: EVENTS
                        };
                        match epoll::ctl(epfd, ctl_op::ADD, sfd, &mut event) {
                            Ok(()) => {
                                trace!("New socket added to epoll list");
                                trace!("epfd: {}", epfd);
                                trace!("fd: {}", sfd);
                            },
                            Err(e) => warn!("Epoll CtrlError during add: {}", e)
                        };
                    }
                    Err(e) => warn!("Error creating nbstream: {}", e)
                }
            }
            Err(e) => warn!("Error encountered during TCP connection: {}", e)
        }
    }
    drop(listener);
}

fn epoll_wait_loop(epfd: RawFd, tx_handler: Sender<EpollEvent>) {
    // Maximum number of events we want to be notified of at one time
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe { events.set_len(100); }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    let _ = tx_handler.send(events[x]);
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        }
    }
}

fn epoll_event_handler(epfd: RawFd,
                       rx: Receiver<EpollEvent>,
                       sockets: SocketList,
                       handler: SafeHandler) {
    // Types of events we care about
    const READ_EVENT: u32 = event_type::EPOLLIN;
    const DROP_EVENT: u32 = event_type::EPOLLRDHUP | event_type::EPOLLHUP;

    // Thread pool
    let mut pool = ResourcePool::new();

    for event in rx.iter() {
        // Get a pointer to the socket in the list
        let socket;
        { // Begin Mutex lock
            let _ = match sockets.lock() {
                Ok(guard) => guard,
                Err(poisoned) => {
                    warn!("SocketList Mutex failed, using anyway...");
                    poisoned.into_inner()
                }
            };
            socket = event.data as *mut Socket;
        } // End Mutex lock

        if (event.events & DROP_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socketfd = unsafe { (*socket).raw_fd() };
            let socketid = unsafe { (*socket).id() };

            pool.run(move || {
                epoll_remove_fd(t_epfd, socketfd);
                remove_socket_from_list(socketid, socket_list.clone());
                { // EventHandler Mutex locked
                    let mut guard = match t_handler.lock() {
                        Ok(guard) => guard,
                        Err(poisoned) => {
                            warn!("EventHandler Mutex failed, using anyway...");
                            poisoned.into_inner()
                        }
                    };
                    let e_handler = guard.deref_mut();
                    e_handler.on_socket_closed(socketid);
                } // EventHandler Mutex unlocked
            });
        } else if (event.events & READ_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let mut s_clone = unsafe { (*socket).clone() };
            let socketfd = s_clone.raw_fd();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socket_ptr = socket as u64;

            pool.run(move || {
                match s_clone.read() {
                    Ok(_) => {
                        for msg in s_clone.buffer().iter() {
                            let debug_msg = msg.clone();
                            match String::from_utf8(debug_msg) {
                                Ok(msg_str) => trace!("msg: {}", msg_str),
                                Err(_) => trace!("msg not UTF-8")
                            };

                            { // EventHandler Mutex locked
                                let mut guard = match t_handler.lock() {
                                    Ok(guard) => guard,
                                    Err(poisoned) => {
                                        warn!("EventHandler Mutex failed, using anyway...");
                                        poisoned.into_inner()
                                    }
                                };
                                let e_handler = guard.deref_mut();
                                e_handler.on_data_received(s_clone.clone(),
                                    socket_list.clone(), msg.clone());
                            } // EventHandler Mutex unlocked

                            // Track message received event and num bytes received
                            stats::msg_recv();
                            stats::bytes_recv(msg.len());

                            // Add socket's fd back to epoll watch list
                            let mut event = EpollEvent {
                                data: socket_ptr,
                                events: EVENTS
                            };
                            match epoll::ctl(t_epfd.clone(), ctl_op::MOD, socketfd, &mut event) {
                                Ok(_) => trace!("Socket back in epoll list"),
                                Err(e) => {
                                    warn!("Epoll CtrlError during mod: {}", e);
                                    warn!("epfd: {}", t_epfd.clone());
                                    warn!("fd: {}", socketfd);
                                }
                            };
                        }
                    }
                    Err(e) => {
                        debug!("Error reading socket: {}", e);
                        // We really don't care what happened, it all results in the same
                        // outcome - remove the socket from system...
                        let s_id = s_clone.id();
                        epoll_remove_fd(t_epfd, socketfd);
                        remove_socket_from_list(s_id, socket_list.clone());
                        let mut guard = match t_handler.lock() {
                            Ok(guard) => guard,
                            Err(poisoned) => {
                                warn!("SocketList Mutex failed, using anyway...");
                                poisoned.into_inner()
                            }
                        };
                        let e_handler = guard.deref_mut();
                        e_handler.on_socket_closed(s_id);
                    }
                };
            });
        } else { warn!("Unknown epoll event received: {}", event.data); continue; }
    }
}

fn epoll_remove_fd(epfd: RawFd, fd: RawFd) {
    debug!("remove_socket_from_epoll");

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
    // before 2.6.9 should specify a non-null pointer in event.
    let mut rm_event = EpollEvent {
        data: 0 as u64,
        events: 0 as u32
    };

    // Depending on how fds are duplicated with .clone(), this may fail.
    //
    // If the failure case is CtlError::ENOENT, we do not care, because
    // epoll will clean the up the descriptor after they are all dropped from
    // program memory
    match epoll::ctl(epfd, ctl_op::DEL, fd, &mut rm_event) {
        Ok(()) => trace!("Socket removed from epoll watch list"),
        Err(e) => {
            match e {
                CtlError::ENOENT => {
                    trace!("Fd not found in epoll, will remove when fd is syscall closed");
                }
                _ => warn!("Epoll CtrlError during del: {}", e)
            }
        }
    };
}

/// Removes socket_ids from master list
fn remove_socket_from_list(socket_id: u32, sockets: SocketList) {
    debug!("remove_socket_from_list");

    let mut s_guard = match sockets.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("SocketList Mutex was poisoned, using anyway");
            poisoned.into_inner()
        }
    };
    let s_list = s_guard.deref_mut();

    let mut s_found = false;
    let mut index = 1usize;
    for s in s_list.iter() {
        if s.id() == socket_id {
            s_found = true;
            break;
        }
        index += 1;
    }

    if !s_found { return; }

    if index == 1 {
        s_list.pop_front();
    } else {
        let mut split = s_list.split_off(index - 1);
        split.pop_front();
        s_list.append(&mut split);
    }

    stats::conn_lost();

    trace!("socket removed from list");
}
<commit_msg>More epoll mod error logs<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// 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/.

use std::thread;
use std::net::{TcpListener, ToSocketAddrs};
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver
};

use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use simple_stream::nbetstream::NbetStream;
use stats;
use types::*;
use socket::Socket;
use resources::ResourcePool;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLIN      - Available for read
// EPOLLRDHUP   - Connection has been closed
// EPOLLONESHOT - After an event has been received, and reported, do not track
//                further changes until explicitly told to do so.
const EVENTS: u32 = (
    event_type::EPOLLET | // Set fd to EdgeTrigger mode
    event_type::EPOLLIN |
    event_type::EPOLLRDHUP |
    event_type::EPOLLONESHOT);

pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // EpollEvent handler thread
    let epfd1 = epfd.clone();
    let sockets1 = sockets.clone();
    let (tx_ep_event, rx_ep_event): (Sender<EpollEvent>, Receiver<EpollEvent>) = channel();
    let safe_handler = Arc::new(Mutex::new(*handler));
    thread::Builder::new()
        .name("EpollEvent Handler".to_string())
        .spawn(move || {
            epoll_event_handler(epfd1, rx_ep_event, sockets1, safe_handler);
        }).unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            epoll_wait_loop(epfd2, tx_ep_event);
        }).unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let sockets2 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
            listen(address, epfd3, sockets2);
        }).unwrap();

    // Stay alive forever
    let _ = prox.join();
}

fn listen<T: ToSocketAddrs>(address: T, epfd: RawFd, sockets: SocketList) {
    let listener = TcpListener::bind(address).unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                trace!("New connection received");
                // Create new socket
                match NbetStream::new(stream) {
                    Ok(nb_stream) => {
                        let socket = Socket::new(nb_stream);
                        let socket_ptr;
                        // Add to master list
                        { // Begin Mutex lock
                            let mut guard = match sockets.lock() {
                                Ok(guard) => guard,
                                Err(poisoned) => {
                                    warn!("SocketList Mutex failed, using anyway...");
                                    poisoned.into_inner()
                                }
                            };
                            let socket_list = guard.deref_mut();
                            socket_list.push_back(socket.clone());
                            socket_ptr = socket_list.back_mut().unwrap() as *mut Socket;
                        } // End Mutex lock

                        // Add to epoll
                        let sfd = socket.raw_fd();
                        let mut event = EpollEvent {
                            data: socket_ptr as u64,
                            events: EVENTS
                        };
                        match epoll::ctl(epfd, ctl_op::ADD, sfd, &mut event) {
                            Ok(()) => {
                                trace!("New socket added to epoll list");
                                trace!("socket.id: {}", socket.id());
                                trace!("epfd: {}", epfd);
                                trace!("fd: {}", sfd);
                            },
                            Err(e) => warn!("Epoll CtrlError during add: {}", e)
                        };
                    }
                    Err(e) => warn!("Error creating nbstream: {}", e)
                }
            }
            Err(e) => warn!("Error encountered during TCP connection: {}", e)
        }
    }
    drop(listener);
}

fn epoll_wait_loop(epfd: RawFd, tx_handler: Sender<EpollEvent>) {
    // Maximum number of events we want to be notified of at one time
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe { events.set_len(100); }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    let _ = tx_handler.send(events[x]);
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        }
    }
}

fn epoll_event_handler(epfd: RawFd,
                       rx: Receiver<EpollEvent>,
                       sockets: SocketList,
                       handler: SafeHandler) {
    // Types of events we care about
    const READ_EVENT: u32 = event_type::EPOLLIN;
    const DROP_EVENT: u32 = event_type::EPOLLRDHUP | event_type::EPOLLHUP;

    // Thread pool
    let mut pool = ResourcePool::new();

    for event in rx.iter() {
        // Get a pointer to the socket in the list
        let socket;
        { // Begin Mutex lock
            let _ = match sockets.lock() {
                Ok(guard) => guard,
                Err(poisoned) => {
                    warn!("SocketList Mutex failed, using anyway...");
                    poisoned.into_inner()
                }
            };
            socket = event.data as *mut Socket;
        } // End Mutex lock

        if (event.events & DROP_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socketfd = unsafe { (*socket).raw_fd() };
            let socketid = unsafe { (*socket).id() };

            pool.run(move || {
                epoll_remove_fd(t_epfd, socketfd);
                remove_socket_from_list(socketid, socket_list.clone());
                { // EventHandler Mutex locked
                    let mut guard = match t_handler.lock() {
                        Ok(guard) => guard,
                        Err(poisoned) => {
                            warn!("EventHandler Mutex failed, using anyway...");
                            poisoned.into_inner()
                        }
                    };
                    let e_handler = guard.deref_mut();
                    e_handler.on_socket_closed(socketid);
                } // EventHandler Mutex unlocked
            });
        } else if (event.events & READ_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let mut s_clone = unsafe { (*socket).clone() };
            let socketfd = s_clone.raw_fd();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socket_ptr = socket as u64;

            pool.run(move || {
                match s_clone.read() {
                    Ok(_) => {
                        for msg in s_clone.buffer().iter() {
                            let debug_msg = msg.clone();
                            match String::from_utf8(debug_msg) {
                                Ok(msg_str) => trace!("msg: {}", msg_str),
                                Err(_) => trace!("msg not UTF-8")
                            };

                            { // EventHandler Mutex locked
                                let mut guard = match t_handler.lock() {
                                    Ok(guard) => guard,
                                    Err(poisoned) => {
                                        warn!("EventHandler Mutex failed, using anyway...");
                                        poisoned.into_inner()
                                    }
                                };
                                let e_handler = guard.deref_mut();
                                e_handler.on_data_received(s_clone.clone(),
                                    socket_list.clone(), msg.clone());
                            } // EventHandler Mutex unlocked

                            // Track message received event and num bytes received
                            stats::msg_recv();
                            stats::bytes_recv(msg.len());

                            // Add socket's fd back to epoll watch list
                            let mut event = EpollEvent {
                                data: socket_ptr,
                                events: EVENTS
                            };
                            let s_id = s_clone.id();
                            match epoll::ctl(t_epfd.clone(), ctl_op::MOD, socketfd, &mut event) {
                                Ok(_) => trace!("Socket back in epoll list"),
                                Err(e) => {
                                    warn!("Epoll CtrlError during mod: {}", e);
                                    warn!("s.id: {}", s_id);
                                    warn!("epfd: {}", t_epfd.clone());
                                    warn!("fd: {}", socketfd);
                                }
                            };
                        }
                    }
                    Err(e) => {
                        debug!("Error reading socket: {}", e);
                        // We really don't care what happened, it all results in the same
                        // outcome - remove the socket from system...
                        let s_id = s_clone.id();
                        epoll_remove_fd(t_epfd, socketfd);
                        remove_socket_from_list(s_id, socket_list.clone());
                        let mut guard = match t_handler.lock() {
                            Ok(guard) => guard,
                            Err(poisoned) => {
                                warn!("SocketList Mutex failed, using anyway...");
                                poisoned.into_inner()
                            }
                        };
                        let e_handler = guard.deref_mut();
                        e_handler.on_socket_closed(s_id);
                    }
                };
            });
        } else { warn!("Unknown epoll event received: {}", event.data); continue; }
    }
}

fn epoll_remove_fd(epfd: RawFd, fd: RawFd) {
    debug!("remove_socket_from_epoll");

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
    // before 2.6.9 should specify a non-null pointer in event.
    let mut rm_event = EpollEvent {
        data: 0 as u64,
        events: 0 as u32
    };

    // Depending on how fds are duplicated with .clone(), this may fail.
    //
    // If the failure case is CtlError::ENOENT, we do not care, because
    // epoll will clean the up the descriptor after they are all dropped from
    // program memory
    match epoll::ctl(epfd, ctl_op::DEL, fd, &mut rm_event) {
        Ok(()) => trace!("Socket removed from epoll watch list"),
        Err(e) => {
            match e {
                CtlError::ENOENT => {
                    trace!("Fd not found in epoll, will remove when fd is syscall closed");
                }
                _ => warn!("Epoll CtrlError during del: {}", e)
            }
        }
    };
}

/// Removes socket_ids from master list
fn remove_socket_from_list(socket_id: u32, sockets: SocketList) {
    debug!("remove_socket_from_list");

    let mut s_guard = match sockets.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("SocketList Mutex was poisoned, using anyway");
            poisoned.into_inner()
        }
    };
    let s_list = s_guard.deref_mut();

    let mut s_found = false;
    let mut index = 1usize;
    for s in s_list.iter() {
        if s.id() == socket_id {
            s_found = true;
            break;
        }
        index += 1;
    }

    if !s_found { return; }

    if index == 1 {
        s_list.pop_front();
    } else {
        let mut split = s_list.split_off(index - 1);
        split.pop_front();
        s_list.append(&mut split);
    }

    stats::conn_lost();

    trace!("socket removed from list");
}
<|endoftext|>