<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{run, os};
use std::io::buffered::BufferedReader;
use std::path::posix::Path;
use std::option::Option;
use std::io::{stdin, stdio, process, IoError, io_error};
use std::run::Process;
use std::io::process::ProcessExit;
use std::run::ProcessOptions;
use extra::getopts;

fn cmd_exists(command : &str) -> bool {
    let ret = run::process_output("which", [command.to_owned()]);
    return ret.expect("exit code error.").status.success();
}

fn is_dead(exit_port : &Option<Port<ProcessExit>>) -> bool {
    let mut dead = false;
    match *exit_port {
        Some(ref p) => {
            match p.try_recv() {
                Some (exitstatus) => {
                    if (exitstatus.success()) {
                        dead = true;
                    }
                },
                _ => {}
            }
        },
        _ => {},
    };
    dead
}

trait Command {
    fn run(&mut self) -> Option<Process>;
}

struct CmdProcess {
    command     : ~str,
    args        : ~[~str],
    stdin       : i32,
    stdout      : i32,
    exit_status : Option<process::ProcessExit>,
}
impl CmdProcess {
    fn new(command: &str, args: ~[~str], stdin : i32, stdout : i32) -> Option<CmdProcess> {
        if (cmd_exists(command)) {
            Some(CmdProcess {
                command     : command.to_owned(),
                args        : args.to_owned(),
                stdin       : stdin,
                stdout      : stdout,
                exit_status : None,
            })
        }
        else { None }
    }
}
impl Command for CmdProcess {
    fn run(&mut self) -> Option<Process> {
        let command = self.command.to_owned();
        let args = self.args.to_owned();
        let options = ProcessOptions {
            env    : None,
            dir    : None,
            in_fd  : Some(self.stdin),
            out_fd : Some(self.stdout),
            err_fd : None,
        };
        Process::new(command, args, options)
    }
}

struct BackgroundProcess {
    command      : ~str,
    args         : ~[~str],
    exit_status  : Option<ProcessExit>,
    exit_port    : Option<Port<ProcessExit>>,
    kill_chan    : Option<Chan<int>>,
}
impl BackgroundProcess {
    fn new(command: &str, args: ~[~str]) -> Option<BackgroundProcess> {
        if (cmd_exists(command)) {
            Some(BackgroundProcess {
                command: command.to_owned(),
                args: args.to_owned(),
                exit_status: None,
                exit_port: None,
                kill_chan: None,
            })
        }
        else { None }
    }
    fn run(&mut self) {
        let (port, chan) : (Port<ProcessExit>, Chan<ProcessExit>)
                = Chan::new();
        let (killport, killchan) : (Port<int>, Chan<int>) = Chan::new();
        let command = self.command.to_owned();
        let args = self.args.to_owned();
        spawn(proc() {
            let options = ProcessOptions {
                env    : None,
                dir    : None,
                in_fd  : None,
                out_fd : None,
                err_fd : None,
            };
            let maybe_process = Process::new(command, args, options);
            match maybe_process {
                Some(mut process) => {
                    let signal = killport.recv();
                    let mut error = None;
                    match signal {
                        9 => {
                            io_error::cond.trap(|e: IoError| {
                                error = Some(e);
                                }).inside(|| {
                                    process.force_destroy()
                                })
                        }
                        15 => {
                            io_error::cond.trap(|e: IoError| {
                                error = Some(e);
                                }).inside(|| {
                                    process.force_destroy()
                                })
                        }
                        _ => {}
                    }
                    chan.try_send_deferred(process.finish());
                }
                None => {
                }
            }
        });
        self.exit_port = Some(port);
        self.kill_chan = Some(killchan);
    }
}

struct Shell {
    cmd_prompt : ~str,
    history    : ~[~str],
    processes  : ~[~BackgroundProcess],
}
impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            history: ~[],
            processes: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            self.kill_dead();
            match program {
                "" => {}
                _  => { self.push_hist(cmd_line) }
            }
            match program {
                ""        =>  { continue; }
                "exit"    =>  {
                    self.kill_all();
                    return;
                }
                "history" =>  { self.show_hist(); }
                "cd"      =>  { self.chdir(cmd_line); }
                _         =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn kill_dead(&mut self) {
        let mut dead : ~[uint];
        dead = ~[];
        let mut i = 0;
        for cmd in self.processes.iter() {
            if is_dead(&cmd.exit_port) {
                dead.push(i);
            }
            i += 1;
        }
        for &p in dead.iter() {
            self.processes.remove(p);
        }
    }

    fn kill_all(&mut self) {
        for p in self.processes.iter() {
            match p.kill_chan {
                Some(ref kill_channel) => {
                    kill_channel.try_send_deferred(15);
                }
                None => {}
            }

        }
    }

    fn push_hist(&mut self, cmd_line: &str) {
        &self.history.push(cmd_line.to_owned());
    }

    fn show_hist(&mut self) {
        println!("{:s}", self.get_hist());
    }

    fn get_hist(&mut self) -> ~str {
        let mut hist = ~"";
        for i in self.history.iter() {
            let s = i.to_owned();
            match hist {
                ~"" => { hist = s; }
                _   => { hist = hist + "\n" + s; }
            }
        }
        return hist
    }

    fn chdir(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != ""
                {
                    Some(x.to_owned())
                }
                else {
                    None
                }).to_owned_vec();
        if argv.len() > 0 {
            argv.remove(0);
            let path = Path::new(argv[0]);
            os::change_dir(&path);
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != ""
                {
                    Some(x.to_owned())
                }
                else {
                    None
                }).to_owned_vec();
        if argv.len() > 0 {
            self.parse_process(argv);
        }
    }

    fn parse_process(&mut self, mut argv : ~[~str]) {
        let program: ~str = argv.remove(0);
        if argv.len() > 0 {
            let last = argv.last().to_owned();
            if last == ~"&" {
                argv.pop();
                self.make_bg_process(program, argv);
            }
            else {
                self.make_fg_process(program, argv);
            }
        }
        else {
            self.make_fg_process(program, argv);
        }
    }

    fn make_fg_process(&mut self, program : ~str, argv : ~[~str]) {
        match CmdProcess::new(program, argv, 0, 1) {
            Some(mut cmdprocess) => {
                cmdprocess.run();
            }
            None              => { }
        }
    }

    fn make_bg_process(&mut self, program : ~str, argv : ~[~str]) {
        match BackgroundProcess::new(program, argv) {
            Some(process) => {self.add_process(~process);}
            None          => { }
        }
    }

    fn add_process(&mut self, mut process : ~BackgroundProcess) {
        &process.run();
        self.processes.push(process);
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                Some(cmd_str) => {cmd_str.to_owned()},
                None          => {~""}
        };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>simplifes background process logic<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{run, os};
use std::io::buffered::BufferedReader;
use std::path::posix::Path;
use std::option::Option;
use std::io::{stdin, stdio, process, IoError, io_error};
use std::run::Process;
use std::io::process::ProcessExit;
use std::run::ProcessOptions;
use extra::getopts;

fn cmd_exists(command : &str) -> bool {
    let ret = run::process_output("which", [command.to_owned()]);
    return ret.expect("exit code error.").status.success();
}

fn is_dead(exit_port : &Option<Port<ProcessExit>>) -> bool {
    let mut dead = false;
    match *exit_port {
        Some(ref p) => {
            match p.try_recv() {
                Some (exitstatus) => {
                    if (exitstatus.success()) {
                        dead = true;
                    }
                },
                _ => {}
            }
        },
        _ => {},
    };
    dead
}

trait Command {
    fn run(&mut self) -> Option<Process>;
}

struct CmdProcess {
    command     : ~str,
    args        : ~[~str],
    stdin       : i32,
    stdout      : i32,
    exit_status : Option<process::ProcessExit>,
}
impl CmdProcess {
    fn new(command: &str, args: ~[~str], stdin : i32, stdout : i32) -> Option<CmdProcess> {
        if (cmd_exists(command)) {
            Some(CmdProcess {
                command     : command.to_owned(),
                args        : args.to_owned(),
                stdin       : stdin,
                stdout      : stdout,
                exit_status : None,
            })
        }
        else { None }
    }
}
impl Command for CmdProcess {
    fn run(&mut self) -> Option<Process> {
        let command = self.command.to_owned();
        let args = self.args.to_owned();
        let options = ProcessOptions {
            env    : None,
            dir    : None,
            in_fd  : Some(self.stdin),
            out_fd : Some(self.stdout),
            err_fd : None,
        };
        Process::new(command, args, options)
    }
}

struct BackgroundProcess {
    command      : ~str,
    args         : ~[~str],
    exit_status  : Option<ProcessExit>,
    exit_port    : Option<Port<ProcessExit>>,
    kill_chan    : Option<Chan<int>>,
}
impl BackgroundProcess {
    fn new(command: &str, args: ~[~str]) -> Option<BackgroundProcess> {
        if (cmd_exists(command)) {
            Some(BackgroundProcess {
                command: command.to_owned(),
                args: args.to_owned(),
                exit_status: None,
                exit_port: None,
                kill_chan: None,
            })
        }
        else { None }
    }
    fn run(&mut self) {
        let (port, chan) : (Port<ProcessExit>, Chan<ProcessExit>)
                = Chan::new();
        let (killport, killchan) : (Port<int>, Chan<int>) = Chan::new();
        let command = self.command.to_owned();
        let args = self.args.to_owned();
        spawn(proc() {
            let options = ProcessOptions {
                env    : None,
                dir    : None,
                in_fd  : None,
                out_fd : None,
                err_fd : None,
            };
            let maybe_process = Process::new(command, args, options);
            match maybe_process {
                Some(mut process) => {
                    let signal = killport.recv();
                    let mut error = None;
                    match signal {
                        9 => {
                            io_error::cond.trap(|e: IoError| {
                                error = Some(e);
                                }).inside(|| {
                                    process.force_destroy()
                                })
                        }
                        15 => {
                            io_error::cond.trap(|e: IoError| {
                                error = Some(e);
                                }).inside(|| {
                                    process.force_destroy()
                                })
                        }
                        _ => {}
                    }
                    chan.try_send_deferred(process.finish());
                }
                None => {
                }
            }
        });
        self.exit_port = Some(port);
        self.kill_chan = Some(killchan);
    }
}

struct Shell {
    cmd_prompt : ~str,
    history    : ~[~str],
    processes  : ~[~BackgroundProcess],
}
impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            history: ~[],
            processes: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            self.kill_dead();
            match program {
                "" => {}
                _  => { self.push_hist(cmd_line) }
            }
            match program {
                ""        =>  { continue; }
                "exit"    =>  {
                    self.kill_all();
                    return;
                }
                "history" =>  { self.show_hist(); }
                "cd"      =>  { self.chdir(cmd_line); }
                _         =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn kill_dead(&mut self) {
        let mut dead : ~[uint];
        dead = ~[];
        let mut i = 0;
        for cmd in self.processes.iter() {
            if is_dead(&cmd.exit_port) {
                dead.push(i);
            }
            i += 1;
        }
        for &p in dead.iter() {
            self.processes.remove(p);
        }
    }

    fn kill_all(&mut self) {
        for p in self.processes.iter() {
            match p.kill_chan {
                Some(ref kill_channel) => {
                    kill_channel.try_send_deferred(15);
                }
                None => {}
            }

        }
    }

    fn push_hist(&mut self, cmd_line: &str) {
        &self.history.push(cmd_line.to_owned());
    }

    fn show_hist(&mut self) {
        println!("{:s}", self.get_hist());
    }

    fn get_hist(&mut self) -> ~str {
        let mut hist = ~"";
        for i in self.history.iter() {
            let s = i.to_owned();
            match hist {
                ~"" => { hist = s; }
                _   => { hist = hist + "\n" + s; }
            }
        }
        return hist
    }

    fn chdir(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != ""
                {
                    Some(x.to_owned())
                }
                else {
                    None
                }).to_owned_vec();
        if argv.len() > 0 {
            argv.remove(0);
            let path = Path::new(argv[0]);
            os::change_dir(&path);
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != ""
                {
                    Some(x.to_owned())
                }
                else {
                    None
                }).to_owned_vec();
        if argv.len() > 0 {
            self.parse_process(argv);
        }
    }

    fn parse_process(&mut self, mut argv : ~[~str]) {
        let program: ~str = argv.remove(0);
        if argv.len() > 0 {
            let last = argv.last().to_owned();
            if last == ~"&" {
                argv.pop();
                self.make_bg_process(program, argv);
            }
            else {
                self.make_fg_process(program, argv);
            }
        }
        else {
            self.make_fg_process(program, argv);
        }
    }

    fn make_fg_process(&mut self, program : ~str, argv : ~[~str]) {
        match CmdProcess::new(program, argv, 0, 1) {
            Some(mut cmdprocess) => {
                cmdprocess.run();
            }
            None              => { }
        }
    }

    fn make_bg_process(&mut self, program : ~str, argv : ~[~str]) {
        match BackgroundProcess::new(program, argv) {
            Some(mut process) => {
                process.run();
                self.processes.push(~process);
            }
            None          => { }
        }
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                Some(cmd_str) => {cmd_str.to_owned()},
                None          => {~""}
        };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>//! #Password Hashing
//!
//! Secret keys used to encrypt or sign confidential data have to be chosen from
//! a very large keyspace. However, passwords are usually short, human-generated
//! strings, making dictionary attacks practical.
//!
//! The pwhash operation derives a secret key of any size from a password and a
//! salt.
//!
//! - The generated key has the size defined by the application, no matter what
//!   the password length is.
//! - The same password hashed with same parameters will
//!   always produce the same key.
//! - The same password hashed with different salts
//!   will produce different keys.
//! - The function deriving a key from a password
//!   and a salt is CPU intensive and intentionally requires a fair amount of
//!   memory. Therefore, it mitigates brute-force attacks by requiring a
//!   significant effort to verify each password.
//!
//! Common use cases:
//!
//! - Protecting an on-disk secret key with a password,
//! - Password storage, or rather: storing what it takes to verify a password
//!   without having to store the actual password.
pub use self::scryptsalsa208sha256::*;
pub mod scryptsalsa208sha256;
<commit_msg>Small documentation update<commit_after>//! Password Hashing
//!
//! Secret keys used to encrypt or sign confidential data have to be chosen from
//! a very large keyspace. However, passwords are usually short, human-generated
//! strings, making dictionary attacks practical.
//!
//! The pwhash operation derives a secret key of any size from a password and a
//! salt.
//!
//! - The generated key has the size defined by the application, no matter what
//!   the password length is.
//! - The same password hashed with same parameters will
//!   always produce the same key.
//! - The same password hashed with different salts
//!   will produce different keys.
//! - The function deriving a key from a password
//!   and a salt is CPU intensive and intentionally requires a fair amount of
//!   memory. Therefore, it mitigates brute-force attacks by requiring a
//!   significant effort to verify each password.
//!
//! Common use cases:
//!
//! - Protecting an on-disk secret key with a password,
//! - Password storage, or rather: storing what it takes to verify a password
//!   without having to store the actual password.
pub use self::scryptsalsa208sha256::*;
pub mod scryptsalsa208sha256;
<|endoftext|>


<commit_before>mod package;
pub mod update;
pub mod find;<commit_msg>Update mod.rs<commit_after>mod pkg;
pub mod update;
pub mod find;<|endoftext|>


<commit_before>use std::cmp::max;
use std::ffi::CString;
use std::ops::Deref;

use byteorder::{WriteBytesExt, NativeEndian};

use libc::{c_char, c_int, off_t, size_t, ftruncate, unlink, write, lseek, SEEK_SET};

use wayland::core::{Buffer, SubSurface, ShellSurface, Surface, WSurface, Registry, ShmPool, ShmFormat};

// The surfaces handling the borders, 8 total, are organised this way:
//
//        0
// ---|-------|---
//    |       |
//  3 | user  | 1
//    |       |
// ---|-------|---
//        2
//
pub const BORDER_TOP         : usize = 0;
pub const BORDER_RIGHT       : usize = 1;
pub const BORDER_BOTTOM      : usize = 2;
pub const BORDER_LEFT        : usize = 3;

const DECORATION_SIZE     : usize = 8;
const DECORATION_TOP_SIZE : usize = 24;

/// A decorated surface, wrapping a wayalnd surface and handling its decorations.
pub struct DecoratedSurface<S: Surface> {
    shell_surface: ShellSurface<WSurface>,
    user_surface: SubSurface<S>,
    border_surfaces: Vec<SubSurface<WSurface>>,
    buffers: Vec<Buffer>,
    shm_fd: c_int,
    pool: ShmPool,
    height: u32,
    width: u32,
    buffer_capacity: usize
}

impl<S: Surface> DecoratedSurface<S> {
    /// Creates a new decorated window around given surface.
    ///
    /// If the creation failed (likely if the registry was not ready), hands back the surface.
    pub fn new(user_surface: S, width: u32, height: u32, registry: &Registry)
        -> Result<DecoratedSurface<S>,S>
    {
        // fetch the global
        let comp = match registry.get_compositor() {
            Some(c) => c,
            None => return Err(user_surface)
        };
        let subcomp = match registry.get_subcompositor() {
            Some(c) => c,
            None => return Err(user_surface)
        };
        let shm = match registry.get_shm() {
            Some(s) => s,
            None => return Err(user_surface)
        };
        let shell = match registry.get_shell() {
            Some(s) => s,
            None => return Err(user_surface)
        };

        // handle Shm
        let pxcount = max(DECORATION_TOP_SIZE * DECORATION_SIZE,
            max(DECORATION_TOP_SIZE * (width as usize), DECORATION_SIZE * (height as usize))
        );

        let pattern = CString::new("wayland-window-rs-XXXXXX").unwrap();
        let fd = unsafe { mkstemp(pattern.as_ptr() as *mut _) };
        if fd < 0 { return Err(user_surface) }
        unsafe {
            ftruncate(fd, (pxcount * 4) as off_t);
            unlink(pattern.as_ptr());
        }

        let pool = shm.pool_from_raw_fd(fd, (pxcount * 4) as i32);

        // create surfaces
        let main_surface = comp.create_surface();
        let user_subsurface = subcomp.get_subsurface(user_surface, &main_surface);
        user_subsurface.set_sync(false);
        let border_surfaces = (0..4).map(|_|
            subcomp.get_subsurface(comp.create_surface(), &main_surface)
        ).collect();

        let shell_surface = shell.get_shell_surface(main_surface);
        shell_surface.set_toplevel();

        let mut me = DecoratedSurface {
            shell_surface: shell_surface,
            user_surface: user_subsurface,
            border_surfaces: border_surfaces,
            buffers: Vec::new(),
            height: height,
            width: width,
            shm_fd: fd,
            pool: pool,
            buffer_capacity: pxcount * 4
        };

        me.resize(width, height);

        Ok(me)
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        let new_pxcount = max(DECORATION_TOP_SIZE * (DECORATION_SIZE * 2 + (width as usize)),
            max(DECORATION_TOP_SIZE * (width as usize), DECORATION_SIZE * (height as usize))
        );
        if new_pxcount * 4 > self.buffer_capacity {
            // reallocation needed !
            unsafe { ftruncate(self.shm_fd, (new_pxcount * 4) as off_t) };
            self.pool.resize((new_pxcount * 4) as i32);
            self.buffer_capacity = new_pxcount * 4;
        }
        self.width = width;
        self.height = height;
        // rewrite the data
        {
            let mut new_data = Vec::<u8>::with_capacity(new_pxcount * 4);
            for _ in 0..(new_pxcount*4) {
                // write a dark gray
                let _ = new_data.write_u32::<NativeEndian>(0xFF444444);
            }
            unsafe {
                lseek(self.shm_fd, 0, SEEK_SET);
                write(self.shm_fd, new_data.as_ptr() as *const _, new_data.len() as size_t);
            }
        }

        //drop(mmap);

        // resize the borders
        self.buffers.clear();
        // top
        {
            let buffer = self.pool.create_buffer(
                0,
                self.width as i32 + (DECORATION_SIZE as i32) * 2,
                DECORATION_TOP_SIZE as i32, (self.width*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            self.border_surfaces[BORDER_TOP].attach(&buffer, 0, 0);
            self.border_surfaces[BORDER_TOP].set_position(0, 0);
            self.buffers.push(buffer);
        }
        // right
        {
            let buffer = self.pool.create_buffer(
                0, DECORATION_SIZE as i32,
                self.height as i32, (DECORATION_SIZE*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            self.border_surfaces[BORDER_RIGHT].attach(&buffer, 0, 0);
            self.border_surfaces[BORDER_RIGHT].set_position(
                DECORATION_SIZE as i32 + self.width as i32, DECORATION_TOP_SIZE as i32);
            self.buffers.push(buffer);
        }
        // bottom
        {
            let buffer = self.pool.create_buffer(
                0,
                self.width as i32 + (DECORATION_SIZE as i32) * 2,
                DECORATION_SIZE as i32, (self.width*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            self.border_surfaces[BORDER_BOTTOM].attach(&buffer, 0, 0);
            self.border_surfaces[BORDER_BOTTOM].set_position(
                0,
                DECORATION_TOP_SIZE as i32 + self.height as i32);
            self.buffers.push(buffer);
        }
        // left
        {
            let buffer = self.pool.create_buffer(
                0, DECORATION_SIZE as i32,
                self.height as i32, (DECORATION_SIZE*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            self.border_surfaces[BORDER_LEFT].attach(&buffer, 0, 0);
            self.border_surfaces[BORDER_LEFT].set_position(0,
                DECORATION_TOP_SIZE as i32);
            self.buffers.push(buffer);
        }
        for s in &self.border_surfaces { s.commit(); }

        self.user_surface.set_position(DECORATION_SIZE as i32, DECORATION_TOP_SIZE as i32);

        {
            let buffer = self.pool.create_buffer(
                0, 1, 1, 4,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            self.shell_surface.attach(&buffer, 0, 0);
            self.buffers.push(buffer);
            self.shell_surface.commit();
        }

    }

    /// Destroys the decorated window and gives back the wrapped surface.
    pub fn unwrap(self) -> S {
        self.user_surface.destroy()
    }
}

impl<S: Surface> Deref for DecoratedSurface<S> {
    type Target = S;
    fn deref(&self) -> &S {
        &*self.user_surface
    }
}

extern {
    fn mkstemp(template: *mut c_char) -> c_int;
}<commit_msg>Create a pointer, and make the whole structure cllback-friendly.<commit_after>use std::cmp::max;
use std::ffi::CString;
use std::ops::Deref;
use std::sync::{Arc, Mutex};

use byteorder::{WriteBytesExt, NativeEndian};

use libc::{c_char, c_int, off_t, size_t, ftruncate, unlink, write, lseek, SEEK_SET};

use wayland::core::{Buffer, SubSurface, ShellSurface, Surface, WSurface,
                    Registry, ShmPool, ShmFormat, Pointer};

// The surfaces handling the borders, 8 total, are organised this way:
//
//        0
// ---|-------|---
//    |       |
//  3 | user  | 1
//    |       |
// ---|-------|---
//        2
//
pub const BORDER_TOP         : usize = 0;
pub const BORDER_RIGHT       : usize = 1;
pub const BORDER_BOTTOM      : usize = 2;
pub const BORDER_LEFT        : usize = 3;

const DECORATION_SIZE     : usize = 8;
const DECORATION_TOP_SIZE : usize = 24;

struct DecoratedInternals {
    shell_surface: ShellSurface<WSurface>,
    border_surfaces: Vec<SubSurface<WSurface>>,
    buffers: Vec<Buffer>,
    shm_fd: c_int,
    pool: ShmPool,
    height: u32,
    width: u32,
    buffer_capacity: usize,
    pointer: Option<Pointer<WSurface>>
}

/// A decorated surface, wrapping a wayalnd surface and handling its decorations.
pub struct DecoratedSurface<S: Surface> {
    internals: Arc<Mutex<DecoratedInternals>>,
    user_surface: SubSurface<S>,
}

impl<S: Surface> DecoratedSurface<S> {
    /// Creates a new decorated window around given surface.
    ///
    /// If the creation failed (likely if the registry was not ready), hands back the surface.
    pub fn new(user_surface: S, width: u32, height: u32, registry: &Registry)
        -> Result<DecoratedSurface<S>,S>
    {
        // fetch the global
        let comp = match registry.get_compositor() {
            Some(c) => c,
            None => return Err(user_surface)
        };
        let subcomp = match registry.get_subcompositor() {
            Some(c) => c,
            None => return Err(user_surface)
        };
        let shm = match registry.get_shm() {
            Some(s) => s,
            None => return Err(user_surface)
        };
        let shell = match registry.get_shell() {
            Some(s) => s,
            None => return Err(user_surface)
        };
        let seats = registry.get_seats();

        // handle Shm
        let pxcount = max(DECORATION_TOP_SIZE * DECORATION_SIZE,
            max(DECORATION_TOP_SIZE * (width as usize), DECORATION_SIZE * (height as usize))
        );

        let pattern = CString::new("wayland-window-rs-XXXXXX").unwrap();
        let fd = unsafe { mkstemp(pattern.as_ptr() as *mut _) };
        if fd < 0 { return Err(user_surface) }
        unsafe {
            ftruncate(fd, (pxcount * 4) as off_t);
            unlink(pattern.as_ptr());
        }

        let pool = shm.pool_from_raw_fd(fd, (pxcount * 4) as i32);

        // create surfaces
        let main_surface = comp.create_surface();
        let user_subsurface = subcomp.get_subsurface(user_surface, &main_surface);
        user_subsurface.set_sync(false);
        let border_surfaces: Vec<_> = (0..4).map(|_|
            subcomp.get_subsurface(comp.create_surface(), &main_surface)
        ).collect();

        let shell_surface = shell.get_shell_surface(main_surface);
        shell_surface.set_toplevel();

        // Pointer
        let pointer = seats.first().and_then(|seat| seat.get_pointer())
                                       .map(|pointer| {
            let (mut pointer, _) = pointer.set_cursor(Some(comp.create_surface()), (0,0));
            for s in &border_surfaces {
                pointer.add_handled_surface(s.get_id());
            }
            pointer
        });

        let internals = Arc::new(Mutex::new(DecoratedInternals {
            shell_surface: shell_surface,
            border_surfaces: border_surfaces,
            buffers: Vec::new(),
            height: height,
            width: width,
            shm_fd: fd,
            pool: pool,
            buffer_capacity: pxcount * 4,
            pointer: pointer
        }));

        let mut me = DecoratedSurface {
            user_surface: user_subsurface,
            internals: internals
        };

        me.resize(width, height);

        Ok(me)
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        let mut internals = self.internals.lock().unwrap();

        let new_pxcount = max(DECORATION_TOP_SIZE * (DECORATION_SIZE * 2 + (width as usize)),
            max(DECORATION_TOP_SIZE * (width as usize), DECORATION_SIZE * (height as usize))
        );
        if new_pxcount * 4 > internals.buffer_capacity {
            // reallocation needed !
            unsafe { ftruncate(internals.shm_fd, (new_pxcount * 4) as off_t) };
            internals.pool.resize((new_pxcount * 4) as i32);
            internals.buffer_capacity = new_pxcount * 4;
        }
        internals.width = width;
        internals.height = height;
        // rewrite the data
        {
            let mut new_data = Vec::<u8>::with_capacity(new_pxcount * 4);
            for _ in 0..(new_pxcount*4) {
                // write a dark gray
                let _ = new_data.write_u32::<NativeEndian>(0xFF444444);
            }
            unsafe {
                lseek(internals.shm_fd, 0, SEEK_SET);
                write(internals.shm_fd, new_data.as_ptr() as *const _, new_data.len() as size_t);
            }
        }

        //drop(mmap);

        // resize the borders
        internals.buffers.clear();
        // top
        {
            let buffer = internals.pool.create_buffer(
                0,
                internals.width as i32 + (DECORATION_SIZE as i32) * 2,
                DECORATION_TOP_SIZE as i32, (internals.width*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            internals.border_surfaces[BORDER_TOP].attach(&buffer, 0, 0);
            internals.border_surfaces[BORDER_TOP].set_position(0, 0);
            internals.buffers.push(buffer);
        }
        // right
        {
            let buffer = internals.pool.create_buffer(
                0, DECORATION_SIZE as i32,
                internals.height as i32, (DECORATION_SIZE*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            internals.border_surfaces[BORDER_RIGHT].attach(&buffer, 0, 0);
            internals.border_surfaces[BORDER_RIGHT].set_position(
                DECORATION_SIZE as i32 + internals.width as i32, DECORATION_TOP_SIZE as i32);
            internals.buffers.push(buffer);
        }
        // bottom
        {
            let buffer = internals.pool.create_buffer(
                0,
                internals.width as i32 + (DECORATION_SIZE as i32) * 2,
                DECORATION_SIZE as i32, (internals.width*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            internals.border_surfaces[BORDER_BOTTOM].attach(&buffer, 0, 0);
            internals.border_surfaces[BORDER_BOTTOM].set_position(
                0,
                DECORATION_TOP_SIZE as i32 + internals.height as i32);
            internals.buffers.push(buffer);
        }
        // left
        {
            let buffer = internals.pool.create_buffer(
                0, DECORATION_SIZE as i32,
                internals.height as i32, (DECORATION_SIZE*4) as i32,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            internals.border_surfaces[BORDER_LEFT].attach(&buffer, 0, 0);
            internals.border_surfaces[BORDER_LEFT].set_position(0,
                DECORATION_TOP_SIZE as i32);
            internals.buffers.push(buffer);
        }
        for s in &internals.border_surfaces { s.commit(); }

        self.user_surface.set_position(DECORATION_SIZE as i32, DECORATION_TOP_SIZE as i32);

        {
            let buffer = internals.pool.create_buffer(
                0, 1, 1, 4,
                ShmFormat::WL_SHM_FORMAT_ARGB8888
            ).unwrap();
            internals.shell_surface.attach(&buffer, 0, 0);
            internals.buffers.push(buffer);
            internals.shell_surface.commit();
        }

    }

    /// Destroys the decorated window and gives back the wrapped surface.
    pub fn unwrap(self) -> S {
        self.user_surface.destroy()
    }
}

impl<S: Surface> Deref for DecoratedSurface<S> {
    type Target = S;
    fn deref(&self) -> &S {
        &*self.user_surface
    }
}

extern {
    fn mkstemp(template: *mut c_char) -> c_int;
}<|endoftext|>


<commit_before>#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];

extern crate getopts;

use std::os;
use std::cast::transmute;
use std::io::{print,File};
use std::libc::{time_t,c_double,c_int,size_t,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts));
        return;
    }

    print_time();
    print_uptime();
    print_nusers();
    print_loadavg();
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{}{}", avg[n], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn print_nusers() {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                nusers += 1;
            }
        }

        endutxent();
    }

    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime() -> int {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return -1
    };

    match uptime_text.words().next() {
        Some(s) => match from_str(s.replace(".","")) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime() {
    let uptime = get_uptime() / 100;
    let updays = uptime / 86400;
    let uphours = (uptime - (updays * 86400)) / 3600;
    let upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<commit_msg>Truncate load averages to 2 decimal places<commit_after>#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];

extern crate getopts;

use std::os;
use std::cast::transmute;
use std::io::{print,File};
use std::libc::{time_t,c_double,c_int,size_t,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts));
        return;
    }

    print_time();
    print_uptime();
    print_nusers();
    print_loadavg();
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2f}{}", avg[n], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn print_nusers() {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                nusers += 1;
            }
        }

        endutxent();
    }

    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime() -> int {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return -1
    };

    match uptime_text.words().next() {
        Some(s) => match from_str(s.replace(".","")) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime() {
    let uptime = get_uptime() / 100;
    let updays = uptime / 86400;
    let uphours = (uptime - (updays * 86400)) / 3600;
    let upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<|endoftext|>


<commit_before>#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];

extern crate getopts;

use std::os;
use std::cast::transmute;
use std::io::{print,File};
use std::libc::{time_t,c_double,c_int,size_t,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts));
        return;
    }

    print_time();
    print_uptime();
    print_nusers();
    print_loadavg();
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{}{}", avg[n], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn print_nusers() {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                nusers += 1;
            }
        }

        endutxent();
    }

    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime() -> int {
    let uptime_text = File::open(&Path::new("/proc/uptime"))
                            .read_to_str().unwrap();

    return match uptime_text.words().next() {
        Some(s) => match from_str(s.replace(".","")) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    };
}

fn print_uptime() {
    let uptime = get_uptime() / 100;
    let updays = uptime / 86400;
    let uphours = (uptime - (updays * 86400)) / 3600;
    let upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<commit_msg>Fix OSX crash for uptime<commit_after>#[crate_id(name="uptime", vers="1.0.0", author="José Neder")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#[allow(non_camel_case_types)];
#[feature(macro_rules, globs)];

extern crate getopts;

use std::os;
use std::cast::transmute;
use std::io::{print,File};
use std::libc::{time_t,c_double,c_int,size_t,c_char};
use std::ptr::null;
use std::from_str::from_str;
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts));
        return;
    }

    print_time();
    print_uptime();
    print_nusers();
    print_loadavg();
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{}{}", avg[n], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn print_nusers() {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                nusers += 1;
            }
        }

        endutxent();
    }

    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime() -> int {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return -1
    };

    match uptime_text.words().next() {
        Some(s) => match from_str(s.replace(".","")) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime() {
    let uptime = get_uptime() / 100;
    let updays = uptime / 86400;
    let uphours = (uptime - (updays * 86400)) / 3600;
    let upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<|endoftext|>


<commit_before>use super::{Observation, Transition, Domain, runge_kutta4};

use consts::{G, TWELVE_DEGREES, FOUR_THIRDS};
use ndarray::{arr1, Array1, NdIndex, Ix1};
use geometry::{ActionSpace, RegularSpace};
use geometry::dimensions::{Continuous, Discrete};

const TAU: f64 = 0.02;

const CART_MASS: f64 = 1.0;
const CART_FORCE: f64 = 10.0;

const POLE_COM: f64 = 0.5;
const POLE_MASS: f64 = 0.1;
const POLE_MOMENT: f64 = POLE_COM * POLE_MASS;

const TOTAL_MASS: f64 = CART_MASS + POLE_MASS;

const LIMITS_X: (f64, f64) = (-2.4, 2.4);
const LIMITS_DX: (f64, f64) = (-6.0, 6.0);
const LIMITS_THETA: (f64, f64) = (-TWELVE_DEGREES, TWELVE_DEGREES);
const LIMITS_DTHETA: (f64, f64) = (-2.0, 2.0);

const REWARD_STEP: f64 = 0.0;
const REWARD_TERMINAL: f64 = -1.0;

const ALL_ACTIONS: [f64; 2] = [-1.0 * CART_FORCE, 1.0 * CART_FORCE];

#[derive(Debug, Clone, Copy)]
enum StateIndex {
    X = 0,
    DX = 1,
    THETA = 2,
    DTHETA = 3,
}

unsafe impl NdIndex<Ix1> for StateIndex {
    #[inline]
    fn index_checked(&self, dim: &Ix1, strides: &Ix1) -> Option<isize> {
        (*self as usize).index_checked(dim, strides)
    }

    #[inline(always)]
    fn index_unchecked(&self, strides: &Ix1) -> isize {
        (*self as usize).index_unchecked(strides)
    }
}

pub struct CartPole {
    state: Array1<f64>,
}

impl CartPole {
    fn new(x: f64, dx: f64, theta: f64, dtheta: f64) -> CartPole {
        CartPole {
            state: arr1(&vec![x, dx, theta, dtheta])
        }
    }

    fn update_state(&mut self, a: usize) {
        let fx = |_x, y| CartPole::grad(ALL_ACTIONS[a], y);
        let mut ns = runge_kutta4(&fx, 0.0, self.state.clone(), TAU);

        ns[StateIndex::X] = clip!(LIMITS_X.0, ns[StateIndex::X], LIMITS_X.1);
        ns[StateIndex::DX] = clip!(LIMITS_DX.0, ns[StateIndex::DX], LIMITS_DX.1);

        ns[StateIndex::THETA] = clip!(LIMITS_THETA.0, ns[StateIndex::THETA], LIMITS_THETA.1);
        ns[StateIndex::DTHETA] = clip!(LIMITS_DTHETA.0, ns[StateIndex::DTHETA], LIMITS_DTHETA.1);

        self.state = ns;
    }

    fn grad(force: f64, state: Array1<f64>) -> Array1<f64> {
        let x = state[StateIndex::X];
        let dx = state[StateIndex::DX];
        let theta = state[StateIndex::THETA];
        let dtheta = state[StateIndex::DTHETA];

        let cos_theta = theta.cos();
        let sin_theta = theta.sin();

        let z = (force + POLE_MOMENT*dtheta*dtheta*sin_theta) / TOTAL_MASS;

        let numer = G*sin_theta - cos_theta*z;
        let denom = FOUR_THIRDS*POLE_COM - POLE_MOMENT*cos_theta*cos_theta;

        let ddtheta = numer/denom;
        let ddx = z - POLE_COM*ddtheta*cos_theta;

        arr1(&vec![dx, ddx, dtheta, ddtheta])
    }
}

impl Default for CartPole {
    fn default() -> CartPole {
        CartPole::new(0.0, 0.0, 0.0, 0.0)
    }
}

impl Domain for CartPole {
    type StateSpace = RegularSpace<Continuous>;
    type ActionSpace = ActionSpace;

    fn emit(&self) -> Observation<Self::StateSpace, Self::ActionSpace> {
        if self.is_terminal() {
            Observation::Terminal(self.state.to_vec())
        } else {
            Observation::Full {
                state: self.state.to_vec(),
                actions: vec![0, 1],
            }
        }
    }

    fn step(&mut self, a: usize) -> Transition<Self::StateSpace, Self::ActionSpace> {
        let from = self.emit();

        self.update_state(a);
        let to = self.emit();
        let r = self.reward(&from, &to);

        Transition {
            from: from,
            action: a,
            reward: r,
            to: to,
        }
    }

    fn is_terminal(&self) -> bool {
        let x = self.state[StateIndex::X];
        let theta = self.state[StateIndex::THETA];

        x <= LIMITS_X.0 || x >= LIMITS_X.1 || theta <= LIMITS_THETA.0 || theta >= LIMITS_THETA.1
    }

    fn reward(&self,
              _: &Observation<Self::StateSpace, Self::ActionSpace>,
              to: &Observation<Self::StateSpace, Self::ActionSpace>)
              -> f64 {
        match to {
            &Observation::Terminal(_) => REWARD_TERMINAL,
            _ => REWARD_STEP,
        }
    }

    fn state_space(&self) -> Self::StateSpace {
        Self::StateSpace::new()
            .push(Continuous::new(LIMITS_X.0, LIMITS_X.1))
            .push(Continuous::new(LIMITS_DX.0, LIMITS_DX.1))
            .push(Continuous::new(LIMITS_THETA.0, LIMITS_THETA.1))
            .push(Continuous::new(LIMITS_DTHETA.0, LIMITS_DTHETA.1))
    }

    fn action_space(&self) -> ActionSpace {
        ActionSpace::new(Discrete::new(2))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use domains::{Observation, Domain};

    #[test]
    fn test_initial_observation() {
        let m = CartPole::default();

        match m.emit() {
            Observation::Full { ref state, .. } => {
                assert_eq!(state[0], 0.0);
                assert_eq!(state[1], 0.0);
                assert_eq!(state[2], 0.0);
                assert_eq!(state[3], 0.0);
            }
            _ => panic!("Should yield a fully observable state."),
        }
    }

    #[test]
    fn test_step_0() {
        let mut m = CartPole::default();

        let t = m.step(0);
        let s = t.to.state();
        assert!((s[0] - 0.0).abs() < 1e-7);
        assert!((s[1] - -0.1951219512195122).abs() < 1e-7);
        assert!((s[2] - 0.0).abs() < 1e-7);
        assert!((s[3] - 0.2926829268292683).abs() < 1e-7);

        let t = m.step(0);
        let s = t.to.state();
        assert!((s[0] - -0.0039024390243902443).abs() < 1e-7);
        assert!((s[1] - -0.3902439024390244).abs() < 1e-7);
        assert!((s[2] - 0.005853658536585366).abs() < 1e-7);
        assert!((s[3] - 0.5853658536585366).abs() < 1e-7);
    }

    #[test]
    fn test_step_1() {
        let mut m = CartPole::default();

        let t = m.step(1);
        let s = t.to.state();
        assert!((s[0] - 0.0).abs() < 1e-7);
        assert!((s[1] - 0.1951219512195122).abs() < 1e-7);
        assert!((s[2] - 0.0).abs() < 1e-7);
        assert!((s[3] - -0.2926829268292683).abs() < 1e-7);

        let t = m.step(1);
        let s = t.to.state();
        assert!((s[0] - 0.0039024390243902443).abs() < 1e-7);
        assert!((s[1] - 0.3902439024390244).abs() < 1e-7);
        assert!((s[2] - -0.005853658536585366).abs() < 1e-7);
        assert!((s[3] - -0.5853658536585366).abs() < 1e-7);
    }
}
<commit_msg>Fix tests for CartPole<commit_after>use super::{Observation, Transition, Domain, runge_kutta4};

use consts::{G, TWELVE_DEGREES, FOUR_THIRDS};
use ndarray::{arr1, Array1, NdIndex, Ix1};
use geometry::{ActionSpace, RegularSpace};
use geometry::dimensions::{Continuous, Discrete};

const TAU: f64 = 0.02;

const CART_MASS: f64 = 1.0;
const CART_FORCE: f64 = 10.0;

const POLE_COM: f64 = 0.5;
const POLE_MASS: f64 = 0.1;
const POLE_MOMENT: f64 = POLE_COM * POLE_MASS;

const TOTAL_MASS: f64 = CART_MASS + POLE_MASS;

const LIMITS_X: (f64, f64) = (-2.4, 2.4);
const LIMITS_DX: (f64, f64) = (-6.0, 6.0);
const LIMITS_THETA: (f64, f64) = (-TWELVE_DEGREES, TWELVE_DEGREES);
const LIMITS_DTHETA: (f64, f64) = (-2.0, 2.0);

const REWARD_STEP: f64 = 0.0;
const REWARD_TERMINAL: f64 = -1.0;

const ALL_ACTIONS: [f64; 2] = [-1.0 * CART_FORCE, 1.0 * CART_FORCE];

#[derive(Debug, Clone, Copy)]
enum StateIndex {
    X = 0,
    DX = 1,
    THETA = 2,
    DTHETA = 3,
}

unsafe impl NdIndex<Ix1> for StateIndex {
    #[inline]
    fn index_checked(&self, dim: &Ix1, strides: &Ix1) -> Option<isize> {
        (*self as usize).index_checked(dim, strides)
    }

    #[inline(always)]
    fn index_unchecked(&self, strides: &Ix1) -> isize {
        (*self as usize).index_unchecked(strides)
    }
}

pub struct CartPole {
    state: Array1<f64>,
}

impl CartPole {
    fn new(x: f64, dx: f64, theta: f64, dtheta: f64) -> CartPole {
        CartPole {
            state: arr1(&vec![x, dx, theta, dtheta])
        }
    }

    fn update_state(&mut self, a: usize) {
        let fx = |_x, y| CartPole::grad(ALL_ACTIONS[a], y);
        let mut ns = runge_kutta4(&fx, 0.0, self.state.clone(), TAU);

        ns[StateIndex::X] = clip!(LIMITS_X.0, ns[StateIndex::X], LIMITS_X.1);
        ns[StateIndex::DX] = clip!(LIMITS_DX.0, ns[StateIndex::DX], LIMITS_DX.1);

        ns[StateIndex::THETA] = clip!(LIMITS_THETA.0, ns[StateIndex::THETA], LIMITS_THETA.1);
        ns[StateIndex::DTHETA] = clip!(LIMITS_DTHETA.0, ns[StateIndex::DTHETA], LIMITS_DTHETA.1);

        self.state = ns;
    }

    fn grad(force: f64, state: Array1<f64>) -> Array1<f64> {
        let x = state[StateIndex::X];
        let dx = state[StateIndex::DX];
        let theta = state[StateIndex::THETA];
        let dtheta = state[StateIndex::DTHETA];

        let cos_theta = theta.cos();
        let sin_theta = theta.sin();

        let z = (force + POLE_MOMENT*dtheta*dtheta*sin_theta) / TOTAL_MASS;

        let numer = G*sin_theta - cos_theta*z;
        let denom = FOUR_THIRDS*POLE_COM - POLE_MOMENT*cos_theta*cos_theta;

        let ddtheta = numer/denom;
        let ddx = z - POLE_COM*ddtheta*cos_theta;

        arr1(&vec![dx, ddx, dtheta, ddtheta])
    }
}

impl Default for CartPole {
    fn default() -> CartPole {
        CartPole::new(0.0, 0.0, 0.0, 0.0)
    }
}

impl Domain for CartPole {
    type StateSpace = RegularSpace<Continuous>;
    type ActionSpace = ActionSpace;

    fn emit(&self) -> Observation<Self::StateSpace, Self::ActionSpace> {
        if self.is_terminal() {
            Observation::Terminal(self.state.to_vec())
        } else {
            Observation::Full {
                state: self.state.to_vec(),
                actions: vec![0, 1],
            }
        }
    }

    fn step(&mut self, a: usize) -> Transition<Self::StateSpace, Self::ActionSpace> {
        let from = self.emit();

        self.update_state(a);
        let to = self.emit();
        let r = self.reward(&from, &to);

        Transition {
            from: from,
            action: a,
            reward: r,
            to: to,
        }
    }

    fn is_terminal(&self) -> bool {
        let x = self.state[StateIndex::X];
        let theta = self.state[StateIndex::THETA];

        x <= LIMITS_X.0 || x >= LIMITS_X.1 || theta <= LIMITS_THETA.0 || theta >= LIMITS_THETA.1
    }

    fn reward(&self,
              _: &Observation<Self::StateSpace, Self::ActionSpace>,
              to: &Observation<Self::StateSpace, Self::ActionSpace>)
              -> f64 {
        match to {
            &Observation::Terminal(_) => REWARD_TERMINAL,
            _ => REWARD_STEP,
        }
    }

    fn state_space(&self) -> Self::StateSpace {
        Self::StateSpace::new()
            .push(Continuous::new(LIMITS_X.0, LIMITS_X.1))
            .push(Continuous::new(LIMITS_DX.0, LIMITS_DX.1))
            .push(Continuous::new(LIMITS_THETA.0, LIMITS_THETA.1))
            .push(Continuous::new(LIMITS_DTHETA.0, LIMITS_DTHETA.1))
    }

    fn action_space(&self) -> ActionSpace {
        ActionSpace::new(Discrete::new(2))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use domains::{Observation, Domain};

    #[test]
    fn test_initial_observation() {
        let m = CartPole::default();

        match m.emit() {
            Observation::Full { ref state, .. } => {
                assert_eq!(state[0], 0.0);
                assert_eq!(state[1], 0.0);
                assert_eq!(state[2], 0.0);
                assert_eq!(state[3], 0.0);
            }
            _ => panic!("Should yield a fully observable state."),
        }
    }

    #[test]
    fn test_step_0() {
        let mut m = CartPole::default();

        let t = m.step(0);
        let s = t.to.state();
        assert!((s[0] + 0.0032931628891235).abs() < 1e-7);
        assert!((s[1] + 0.3293940797883472).abs() < 1e-7);
        assert!((s[2] - 0.0029499634056967).abs() < 1e-7);
        assert!((s[3] - 0.2951522145037250).abs() < 1e-7);

        let t = m.step(0);
        let s = t.to.state();
        assert!((s[0] + 0.0131819582085161).abs() < 1e-7);
        assert!((s[1] + 0.6597158115002169).abs() < 1e-7);
        assert!((s[2] - 0.0118185373734479).abs() < 1e-7);
        assert!((s[3] - 0.5921703414056713).abs() < 1e-7);
    }

    #[test]
    fn test_step_1() {
        let mut m = CartPole::default();

        let t = m.step(1);
        let s = t.to.state();
        assert!((s[0] - 0.0032931628891235).abs() < 1e-7);
        assert!((s[1] - 0.3293940797883472).abs() < 1e-7);
        assert!((s[2] + 0.0029499634056967).abs() < 1e-7);
        assert!((s[3] + 0.2951522145037250).abs() < 1e-7);

        let t = m.step(1);
        let s = t.to.state();
        assert!((s[0] - 0.0131819582085161).abs() < 1e-7);
        assert!((s[1] - 0.6597158115002169).abs() < 1e-7);
        assert!((s[2] + 0.0118185373734479).abs() < 1e-7);
        assert!((s[3] + 0.5921703414056713).abs() < 1e-7);
    }
}
<|endoftext|>


<commit_before>use raft::{SyncClient, ClientClusterInfo, RaftMsg, RaftStateMachine, LogEntry, ClientQryResponse};
use raft::state_machine::OpType;
use std::collections::{HashMap, BTreeMap, HashSet};
use std::iter::FromIterator;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, Ordering};
use std::cell::RefCell;
use bifrost_plugins::hash_str;
use rand;

const ORDERING: Ordering = Ordering::Relaxed;

struct QryMeta {
    last_log_id: AtomicU64,
    last_log_term: AtomicU64,
    pos: AtomicU64
}

struct Members {
    clients: BTreeMap<u64, Mutex<SyncClient>>,
    id_map: HashMap<u64, String>,
}

pub struct RaftClient {
    qry_meta: QryMeta,
    members: Members,
    term: u64, // last member list update term
}

impl RaftClient {
    pub fn new(servers: Vec<String>) -> Option<RaftClient> {
        let mut client = RaftClient {
            qry_meta: QryMeta {
                last_log_id: AtomicU64::new(0),
                last_log_term: AtomicU64::new(0),
                pos: AtomicU64::new(rand::random::<u64>())
            },
            members: Members {
                clients: BTreeMap::new(),
                id_map: HashMap::new()
            },
            term: 0,
        };
        match client.update_info(&HashSet::from_iter(servers)) {
            Ok(_) => Some(client),
            Err(_) => None
        }
    }

    fn update_info(&mut self, addrs: &HashSet<String>) -> Result<(), ()> {
        let info: ClientClusterInfo;
        let mut servers = None;
        for server_addr in addrs {
            let id = hash_str(server_addr.clone());
            let mut client = self.members.clients.entry(id).or_insert_with(|| {
                Mutex::new(SyncClient::new(server_addr))
            });
            if let Some(Ok(info)) = client.lock().unwrap().c_server_cluster_info() {
                servers = Some(info);
                break;
            }
        }
        match servers {
            Some(servers) => {
                let remote_members = servers.members;
                let mut remote_ids = HashSet::with_capacity(remote_members.len());
                self.members.id_map.clear();
                for (id, addr) in remote_members {
                    self.members.id_map.insert(id, addr);
                    remote_ids.insert(id);
                }
                let mut connected_ids = HashSet::with_capacity(self.members.clients.len());
                for id in self.members.clients.keys() {connected_ids.insert(*id);}
                let ids_to_remove = connected_ids.difference(&remote_ids);
                for id in ids_to_remove {self.members.clients.remove(id);}
                for id in remote_ids.difference(&connected_ids) {
                    let addr = self.members.id_map.get(id).unwrap();
                    self.members.clients.entry(id.clone()).or_insert_with(|| {
                        Mutex::new(SyncClient::new(addr))
                    });
                }
                Ok(())
            },
            None => Err(()),
        }
    }

    pub fn execute<R>(&self, sm: RaftStateMachine, msg: &RaftMsg<R>) -> Option<R> {
        let (fn_id, op, req_data) = msg.encode();
        let sm_id = sm.id;
        let response = match op {
            OpType::QUERY => {

            },
            OpType::COMMAND => {

            },
        };
        None
    }

    fn query(&self, sm_id: u64, fn_id: u64, data: &Vec<u8>) -> Option<Vec<u8>> {
        let pos = self.qry_meta.pos.fetch_add(1, ORDERING);
        let clients_count = self.members.clients.len();
        let res = {
            let mut client = self.members.clients.values()
                .nth(pos as usize % clients_count)
                .unwrap().lock().unwrap();
            client.c_query(LogEntry {
                id: self.qry_meta.last_log_id.load(ORDERING),
                term: self.qry_meta.last_log_term.load(ORDERING),
                sm_id: sm_id,
                fn_id: fn_id,
                data: data.clone()
            })
        };
        match res {
            Some(Ok(res)) => {
                match res {
                    ClientQryResponse::LeftBehind => {
                        self.query(sm_id, fn_id, data)
                    },
                    ClientQryResponse::Success{
                        data: data,
                        last_log_term: last_log_term,
                        last_log_id: last_log_id
                    } => {
                        self.qry_meta.last_log_id.store(last_log_id, ORDERING);
                        self.qry_meta.last_log_term.store(last_log_term, ORDERING);
                        Some(data)
                    },
                }
            },
            _ => None
        }
    }
}<commit_msg>swap when larger to ensure increasement<commit_after>use raft::{SyncClient, ClientClusterInfo, RaftMsg, RaftStateMachine, LogEntry, ClientQryResponse};
use raft::state_machine::OpType;
use std::collections::{HashMap, BTreeMap, HashSet};
use std::iter::FromIterator;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, Ordering};
use std::cell::RefCell;
use bifrost_plugins::hash_str;
use rand;

const ORDERING: Ordering = Ordering::Relaxed;

struct QryMeta {
    last_log_id: AtomicU64,
    last_log_term: AtomicU64,
    pos: AtomicU64
}

struct Members {
    clients: BTreeMap<u64, Mutex<SyncClient>>,
    id_map: HashMap<u64, String>,
}

pub struct RaftClient {
    qry_meta: QryMeta,
    members: Members,
    term: u64, // last member list update term
}

impl RaftClient {
    pub fn new(servers: Vec<String>) -> Option<RaftClient> {
        let mut client = RaftClient {
            qry_meta: QryMeta {
                last_log_id: AtomicU64::new(0),
                last_log_term: AtomicU64::new(0),
                pos: AtomicU64::new(rand::random::<u64>())
            },
            members: Members {
                clients: BTreeMap::new(),
                id_map: HashMap::new()
            },
            term: 0,
        };
        match client.update_info(&HashSet::from_iter(servers)) {
            Ok(_) => Some(client),
            Err(_) => None
        }
    }

    fn update_info(&mut self, addrs: &HashSet<String>) -> Result<(), ()> {
        let info: ClientClusterInfo;
        let mut servers = None;
        for server_addr in addrs {
            let id = hash_str(server_addr.clone());
            let mut client = self.members.clients.entry(id).or_insert_with(|| {
                Mutex::new(SyncClient::new(server_addr))
            });
            if let Some(Ok(info)) = client.lock().unwrap().c_server_cluster_info() {
                servers = Some(info);
                break;
            }
        }
        match servers {
            Some(servers) => {
                let remote_members = servers.members;
                let mut remote_ids = HashSet::with_capacity(remote_members.len());
                self.members.id_map.clear();
                for (id, addr) in remote_members {
                    self.members.id_map.insert(id, addr);
                    remote_ids.insert(id);
                }
                let mut connected_ids = HashSet::with_capacity(self.members.clients.len());
                for id in self.members.clients.keys() {connected_ids.insert(*id);}
                let ids_to_remove = connected_ids.difference(&remote_ids);
                for id in ids_to_remove {self.members.clients.remove(id);}
                for id in remote_ids.difference(&connected_ids) {
                    let addr = self.members.id_map.get(id).unwrap();
                    self.members.clients.entry(id.clone()).or_insert_with(|| {
                        Mutex::new(SyncClient::new(addr))
                    });
                }
                Ok(())
            },
            None => Err(()),
        }
    }

    pub fn execute<R>(&self, sm: RaftStateMachine, msg: &RaftMsg<R>) -> Option<R> {
        let (fn_id, op, req_data) = msg.encode();
        let sm_id = sm.id;
        let response = match op {
            OpType::QUERY => {

            },
            OpType::COMMAND => {

            },
        };
        None
    }

    fn query(&self, sm_id: u64, fn_id: u64, data: &Vec<u8>) -> Option<Vec<u8>> {
        let pos = self.qry_meta.pos.fetch_add(1, ORDERING);
        let clients_count = self.members.clients.len();
        let res = {
            let mut client = self.members.clients.values()
                .nth(pos as usize % clients_count)
                .unwrap().lock().unwrap();
            client.c_query(LogEntry {
                id: self.qry_meta.last_log_id.load(ORDERING),
                term: self.qry_meta.last_log_term.load(ORDERING),
                sm_id: sm_id,
                fn_id: fn_id,
                data: data.clone()
            })
        };
        match res {
            Some(Ok(res)) => {
                match res {
                    ClientQryResponse::LeftBehind => {
                        self.query(sm_id, fn_id, data)
                    },
                    ClientQryResponse::Success{
                        data: data,
                        last_log_term: last_log_term,
                        last_log_id: last_log_id
                    } => {
                        swap_when_larger(&self.qry_meta.last_log_id, last_log_id);
                        swap_when_larger(&self.qry_meta.last_log_term, last_log_term);
                        Some(data)
                    },
                }
            },
            _ => None
        }
    }
}

fn swap_when_larger(atomic: &AtomicU64, value: u64) {
    let mut orig_num = atomic.load(ORDERING);
    loop {
        if orig_num >= value {
            return;
        }
        let actual = atomic.compare_and_swap(orig_num, value, ORDERING);
        if actual == orig_num {
            return;
        } else {
            orig_num = actual;
        }
    }
}<|endoftext|>


<commit_before>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

use std::fmt::Debug;

/// Simple sort: insertion sort.
///
/// # Details
///
/// Insertion sort is one of the simplest sorting algorithm. Every elements of the list to sort
/// are picked one at a time and inserted into a the sorted list at the right location.
///
/// This function takes an immutable reference vector of any type and returns a vector of `usize`
/// of the same length containing the indices of the initial vector sorted.
///
/// # Scaling
///
/// In the best case scenario, the list is already sorted and the work is simply to append the
/// element at the end of the list, hence a O(N) scaling.
///
/// In the worst case scenario, the list is in reverse order. Hence, every element is compared to
/// all previous elements already sorted until this new one gets inserted at the beginning of the
/// sorted list, thus making this case O(N^2).
///
/// Insertion sort is still useful as its simplicity (and thus small overhead) makes it ideal for
/// small vectors.
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// assert_eq!(vec![3, 1, 2, 0], sorting::simplesorts::insertion::sort(&data));
/// ```
///
pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    // Place the first element's index (0) as the first element of the output_index vector.
    output_index.push(0);

    println!("n = {:?}", n);
    println!("input:        {:?}", input);
    println!("output_index: {:?}", output_index);

    if n > 1 {
        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            let i = i_start_at_0 + 1;
            println!("  i={:?} Finding where to put element {:?} (i={:?}) in output_index: {:?}", i, elem, i, output_index);

            // Verify next element if it is smaller
            // If next element is larger than the last stored index, just place that element at
            // the end.
            if *elem >= input[*output_index.last().unwrap()] {
                // Next element "elem" is already larger than the previous stored index.
                // Just use its index.
                output_index.push(i);

                println!("    1. Pushing element '{:?}' at the end.", elem);
            } else {
                println!("    2. elem ?< input[output_index[0]]");
                println!("           {:?} ?< {:?}", elem, input[output_index[0]]);
                // The next element of the input vector is smaller than the last stored on.
                // Let's find where it should go by looping back on the stored indices.
                // NOTE: we must use a loop on indices as to prevent problems with the borrow-checker.
                if *elem < input[output_index[0]] {
                    println!("        2a. Yes: --> putting i in front");
                    output_index.insert(0, i);
                } else {
                    println!("        2b. No: --> Looping back");
                    for j in (0..i).rev() {
                        println!("            j={:?}   elem={:?}   input[output_index[j]]={:?}", j, elem, input[output_index[j]]);
                        if *elem > input[output_index[j]] {
                            output_index.insert(j+1, i);
                            break;
                        }
                    }
                }
                println!("        3. output_index: {:?}", output_index);
            }

            print!("           output: [");
            for j in output_index.iter() {
                    print!("{:?}, ", input[*j]);
            }
            println!("]");
        }
    }

    println!("");
    println!("END: input:        {:?}", input);
    println!("END: output_index: {:?}", output_index);
    print!("END: output:       [");
    for j in output_index.iter() {
            print!("{:?}, ", input[*j]);
    }
    println!("]");

    assert_eq!(output_index.len(), n);

    return output_index;
}
<commit_msg>Cleanup<commit_after>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

use std::fmt::Debug;

/// Simple sort: insertion sort.
///
/// # Details
///
/// Insertion sort is one of the simplest sorting algorithm. Every elements of the list to sort
/// are picked one at a time and inserted into a the sorted list at the right location.
///
/// This function takes an immutable reference vector of any type and returns a vector of `usize`
/// of the same length containing the indices of the initial vector sorted.
///
/// # Scaling
///
/// In the best case scenario, the list is already sorted and the work is simply to append the
/// element at the end of the list, hence a O(N) scaling.
///
/// In the worst case scenario, the list is in reverse order. Hence, every element is compared to
/// all previous elements already sorted until this new one gets inserted at the beginning of the
/// sorted list, thus making this case O(N^2).
///
/// Insertion sort is still useful as its simplicity (and thus small overhead) makes it ideal for
/// small vectors.
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// assert_eq!(vec![3, 1, 2, 0], sorting::simplesorts::insertion::sort(&data));
/// ```
///
pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    // Place the first element's index (0) as the first element of the output_index vector.
    output_index.push(0);

    if n > 1 {
        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            let i = i_start_at_0 + 1;
            println!("  i={:?} Finding where to put element {:?} (i={:?}) in output_index: {:?}", i, elem, i, output_index);

            // Verify next element if it is smaller
            // If next element is larger than the last stored index, just place that element at
            // the end.
            if *elem >= input[*output_index.last().unwrap()] {
                // Next element "elem" is already larger than the previous stored index.
                // Just use its index.
                output_index.push(i);

                println!("    1. Pushing element '{:?}' at the end.", elem);
            } else {
                println!("    2. elem ?< input[output_index[0]]");
                println!("           {:?} ?< {:?}", elem, input[output_index[0]]);
                // The next element of the input vector is smaller than the last stored on.
                // Let's find where it should go by looping back on the stored indices.
                // NOTE: we must use a loop on indices as to prevent problems with the borrow-checker.
                if *elem < input[output_index[0]] {
                    println!("        2a. Yes: --> putting i in front");
                    output_index.insert(0, i);
                } else {
                    println!("        2b. No: --> Looping back");
                    for j in (0..i).rev() {
                        println!("            j={:?}   elem={:?}   input[output_index[j]]={:?}", j, elem, input[output_index[j]]);
                        if *elem > input[output_index[j]] {
                            output_index.insert(j+1, i);
                            break;
                        }
                    }
                }
                println!("        3. output_index: {:?}", output_index);
            }

            print!("           output: [");
            for j in output_index.iter() {
                    print!("{:?}, ", input[*j]);
            }
            println!("]");
        }
    }

    println!("");
    println!("END: input:        {:?}", input);
    println!("END: output_index: {:?}", output_index);
    print!("END: output:       [");
    for j in output_index.iter() {
            print!("{:?}, ", input[*j]);
    }
    println!("]");

    assert_eq!(output_index.len(), n);

    return output_index;
}
<|endoftext|>