<commit_before>#![cfg(windows)]
/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::Error;
use std::io::Error as IoError;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::net::windows::named_pipe::NamedPipeClient;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE};

/// Wrapper around a tokio [`NamedPipeClient`]
pub struct NamedPipe {
    io: NamedPipeClient,
}

impl NamedPipe {
    pub async fn connect(path: PathBuf) -> Result<Self, Error> {
        let win_path = path
            .as_os_str()
            .encode_wide()
            .chain(Some(0))
            .collect::<Vec<_>>();

        let handle = unsafe {
            CreateFileW(
                win_path.as_ptr(),
                GENERIC_READ | GENERIC_WRITE,
                0,
                std::ptr::null_mut(),
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                std::ptr::null_mut(),
            )
        };
        if handle.is_null() {
            let err = IoError::last_os_error();
            return Err(Error::Connect {
                endpoint: path,
                source: Box::new(err),
            });
        }

        let io = unsafe {
            NamedPipeClient::from_raw_handle(handle).map_err(|err| Error::Connect {
                endpoint: path,
                source: Box::new(err),
            })?
        };
        Ok(Self { io })
    }
}

impl AsyncRead for NamedPipe {
    fn poll_read(
        self: Pin<&mut Self>,
        ctx: &mut Context,
        buf: &mut ReadBuf,
    ) -> Poll<Result<(), IoError>> {
        AsyncRead::poll_read(Pin::new(&mut self.get_mut().io), ctx, buf)
    }
}

impl AsyncWrite for NamedPipe {
    fn poll_write(
        self: Pin<&mut Self>,
        ctx: &mut Context,
        buf: &[u8],
    ) -> Poll<Result<usize, IoError>> {
        AsyncWrite::poll_write(Pin::new(&mut self.get_mut().io), ctx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Result<(), IoError>> {
        AsyncWrite::poll_flush(Pin::new(&mut self.get_mut().io), ctx)
    }

    fn poll_shutdown(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Result<(), IoError>> {
        AsyncWrite::poll_shutdown(Pin::new(&mut self.get_mut().io), ctx)
    }
}

impl crate::ReadWriteStream for NamedPipe {}
<commit_msg>eden/watchman/re: clean up unused deps<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#![cfg(windows)]

use crate::Error;
use std::io::Error as IoError;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::net::windows::named_pipe::NamedPipeClient;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE};

/// Wrapper around a tokio [`NamedPipeClient`]
pub struct NamedPipe {
    io: NamedPipeClient,
}

impl NamedPipe {
    pub async fn connect(path: PathBuf) -> Result<Self, Error> {
        let win_path = path
            .as_os_str()
            .encode_wide()
            .chain(Some(0))
            .collect::<Vec<_>>();

        let handle = unsafe {
            CreateFileW(
                win_path.as_ptr(),
                GENERIC_READ | GENERIC_WRITE,
                0,
                std::ptr::null_mut(),
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                std::ptr::null_mut(),
            )
        };
        if handle.is_null() {
            let err = IoError::last_os_error();
            return Err(Error::Connect {
                endpoint: path,
                source: Box::new(err),
            });
        }

        let io = unsafe {
            NamedPipeClient::from_raw_handle(handle).map_err(|err| Error::Connect {
                endpoint: path,
                source: Box::new(err),
            })?
        };
        Ok(Self { io })
    }
}

impl AsyncRead for NamedPipe {
    fn poll_read(
        self: Pin<&mut Self>,
        ctx: &mut Context,
        buf: &mut ReadBuf,
    ) -> Poll<Result<(), IoError>> {
        AsyncRead::poll_read(Pin::new(&mut self.get_mut().io), ctx, buf)
    }
}

impl AsyncWrite for NamedPipe {
    fn poll_write(
        self: Pin<&mut Self>,
        ctx: &mut Context,
        buf: &[u8],
    ) -> Poll<Result<usize, IoError>> {
        AsyncWrite::poll_write(Pin::new(&mut self.get_mut().io), ctx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Result<(), IoError>> {
        AsyncWrite::poll_flush(Pin::new(&mut self.get_mut().io), ctx)
    }

    fn poll_shutdown(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Result<(), IoError>> {
        AsyncWrite::poll_shutdown(Pin::new(&mut self.get_mut().io), ctx)
    }
}

impl crate::ReadWriteStream for NamedPipe {}
<|endoftext|>


<commit_before>//! Printer for displaying crate as a graoh.

use petgraph::{
    graph::NodeIndex,
    visit::{IntoNodeReferences, NodeRef},
};
use ra_ap_ide::RootDatabase;

use crate::{
    format::{kind::FormattedKind, visibility::FormattedVisibility},
    graph::{Edge, Graph, Node, NodeKind},
    theme::{color_palette, colors, Rgb},
};

const INDENTATION: &str = "    ";

#[derive(Clone, Debug)]
pub struct Options {
    pub absolute_paths: bool,
    pub layout: String,
}

pub struct Printer<'a> {
    options: Options,
    db: &'a RootDatabase,
}

impl<'a> Printer<'a> {
    pub fn new(options: Options, db: &'a RootDatabase) -> Self {
        Self { options, db }
    }

    pub fn print(&self, graph: &Graph, start_node_idx: NodeIndex) -> Result<(), anyhow::Error> {
        let root_node = &graph[start_node_idx];
        let crate_name = root_node.name();
        let layout_name = &self.options.layout[..];

        println!("digraph {} {{", crate_name);

        println!();

        indoc::printdoc!(
            r#"
            {i}graph [
            {i}    label="{label}",
            {i}    labelloc=t,

            {i}    pad=0.4,

            {i}    // Consider rendering the graph using a different layout algorithm, such as:
            {i}    // [dot, neato, twopi, circo, fdp, sfdp]
            {i}    layout={layout},
            {i}    overlap=false,
            {i}    splines="line",
            {i}    rankdir=LR,

            {i}    fontname="Helvetica",
            {i}    fontsize="36",
            {i}];
            "#,
            i = INDENTATION,
            label = crate_name,
            layout = layout_name,
        );

        println!();

        indoc::printdoc!(
            r#"
            {i}node [
            {i}    fontname="monospace",
            {i}    fontsize="10",
            {i}    shape="record",
            {i}    style="filled",
            {i}];
            "#,
            i = INDENTATION,
        );

        println!();

        indoc::printdoc!(
            r#"
            {i}edge [
            {i}    fontname="monospace",
            {i}    fontsize="10",
            {i}];
            "#,
            i = INDENTATION,
        );

        println!();

        self.print_nodes(graph, start_node_idx);

        println!();

        self.print_edges(graph);

        println!();

        println!("}}");

        Ok(())
    }

    fn print_nodes(&self, graph: &Graph, highlight_node_idx: NodeIndex) {
        for node_ref in graph.node_references() {
            let node: &Node = node_ref.weight();
            let node_idx: NodeIndex = node_ref.id();

            let id = node_idx.index();
            let kind = node.kind(self.db);

            let is_highlighted = node_idx == highlight_node_idx;

            let label = self.node_label(node);
            let attributes = self.node_attributes(node, is_highlighted);

            println!(
                r#"{i}{id} [label="{label}"{attributes}]; // "{kind}" node"#,
                i = INDENTATION,
                id = id,
                label = label,
                attributes = attributes,
                kind = kind,
            );
        }
    }

    fn print_edges(&self, graph: &Graph) {
        for edge_idx in graph.edge_indices() {
            let edge = &graph[edge_idx];
            let (source, target) = graph
                .edge_endpoints(edge_idx)
                .map(|(source, target)| (source.index(), target.index()))
                .unwrap();

            let kind = edge.kind();

            let label = self.edge_label(edge);
            let attributes = self.edge_attributes(edge);

            println!(
                r#"{i}{source} -> {target} [label="{label}"{attributes}]; // "{kind}" edge"#,
                i = INDENTATION,
                source = source,
                target = target,
                label = label,
                attributes = attributes,
                kind = kind,
            );
        }
    }

    fn node_label(&self, node: &Node) -> String {
        let header = self.node_header(node);
        let body = self.node_body(node);

        format!("{}|{}", header, body)
    }

    fn node_header(&self, node: &Node) -> String {
        match node.hir {
            Some(module_def) => {
                let absolute_paths = self.options.absolute_paths;

                let visibility = if node.is_external & !absolute_paths {
                    FormattedVisibility::Public
                } else {
                    FormattedVisibility::new(module_def, self.db)
                };
                let node_kind = node.kind(self.db);
                let kind = match (node_kind, node.is_external, absolute_paths) {
                    (NodeKind::Crate, _, _) => FormattedKind::Crate,
                    (NodeKind::Module, true, false) => FormattedKind::Crate,
                    _ => FormattedKind::new(module_def),
                };
                format!("{} {}", visibility, kind)
            }
            None => format!("orphan {}", FormattedKind::Module),
        }
    }

    fn node_body(&self, node: &Node) -> String {
        if self.options.absolute_paths {
            node.path.clone()
        } else {
            if node.is_external {
                node.crate_name()
            } else {
                node.name()
            }
        }
    }

    fn node_attributes(&self, node: &Node, is_highlighted: bool) -> String {
        let fill_color = match is_highlighted {
            true => self.node_highlight_color(node),
            false => self.node_color(node),
        };
        format!(r#", fillcolor="{}""#, fill_color)
    }

    fn node_color(&self, node: &Node) -> String {
        let colors = colors();
        let color_palette = color_palette();

        let rgb = if node.is_external {
            color_palette.blue
        } else {
            match node.hir {
                Some(module_def) => match FormattedVisibility::new(module_def, self.db) {
                    FormattedVisibility::Crate => colors.visibility.pub_crate,
                    FormattedVisibility::Module(_) => colors.visibility.pub_module,
                    FormattedVisibility::Private => colors.visibility.pub_private,
                    FormattedVisibility::Public => colors.visibility.pub_global,
                    FormattedVisibility::Super => colors.visibility.pub_super,
                },
                None => colors.orphan,
            }
        };

        self.hex_color(rgb)
    }

    fn node_highlight_color(&self, _node: &Node) -> String {
        let color_palette = color_palette();

        self.hex_color(color_palette.cyan)
    }

    fn edge_label(&self, edge: &Edge) -> String {
        match edge {
            Edge::UsesA => "uses".to_owned(),
            Edge::HasA => "has".to_owned(),
        }
    }

    fn edge_attributes(&self, edge: &Edge) -> String {
        // NOTE: To ignore edge in layout add: [constraint=false]

        match edge {
            Edge::UsesA => r#", color="gray", style="dashed", weight="0.5""#.to_string(),
            Edge::HasA => r#", color="black", style="solid", weight="1.0""#.to_string(),
        }
    }

    fn hex_color(&self, rgb: Rgb) -> String {
        let Rgb { r, g, b, .. } = rgb;
        format!("#{:02x}{:02x}{:02x}", r, g, b)
    }
}
<commit_msg>Improved name of local variable<commit_after>//! Printer for displaying crate as a graoh.

use petgraph::{
    graph::NodeIndex,
    visit::{IntoNodeReferences, NodeRef},
};
use ra_ap_ide::RootDatabase;

use crate::{
    format::{kind::FormattedKind, visibility::FormattedVisibility},
    graph::{Edge, Graph, Node, NodeKind},
    theme::{color_palette, colors, Rgb},
};

const INDENTATION: &str = "    ";

#[derive(Clone, Debug)]
pub struct Options {
    pub absolute_paths: bool,
    pub layout: String,
}

pub struct Printer<'a> {
    options: Options,
    db: &'a RootDatabase,
}

impl<'a> Printer<'a> {
    pub fn new(options: Options, db: &'a RootDatabase) -> Self {
        Self { options, db }
    }

    pub fn print(&self, graph: &Graph, start_node_idx: NodeIndex) -> Result<(), anyhow::Error> {
        let root_node = &graph[start_node_idx];
        let crate_name = root_node.name();
        let layout_name = &self.options.layout[..];

        println!("digraph {} {{", crate_name);

        println!();

        indoc::printdoc!(
            r#"
            {i}graph [
            {i}    label="{label}",
            {i}    labelloc=t,

            {i}    pad=0.4,

            {i}    // Consider rendering the graph using a different layout algorithm, such as:
            {i}    // [dot, neato, twopi, circo, fdp, sfdp]
            {i}    layout={layout},
            {i}    overlap=false,
            {i}    splines="line",
            {i}    rankdir=LR,

            {i}    fontname="Helvetica",
            {i}    fontsize="36",
            {i}];
            "#,
            i = INDENTATION,
            label = crate_name,
            layout = layout_name,
        );

        println!();

        indoc::printdoc!(
            r#"
            {i}node [
            {i}    fontname="monospace",
            {i}    fontsize="10",
            {i}    shape="record",
            {i}    style="filled",
            {i}];
            "#,
            i = INDENTATION,
        );

        println!();

        indoc::printdoc!(
            r#"
            {i}edge [
            {i}    fontname="monospace",
            {i}    fontsize="10",
            {i}];
            "#,
            i = INDENTATION,
        );

        println!();

        self.print_nodes(graph, start_node_idx);

        println!();

        self.print_edges(graph);

        println!();

        println!("}}");

        Ok(())
    }

    fn print_nodes(&self, graph: &Graph, start_node_idx: NodeIndex) {
        for node_ref in graph.node_references() {
            let node: &Node = node_ref.weight();
            let node_idx: NodeIndex = node_ref.id();

            let id = node_idx.index();
            let kind = node.kind(self.db);

            let is_highlighted = node_idx == start_node_idx;

            let label = self.node_label(node);
            let attributes = self.node_attributes(node, is_highlighted);

            println!(
                r#"{i}{id} [label="{label}"{attributes}]; // "{kind}" node"#,
                i = INDENTATION,
                id = id,
                label = label,
                attributes = attributes,
                kind = kind,
            );
        }
    }

    fn print_edges(&self, graph: &Graph) {
        for edge_idx in graph.edge_indices() {
            let edge = &graph[edge_idx];
            let (source, target) = graph
                .edge_endpoints(edge_idx)
                .map(|(source, target)| (source.index(), target.index()))
                .unwrap();

            let kind = edge.kind();

            let label = self.edge_label(edge);
            let attributes = self.edge_attributes(edge);

            println!(
                r#"{i}{source} -> {target} [label="{label}"{attributes}]; // "{kind}" edge"#,
                i = INDENTATION,
                source = source,
                target = target,
                label = label,
                attributes = attributes,
                kind = kind,
            );
        }
    }

    fn node_label(&self, node: &Node) -> String {
        let header = self.node_header(node);
        let body = self.node_body(node);

        format!("{}|{}", header, body)
    }

    fn node_header(&self, node: &Node) -> String {
        match node.hir {
            Some(module_def) => {
                let absolute_paths = self.options.absolute_paths;

                let visibility = if node.is_external & !absolute_paths {
                    FormattedVisibility::Public
                } else {
                    FormattedVisibility::new(module_def, self.db)
                };
                let node_kind = node.kind(self.db);
                let kind = match (node_kind, node.is_external, absolute_paths) {
                    (NodeKind::Crate, _, _) => FormattedKind::Crate,
                    (NodeKind::Module, true, false) => FormattedKind::Crate,
                    _ => FormattedKind::new(module_def),
                };
                format!("{} {}", visibility, kind)
            }
            None => format!("orphan {}", FormattedKind::Module),
        }
    }

    fn node_body(&self, node: &Node) -> String {
        if self.options.absolute_paths {
            node.path.clone()
        } else {
            if node.is_external {
                node.crate_name()
            } else {
                node.name()
            }
        }
    }

    fn node_attributes(&self, node: &Node, is_highlighted: bool) -> String {
        let fill_color = match is_highlighted {
            true => self.node_highlight_color(node),
            false => self.node_color(node),
        };
        format!(r#", fillcolor="{}""#, fill_color)
    }

    fn node_color(&self, node: &Node) -> String {
        let colors = colors();
        let color_palette = color_palette();

        let rgb = if node.is_external {
            color_palette.blue
        } else {
            match node.hir {
                Some(module_def) => match FormattedVisibility::new(module_def, self.db) {
                    FormattedVisibility::Crate => colors.visibility.pub_crate,
                    FormattedVisibility::Module(_) => colors.visibility.pub_module,
                    FormattedVisibility::Private => colors.visibility.pub_private,
                    FormattedVisibility::Public => colors.visibility.pub_global,
                    FormattedVisibility::Super => colors.visibility.pub_super,
                },
                None => colors.orphan,
            }
        };

        self.hex_color(rgb)
    }

    fn node_highlight_color(&self, _node: &Node) -> String {
        let color_palette = color_palette();

        self.hex_color(color_palette.cyan)
    }

    fn edge_label(&self, edge: &Edge) -> String {
        match edge {
            Edge::UsesA => "uses".to_owned(),
            Edge::HasA => "has".to_owned(),
        }
    }

    fn edge_attributes(&self, edge: &Edge) -> String {
        // NOTE: To ignore edge in layout add: [constraint=false]

        match edge {
            Edge::UsesA => r#", color="gray", style="dashed", weight="0.5""#.to_string(),
            Edge::HasA => r#", color="black", style="solid", weight="1.0""#.to_string(),
        }
    }

    fn hex_color(&self, rgb: Rgb) -> String {
        let Rgb { r, g, b, .. } = rgb;
        format!("#{:02x}{:02x}{:02x}", r, g, b)
    }
}
<|endoftext|>


<commit_before>use console::{kprint, kprintln};

use core::fmt;

#[lang = "eh_personality"]
pub extern "C" fn eh_personality() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn panic_fmt(msg: fmt::Arguments, file: &'static str, line: u32, col: u32) -> ! {
    kprintln!("\n\n");
    kprintln!("---------- KERNEL PANIC ----------");
    kprintln!("");
    kprintln!("FILE: {}", file);
    kprintln!("LINE: {}", line);
    kprintln!(" COL: {}", col);
    kprintln!("");
    kprintln!("{}", msg);

    loop { unsafe { asm!("wfe") } }
}
<commit_msg>fix kernel/src/panic.rs<commit_after>use pi::uart::MiniUart;
use core::fmt::{self, Write, Arguments};

#[lang = "eh_personality"]
pub extern "C" fn eh_personality() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn panic_fmt(msg: Arguments, file: &'static str, line: u32, col: u32) -> ! {
    let mut uart = MiniUart::new();

    let _ = uart.write_str("\n\n---------- KERNEL PANIC ----------\n");
    let _ = uart.write_fmt(format_args!("FILE: {}\nLINE: {}\n COL: {}\n", file, line, col));
    let _ = uart.write_fmt(format_args!("{}", msg));

    loop { unsafe { asm!("wfe") } }
}
<|endoftext|>


<commit_before>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::IoResult;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    loop {
        // Kill existing warnings
        // TODO

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    // TODO
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    // TODO
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<commit_msg>change nagproc<commit_after>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::IoResult;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        println!("spawn");
        match Command::new("i3-nagbar").arg("10").spawn() {
            Err(err) =>
                println!("ERROR: {}", err),
            Ok(child) =>
                nagproc = Some(child),
        };

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    // TODO
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    // TODO
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<|endoftext|>


<commit_before>use platform::process::get_pid;
use platform::time::time_now;
use storage::Cache;
use storage::Key;
use storage::Value;
use tcp_transport::stats::TransportStats;

use super::cmd::Cmd;
use super::cmd::Get;
use super::cmd::Resp;
use super::cmd::Set;
use super::cmd::Stat;
use super::cmd::Value as CmdValue;

struct DriverMetrics {
    cmd_get: u64,
    cmd_set: u64,
    cmd_flush: u64,
    cmd_touch: u64,
}

impl DriverMetrics {
    pub fn new() -> DriverMetrics {
        DriverMetrics {
            cmd_get: 0,
            cmd_set: 0,
            cmd_flush: 0,
            cmd_touch: 0,
        }
    }
}

pub struct Driver {
    cache: Cache,
    time_start: f64,

    metrics: DriverMetrics,
    transport_stats: TransportStats, // this is a global snapshot
}

impl Driver {
    pub fn new(cache: Cache) -> Driver {
        Driver {
            cache: cache,
            metrics: DriverMetrics::new(),
            time_start: time_now(),
            transport_stats: TransportStats::new(),
        }
    }

    fn set_exptime(&self, value: &mut Value, exptime: u32) {
        // If exptime is greater than zero we need to set it on the value
        if exptime > 0 {
            let tm;

            // Is it an interval greater than 30 days? Then it's a timestamp
            if exptime > 60 * 60 * 24 * 30 {
                tm = exptime as f64;

            } else {
                // Otherwise it's relative from now
                tm = time_now() + exptime as f64;
            }

            value.set_exptime(tm);
        }
    }

    fn do_get(&mut self, get: Get) -> Resp {
        // Update metrics
        self.metrics.cmd_get += 1;

        // XXX get rid of all the cloning
        let get_clone = get.clone();
        let key = Key::new(get.key.into_bytes());

        let rv = self.cache.get(&key);

        match rv {
            Ok(value) => {
                Resp::Value(CmdValue {
                    key: get_clone.key,
                    data: value.item.clone(),
                })
            }
            Err(_) => Resp::Error,
        }
    }

    fn do_set(&mut self, set: Set) -> Resp {
        // Update metrics
        self.metrics.cmd_set += 1;

        let key = Key::new(set.key.into_bytes());
        let mut value = Value::new(set.data);
        self.set_exptime(&mut value, set.exptime);

        let rv = self.cache.set(key, value);

        match rv {
            Ok(_) => Resp::Stored,
            Err(_) => Resp::Error,
        }
    }

    fn do_stats(&self) -> Resp {
        let storage = self.cache.get_metrics();

        let pid = get_pid().to_string();
        let uptime = ((time_now() - self.time_start) as u64).to_string();
        let time = (time_now() as u64).to_string();
        let cmd_get = self.metrics.cmd_get.to_string();
        let cmd_set = self.metrics.cmd_set.to_string();
        let cmd_flush = self.metrics.cmd_flush.to_string();
        let cmd_touch = self.metrics.cmd_touch.to_string();
        let get_hits = storage.get_hits.to_string();
        let get_misses = storage.get_misses.to_string();
        let bytes_read = self.transport_stats.bytes_read.to_string();
        let bytes_written = self.transport_stats.bytes_written.to_string();
        let limit_maxbytes = self.cache.capacity.to_string();
        let bytes = storage.bytes.to_string();
        let curr_items = self.cache.len().to_string();
        let total_items = storage.total_items.to_string();
        let evictions = storage.evictions.to_string();
        let reclaimed = storage.reclaimed.to_string();

        let st_pid = Stat::new("pid", pid);
        let st_uptime = Stat::new("uptime", uptime);
        let st_time = Stat::new("time", time);
        let st_cmd_get = Stat::new("cmd_get", cmd_get);
        let st_cmd_set = Stat::new("cmd_set", cmd_set);
        let st_cmd_flush = Stat::new("cmd_flush", cmd_flush);
        let st_cmd_touch = Stat::new("cmd_touch", cmd_touch);
        let st_get_hits = Stat::new("get_hits", get_hits);
        let st_get_misses = Stat::new("get_misses", get_misses);
        let st_bytes_read = Stat::new("bytes_read", bytes_read);
        let st_bytes_written = Stat::new("bytes_written", bytes_written);
        let st_limit_maxbytes = Stat::new("limit_maxbytes", limit_maxbytes);
        let st_bytes = Stat::new("bytes", bytes);
        let st_curr_items = Stat::new("curr_items", curr_items);
        let st_total_items = Stat::new("total_items", total_items);
        let st_evictions = Stat::new("evictions", evictions);
        let st_reclaimed = Stat::new("reclaimed", reclaimed);

        Resp::Stats(vec![st_pid,
                         st_uptime,
                         st_time,
                         st_cmd_get,
                         st_cmd_set,
                         st_cmd_flush,
                         st_cmd_touch,
                         st_get_hits,
                         st_get_misses,
                         st_bytes_read,
                         st_bytes_written,
                         st_limit_maxbytes,
                         st_bytes,
                         st_curr_items,
                         st_total_items,
                         st_evictions,
                         st_reclaimed])
    }

    pub fn run(&mut self, cmd: Cmd) -> Resp {
        match cmd {
            Cmd::Get(get) => self.do_get(get),
            Cmd::Set(set) => self.do_set(set),
            Cmd::Stats => self.do_stats(),
        }
    }

    pub fn update_transport_stats(&mut self, stats: TransportStats) {
        self.transport_stats = stats;
    }
}
<commit_msg>rename all mentions of driver metrics to driver stats<commit_after>use platform::process::get_pid;
use platform::time::time_now;
use storage::Cache;
use storage::Key;
use storage::Value;
use tcp_transport::stats::TransportStats;

use super::cmd::Cmd;
use super::cmd::Get;
use super::cmd::Resp;
use super::cmd::Set;
use super::cmd::Stat;
use super::cmd::Value as CmdValue;

struct DriverStats {
    cmd_get: u64,
    cmd_set: u64,
    cmd_flush: u64,
    cmd_touch: u64,
}

impl DriverStats {
    pub fn new() -> DriverStats {
        DriverStats {
            cmd_get: 0,
            cmd_set: 0,
            cmd_flush: 0,
            cmd_touch: 0,
        }
    }
}

pub struct Driver {
    cache: Cache,
    time_start: f64,

    stats: DriverStats,
    transport_stats: TransportStats, // this is a global snapshot
}

impl Driver {
    pub fn new(cache: Cache) -> Driver {
        Driver {
            cache: cache,
            stats: DriverStats::new(),
            time_start: time_now(),
            transport_stats: TransportStats::new(),
        }
    }

    fn set_exptime(&self, value: &mut Value, exptime: u32) {
        // If exptime is greater than zero we need to set it on the value
        if exptime > 0 {
            let tm;

            // Is it an interval greater than 30 days? Then it's a timestamp
            if exptime > 60 * 60 * 24 * 30 {
                tm = exptime as f64;

            } else {
                // Otherwise it's relative from now
                tm = time_now() + exptime as f64;
            }

            value.set_exptime(tm);
        }
    }

    fn do_get(&mut self, get: Get) -> Resp {
        // Update stats
        self.stats.cmd_get += 1;

        // XXX get rid of all the cloning
        let get_clone = get.clone();
        let key = Key::new(get.key.into_bytes());

        let rv = self.cache.get(&key);

        match rv {
            Ok(value) => {
                Resp::Value(CmdValue {
                    key: get_clone.key,
                    data: value.item.clone(),
                })
            }
            Err(_) => Resp::Error,
        }
    }

    fn do_set(&mut self, set: Set) -> Resp {
        // Update stats
        self.stats.cmd_set += 1;

        let key = Key::new(set.key.into_bytes());
        let mut value = Value::new(set.data);
        self.set_exptime(&mut value, set.exptime);

        let rv = self.cache.set(key, value);

        match rv {
            Ok(_) => Resp::Stored,
            Err(_) => Resp::Error,
        }
    }

    fn do_stats(&self) -> Resp {
        let storage = self.cache.get_metrics();

        let pid = get_pid().to_string();
        let uptime = ((time_now() - self.time_start) as u64).to_string();
        let time = (time_now() as u64).to_string();
        let cmd_get = self.stats.cmd_get.to_string();
        let cmd_set = self.stats.cmd_set.to_string();
        let cmd_flush = self.stats.cmd_flush.to_string();
        let cmd_touch = self.stats.cmd_touch.to_string();
        let get_hits = storage.get_hits.to_string();
        let get_misses = storage.get_misses.to_string();
        let bytes_read = self.transport_stats.bytes_read.to_string();
        let bytes_written = self.transport_stats.bytes_written.to_string();
        let limit_maxbytes = self.cache.capacity.to_string();
        let bytes = storage.bytes.to_string();
        let curr_items = self.cache.len().to_string();
        let total_items = storage.total_items.to_string();
        let evictions = storage.evictions.to_string();
        let reclaimed = storage.reclaimed.to_string();

        let st_pid = Stat::new("pid", pid);
        let st_uptime = Stat::new("uptime", uptime);
        let st_time = Stat::new("time", time);
        let st_cmd_get = Stat::new("cmd_get", cmd_get);
        let st_cmd_set = Stat::new("cmd_set", cmd_set);
        let st_cmd_flush = Stat::new("cmd_flush", cmd_flush);
        let st_cmd_touch = Stat::new("cmd_touch", cmd_touch);
        let st_get_hits = Stat::new("get_hits", get_hits);
        let st_get_misses = Stat::new("get_misses", get_misses);
        let st_bytes_read = Stat::new("bytes_read", bytes_read);
        let st_bytes_written = Stat::new("bytes_written", bytes_written);
        let st_limit_maxbytes = Stat::new("limit_maxbytes", limit_maxbytes);
        let st_bytes = Stat::new("bytes", bytes);
        let st_curr_items = Stat::new("curr_items", curr_items);
        let st_total_items = Stat::new("total_items", total_items);
        let st_evictions = Stat::new("evictions", evictions);
        let st_reclaimed = Stat::new("reclaimed", reclaimed);

        Resp::Stats(vec![st_pid,
                         st_uptime,
                         st_time,
                         st_cmd_get,
                         st_cmd_set,
                         st_cmd_flush,
                         st_cmd_touch,
                         st_get_hits,
                         st_get_misses,
                         st_bytes_read,
                         st_bytes_written,
                         st_limit_maxbytes,
                         st_bytes,
                         st_curr_items,
                         st_total_items,
                         st_evictions,
                         st_reclaimed])
    }

    pub fn run(&mut self, cmd: Cmd) -> Resp {
        match cmd {
            Cmd::Get(get) => self.do_get(get),
            Cmd::Set(set) => self.do_set(set),
            Cmd::Stats => self.do_stats(),
        }
    }

    pub fn update_transport_stats(&mut self, stats: TransportStats) {
        self.transport_stats = stats;
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::str;
use std::kinds::marker::NoCopy;
use std::io::fs::File;
use std::io::Reader;
use gl;
use gl::types::*;
use camera::Camera;
use resource::{GLPrimitive, GPUVector};

#[path = "../error.rs"]
mod error;

/// Structure encapsulating a shader program.
pub struct Shader {
    program: GLuint,
    vshader: GLuint,
    fshader: GLuint,
    nocpy:   NoCopy
}

impl Shader {
    /// Creates a new shader program from two files containing the vertex and fragment shader.
    pub fn new(vshader_path: &Path, fshader_path: &Path) -> Option<Shader> {
        if !vshader_path.exists() || !fshader_path.exists() {
            None
        }
        else {
            let vshader = File::open(vshader_path).map(|mut v| v.read_to_string());
            let fshader = File::open(fshader_path).map(|mut f| f.read_to_string());

            if vshader.is_err() || fshader.is_err() {
                return None;
            }

            let vshader = vshader.unwrap();
            let fshader = fshader.unwrap();

            if vshader.is_err() || fshader.is_err() {
                return None;
            }

            Some(Shader::new_from_str(vshader.unwrap().as_slice(), fshader.unwrap().as_slice()))
        }
    }

    /// Creates a new shader program from strings of the vertex and fragment shader.
    pub fn new_from_str(vshader: &str, fshader: &str) -> Shader {
        let (program, vshader, fshader) = load_shader_program(vshader, fshader);

        Shader {
            program: program,
            vshader: vshader,
            fshader: fshader,
            nocpy:   NoCopy
        }
    }

    /// Gets a uniform variable from the shader program.
    pub fn get_uniform<T: GLPrimitive>(&self, name: &str) -> Option<ShaderUniform<T>> {
        let location = unsafe { gl::GetUniformLocation(self.program, name.to_c_str().unwrap()) };

        if gl::GetError() == 0 && location != -1 {
            Some(ShaderUniform { id: location as GLuint })
        }
        else {
            None
        }
    }

    /// Gets an attribute from the shader program.
    pub fn get_attrib<T: GLPrimitive>(&self, name: &str) -> Option<ShaderAttribute<T>> {
        let location = unsafe { gl::GetAttribLocation(self.program, name.to_c_str().unwrap()) };

        if gl::GetError() == 0 && location != -1 {
            Some(ShaderAttribute { id: location as GLuint })
        }
        else {
            None
        }
    }

    /// Make this program active.
    pub fn use_program(&mut self) {
        verify!(gl::UseProgram(self.program));
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        gl::DeleteProgram(self.program);
        gl::DeleteShader(self.fshader);
        gl::DeleteShader(self.vshader);
    }
}

/// Structure encapsulating an uniform variable.
pub struct ShaderUniform<T> {
    id: GLuint
}

impl<T: GLPrimitive> ShaderUniform<T> {
    /// Upload a value to this variable.
    pub fn upload(&mut self, value: &T) {
        value.upload(self.id)
    }
}

/// Structure encapsulating an attribute.
pub struct ShaderAttribute<T> {
    id: GLuint
}

impl<T: GLPrimitive> ShaderAttribute<T> {
    /// Disable this attribute.
    pub fn disable(&mut self) {
        verify!(gl::DisableVertexAttribArray(self.id));
    }

    /// Enable this attribute.
    pub fn enable(&mut self) {
        verify!(gl::EnableVertexAttribArray(self.id));
    }

    /// Binds this attribute to a gpu vector.
    pub fn bind(&mut self, vector: &mut GPUVector<T>) {
        vector.bind();

        unsafe {
            verify!(gl::VertexAttribPointer(
                        self.id,
                        GLPrimitive::size(None::<T>) as i32,
                        GLPrimitive::gl_type(None::<T>),
                        gl::FALSE,
                        0,
                        ptr::null()));
        }
    }

    /// Binds this attribute to non contiguous parts of a gpu vector.
    pub fn bind_sub_buffer(&mut self, vector: &mut GPUVector<T>, strides: uint, start_index: uint) {
        vector.bind();

        unsafe {
            verify!(gl::VertexAttribPointer(
                        self.id,
                        GLPrimitive::size(None::<T>) as i32,
                        GLPrimitive::gl_type(None::<T>),
                        gl::FALSE,
                        ((strides + 1) * mem::size_of::<T>()) as GLint,
                        mem::transmute(start_index * mem::size_of::<T>())));
        }
    }
}

/// Loads a shader program using the given source codes for the vertex and fragment shader.
///
/// Fails after displaying opengl compilation errors if the shaders are invalid.
fn load_shader_program(vertex_shader: &str, fragment_shader: &str) -> (GLuint, GLuint, GLuint) {
    // Create and compile the vertex shader
    let vshader = gl::CreateShader(gl::VERTEX_SHADER);
    unsafe {
        verify!(gl::ShaderSource(vshader, 1, &vertex_shader.to_c_str().unwrap(), ptr::null()));
        verify!(gl::CompileShader(vshader));
    }
    check_shader_error(vshader);

    // Create and compile the fragment shader
    let fshader = gl::CreateShader(gl::FRAGMENT_SHADER);
    unsafe {
        verify!(gl::ShaderSource(fshader, 1, &fragment_shader.to_c_str().unwrap(), ptr::null()));
        verify!(gl::CompileShader(fshader));
    }

    check_shader_error(fshader);

    // Link the vertex and fragment shader into a shader program
    let program = gl::CreateProgram();
    verify!(gl::AttachShader(program, vshader));
    verify!(gl::AttachShader(program, fshader));
    verify!(gl::LinkProgram(program));

    (program, vshader, fshader)
}

/// Checks if a shader handle is valid.
///
/// If it is not valid, it fails with a descriptive error message.
fn check_shader_error(shader: GLuint) {
    let mut compiles: i32 = 0;

    unsafe{
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compiles);

        if compiles == 0 {
            println!("Shader compilation failed.");
            let mut info_log_len = 0;

            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut info_log_len);

            if info_log_len > 0 {
                // error check for fail to allocate memory omitted
                let mut chars_written = 0;
                let info_log = " ".repeat(info_log_len as uint);

                let mut c_str = info_log.to_c_str();

                gl::GetShaderInfoLog(shader, info_log_len, &mut chars_written, c_str.as_mut_ptr());

                let bytes = c_str.as_bytes();
                let bytes = bytes.slice_to(bytes.len() - 1);
                fail!("Shader compilation failed: {}", str::from_utf8(bytes).unwrap());
            }
        }
    }
}
<commit_msg>Update to the latest rust-nightly<commit_after>use std::mem;
use std::ptr;
use std::str;
use std::kinds::marker::NoCopy;
use std::io::fs::File;
use std::io::fs::PathExtensions;
use std::io::Reader;
use gl;
use gl::types::*;
use camera::Camera;
use resource::{GLPrimitive, GPUVector};

#[path = "../error.rs"]
mod error;

/// Structure encapsulating a shader program.
pub struct Shader {
    program: GLuint,
    vshader: GLuint,
    fshader: GLuint,
    nocpy:   NoCopy
}

impl Shader {
    /// Creates a new shader program from two files containing the vertex and fragment shader.
    pub fn new(vshader_path: &Path, fshader_path: &Path) -> Option<Shader> {
        if !vshader_path.exists() || !fshader_path.exists() {
            None
        }
        else {
            let vshader = File::open(vshader_path).map(|mut v| v.read_to_string());
            let fshader = File::open(fshader_path).map(|mut f| f.read_to_string());

            if vshader.is_err() || fshader.is_err() {
                return None;
            }

            let vshader = vshader.unwrap();
            let fshader = fshader.unwrap();

            if vshader.is_err() || fshader.is_err() {
                return None;
            }

            Some(Shader::new_from_str(vshader.unwrap().as_slice(), fshader.unwrap().as_slice()))
        }
    }

    /// Creates a new shader program from strings of the vertex and fragment shader.
    pub fn new_from_str(vshader: &str, fshader: &str) -> Shader {
        let (program, vshader, fshader) = load_shader_program(vshader, fshader);

        Shader {
            program: program,
            vshader: vshader,
            fshader: fshader,
            nocpy:   NoCopy
        }
    }

    /// Gets a uniform variable from the shader program.
    pub fn get_uniform<T: GLPrimitive>(&self, name: &str) -> Option<ShaderUniform<T>> {
        let location = unsafe { gl::GetUniformLocation(self.program, name.to_c_str().unwrap()) };

        if gl::GetError() == 0 && location != -1 {
            Some(ShaderUniform { id: location as GLuint })
        }
        else {
            None
        }
    }

    /// Gets an attribute from the shader program.
    pub fn get_attrib<T: GLPrimitive>(&self, name: &str) -> Option<ShaderAttribute<T>> {
        let location = unsafe { gl::GetAttribLocation(self.program, name.to_c_str().unwrap()) };

        if gl::GetError() == 0 && location != -1 {
            Some(ShaderAttribute { id: location as GLuint })
        }
        else {
            None
        }
    }

    /// Make this program active.
    pub fn use_program(&mut self) {
        verify!(gl::UseProgram(self.program));
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        gl::DeleteProgram(self.program);
        gl::DeleteShader(self.fshader);
        gl::DeleteShader(self.vshader);
    }
}

/// Structure encapsulating an uniform variable.
pub struct ShaderUniform<T> {
    id: GLuint
}

impl<T: GLPrimitive> ShaderUniform<T> {
    /// Upload a value to this variable.
    pub fn upload(&mut self, value: &T) {
        value.upload(self.id)
    }
}

/// Structure encapsulating an attribute.
pub struct ShaderAttribute<T> {
    id: GLuint
}

impl<T: GLPrimitive> ShaderAttribute<T> {
    /// Disable this attribute.
    pub fn disable(&mut self) {
        verify!(gl::DisableVertexAttribArray(self.id));
    }

    /// Enable this attribute.
    pub fn enable(&mut self) {
        verify!(gl::EnableVertexAttribArray(self.id));
    }

    /// Binds this attribute to a gpu vector.
    pub fn bind(&mut self, vector: &mut GPUVector<T>) {
        vector.bind();

        unsafe {
            verify!(gl::VertexAttribPointer(
                        self.id,
                        GLPrimitive::size(None::<T>) as i32,
                        GLPrimitive::gl_type(None::<T>),
                        gl::FALSE,
                        0,
                        ptr::null()));
        }
    }

    /// Binds this attribute to non contiguous parts of a gpu vector.
    pub fn bind_sub_buffer(&mut self, vector: &mut GPUVector<T>, strides: uint, start_index: uint) {
        vector.bind();

        unsafe {
            verify!(gl::VertexAttribPointer(
                        self.id,
                        GLPrimitive::size(None::<T>) as i32,
                        GLPrimitive::gl_type(None::<T>),
                        gl::FALSE,
                        ((strides + 1) * mem::size_of::<T>()) as GLint,
                        mem::transmute(start_index * mem::size_of::<T>())));
        }
    }
}

/// Loads a shader program using the given source codes for the vertex and fragment shader.
///
/// Fails after displaying opengl compilation errors if the shaders are invalid.
fn load_shader_program(vertex_shader: &str, fragment_shader: &str) -> (GLuint, GLuint, GLuint) {
    // Create and compile the vertex shader
    let vshader = gl::CreateShader(gl::VERTEX_SHADER);
    unsafe {
        verify!(gl::ShaderSource(vshader, 1, &vertex_shader.to_c_str().unwrap(), ptr::null()));
        verify!(gl::CompileShader(vshader));
    }
    check_shader_error(vshader);

    // Create and compile the fragment shader
    let fshader = gl::CreateShader(gl::FRAGMENT_SHADER);
    unsafe {
        verify!(gl::ShaderSource(fshader, 1, &fragment_shader.to_c_str().unwrap(), ptr::null()));
        verify!(gl::CompileShader(fshader));
    }

    check_shader_error(fshader);

    // Link the vertex and fragment shader into a shader program
    let program = gl::CreateProgram();
    verify!(gl::AttachShader(program, vshader));
    verify!(gl::AttachShader(program, fshader));
    verify!(gl::LinkProgram(program));

    (program, vshader, fshader)
}

/// Checks if a shader handle is valid.
///
/// If it is not valid, it fails with a descriptive error message.
fn check_shader_error(shader: GLuint) {
    let mut compiles: i32 = 0;

    unsafe{
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compiles);

        if compiles == 0 {
            println!("Shader compilation failed.");
            let mut info_log_len = 0;

            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut info_log_len);

            if info_log_len > 0 {
                // error check for fail to allocate memory omitted
                let mut chars_written = 0;
                let info_log = " ".repeat(info_log_len as uint);

                let mut c_str = info_log.to_c_str();

                gl::GetShaderInfoLog(shader, info_log_len, &mut chars_written, c_str.as_mut_ptr());

                let bytes = c_str.as_bytes();
                let bytes = bytes.slice_to(bytes.len() - 1);
                fail!("Shader compilation failed: {}", str::from_utf8(bytes).unwrap());
            }
        }
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate hex;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate url;

use std::ffi::OsStr;
use std::time::Duration;

use cargo::util::Rustc;
use std::path::PathBuf;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env("__CARGO_TEST_ROOT", support::paths::root())

     // Force cargo to think it's on the stable channel for all tests, this
     // should hopefully not suprise us as we add cargo features over time and
     // cargo rides the trains
     .env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "stable")

     // For now disable incremental by default as support hasn't ridden to the
     // stable channel yet. Once incremental support hits the stable compiler we
     // can switch this to one and then fix the tests.
     .env("CARGO_INCREMENTAL", "0")

     .env_remove("__CARGO_DEFAULT_LIB_METADATA")
     .env_remove("RUSTC")
     .env_remove("RUSTDOC")
     .env_remove("RUSTC_WRAPPER")
     .env_remove("RUSTFLAGS")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("MFLAGS")
     .env_remove("MAKEFLAGS")
     .env_remove("CARGO_MAKEFLAGS")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows
    return p
}

pub trait ChannelChanger: Sized {
    fn masquerade_as_nightly_cargo(&mut self) -> &mut Self;
}

impl ChannelChanger for cargo::util::ProcessBuilder {
    fn masquerade_as_nightly_cargo(&mut self) -> &mut Self {
        self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly")
    }
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_exe())
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<commit_msg>Auto merge of #4856 - alexcrichton:no-revoke, r=alexcrichton<commit_after>#![deny(warnings)]

extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate hex;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate url;

use std::ffi::OsStr;
use std::time::Duration;

use cargo::util::Rustc;
use std::path::PathBuf;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env("__CARGO_TEST_ROOT", support::paths::root())

     // Force cargo to think it's on the stable channel for all tests, this
     // should hopefully not suprise us as we add cargo features over time and
     // cargo rides the trains
     .env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "stable")

     // For now disable incremental by default as support hasn't ridden to the
     // stable channel yet. Once incremental support hits the stable compiler we
     // can switch this to one and then fix the tests.
     .env("CARGO_INCREMENTAL", "0")

     // This env var can switch the git backend from libgit2 to git2-curl, which
     // can tweak error messages and cause some tests to fail, so let's forcibly
     // remove it.
     .env_remove("CARGO_HTTP_CHECK_REVOKE")

     .env_remove("__CARGO_DEFAULT_LIB_METADATA")
     .env_remove("RUSTC")
     .env_remove("RUSTDOC")
     .env_remove("RUSTC_WRAPPER")
     .env_remove("RUSTFLAGS")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("MFLAGS")
     .env_remove("MAKEFLAGS")
     .env_remove("CARGO_MAKEFLAGS")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows
    return p
}

pub trait ChannelChanger: Sized {
    fn masquerade_as_nightly_cargo(&mut self) -> &mut Self;
}

impl ChannelChanger for cargo::util::ProcessBuilder {
    fn masquerade_as_nightly_cargo(&mut self) -> &mut Self {
        self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly")
    }
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_exe())
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::fs::create_dir_all;
use std::fs::remove_file;
use std::io::Read;
use std::io::Write;
use std::vec::IntoIter;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult<T = ()> = Result<T, StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
    storepath: String,
}

impl StorageBackend {

    pub fn new(rt: &Runtime) -> BackendOperationResult<StorageBackend> {
        let storepath = rt.get_rtp() + "/store/";
        debug!("Trying to create {}", storepath);
        create_dir_all(&storepath).and_then(|_| {
            debug!("Creating succeeded, constructing backend instance");
            Ok(StorageBackend {
                basepath: rt.get_rtp(),
                storepath: storepath.clone(),
            })
        }).or_else(|e| {
            debug!("Creating failed, constructing error instance");
            let mut serr = StorageBackendError::new(
                "create_dir_all()",
                "Could not create store directories",
                Some(storepath)
            );
            serr.caused_by = Some(Box::new(e));
            Err(serr)
        })
    }

    pub fn iter_ids(&self, m: &Module) -> Result<IntoIter<FileID>, StorageBackendError>
    {
        let globstr = self.prefix_of_files_for_module(m) + "*.imag";
        debug!("Globstring = {}", globstr);
        glob(&globstr[..])
            .and_then(|globlist| {
                debug!("Iterating over globlist");
                Ok(globlist_to_file_id_vec(globlist).into_iter())
            })
            .map_err(|e| {
                debug!("glob() returned error: {:?}", e);
                let serr = StorageBackendError::new(
                        "iter_ids()",
                        "Cannot iter on file ids",
                        None);
                // Why the hack is Error not implemented for glob::PatternError
                // serr.caused_by = Some(Box::new(e));
                serr
            })
    }

    pub fn iter_files<'a, HP>(&self, m: &'a Module, p: &Parser<HP>)
        -> Result<IntoIter<File<'a>>, StorageBackendError>
        where HP: FileHeaderParser
    {
        self.iter_ids(m)
            .and_then(|ids| {
                debug!("Iterating ids and building files from them");
                debug!("  number of ids = {}", ids.len());
                Ok(ids.filter_map(|id| self.get_file_by_id(m, &id, p))
                        .collect::<Vec<File>>()
                        .into_iter())
            })
            .map_err(|e| {
                debug!("StorageBackend::iter_ids() returned error = {:?}", e);
                let mut serr = StorageBackendError::new("iter_files()",
                                           "Cannot iter on files",
                                           None);
                serr.caused_by = Some(Box::new(e));
                serr
            })
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let written = write_with_parser(&f, p);
        if written.is_err() { return Err(written.err().unwrap()); }
        let string = written.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::create(&path).map(|mut file| {
            debug!("Created file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::new(
                            "File::write_all()",
                            "Could not write out File contents",
                            None
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not create file at '{}'", path);
            let mut err = StorageBackendError::new(
                "File::create()",
                "Creating file on disk failed",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let contents = write_with_parser(&f, p);
        if contents.is_err() { return Err(contents.err().unwrap()); }
        let string = contents.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::open(&path).map(|mut file| {
            debug!("Open file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::new(
                            "File::write()",
                            "Tried to write contents of this file, though operation did not succeed",
                            Some(string)
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not write file at '{}'", path);
            let mut err = StorageBackendError::new(
                "File::open()",
                "Tried to update contents of this file, though file doesn't exist",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<'a, HP>(&self, m: &'a Module, id: &FileID, p: &Parser<HP>) -> Option<File<'a>>
        where HP: FileHeaderParser
    {
        use std::ops::Index;

        debug!("Searching for file with id '{}'", id);

        if id.get_type() == FileIDType::NONE {
            // We don't know the hash type, so we glob() around a bit.
            debug!("Having FileIDType::NONE, so we glob() for the raw ID");

            let globstr = self.prefix_of_files_for_module(m) + "*" + ".imag";
            glob(&globstr[..]).map(|globlist| {
                let mut vec = globlist_to_file_id_vec(globlist).into_iter()
                                .filter_map(|id| self.get_file_by_id(m, &id, p))
                                .collect::<Vec<File>>();
                vec.reverse();
                vec.pop()
            }).unwrap_or({
                debug!("No glob matches, actually. We can't do anything at this point");
                None
            })
        } else {
            // The (hash)type is already in the FileID object, so we can just
            // build a path from the information we already have
            debug!("We know FileIDType, so we build the path directly now");
            if let Ok(mut fs) = FSFile::open(self.build_filepath_with_id(m, id.clone())) {
                let mut s = String::new();
                fs.read_to_string(&mut s);
                debug!("Success opening file with id '{}'", id);
                debug!("Parsing to internal structure now");
                p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(m, id.clone(), h, d))).ok()
            } else {
                debug!("No file with id '{}'", id);
                None
            }
        }
    }

    pub fn remove_file(&self, m: &Module, file: File, checked: bool) -> BackendOperationResult {
        if checked {
            error!("Checked remove not implemented yet. I will crash now");
            unimplemented!()
        }

        debug!("Doing unchecked remove");
        info!("Going to remove file: {}", file);

        let fp = self.build_filepath(&file);
        remove_file(fp).map_err(|e| {
            let mut serr = StorageBackendError::new(
                "remove_file()",
                "File removal failed",
                Some(format!("{}", file))
            );
            serr.caused_by = Some(Box::new(e));
            serr
        })
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.owner(), f.id())
    }

    fn build_filepath_with_id(&self, owner: &Module, id: FileID) -> String {
        let idstr   : String        = id.clone().into();
        let idtype  : FileIDType    = id.into();
        let typestr : String        = idtype.into();

        debug!("Building filepath with id");
        debug!("  basepath: '{}'", self.basepath);
        debug!(" storepath: '{}'", self.storepath);
        debug!("        id: '{}'", idstr);
        debug!("      type: '{}'", typestr);

        self.prefix_of_files_for_module(owner) +
            "-" + &typestr[..] +
            "-" + &idstr[..] +
            ".imag"
    }

    fn prefix_of_files_for_module(&self, m: &Module) -> String {
        self.storepath.clone() + m.name()
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub data_dump: Option<String>,  // Data dump, if any
    pub caused_by: Option<Box<Error>>,  // caused from this error
}

impl StorageBackendError {

    fn new<S>(action: S, desc: S, data: Option<String>) -> StorageBackendError
        where S: Into<String>
    {
        StorageBackendError {
            action:         action.into(),
            desc:           desc.into(),
            data_dump:      data,
            caused_by:      None,
        }
    }

}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        self.caused_by.as_ref().map(|e| &**e)
    }

}

impl<'a> Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}",
               self.action, self.desc)
    }
}

fn write_with_parser<'a, HP>(f: &File, p: &Parser<HP>) -> Result<String, StorageBackendError>
    where HP: FileHeaderParser
{
    p.write(f.contents())
        .or_else(|err| {
            let mut serr = StorageBackendError::new(
                "Parser::write()",
                "Cannot translate internal representation of file contents into on-disk representation",
                None
            );
            serr.caused_by = Some(Box::new(err));
            Err(serr)
        })
}

fn globlist_to_file_id_vec(globlist: Paths) -> Vec<FileID> {
    globlist.filter_map(Result::ok)
            .map(|pbuf| FileID::from(&pbuf))
            .collect::<Vec<FileID>>()
}
<commit_msg>Ensure we build the globstring _with_ the ID in it<commit_after>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::fs::create_dir_all;
use std::fs::remove_file;
use std::io::Read;
use std::io::Write;
use std::vec::IntoIter;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult<T = ()> = Result<T, StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
    storepath: String,
}

impl StorageBackend {

    pub fn new(rt: &Runtime) -> BackendOperationResult<StorageBackend> {
        let storepath = rt.get_rtp() + "/store/";
        debug!("Trying to create {}", storepath);
        create_dir_all(&storepath).and_then(|_| {
            debug!("Creating succeeded, constructing backend instance");
            Ok(StorageBackend {
                basepath: rt.get_rtp(),
                storepath: storepath.clone(),
            })
        }).or_else(|e| {
            debug!("Creating failed, constructing error instance");
            let mut serr = StorageBackendError::new(
                "create_dir_all()",
                "Could not create store directories",
                Some(storepath)
            );
            serr.caused_by = Some(Box::new(e));
            Err(serr)
        })
    }

    pub fn iter_ids(&self, m: &Module) -> Result<IntoIter<FileID>, StorageBackendError>
    {
        let globstr = self.prefix_of_files_for_module(m) + "*.imag";
        debug!("Globstring = {}", globstr);
        glob(&globstr[..])
            .and_then(|globlist| {
                debug!("Iterating over globlist");
                Ok(globlist_to_file_id_vec(globlist).into_iter())
            })
            .map_err(|e| {
                debug!("glob() returned error: {:?}", e);
                let serr = StorageBackendError::new(
                        "iter_ids()",
                        "Cannot iter on file ids",
                        None);
                // Why the hack is Error not implemented for glob::PatternError
                // serr.caused_by = Some(Box::new(e));
                serr
            })
    }

    pub fn iter_files<'a, HP>(&self, m: &'a Module, p: &Parser<HP>)
        -> Result<IntoIter<File<'a>>, StorageBackendError>
        where HP: FileHeaderParser
    {
        self.iter_ids(m)
            .and_then(|ids| {
                debug!("Iterating ids and building files from them");
                debug!("  number of ids = {}", ids.len());
                Ok(ids.filter_map(|id| self.get_file_by_id(m, &id, p))
                        .collect::<Vec<File>>()
                        .into_iter())
            })
            .map_err(|e| {
                debug!("StorageBackend::iter_ids() returned error = {:?}", e);
                let mut serr = StorageBackendError::new("iter_files()",
                                           "Cannot iter on files",
                                           None);
                serr.caused_by = Some(Box::new(e));
                serr
            })
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let written = write_with_parser(&f, p);
        if written.is_err() { return Err(written.err().unwrap()); }
        let string = written.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::create(&path).map(|mut file| {
            debug!("Created file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::new(
                            "File::write_all()",
                            "Could not write out File contents",
                            None
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not create file at '{}'", path);
            let mut err = StorageBackendError::new(
                "File::create()",
                "Creating file on disk failed",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let contents = write_with_parser(&f, p);
        if contents.is_err() { return Err(contents.err().unwrap()); }
        let string = contents.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::open(&path).map(|mut file| {
            debug!("Open file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::new(
                            "File::write()",
                            "Tried to write contents of this file, though operation did not succeed",
                            Some(string)
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not write file at '{}'", path);
            let mut err = StorageBackendError::new(
                "File::open()",
                "Tried to update contents of this file, though file doesn't exist",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<'a, HP>(&self, m: &'a Module, id: &FileID, p: &Parser<HP>) -> Option<File<'a>>
        where HP: FileHeaderParser
    {
        use std::ops::Index;

        debug!("Searching for file with id '{}'", id);

        if id.get_type() == FileIDType::NONE {
            // We don't know the hash type, so we glob() around a bit.
            debug!("Having FileIDType::NONE, so we glob() for the raw ID");

            let id_str = id.get_id().unwrap_or(String::from("INVALID"));
            let globstr = self.prefix_of_files_for_module(m) + "*" + &id_str[..] + ".imag";
            debug!("Globbing with globstr = '{}'", globstr);
            glob(&globstr[..]).map(|globlist| {
                let mut vec = globlist_to_file_id_vec(globlist).into_iter()
                                .filter_map(|id| self.get_file_by_id(m, &id, p))
                                .collect::<Vec<File>>();
                vec.reverse();
                vec.pop()
            }).unwrap_or({
                debug!("No glob matches, actually. We can't do anything at this point");
                None
            })
        } else {
            // The (hash)type is already in the FileID object, so we can just
            // build a path from the information we already have
            debug!("We know FileIDType, so we build the path directly now");
            if let Ok(mut fs) = FSFile::open(self.build_filepath_with_id(m, id.clone())) {
                let mut s = String::new();
                fs.read_to_string(&mut s);
                debug!("Success opening file with id '{}'", id);
                debug!("Parsing to internal structure now");
                p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(m, id.clone(), h, d))).ok()
            } else {
                debug!("No file with id '{}'", id);
                None
            }
        }
    }

    pub fn remove_file(&self, m: &Module, file: File, checked: bool) -> BackendOperationResult {
        if checked {
            error!("Checked remove not implemented yet. I will crash now");
            unimplemented!()
        }

        debug!("Doing unchecked remove");
        info!("Going to remove file: {}", file);

        let fp = self.build_filepath(&file);
        remove_file(fp).map_err(|e| {
            let mut serr = StorageBackendError::new(
                "remove_file()",
                "File removal failed",
                Some(format!("{}", file))
            );
            serr.caused_by = Some(Box::new(e));
            serr
        })
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.owner(), f.id())
    }

    fn build_filepath_with_id(&self, owner: &Module, id: FileID) -> String {
        let idstr   : String        = id.clone().into();
        let idtype  : FileIDType    = id.into();
        let typestr : String        = idtype.into();

        debug!("Building filepath with id");
        debug!("  basepath: '{}'", self.basepath);
        debug!(" storepath: '{}'", self.storepath);
        debug!("        id: '{}'", idstr);
        debug!("      type: '{}'", typestr);

        self.prefix_of_files_for_module(owner) +
            "-" + &typestr[..] +
            "-" + &idstr[..] +
            ".imag"
    }

    fn prefix_of_files_for_module(&self, m: &Module) -> String {
        self.storepath.clone() + m.name()
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub data_dump: Option<String>,  // Data dump, if any
    pub caused_by: Option<Box<Error>>,  // caused from this error
}

impl StorageBackendError {

    fn new<S>(action: S, desc: S, data: Option<String>) -> StorageBackendError
        where S: Into<String>
    {
        StorageBackendError {
            action:         action.into(),
            desc:           desc.into(),
            data_dump:      data,
            caused_by:      None,
        }
    }

}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        self.caused_by.as_ref().map(|e| &**e)
    }

}

impl<'a> Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}",
               self.action, self.desc)
    }
}

fn write_with_parser<'a, HP>(f: &File, p: &Parser<HP>) -> Result<String, StorageBackendError>
    where HP: FileHeaderParser
{
    p.write(f.contents())
        .or_else(|err| {
            let mut serr = StorageBackendError::new(
                "Parser::write()",
                "Cannot translate internal representation of file contents into on-disk representation",
                None
            );
            serr.caused_by = Some(Box::new(err));
            Err(serr)
        })
}

fn globlist_to_file_id_vec(globlist: Paths) -> Vec<FileID> {
    globlist.filter_map(Result::ok)
            .map(|pbuf| FileID::from(&pbuf))
            .collect::<Vec<FileID>>()
}
<|endoftext|>


<commit_before>use std::iter::repeat;

use graph::{Graph, Edge};
use bit_vector::BitVector;

// maximal_independent_set processes vertices in order and returns the resulting maximal independent
// set in g.
pub fn maximal_independent_set(g: &Graph, vertices: &Vec<usize>) -> Vec<usize> {
    let mut adjacency_list: Vec<_> = repeat(BitVector::new()).take(g.vertex_count).collect();
    for &Edge { x, y } in &g.edges {
        adjacency_list[x].set(y);
        adjacency_list[y].set(x);
    }

    let mut maximal_set = BitVector::new();
    for &x in vertices {
        let neighbors = &adjacency_list[x];
        if maximal_set.intersect(&neighbors).is_empty() {
            // x is not adjacent to any set vertices. This means x is eligible to join the set.
            maximal_set.set(x)
        }
    }

    maximal_set.to_vec()
}

// maximum_independent_set returns an independent set that is hopefully the maximum independent set
// in g.
pub fn maximum_independent_set(g: &Graph) -> Vec<usize> {
    let mut degrees: Vec<_> = vec![0; g.vertex_count];
    for &Edge { x, y } in &g.edges {
        degrees[x] += 1;
        degrees[y] += 1;
    }

    let mut vertices_sorted_by_decreasing_degree: Vec<_> = (0..g.vertex_count).collect();
    vertices_sorted_by_decreasing_degree.sort_by(|&x, &y| degrees[x].cmp(&degrees[y]));

    maximal_independent_set(g, &vertices_sorted_by_decreasing_degree)
}
<commit_msg>[independent_set/rust] Correctly reflect sorting order in var name<commit_after>use std::iter::repeat;

use graph::{Graph, Edge};
use bit_vector::BitVector;

// maximal_independent_set processes vertices in order and returns the resulting maximal independent
// set in g.
pub fn maximal_independent_set(g: &Graph, vertices: &Vec<usize>) -> Vec<usize> {
    let mut adjacency_list: Vec<_> = repeat(BitVector::new()).take(g.vertex_count).collect();
    for &Edge { x, y } in &g.edges {
        adjacency_list[x].set(y);
        adjacency_list[y].set(x);
    }

    let mut maximal_set = BitVector::new();
    for &x in vertices {
        let neighbors = &adjacency_list[x];
        if maximal_set.intersect(&neighbors).is_empty() {
            // x is not adjacent to any set vertices. This means x is eligible to join the set.
            maximal_set.set(x)
        }
    }

    maximal_set.to_vec()
}

// maximum_independent_set returns an independent set that is hopefully the maximum independent set
// in g.
pub fn maximum_independent_set(g: &Graph) -> Vec<usize> {
    let mut degrees: Vec<_> = vec![0; g.vertex_count];
    for &Edge { x, y } in &g.edges {
        degrees[x] += 1;
        degrees[y] += 1;
    }

    let mut vertices_sorted_by_increasing_degree: Vec<_> = (0..g.vertex_count).collect();
    vertices_sorted_by_increasing_degree.sort_by(|&x, &y| degrees[x].cmp(&degrees[y]));

    maximal_independent_set(g, &vertices_sorted_by_increasing_degree)
}
<|endoftext|>


<commit_before>// This module defines constants and functions for working with zakocmp
// configuration files.

extern crate yaml_rust;

use std::io::{Error, ErrorKind};
use std::result::Result;
use std::vec::Vec;

// Enumerates the string representations of known policies.
const POLICY_REPR_IGNORE: &str = "ignore";
const POLICY_REPR_NOADD: &str = "noadd";
const POLICY_REPR_NODELETE: &str = "nodelete";
const POLICY_REPR_NOMODIFY: &str = "nomodify";
const POLICY_REPR_IMMUTABLE: &str = "immutable";

// Represents known policies as integers.
pub const POLICY_IGNORE: i32 = 0;
pub const POLICY_NOADD: i32 = 1 << 0;
pub const POLICY_NODELETE: i32 = 1 << 1;
pub const POLICY_NOMODIFY: i32 = 1 << 2;
pub const POLICY_IMMUTABLE: i32 = POLICY_NOADD | POLICY_NODELETE | POLICY_NOMODIFY;

// Borrows the string representation of one policy `token` and returns
// the equivalent integral representation.
fn policy_token_as_int(token: &str) -> Result<i32, Error> {
    match token {
        POLICY_REPR_IGNORE => Ok(POLICY_IGNORE),
        POLICY_REPR_NOADD => Ok(POLICY_NOADD),
        POLICY_REPR_NODELETE => Ok(POLICY_NODELETE),
        POLICY_REPR_NOMODIFY => Ok(POLICY_NOMODIFY),
        POLICY_REPR_IMMUTABLE => Ok(POLICY_IMMUTABLE),
        _ => Err(Error::new(
            ErrorKind::InvalidInput,
            format!("bad token: ``{}''", token),
        )),
    }
}

/// Borrows the string representation of a combined `policy` and returns
/// the equivalent integral representation. This function expects
/// `policy` to comprise one or more policy tokens separated by commas.
///
/// # Examples
///
/// ```
/// # mod zakocmp;
/// let policy: i32 = config::policy_repr_as_int(&"immutable").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// ```
/// # mod zakocmp;
/// // Multiple policies are bitwise OR'd together.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nomodify").unwrap();
/// assert!(policy == config::POLICY_NOADD | config::POLICY_NOMODIFY);
/// ```
///
/// ```
/// # mod zakocmp;
/// // The biggest bitwise OR equals POLICY_IMMUTABLE.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nodelete,nomodify").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// # Failures
///
/// ```
/// # mod zakocmp;
/// // Obi-wan was witty, but not good at dictating zakocmp policy.
/// assert!(!config::policy_repr_as_int(&"hello there!").is_ok());
/// ```
///
pub fn policy_repr_as_int(policy: &str) -> Result<i32, Error> {
    let policy_ints: Vec<i32> = policy
        .split(",")
        .map(|tok| policy_token_as_int(tok))
        .collect::<Result<Vec<i32>, Error>>()?;
    return Ok(policy_ints
        .iter()
        .fold(POLICY_IGNORE, |accum, elem| accum | elem));
}

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

    #[test]
    fn test_bare_noadd() {
        let policy: i32 = match policy_repr_as_int(&"noadd") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD);
    }

    #[test]
    fn test_bare_nodelete() {
        let policy: i32 = match policy_repr_as_int(&"nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NODELETE);
    }

    #[test]
    fn test_bare_nomodify() {
        let policy: i32 = match policy_repr_as_int(&"nomodify") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOMODIFY);
    }

    #[test]
    fn test_combo_policy() {
        let policy: i32 = match policy_repr_as_int(&"noadd,nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }

    #[test]
    fn test_repetitive_policy() {
        let policy: i32 =
            match policy_repr_as_int(&"noadd,noadd,noadd,noadd,nodelete,nodelete,nodelete,noadd") {
                Ok(value) => value,
                Err(oof) => panic!(oof),
            };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }
}
<commit_msg>zakocmp: clarify static lifetimes<commit_after>// This module defines constants and functions for working with zakocmp
// configuration files.

extern crate yaml_rust;

use std::io::{Error, ErrorKind};
use std::result::Result;
use std::vec::Vec;

// Enumerates the string representations of known policies.
const POLICY_REPR_IGNORE: &'static str = "ignore";
const POLICY_REPR_NOADD: &'static str = "noadd";
const POLICY_REPR_NODELETE: &'static str = "nodelete";
const POLICY_REPR_NOMODIFY: &'static str = "nomodify";
const POLICY_REPR_IMMUTABLE: &'static str = "immutable";

// Represents known policies as integers.
pub const POLICY_IGNORE: i32 = 0;
pub const POLICY_NOADD: i32 = 1 << 0;
pub const POLICY_NODELETE: i32 = 1 << 1;
pub const POLICY_NOMODIFY: i32 = 1 << 2;
pub const POLICY_IMMUTABLE: i32 = POLICY_NOADD | POLICY_NODELETE | POLICY_NOMODIFY;

// Borrows the string representation of one policy `token` and returns
// the equivalent integral representation.
fn policy_token_as_int(token: &str) -> Result<i32, Error> {
    match token {
        POLICY_REPR_IGNORE => Ok(POLICY_IGNORE),
        POLICY_REPR_NOADD => Ok(POLICY_NOADD),
        POLICY_REPR_NODELETE => Ok(POLICY_NODELETE),
        POLICY_REPR_NOMODIFY => Ok(POLICY_NOMODIFY),
        POLICY_REPR_IMMUTABLE => Ok(POLICY_IMMUTABLE),
        _ => Err(Error::new(
            ErrorKind::InvalidInput,
            format!("bad token: ``{}''", token),
        )),
    }
}

/// Borrows the string representation of a combined `policy` and returns
/// the equivalent integral representation. This function expects
/// `policy` to comprise one or more policy tokens separated by commas.
///
/// # Examples
///
/// ```
/// # mod zakocmp;
/// let policy: i32 = config::policy_repr_as_int(&"immutable").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// ```
/// # mod zakocmp;
/// // Multiple policies are bitwise OR'd together.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nomodify").unwrap();
/// assert!(policy == config::POLICY_NOADD | config::POLICY_NOMODIFY);
/// ```
///
/// ```
/// # mod zakocmp;
/// // The biggest bitwise OR equals POLICY_IMMUTABLE.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nodelete,nomodify").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// # Failures
///
/// ```
/// # mod zakocmp;
/// // Obi-wan was witty, but not good at dictating zakocmp policy.
/// assert!(!config::policy_repr_as_int(&"hello there!").is_ok());
/// ```
///
pub fn policy_repr_as_int(policy: &str) -> Result<i32, Error> {
    let policy_ints: Vec<i32> = policy
        .split(",")
        .map(|tok| policy_token_as_int(tok))
        .collect::<Result<Vec<i32>, Error>>()?;
    return Ok(policy_ints
        .iter()
        .fold(POLICY_IGNORE, |accum, elem| accum | elem));
}

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

    #[test]
    fn test_bare_noadd() {
        let policy: i32 = match policy_repr_as_int(&"noadd") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD);
    }

    #[test]
    fn test_bare_nodelete() {
        let policy: i32 = match policy_repr_as_int(&"nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NODELETE);
    }

    #[test]
    fn test_bare_nomodify() {
        let policy: i32 = match policy_repr_as_int(&"nomodify") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOMODIFY);
    }

    #[test]
    fn test_combo_policy() {
        let policy: i32 = match policy_repr_as_int(&"noadd,nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }

    #[test]
    fn test_repetitive_policy() {
        let policy: i32 =
            match policy_repr_as_int(&"noadd,noadd,noadd,noadd,nodelete,nodelete,nodelete,noadd") {
                Ok(value) => value,
                Err(oof) => panic!(oof),
            };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }
}
<|endoftext|>