<commit_before>extern crate iron;
extern crate staticfile;
extern crate redis;
extern crate rustc_serialize;
extern crate hyper;
extern crate url;
extern crate time;
extern crate tempdir;
extern crate zip;

#[macro_use]
extern crate router;

// for logging
#[macro_use]
extern crate log;
extern crate env_logger;

use std::fs::create_dir_all;
use std::fs::File;
use std::path::Path;
use std::io::{Read, Cursor, Result as ioResult, Write};
use std::fs;
use std::u8;
use std::env;
use std::process::Command;
use tempdir::TempDir;
use time::now_utc;
use zip::*;

use rustc_serialize::json::Json;

use iron::modifiers::Redirect;
use iron::prelude::*;
use iron::status;
use iron::Url as iUrl;

use url::Url;

use hyper::Client;
use hyper::header;

use staticfile::Static;
use router::Router;

use redis::{Commands, PipelineCommands};

struct ClippyResult {
    failed: bool,
    warnings: u32,
    errors: u32
}

fn update_for_github(user: &str, repo: &str, sha: &str) -> Result<ClippyResult, &'static str> {
    let redis: redis::Connection = setup_redis();
    let github_url = format!("https://github.com/{0}/{1}/archive/{2}.zip",
                             user,
                             repo,
                             sha);
    let log_key =  format!("log/github/{0}/{1}:{2}",
                             user,
                             repo,
                             sha);

    // starting a log file
    if let Ok(existing) = redis::transaction(&redis, &[log_key.clone()], |pipe| {
        match redis.exists(log_key.clone()) {
            Ok(Some(false)) => {
                pipe.cmd("RPUSH")
                        .arg(log_key.clone())
                        .arg(format!("{0} started processing github/{1}/{2}:{3}",
                                            time::now_utc().rfc3339(),
                                            user,
                                            repo,
                                            sha))
                        .ignore()
                        .execute(&redis);
                return Ok(Some(false));
                },
            _ => Ok(Some(true))
        }}) {
        if existing {
            // we have been alerted, the key already existed
            // so someone else is writing a log file. We should stop now.
            return Err("Already running!");
        }
    }

    log_redis(&redis, &log_key, "Creating Temp Directory...");

    if let Ok(tmp_dir) = TempDir::new(&format!("github_{0}_{1}_{2}",
                                                user,
                                                repo,
                                                sha)) {
        log_redis(&redis, &log_key, &format!("Fetching {}", &github_url));

        if let Some(zip_body) = fetch(&Client::new(), &github_url) {
            log_redis(&redis, &log_key, "Extracting archive");
            if let Ok(mut archive) = zip::ZipArchive::new(std::io::Cursor::new(zip_body)) {
                for i in 0..archive.len()
                {
                    let mut zip_file = archive.by_index(i).unwrap();
                    let full_path = tmp_dir.path().join(zip_file.name());
                    let extracted_path = full_path.as_path();
                    let mut writer = File::create(extracted_path).unwrap();
                    let mut buffer: Vec<u8> = vec![];

                    fs::create_dir_all(extracted_path.parent().unwrap()).unwrap();
                    zip_file.read_to_end(&mut buffer).unwrap();
                    writer.write(&buffer).unwrap();
                }

                log_redis(&redis, &log_key, "Running clippy.");

                let output = Command::new("cargo").args(&["rustc", "--", "-Zunstable-options", "-Zextra-plugins=clippy", "-Zno-trans", "-lclippy", "--error-format=json"])
                                      .current_dir(&tmp_dir.path())
                                      .output()
                                      .unwrap_or_else(|e| {
                                          log_redis(&redis, &log_key,
                                                    &format!("Clippy execution failed: {}", &e));
                                          panic!("Failed to execute clippy: {}", e);
                                      });
                Err("Not Yet Implemented")
            } else {
                log_redis(&redis, &log_key, "Extracting archive failed.");
                Err("Extracting archive failed.")
            }
        } else {
            log_redis(&redis, &log_key, "Fetching from github failed!");
            Err("Fetching from github failed!")
        }
    } else {
        log_redis(&redis, &log_key, "Creating Temp Directory failed");
        Err("Creating Temp Directory failed")
    }
}

fn main() {
    // setup logger
    env_logger::init().unwrap();

    let router = router!(
        get "/github/:user/:repo/:branch/badge.svg" => github_handler,
        get "/github/:user/:repo/badge.svg" => github_handler,
        get "/" => Static::new(Path::new("static"))
    );

    warn!("Server running at 8080");
    Iron::new(router).http("0.0.0.0:8080").unwrap();

    fn github_handler(req: &mut Request) -> IronResult<Response> {

        let ref router = req.extensions.get::<Router>().unwrap();
        let user = router.find("user").unwrap();
        let repo = router.find("repo").unwrap();
        let branch = router.find("branch").unwrap_or("master");
        let ext = router.find("ext").unwrap_or("svg");
        let key = format!("badge/github/{}/{}:{}", user, repo, branch);

        let redis: redis::Connection = setup_redis();
        // Create a client.

        if let Some(url) = get_redis_redir(&redis, &key) {
            return redir(&url, &req.url);
        }

        let hyper_client: Client = Client::new();

        let github_url = format!("https://api.github.com/repos/{0}/{1}/git/refs/heads/{2}",
                                 user,
                                 repo,
                                 branch);
        if let Some(body) = fetch(&hyper_client, &github_url) {
            if let Ok(json) = Json::from_str(&body) {
                if let Some(sha) = json.find_path(&["object", "sha"]) {
                    let sha_key = format!("badge/github/{}/{}:{} ", user, repo, sha);

                    if let Some(url) = get_redis_redir(&redis, &sha_key) {
                        set_redis_cache(&redis, &key, &url.clone().serialize());
                        return redir(&url, &req.url);
                    }

                    let linting_url = format!("https://img.shields.io/badge/clippy-linting-blue.\
                                               {}?",
                                              &ext);

                    set_redis_cache(&redis, &sha_key, &linting_url);
                    set_redis_cache(&redis, &key, &linting_url);

                    // let resp = format!("There shall be content here for {}", key);
                    return redir(&Url::parse(&linting_url).unwrap(), &req.url);
                } else {
                    warn!("{}: SHA not found in JSON: {}", &github_url, &json);
                    return Ok(Response::with((status::NotFound,
                                              format!("Couldn't find on github {}", &github_url))));
                }
            } else {
                warn!("{}: Couldn't parse Githubs JSON response: {}",
                      &github_url,
                      &body);
                return Ok(Response::with((status::InternalServerError,
                                          "Couldn't parse Githubs JSON response")));
            }
        } else {
            return Ok(Response::with((status::NotFound,
                                      format!("Couldn't find on github {}", &github_url))));
        }

        Ok(Response::with(status::InternalServerError))
    }
}

fn log_redis(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("RPUSH")
            .arg(key.clone())
            .arg(format!("{0} {1}",
                         time::now_utc().rfc3339(),
                         value))
            .ignore()
        .execute(redis);
}

fn set_redis_cache(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("SET").arg(key.clone()).arg(value).ignore()
        .cmd("EXPIRE").arg(key.clone()).arg(5 * 60).ignore() // we expire in 5min
        .execute(redis);
}

fn redir(url: &Url, source_url: &iUrl) -> IronResult<Response> {
    match iUrl::from_generic_url(url.clone()) {
        Ok(mut redir_url) => {
            if let Some(ref query) = source_url.query {
                redir_url.query = Some(query.clone());
            }
            Ok(Response::with((status::TemporaryRedirect, Redirect(redir_url))))
        }
        Err(err) => Ok(Response::with((status::InternalServerError, err))),
    }
}

fn get_redis_redir(redis: &redis::Connection, key: &str) -> Option<Url> {
    let result: Option<String> = get_redis_value(redis, key);
    if result.is_some() {
        if let Ok(url) = Url::parse(&result.unwrap()) {
            return Some(url);
        }
    }
    return None;
}

fn get_redis_value(redis: &redis::Connection, key: &str) -> Option<String> {

    if let Ok(Some(cached_result)) = redis.get(key) {
        let cached_value: Option<String> = cached_result;
        if cached_value.is_some() {
            return cached_value;
        }
    }

    return None;
}

fn fetch(client: &Client, url: &str) -> Option<String> {
    let res = client.get(url)
                    .header(header::UserAgent("Clippy".to_owned()))
                    .header(header::Connection::close());
    if let Ok(mut res) = res.send() {
        let mut body = String::new();
        if res.read_to_string(&mut body).is_ok() {
            return Some(body);
        }
    }

    return None;
}

fn setup_redis() -> redis::Connection {
    let url = redis::parse_redis_url(&env::var("REDIS_URL")
                                          .unwrap_or("redis://redis/".to_owned()))
                  .unwrap();
    redis::Client::open(url)
        .unwrap()
        .get_connection()
        .unwrap()
}
<commit_msg>background threading<commit_after>extern crate iron;
extern crate staticfile;
extern crate redis;
extern crate rustc_serialize;
extern crate hyper;
extern crate url;
extern crate time;
extern crate tempdir;
extern crate zip;

#[macro_use]
extern crate router;

// for logging
#[macro_use]
extern crate log;
extern crate env_logger;

use std::fs::create_dir_all;
use std::fs::File;
use std::path::Path;
use std::io::{Read, Cursor, Result as ioResult, Write};
use std::fs;
use std::u8;
use std::env;
use std::thread;
use std::sync::mpsc;
use std::process::Command;
use tempdir::TempDir;
use time::now_utc;
use zip::*;

use rustc_serialize::json::Json;

use iron::modifiers::Redirect;
use iron::prelude::*;
use iron::status;
use iron::Url as iUrl;

use url::Url;

use hyper::Client;
use hyper::header;

use staticfile::Static;
use router::Router;

use redis::{Commands, PipelineCommands};

struct ClippyResult {
    failed: bool,
    warnings: u32,
    errors: u32
}

fn update_for_github(user: &str, repo: &str, sha: &str) -> Result<ClippyResult, &'static str> {
    let redis: redis::Connection = setup_redis();
    let github_url = format!("https://github.com/{0}/{1}/archive/{2}.zip",
                             user,
                             repo,
                             sha);
    let log_key =  format!("log/github/{0}/{1}:{2}",
                             user,
                             repo,
                             sha);

    // starting a log file
    if let Ok(existing) = redis::transaction(&redis, &[log_key.clone()], |pipe| {
        match redis.exists(log_key.clone()) {
            Ok(Some(false)) => {
                pipe.cmd("RPUSH")
                        .arg(log_key.clone())
                        .arg(format!("{0} started processing github/{1}/{2}:{3}",
                                            time::now_utc().rfc3339(),
                                            user,
                                            repo,
                                            sha))
                        .ignore()
                        .execute(&redis);
                return Ok(Some(false));
                },
            _ => Ok(Some(true))
        }}) {
        if existing {
            // we have been alerted, the key already existed
            // so someone else is writing a log file. We should stop now.
            return Err("Already running!");
        }
    }

    log_redis(&redis, &log_key, "Creating Temp Directory...");

    if let Ok(tmp_dir) = TempDir::new(&format!("github_{0}_{1}_{2}",
                                                user,
                                                repo,
                                                sha)) {
        log_redis(&redis, &log_key, &format!("Fetching {}", &github_url));

        if let Some(zip_body) = fetch(&Client::new(), &github_url) {
            log_redis(&redis, &log_key, "Extracting archive");
            if let Ok(mut archive) = zip::ZipArchive::new(std::io::Cursor::new(zip_body)) {
                for i in 0..archive.len()
                {
                    let mut zip_file = archive.by_index(i).unwrap();
                    let full_path = tmp_dir.path().join(zip_file.name());
                    let extracted_path = full_path.as_path();
                    let mut writer = File::create(extracted_path).unwrap();
                    let mut buffer: Vec<u8> = vec![];

                    fs::create_dir_all(extracted_path.parent().unwrap()).unwrap();
                    zip_file.read_to_end(&mut buffer).unwrap();
                    writer.write(&buffer).unwrap();
                }

                log_redis(&redis, &log_key, "Running clippy.");

                let output = Command::new("cargo").args(&["rustc", "--", "-Zunstable-options", "-Zextra-plugins=clippy", "-Zno-trans", "-lclippy", "--error-format=json"])
                                      .current_dir(&tmp_dir.path())
                                      .output()
                                      .unwrap_or_else(|e| {
                                          log_redis(&redis, &log_key,
                                                    &format!("Clippy execution failed: {}", &e));
                                          panic!("Failed to execute clippy: {}", e);
                                      });
                Err("Not Yet Implemented")
            } else {
                log_redis(&redis, &log_key, "Extracting archive failed.");
                Err("Extracting archive failed.")
            }
        } else {
            log_redis(&redis, &log_key, "Fetching from github failed!");
            Err("Fetching from github failed!")
        }
    } else {
        log_redis(&redis, &log_key, "Creating Temp Directory failed");
        Err("Creating Temp Directory failed")
    }
}

fn main() {
    // setup logger
    env_logger::init().unwrap();

    let router = router!(
        get "/github/:user/:repo/:branch/badge.svg" => github_handler,
        get "/github/:user/:repo/badge.svg" => github_handler,
        get "/" => Static::new(Path::new("static"))
    );

    warn!("Server running at 8080");
    Iron::new(router).http("0.0.0.0:8080").unwrap();

    fn github_handler(req: &mut Request) -> IronResult<Response> {

        let ref router = req.extensions.get::<Router>().unwrap();
        let redis: redis::Connection = setup_redis();

        let user = router.find("user").unwrap();
        let repo = router.find("repo").unwrap();
        let branch = router.find("branch").unwrap_or("master");
        let ext = router.find("ext").unwrap_or("svg");
        let key = format!("badge/github/{}/{}:{}", user, repo, branch);

        // Create a client.

        if let Some(url) = get_redis_redir(&redis, &key) {
            return redir(&url, &req.url);
        }

        let hyper_client: Client = Client::new();

        let github_url = format!("https://api.github.com/repos/{0}/{1}/git/refs/heads/{2}",
                                 user,
                                 repo,
                                 branch);
        if let Some(body) = fetch(&hyper_client, &github_url) {
            if let Ok(json) = Json::from_str(&body) {
                if let Some(sha) = json.find_path(&["object", "sha"]) {
                    let sha_key = format!("badge/github/{}/{}:{} ", user, repo, sha);

                    if let Some(url) = get_redis_redir(&redis, &sha_key) {
                        set_redis_cache(&redis, &key, &url.clone().serialize());
                        return redir(&url, &req.url);
                    }

                    let linting_url = format!("https://img.shields.io/badge/clippy-linting-blue.\
                                               {}?",
                                              &ext);

                    set_redis_cache(&redis, &sha_key, &linting_url);
                    set_redis_cache(&redis, &key, &linting_url);

                    let user = user.to_owned();
                    let repo =repo.to_owned();
                    let sha = sha.to_string().to_owned();
                    thread::spawn(move || {
                        update_for_github(&user, &repo, &sha);
                    });

                    // let resp = format!("There shall be content here for {}", key);
                    return redir(&Url::parse(&linting_url).unwrap(), &req.url);
                } else {
                    warn!("{}: SHA not found in JSON: {}", &github_url, &json);
                    return Ok(Response::with((status::NotFound,
                                              format!("Couldn't find on github {}", &github_url))));
                }
            } else {
                warn!("{}: Couldn't parse Githubs JSON response: {}",
                      &github_url,
                      &body);
                return Ok(Response::with((status::InternalServerError,
                                          "Couldn't parse Githubs JSON response")));
            }
        } else {
            return Ok(Response::with((status::NotFound,
                                      format!("Couldn't find on github {}", &github_url))));
        }

        Ok(Response::with(status::InternalServerError))
    }
}

fn log_redis(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("RPUSH")
            .arg(key.clone())
            .arg(format!("{0} {1}",
                         time::now_utc().rfc3339(),
                         value))
            .ignore()
        .execute(redis);
}

fn set_redis_cache(redis: &redis::Connection, key: &str, value: &str) {
    redis::pipe()
        .cmd("SET").arg(key.clone()).arg(value).ignore()
        .cmd("EXPIRE").arg(key.clone()).arg(5 * 60).ignore() // we expire in 5min
        .execute(redis);
}

fn redir(url: &Url, source_url: &iUrl) -> IronResult<Response> {
    match iUrl::from_generic_url(url.clone()) {
        Ok(mut redir_url) => {
            if let Some(ref query) = source_url.query {
                redir_url.query = Some(query.clone());
            }
            Ok(Response::with((status::TemporaryRedirect, Redirect(redir_url))))
        }
        Err(err) => Ok(Response::with((status::InternalServerError, err))),
    }
}

fn get_redis_redir(redis: &redis::Connection, key: &str) -> Option<Url> {
    let result: Option<String> = get_redis_value(redis, key);
    if result.is_some() {
        if let Ok(url) = Url::parse(&result.unwrap()) {
            return Some(url);
        }
    }
    return None;
}

fn get_redis_value(redis: &redis::Connection, key: &str) -> Option<String> {

    if let Ok(Some(cached_result)) = redis.get(key) {
        let cached_value: Option<String> = cached_result;
        if cached_value.is_some() {
            return cached_value;
        }
    }

    return None;
}

fn fetch(client: &Client, url: &str) -> Option<String> {
    let res = client.get(url)
                    .header(header::UserAgent("Clippy".to_owned()))
                    .header(header::Connection::close());
    if let Ok(mut res) = res.send() {
        let mut body = String::new();
        if res.read_to_string(&mut body).is_ok() {
            return Some(body);
        }
    }

    return None;
}

fn setup_redis() -> redis::Connection {
    let url = redis::parse_redis_url(&env::var("REDIS_URL")
                                          .unwrap_or("redis://redis/".to_owned()))
                  .unwrap();
    redis::Client::open(url)
        .unwrap()
        .get_connection()
        .unwrap()
}
<|endoftext|>


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

use dbus;
use dbus::Message;
use dbus::MessageItem;
use dbus::arg::IterAppend;
use dbus::tree::Access;
use dbus::tree::EmitsChangedSignal;
use dbus::tree::Factory;
use dbus::tree::MTFn;
use dbus::tree::MethodErr;
use dbus::tree::MethodInfo;
use dbus::tree::MethodResult;
use dbus::tree::PropInfo;

use engine::RenameAction;

use super::types::{DbusContext, DbusErrorEnum, TData};

use super::util::STRATIS_BASE_PATH;
use super::util::STRATIS_BASE_SERVICE;
use super::util::code_to_message_items;
use super::util::default_object_path;
use super::util::engine_to_dbus_err;
use super::util::fs_object_path_to_pair;
use super::util::get_next_arg;
use super::util::ok_message_items;
use super::util::pool_object_path_to_pair;

pub fn create_dbus_filesystem<'a>(dbus_context: &DbusContext) -> dbus::Path<'a> {
    let f = Factory::new_fn();

    let create_snapshot_method = f.method("CreateSnapshot", (), create_snapshot)
        .in_arg(("name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let rename_method = f.method("SetName", (), rename_filesystem)
        .in_arg(("name", "s"))
        .out_arg(("action", "b"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let name_property = f.property::<&str, _>("Name", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::False)
        .on_get(get_filesystem_name);

    let uuid_property = f.property::<&str, _>("Uuid", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_filesystem_uuid);

    let object_name = format!("{}/{}",
                              STRATIS_BASE_PATH,
                              dbus_context.get_next_id().to_string());

    let interface_name = format!("{}.{}", STRATIS_BASE_SERVICE, "filesystem");

    let object_path = f.object_path(object_name, ())
        .introspectable()
        .add(f.interface(interface_name, ())
            .add_m(create_snapshot_method)
            .add_m(rename_method)
            .add_p(name_property)
            .add_p(uuid_property));

    let path = object_path.get_name().to_owned();
    dbus_context.actions.borrow_mut().push_add(object_path);
    path
}

fn create_snapshot(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message = m.msg;
    let mut iter = message.iter_init();
    let snapshot_name: &str = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let object_path = m.path.get_name();
    let return_message = message.method_return();
    let default_return = MessageItem::ObjectPath(default_object_path());

    let (pool_object_path, fs_uuid) = dbus_try!(fs_object_path_to_pair(dbus_context, object_path);
                                         default_return; return_message);

    let (_, pool_uuid) = dbus_try!(pool_object_path_to_pair(dbus_context, &pool_object_path);
                                   default_return; return_message);

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = get_pool!(engine; pool_uuid; default_return; return_message);

    let msg = match pool.create_snapshot(snapshot_name, &fs_uuid) {
        Ok(sn_uuid) => {
            let fs_object_path = create_dbus_filesystem(dbus_context);
            dbus_context.filesystems
                .borrow_mut()
                .insert(fs_object_path.clone(), (pool_object_path, sn_uuid));
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::ObjectPath(fs_object_path), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };
    Ok(vec![msg])
}

fn rename_filesystem(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let new_name: &str = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let object_path = m.path.get_name();
    let return_message = message.method_return();
    let default_return = MessageItem::Bool(false);

    let (pool_object_path, filesystem_uuid) =
        dbus_try!(fs_object_path_to_pair(dbus_context, object_path);
                                         default_return; return_message);

    let (_, pool_uuid) = dbus_try!(pool_object_path_to_pair(dbus_context, &pool_object_path);
                                   default_return; return_message);

    let mut b_engine = dbus_context.engine.borrow_mut();
    let ref mut pool = get_pool!(b_engine; pool_uuid; default_return; return_message);

    let result = pool.rename_filesystem(&filesystem_uuid, &new_name);

    let msg = match result {
        Ok(RenameAction::NoSource) => {
            let error_message = format!("engine doesn't know about filesystem {} on pool {}",
                                        filesystem_uuid,
                                        pool_uuid);
            let (rc, rs) = code_to_message_items(DbusErrorEnum::INTERNAL_ERROR, error_message);
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Identity) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Renamed) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::Bool(true), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };

    Ok(vec![msg])
}

fn get_filesystem_uuid(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();
    i.append(try!(dbus_context.filesystems
        .borrow()
        .get(object_path)
        .map(|x| MessageItem::Str(format!("{}", x.1.simple())))
        .ok_or(MethodErr::failed(&format!("no uuid for filesystem with object path {}",
                                          object_path)))));
    Ok(())
}

fn get_filesystem_name(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();
    let (pool_object_path, uuid) = try!(dbus_context.filesystems
        .borrow()
        .get(object_path)
        .map(|x| x.clone())
        .ok_or(MethodErr::failed(&format!("no uuid for filesystem with object path {}",
                                          object_path))));

    let &(_, pool_uuid) = try!(dbus_context.pools
        .borrow()
        .get(&pool_object_path)
        .ok_or(MethodErr::failed(&format!("no pool uuid for filesystem with object path {}",
                                          object_path))));

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = try!(engine.get_pool(&pool_uuid)
        .ok_or(MethodErr::failed(&format!("no pool corresponding to uuid {}", &pool_uuid))));

    i.append(try!(pool.get_filesystem(&uuid)
        .map(|x| MessageItem::Str(x.name().to_owned()))
        .ok_or(MethodErr::failed(&format!("no name for filesystem with uuid {}", &uuid)))));
    Ok(())
}
<commit_msg>Add a Pool property to filesystem interface<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use dbus;
use dbus::Message;
use dbus::MessageItem;
use dbus::arg::IterAppend;
use dbus::tree::Access;
use dbus::tree::EmitsChangedSignal;
use dbus::tree::Factory;
use dbus::tree::MTFn;
use dbus::tree::MethodErr;
use dbus::tree::MethodInfo;
use dbus::tree::MethodResult;
use dbus::tree::PropInfo;

use engine::RenameAction;

use super::types::{DbusContext, DbusErrorEnum, TData};

use super::util::STRATIS_BASE_PATH;
use super::util::STRATIS_BASE_SERVICE;
use super::util::code_to_message_items;
use super::util::default_object_path;
use super::util::engine_to_dbus_err;
use super::util::fs_object_path_to_pair;
use super::util::get_next_arg;
use super::util::ok_message_items;
use super::util::pool_object_path_to_pair;

pub fn create_dbus_filesystem<'a>(dbus_context: &DbusContext) -> dbus::Path<'a> {
    let f = Factory::new_fn();

    let create_snapshot_method = f.method("CreateSnapshot", (), create_snapshot)
        .in_arg(("name", "s"))
        .out_arg(("object_path", "o"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let rename_method = f.method("SetName", (), rename_filesystem)
        .in_arg(("name", "s"))
        .out_arg(("action", "b"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let name_property = f.property::<&str, _>("Name", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::False)
        .on_get(get_filesystem_name);

    let pool_property = f.property::<&dbus::Path, _>("Pool", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_filesystem_pool);

    let uuid_property = f.property::<&str, _>("Uuid", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_filesystem_uuid);

    let object_name = format!("{}/{}",
                              STRATIS_BASE_PATH,
                              dbus_context.get_next_id().to_string());

    let interface_name = format!("{}.{}", STRATIS_BASE_SERVICE, "filesystem");

    let object_path = f.object_path(object_name, ())
        .introspectable()
        .add(f.interface(interface_name, ())
            .add_m(create_snapshot_method)
            .add_m(rename_method)
            .add_p(name_property)
            .add_p(pool_property)
            .add_p(uuid_property));

    let path = object_path.get_name().to_owned();
    dbus_context.actions.borrow_mut().push_add(object_path);
    path
}

fn create_snapshot(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message = m.msg;
    let mut iter = message.iter_init();
    let snapshot_name: &str = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let object_path = m.path.get_name();
    let return_message = message.method_return();
    let default_return = MessageItem::ObjectPath(default_object_path());

    let (pool_object_path, fs_uuid) = dbus_try!(fs_object_path_to_pair(dbus_context, object_path);
                                         default_return; return_message);

    let (_, pool_uuid) = dbus_try!(pool_object_path_to_pair(dbus_context, &pool_object_path);
                                   default_return; return_message);

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = get_pool!(engine; pool_uuid; default_return; return_message);

    let msg = match pool.create_snapshot(snapshot_name, &fs_uuid) {
        Ok(sn_uuid) => {
            let fs_object_path = create_dbus_filesystem(dbus_context);
            dbus_context.filesystems
                .borrow_mut()
                .insert(fs_object_path.clone(), (pool_object_path, sn_uuid));
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::ObjectPath(fs_object_path), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };
    Ok(vec![msg])
}

fn rename_filesystem(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let new_name: &str = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let object_path = m.path.get_name();
    let return_message = message.method_return();
    let default_return = MessageItem::Bool(false);

    let (pool_object_path, filesystem_uuid) =
        dbus_try!(fs_object_path_to_pair(dbus_context, object_path);
                                         default_return; return_message);

    let (_, pool_uuid) = dbus_try!(pool_object_path_to_pair(dbus_context, &pool_object_path);
                                   default_return; return_message);

    let mut b_engine = dbus_context.engine.borrow_mut();
    let ref mut pool = get_pool!(b_engine; pool_uuid; default_return; return_message);

    let result = pool.rename_filesystem(&filesystem_uuid, &new_name);

    let msg = match result {
        Ok(RenameAction::NoSource) => {
            let error_message = format!("engine doesn't know about filesystem {} on pool {}",
                                        filesystem_uuid,
                                        pool_uuid);
            let (rc, rs) = code_to_message_items(DbusErrorEnum::INTERNAL_ERROR, error_message);
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Identity) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(default_return, rc, rs)
        }
        Ok(RenameAction::Renamed) => {
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::Bool(true), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };

    Ok(vec![msg])
}

fn get_filesystem_uuid(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();
    i.append(try!(dbus_context.filesystems
        .borrow()
        .get(object_path)
        .map(|x| MessageItem::Str(format!("{}", x.1.simple())))
        .ok_or(MethodErr::failed(&format!("no uuid for filesystem with object path {}",
                                          object_path)))));
    Ok(())
}

fn get_filesystem_name(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();
    let (pool_object_path, uuid) = try!(dbus_context.filesystems
        .borrow()
        .get(object_path)
        .map(|x| x.clone())
        .ok_or(MethodErr::failed(&format!("no uuid for filesystem with object path {}",
                                          object_path))));

    let &(_, pool_uuid) = try!(dbus_context.pools
        .borrow()
        .get(&pool_object_path)
        .ok_or(MethodErr::failed(&format!("no pool uuid for filesystem with object path {}",
                                          object_path))));

    let mut engine = dbus_context.engine.borrow_mut();
    let pool = try!(engine.get_pool(&pool_uuid)
        .ok_or(MethodErr::failed(&format!("no pool corresponding to uuid {}", &pool_uuid))));

    i.append(try!(pool.get_filesystem(&uuid)
        .map(|x| MessageItem::Str(x.name().to_owned()))
        .ok_or(MethodErr::failed(&format!("no name for filesystem with uuid {}", &uuid)))));
    Ok(())
}

fn get_filesystem_pool(i: &mut IterAppend,
                       p: &PropInfo<MTFn<TData>, TData>)
                       -> Result<(), MethodErr> {
    let dbus_context = p.tree.get_data();
    let object_path = p.path.get_name();
    i.append(try!(dbus_context.filesystems
        .borrow()
        .get(object_path)
        .map(|x| MessageItem::ObjectPath(x.0.clone()))
        .ok_or(MethodErr::failed(&format!("no pool object path for filesystem object path {}",
                                          object_path)))));

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

enum Sexpression {
    Num(()),
    Cons(&'static mut Sexpression)
}

fn causes_ice(mut l: &mut Sexpression) {
    loop { match l {
        &mut Sexpression::Num(ref mut n) => {},
        &mut Sexpression::Cons(ref mut expr) => { //~ ERROR cannot borrow `l.0` as mutable more than once at a time [E0499]
            //~| ERROR cannot borrow `l.0` as mutable more than once at a time [E0499]
            l = &mut **expr; //~ ERROR cannot assign to `l` because it is borrowed [E0506]
        }
    }}
}

fn main() {
}<commit_msg>Resolving line length build fail<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

enum Sexpression {
    Num(()),
    Cons(&'static mut Sexpression)
}

fn causes_ice(mut l: &mut Sexpression) {
    loop { match l {
        &mut Sexpression::Num(ref mut n) => {},
        &mut Sexpression::Cons(ref mut expr) => { //~ ERROR cannot borrow `l.0`
            //~| ERROR cannot borrow `l.0`
            l = &mut **expr; //~ ERROR cannot assign to `l`
        }
    }}
}

fn main() {
}
<|endoftext|>


<commit_before>// run-pass

#![allow(unused_must_use)]
#![feature(unwind_attributes)]
// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
// we never unwind through them.

// ignore-emscripten no processes
// ignore-sgx no processes

use std::{env, panic};
use std::io::prelude::*;
use std::io;
use std::process::{Command, Stdio};

#[unwind(aborts)] // FIXME(#58794) should work even without the attribute
extern "C" fn panic_in_ffi() {
    panic!("Test");
}

#[unwind(aborts)]
extern "Rust" fn panic_in_rust_abi() {
    panic!("TestRust");
}

fn should_have_aborted() {
    io::stdout().write(b"This should never be printed.\n");
    let _ = io::stdout().flush();
}

fn bomb_out_but_not_abort(msg: &str) {
    eprintln!("bombing out: {}", msg);
    exit(1);
}

fn test() {
    let _ = panic::catch_unwind(|| { panic_in_ffi(); });
    should_have_aborted();
}

fn testrust() {
    let _ = panic::catch_unwind(|| { panic_in_rust_abi(); });
    should_have_aborted();
}

fn main() {
    let tests: &[(_, fn())] = &[
        ("test", test),
        ("testrust", testrust),
    ];

    let args: Vec<String> = env::args().collect();
    if args.len() > 1 {
        // This is inside the self-executed command.
        for (a,f) in tests {
            if &args[1] == a { return f() }
        }
        bomb_out_but_not_abort("bad test");
    }

    let execute_self_expecting_abort = |arg| {
        let mut p = Command::new(&args[0])
                            .stdout(Stdio::piped())
                            .stdin(Stdio::piped())
                            .arg(arg).spawn().unwrap();
        let status = p.wait().unwrap();
        assert!(!status.success());
        // Any reasonable platform can distinguish a process which
        // called exit(1) from one which panicked.
        assert_ne!(status.code(), Some(1));
    };

    for (a,_f) in tests {
        execute_self_expecting_abort(a);
    }
}
<commit_msg>panic ui test: Add a test for panic::always_abort<commit_after>// run-pass

#![allow(unused_must_use)]
#![feature(unwind_attributes)]
// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
// we never unwind through them.

// ignore-emscripten no processes
// ignore-sgx no processes

use std::{env, panic};
use std::io::prelude::*;
use std::io;
use std::process::{Command, Stdio};

#[unwind(aborts)] // FIXME(#58794) should work even without the attribute
extern "C" fn panic_in_ffi() {
    panic!("Test");
}

#[unwind(aborts)]
extern "Rust" fn panic_in_rust_abi() {
    panic!("TestRust");
}

fn should_have_aborted() {
    io::stdout().write(b"This should never be printed.\n");
    let _ = io::stdout().flush();
}

fn bomb_out_but_not_abort(msg: &str) {
    eprintln!("bombing out: {}", msg);
    exit(1);
}

fn test() {
    let _ = panic::catch_unwind(|| { panic_in_ffi(); });
    should_have_aborted();
}

fn testrust() {
    let _ = panic::catch_unwind(|| { panic_in_rust_abi(); });
    should_have_aborted();
}

fn test_always_abort() {
    panic::always_abort();
    let _ = panic::catch_unwind(|| { panic!(); });
    should_have_aborted();
}

fn main() {
    let tests: &[(_, fn())] = &[
        ("test", test),
        ("testrust", testrust),
        ("test_always_abort", test_always_abort),
    ];

    let args: Vec<String> = env::args().collect();
    if args.len() > 1 {
        // This is inside the self-executed command.
        for (a,f) in tests {
            if &args[1] == a { return f() }
        }
        bomb_out_but_not_abort("bad test");
    }

    let execute_self_expecting_abort = |arg| {
        let mut p = Command::new(&args[0])
                            .stdout(Stdio::piped())
                            .stdin(Stdio::piped())
                            .arg(arg).spawn().unwrap();
        let status = p.wait().unwrap();
        assert!(!status.success());
        // Any reasonable platform can distinguish a process which
        // called exit(1) from one which panicked.
        assert_ne!(status.code(), Some(1));
    };

    for (a,_f) in tests {
        execute_self_expecting_abort(a);
    }
}
<|endoftext|>


<commit_before>use std::path::{Path};

use super::ffi;
use {SqliteError, SqliteResult, SqliteConnection};

impl SqliteConnection {
    /// Open or create a database file named `dest_path`.  Transfer the
    /// content of local database `name` into the `dest_path` database.
    pub fn backup<P: AsRef<Path>>(&self, name: &str, dest_path: &P) -> SqliteResult<()> {
        let dest = try!(SqliteConnection::open(dest_path)); // "cannot open target database: "

        let mut dest_db = dest.db.borrow_mut();
        let dest_name = try!(super::str_to_cstring("main"));
        let src_db = self.db.borrow_mut();
        let src_name = try!(super::str_to_cstring(name));
        let backup = unsafe { ffi::sqlite3_backup_init(dest_db.db(), dest_name.as_ptr(), src_db.db(), src_name.as_ptr()) };
        if backup.is_null() {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            let err = Err(SqliteError{code: unsafe { ffi::sqlite3_errcode(dest_db.db()) }, message: "backup failed: ".to_string() + &msg });
            let _ = dest_db.close();
            return err;
        }

        let mut rc;
        loop {
            rc = unsafe { ffi::sqlite3_backup_step(backup, 100) };
            if rc != ffi::SQLITE_OK {
                break;
            }
        }
        unsafe { ffi::sqlite3_backup_finish(backup) };
        let result = if rc == ffi::SQLITE_DONE {
            Ok(())
        } else {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            Err(SqliteError{code: rc, message: "backup failed: ".to_string() + &msg })
        };
        let _ = dest_db.close();
        result
    }

    /// Open a database file named `src_path`.  Transfer the content
    /// of `src_path` into the local database `name`.
    pub fn restore<P: AsRef<Path>>(&self, name: &str, src_path: &P) -> SqliteResult<()> {
        let src = try!(SqliteConnection::open_with_flags(src_path, super::SQLITE_OPEN_READ_ONLY | super::SQLITE_OPEN_URI)); // "cannot open source database: "

        let dest_db = self.db.borrow_mut();
        let dest_name = try!(super::str_to_cstring(name));
        let mut src_db = src.db.borrow_mut();
        let src_name = try!(super::str_to_cstring("main"));
        let backup = unsafe { ffi::sqlite3_backup_init(dest_db.db(), dest_name.as_ptr(), src_db.db(), src_name.as_ptr()) };
        if backup.is_null() {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            let err = Err(SqliteError{code: unsafe { ffi::sqlite3_errcode(dest_db.db()) }, message: "restore failed: ".to_string() + &msg });
            let _ = src_db.close();
            return err;
        }
        let mut rc;
        let mut n_timeout = 0;
        loop {
            rc = unsafe { ffi::sqlite3_backup_step(backup, 100) };
            if rc == ffi::SQLITE_OK {
            } else if rc == ffi::SQLITE_BUSY {
                n_timeout += 1;
                if n_timeout >= 3 {
                    break;
                }
                unsafe { ffi::sqlite3_sleep(100) };
            } else {
                break;
            }
        }
        unsafe { ffi::sqlite3_backup_finish(backup) };
        let result = if rc == ffi::SQLITE_DONE {
            Ok(())
        } else if rc == ffi::SQLITE_BUSY || rc == ffi::SQLITE_LOCKED {
            Err(SqliteError{code: rc, message: "restore failed: source database busy".to_string() })
        } else {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            Err(SqliteError{code: rc, message: "restore failed: ".to_string() + &msg })
        };
        let _ = src_db.close();
        result
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;
    use {SQLITE_OPEN_URI, SQLITE_OPEN_CREATE, SQLITE_OPEN_READ_WRITE};

    #[test]
    fn test_backup() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                CREATE TABLE foo(x INTEGER);
                INSERT INTO foo VALUES(42);
                END;";
        db.execute_batch(sql).unwrap();
        db.backup("main", &":memory:").unwrap();
        assert!(db.close().is_ok());
    }

    #[test]
    fn test_restore() {
        let src_path = "file:dummy.db?mode=memory&cache=shared";
        let src = SqliteConnection::open_with_flags(&src_path, SQLITE_OPEN_URI | SQLITE_OPEN_CREATE | SQLITE_OPEN_READ_WRITE).unwrap();
        let sql = "BEGIN;
               CREATE TABLE foo(x INTEGER);
               INSERT INTO foo VALUES(42);
               END;";
        src.execute_batch(sql).unwrap();

        let db = SqliteConnection::open_in_memory().unwrap();
        db.restore("main", &src_path).unwrap();

        let the_answer = db.query_row("SELECT x FROM foo",
                                           &[],
                                           |r| r.get::<i64>(0));
        assert_eq!(42i64, the_answer.unwrap());

        assert!(db.close().is_ok());
        assert!(src.close().is_ok());
    }
}
<commit_msg>Add module documentation<commit_after>//! Online backup API
use std::path::{Path};

use super::ffi;
use {SqliteError, SqliteResult, SqliteConnection};

impl SqliteConnection {
    /// Open or create a database file named `dest_path`.  Transfer the
    /// content of local database `name` into the `dest_path` database.
    pub fn backup<P: AsRef<Path>>(&self, name: &str, dest_path: &P) -> SqliteResult<()> {
        let dest = try!(SqliteConnection::open(dest_path)); // "cannot open target database: "

        let mut dest_db = dest.db.borrow_mut();
        let dest_name = try!(super::str_to_cstring("main"));
        let src_db = self.db.borrow_mut();
        let src_name = try!(super::str_to_cstring(name));
        let backup = unsafe { ffi::sqlite3_backup_init(dest_db.db(), dest_name.as_ptr(), src_db.db(), src_name.as_ptr()) };
        if backup.is_null() {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            let err = Err(SqliteError{code: unsafe { ffi::sqlite3_errcode(dest_db.db()) }, message: "backup failed: ".to_string() + &msg });
            let _ = dest_db.close();
            return err;
        }

        let mut rc;
        loop {
            rc = unsafe { ffi::sqlite3_backup_step(backup, 100) };
            if rc != ffi::SQLITE_OK {
                break;
            }
        }
        unsafe { ffi::sqlite3_backup_finish(backup) };
        let result = if rc == ffi::SQLITE_DONE {
            Ok(())
        } else {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            Err(SqliteError{code: rc, message: "backup failed: ".to_string() + &msg })
        };
        let _ = dest_db.close();
        result
    }

    /// Open a database file named `src_path`.  Transfer the content
    /// of `src_path` into the local database `name`.
    pub fn restore<P: AsRef<Path>>(&self, name: &str, src_path: &P) -> SqliteResult<()> {
        let src = try!(SqliteConnection::open_with_flags(src_path, super::SQLITE_OPEN_READ_ONLY | super::SQLITE_OPEN_URI)); // "cannot open source database: "

        let dest_db = self.db.borrow_mut();
        let dest_name = try!(super::str_to_cstring(name));
        let mut src_db = src.db.borrow_mut();
        let src_name = try!(super::str_to_cstring("main"));
        let backup = unsafe { ffi::sqlite3_backup_init(dest_db.db(), dest_name.as_ptr(), src_db.db(), src_name.as_ptr()) };
        if backup.is_null() {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            let err = Err(SqliteError{code: unsafe { ffi::sqlite3_errcode(dest_db.db()) }, message: "restore failed: ".to_string() + &msg });
            let _ = src_db.close();
            return err;
        }
        let mut rc;
        let mut n_timeout = 0;
        loop {
            rc = unsafe { ffi::sqlite3_backup_step(backup, 100) };
            if rc == ffi::SQLITE_OK {
            } else if rc == ffi::SQLITE_BUSY {
                n_timeout += 1;
                if n_timeout >= 3 {
                    break;
                }
                unsafe { ffi::sqlite3_sleep(100) };
            } else {
                break;
            }
        }
        unsafe { ffi::sqlite3_backup_finish(backup) };
        let result = if rc == ffi::SQLITE_DONE {
            Ok(())
        } else if rc == ffi::SQLITE_BUSY || rc == ffi::SQLITE_LOCKED {
            Err(SqliteError{code: rc, message: "restore failed: source database busy".to_string() })
        } else {
            let msg = unsafe { super::errmsg_to_string(ffi::sqlite3_errmsg(dest_db.db())) };
            Err(SqliteError{code: rc, message: "restore failed: ".to_string() + &msg })
        };
        let _ = src_db.close();
        result
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;
    use {SQLITE_OPEN_URI, SQLITE_OPEN_CREATE, SQLITE_OPEN_READ_WRITE};

    #[test]
    fn test_backup() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                CREATE TABLE foo(x INTEGER);
                INSERT INTO foo VALUES(42);
                END;";
        db.execute_batch(sql).unwrap();
        db.backup("main", &":memory:").unwrap();
        assert!(db.close().is_ok());
    }

    #[test]
    fn test_restore() {
        let src_path = "file:dummy.db?mode=memory&cache=shared";
        let src = SqliteConnection::open_with_flags(&src_path, SQLITE_OPEN_URI | SQLITE_OPEN_CREATE | SQLITE_OPEN_READ_WRITE).unwrap();
        let sql = "BEGIN;
               CREATE TABLE foo(x INTEGER);
               INSERT INTO foo VALUES(42);
               END;";
        src.execute_batch(sql).unwrap();

        let db = SqliteConnection::open_in_memory().unwrap();
        db.restore("main", &src_path).unwrap();

        let the_answer = db.query_row("SELECT x FROM foo",
                                           &[],
                                           |r| r.get::<i64>(0));
        assert_eq!(42i64, the_answer.unwrap());

        assert!(db.close().is_ok());
        assert!(src.close().is_ok());
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

#![allow(clippy::too_many_arguments)]

use std::fs::File;
use std::io::Read;

use ProcessorExt;

/// Struct containing values to compute a CPU usage.
#[derive(Clone, Copy)]
pub struct CpuValues {
    user: u64,
    nice: u64,
    system: u64,
    idle: u64,
    iowait: u64,
    irq: u64,
    softirq: u64,
    steal: u64,
    guest: u64,
    guest_nice: u64,
}

impl CpuValues {
    /// Creates a new instance of `CpuValues` with everything set to `0`.
    pub fn new() -> CpuValues {
        CpuValues {
            user: 0,
            nice: 0,
            system: 0,
            idle: 0,
            iowait: 0,
            irq: 0,
            softirq: 0,
            steal: 0,
            guest: 0,
            guest_nice: 0,
        }
    }

    /// Creates a new instance of `CpuValues` with everything set to the corresponding argument.
    pub fn new_with_values(
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    ) -> CpuValues {
        CpuValues {
            user,
            nice,
            system,
            idle,
            iowait,
            irq,
            softirq,
            steal,
            guest,
            guest_nice,
        }
    }

    /*pub fn is_zero(&self) -> bool {
        self.user == 0 && self.nice == 0 && self.system == 0 && self.idle == 0 &&
        self.iowait == 0 && self.irq == 0 && self.softirq == 0 && self.steal == 0 &&
        self.guest == 0 && self.guest_nice == 0
    }*/

    /// Sets the given argument to the corresponding fields.
    pub fn set(
        &mut self,
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    ) {
        self.user = user;
        self.nice = nice;
        self.system = system;
        self.idle = idle;
        self.iowait = iowait;
        self.irq = irq;
        self.softirq = softirq;
        self.steal = steal;
        self.guest = guest;
        self.guest_nice = guest_nice;
    }

    /// Returns work time.
    pub fn work_time(&self) -> u64 {
        self.user + self.nice + self.system
    }

    /// Returns total time.
    pub fn total_time(&self) -> u64 {
        self.work_time()
            + self.idle
            + self.iowait
            + self.irq
            + self.softirq
            + self.steal
            + self.guest
            + self.guest_nice
    }
}

/// Struct containing a processor information.
pub struct Processor {
    old_values: CpuValues,
    new_values: CpuValues,
    pub(crate) name: String,
    cpu_usage: f32,
    total_time: u64,
    old_total_time: u64,
    frequency: u64,
    pub(crate) vendor_id: String,
    pub(crate) brand: String,
}

impl Processor {
    pub(crate) fn new_with_values(
        name: &str,
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
        frequency: u64,
        vendor_id: String,
        brand: String,
    ) -> Processor {
        Processor {
            name: name.to_owned(),
            old_values: CpuValues::new(),
            new_values: CpuValues::new_with_values(
                user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
            ),
            cpu_usage: 0f32,
            total_time: 0,
            old_total_time: 0,
            frequency,
            vendor_id,
            brand,
        }
    }

    pub(crate) fn set(
        &mut self,
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    ) {
        fn min(a: u64, b: u64) -> f32 {
            (if a == b {
                1
            } else if a > b {
                a - b
            } else {
                b - a
            }) as f32
        }
        //if !self.new_values.is_zero() {
        self.old_values = self.new_values;
        //}
        self.new_values.set(
            user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
        );
        self.cpu_usage = min(self.new_values.work_time(), self.old_values.work_time())
            / min(self.new_values.total_time(), self.old_values.total_time())
            * 100.;
        self.old_total_time = self.old_values.total_time();
        self.total_time = self.new_values.total_time();
    }
}

impl ProcessorExt for Processor {
    fn get_cpu_usage(&self) -> f32 {
        self.cpu_usage
    }

    fn get_name(&self) -> &str {
        &self.name
    }

    /// Returns the CPU frequency in MHz.
    fn get_frequency(&self) -> u64 {
        self.frequency
    }

    fn get_vendor_id(&self) -> &str {
        &self.vendor_id
    }

    fn get_brand(&self) -> &str {
        &self.brand
    }
}

pub fn get_raw_times(p: &Processor) -> (u64, u64) {
    (p.new_values.total_time(), p.old_values.total_time())
}

pub fn get_cpu_frequency() -> u64 {
    // /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
    let mut s = String::new();
    if File::open("/proc/cpuinfo")
        .and_then(|mut f| f.read_to_string(&mut s))
        .is_err()
    {
        return 0;
    }

    let find_cpu_mhz = s.split('\n').find(|line| {
        line.starts_with("cpu MHz\t")
            || line.starts_with("BogoMIPS")
            || line.starts_with("clock\t")
            || line.starts_with("bogomips per cpu")
    });

    find_cpu_mhz
        .and_then(|line| line.split(':').last())
        .and_then(|val| val.replace("MHz", "").trim().parse::<f64>().ok())
        .map(|speed| speed as u64)
        .unwrap_or_default()
}

/// Returns the brand/vendor string for the first CPU (which should be the same for all CPUs).
pub fn get_vendor_id_and_brand() -> (String, String) {
    let mut s = String::new();
    if File::open("/proc/cpuinfo")
        .and_then(|mut f| f.read_to_string(&mut s))
        .is_err()
    {
        return (String::new(), String::new());
    }

    fn get_value(s: &str) -> String {
        s.split(':')
            .last()
            .map(|x| x.trim().to_owned())
            .unwrap_or_default()
    }

    let mut vendor_id = None;
    let mut brand = None;

    for it in s.split('\n') {
        if it.starts_with("vendor_id\t") {
            vendor_id = Some(get_value(it));
        } else if it.starts_with("model name\t") {
            brand = Some(get_value(it));
        } else {
            continue;
        }
        if brand.is_some() && vendor_id.is_some() {
            break;
        }
    }
    (vendor_id.unwrap_or_default(), brand.unwrap_or_default())
}
<commit_msg>Apply clippy lint for if_chain => match<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

#![allow(clippy::too_many_arguments)]

use std::fs::File;
use std::io::Read;

use ProcessorExt;

/// Struct containing values to compute a CPU usage.
#[derive(Clone, Copy)]
pub struct CpuValues {
    user: u64,
    nice: u64,
    system: u64,
    idle: u64,
    iowait: u64,
    irq: u64,
    softirq: u64,
    steal: u64,
    guest: u64,
    guest_nice: u64,
}

impl CpuValues {
    /// Creates a new instance of `CpuValues` with everything set to `0`.
    pub fn new() -> CpuValues {
        CpuValues {
            user: 0,
            nice: 0,
            system: 0,
            idle: 0,
            iowait: 0,
            irq: 0,
            softirq: 0,
            steal: 0,
            guest: 0,
            guest_nice: 0,
        }
    }

    /// Creates a new instance of `CpuValues` with everything set to the corresponding argument.
    pub fn new_with_values(
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    ) -> CpuValues {
        CpuValues {
            user,
            nice,
            system,
            idle,
            iowait,
            irq,
            softirq,
            steal,
            guest,
            guest_nice,
        }
    }

    /*pub fn is_zero(&self) -> bool {
        self.user == 0 && self.nice == 0 && self.system == 0 && self.idle == 0 &&
        self.iowait == 0 && self.irq == 0 && self.softirq == 0 && self.steal == 0 &&
        self.guest == 0 && self.guest_nice == 0
    }*/

    /// Sets the given argument to the corresponding fields.
    pub fn set(
        &mut self,
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    ) {
        self.user = user;
        self.nice = nice;
        self.system = system;
        self.idle = idle;
        self.iowait = iowait;
        self.irq = irq;
        self.softirq = softirq;
        self.steal = steal;
        self.guest = guest;
        self.guest_nice = guest_nice;
    }

    /// Returns work time.
    pub fn work_time(&self) -> u64 {
        self.user + self.nice + self.system
    }

    /// Returns total time.
    pub fn total_time(&self) -> u64 {
        self.work_time()
            + self.idle
            + self.iowait
            + self.irq
            + self.softirq
            + self.steal
            + self.guest
            + self.guest_nice
    }
}

/// Struct containing a processor information.
pub struct Processor {
    old_values: CpuValues,
    new_values: CpuValues,
    pub(crate) name: String,
    cpu_usage: f32,
    total_time: u64,
    old_total_time: u64,
    frequency: u64,
    pub(crate) vendor_id: String,
    pub(crate) brand: String,
}

impl Processor {
    pub(crate) fn new_with_values(
        name: &str,
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
        frequency: u64,
        vendor_id: String,
        brand: String,
    ) -> Processor {
        Processor {
            name: name.to_owned(),
            old_values: CpuValues::new(),
            new_values: CpuValues::new_with_values(
                user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
            ),
            cpu_usage: 0f32,
            total_time: 0,
            old_total_time: 0,
            frequency,
            vendor_id,
            brand,
        }
    }

    pub(crate) fn set(
        &mut self,
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    ) {
        fn min(a: u64, b: u64) -> f32 {
            use std::cmp::Ordering;
            (match a.cmp(&b) {
                Ordering::Equal => 1,
                Ordering::Greater => a - b,
                Ordering::Less => b - a,
            }) as f32
        }
        //if !self.new_values.is_zero() {
        self.old_values = self.new_values;
        //}
        self.new_values.set(
            user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
        );
        self.cpu_usage = min(self.new_values.work_time(), self.old_values.work_time())
            / min(self.new_values.total_time(), self.old_values.total_time())
            * 100.;
        self.old_total_time = self.old_values.total_time();
        self.total_time = self.new_values.total_time();
    }
}

impl ProcessorExt for Processor {
    fn get_cpu_usage(&self) -> f32 {
        self.cpu_usage
    }

    fn get_name(&self) -> &str {
        &self.name
    }

    /// Returns the CPU frequency in MHz.
    fn get_frequency(&self) -> u64 {
        self.frequency
    }

    fn get_vendor_id(&self) -> &str {
        &self.vendor_id
    }

    fn get_brand(&self) -> &str {
        &self.brand
    }
}

pub fn get_raw_times(p: &Processor) -> (u64, u64) {
    (p.new_values.total_time(), p.old_values.total_time())
}

pub fn get_cpu_frequency() -> u64 {
    // /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
    let mut s = String::new();
    if File::open("/proc/cpuinfo")
        .and_then(|mut f| f.read_to_string(&mut s))
        .is_err()
    {
        return 0;
    }

    let find_cpu_mhz = s.split('\n').find(|line| {
        line.starts_with("cpu MHz\t")
            || line.starts_with("BogoMIPS")
            || line.starts_with("clock\t")
            || line.starts_with("bogomips per cpu")
    });

    find_cpu_mhz
        .and_then(|line| line.split(':').last())
        .and_then(|val| val.replace("MHz", "").trim().parse::<f64>().ok())
        .map(|speed| speed as u64)
        .unwrap_or_default()
}

/// Returns the brand/vendor string for the first CPU (which should be the same for all CPUs).
pub fn get_vendor_id_and_brand() -> (String, String) {
    let mut s = String::new();
    if File::open("/proc/cpuinfo")
        .and_then(|mut f| f.read_to_string(&mut s))
        .is_err()
    {
        return (String::new(), String::new());
    }

    fn get_value(s: &str) -> String {
        s.split(':')
            .last()
            .map(|x| x.trim().to_owned())
            .unwrap_or_default()
    }

    let mut vendor_id = None;
    let mut brand = None;

    for it in s.split('\n') {
        if it.starts_with("vendor_id\t") {
            vendor_id = Some(get_value(it));
        } else if it.starts_with("model name\t") {
            brand = Some(get_value(it));
        } else {
            continue;
        }
        if brand.is_some() && vendor_id.is_some() {
            break;
        }
    }
    (vendor_id.unwrap_or_default(), brand.unwrap_or_default())
}
<|endoftext|>


<commit_before>use rand::Rng;
use rand::distributions::{Sample, IndependentSample};
use statistics::*;
use {Result, StatsError};

/// Implements the [Erlang](https://en.wikipedia.org/wiki/Erlang_distribution) distribution
/// which is a special case of the [Gamma](https://en.wikipedia.org/wiki/Gamma_distribution)
/// distribution
///
/// # Examples
///
/// ```
/// use statrs::distribution::{Erlang, Continuous};
/// use statrs::statistics::Mean;
/// use statrs::prec;
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Erlang {
    shape: u64,
    rate: f64,
}

impl Erlang {
    /// Constructs a new erlang distribution with a shape (k)
    /// of `shape` and a rate (λ) of `rate`
    ///
    /// # Errors
    ///
    /// Returns an error if `shape` or `rate` are `NaN`.
    /// Also returns an error if `shape == 0` or `rate <= 0.0`
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Erlang;
    ///
    /// let mut result = Erlang::new(3, 1.0);
    /// assert!(result.is_ok());
    ///
    /// result = Erlang::new(0, 0.0);
    /// assert!(result.is_err());
    /// ```
    pub fn new(shape: u64, rate: f64) -> Result<Erlang> {
        if rate.is_nan() || shape == 0 || rate <= 0.0 {
            Err(StatsError::BadParams)
        } else {
            Ok(Erlang { shape: shape, rate: rate })
        }
    }

    /// Returns the shape (k) of the erlang distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Erlang;
    ///
    /// let n = Erlang::new(3, 1.0).unwrap();
    /// assert_eq!(n.shape(), 3);
    /// ```
    pub fn shape(&self) -> u64 {
        self.shape
    }

    /// Returns the rate (λ) of the erlang distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Erlang;
    ///
    /// let n = Erlang::new(3, 1.0).unwrap();
    /// assert_eq!(n.rate(), 1.0);
    /// ```
    pub fn rate(&self) -> f64 {
        self.rate
    }
}

impl Sample<f64> for Erlang {
    /// Generate a random sample from a erlang
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl IndependentSample<f64> for Erlang {
    /// Generate a random independent sample from a erlang
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl Distribution<f64> for Erlang {
    /// Generate a random sample from a erlang distribution using
    /// `r` as the source of randomness.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate rand;
    /// # extern crate statrs;
    /// use rand::StdRng;
    /// use statrs::distribution::{Erlang, Distribution};
    ///
    /// # fn main() {
    /// let mut r = rand::StdRng::new().unwrap();
    /// let n = Erlang::new(3, 1.0).unwrap();
    /// print!("{}", n.sample::<StdRng>(&mut r));
    /// # }
    /// ```
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::gammma::sample_unchecked(r, self.shape, self.rate)
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use distribution::{Univariate, Continuous, Erlang};

    fn try_create(shape: u64, rate: f64) -> Erlang {
        let n = Erlang::new(shape, rate);
        assert!(n.is_ok());
        n.unwrap()
    }

    fn create_case(shape: u64, rate: f64) {
        let n = try_create(shape, rate);
        assert_eq!(shape, n.shape());
        assert_eq!(rate, n.rate());
    }

    fn bad_create_case(shape: u64, rate: f64) {
        let n = Erlang::new(shape, rate);
        assert!(n.is_err());
    }

    #[test]
    fn test_create() {
        create_case(1, 0.1);
        create_case(1, 1.0);
        create_case(10, 10.0);
        create_case(10, 1.0);
        create_case(10, f64::INFINITY);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(0, 1.0);
        bad_create_case(1, 0.0);
        bad_create_case(1, f64::NAN);
        bad_create_case(1, -1.0);
    }
}<commit_msg>feat: impl univariate for erlang<commit_after>use rand::Rng;
use rand::distributions::{Sample, IndependentSample};
use statistics::*;
use distribution::{Univariate, Continuous, Distribution, Gamma};
use {Result, StatsError};

/// Implements the [Erlang](https://en.wikipedia.org/wiki/Erlang_distribution) distribution
/// which is a special case of the [Gamma](https://en.wikipedia.org/wiki/Gamma_distribution)
/// distribution
///
/// # Examples
///
/// ```
/// use statrs::distribution::{Erlang, Continuous};
/// use statrs::statistics::Mean;
/// use statrs::prec;
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Erlang {
    g: Gamma
}

impl Erlang {
    /// Constructs a new erlang distribution with a shape (k)
    /// of `shape` and a rate (λ) of `rate`
    ///
    /// # Errors
    ///
    /// Returns an error if `shape` or `rate` are `NaN`.
    /// Also returns an error if `shape == 0` or `rate <= 0.0`
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Erlang;
    ///
    /// let mut result = Erlang::new(3, 1.0);
    /// assert!(result.is_ok());
    ///
    /// result = Erlang::new(0, 0.0);
    /// assert!(result.is_err());
    /// ```
    pub fn new(shape: u64, rate: f64) -> Result<Erlang> {
        Gamma::new(shape as f64, rate).map(|g| Erlang { g: g })
    }

    /// Returns the shape (k) of the erlang distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Erlang;
    ///
    /// let n = Erlang::new(3, 1.0).unwrap();
    /// assert_eq!(n.shape(), 3);
    /// ```
    pub fn shape(&self) -> u64 {
        self.g.shape() as u64
    }

    /// Returns the rate (λ) of the erlang distribution
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Erlang;
    ///
    /// let n = Erlang::new(3, 1.0).unwrap();
    /// assert_eq!(n.rate(), 1.0);
    /// ```
    pub fn rate(&self) -> f64 {
        self.g.rate()
    }
}

impl Sample<f64> for Erlang {
    /// Generate a random sample from a erlang
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl IndependentSample<f64> for Erlang {
    /// Generate a random independent sample from a erlang
    /// distribution using `r` as the source of randomness.
    /// Refer [here](#method.sample-1) for implementation details
    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl Distribution<f64> for Erlang {
    /// Generate a random sample from a erlang distribution using
    /// `r` as the source of randomness.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate rand;
    /// # extern crate statrs;
    /// use rand::StdRng;
    /// use statrs::distribution::{Erlang, Distribution};
    ///
    /// # fn main() {
    /// let mut r = rand::StdRng::new().unwrap();
    /// let n = Erlang::new(3, 1.0).unwrap();
    /// print!("{}", n.sample::<StdRng>(&mut r));
    /// # }
    /// ```
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        self.g.sample(r)
    }
}

impl Univariate<f64, f64> for Erlang {
    /// Calculates the cumulative distribution function for the erlang distribution
    /// at `x`
    ///
    /// # Panics
    ///
    /// If `x <= 0.0`
    ///
    /// # Formula
    ///
    /// ```ignore
    /// γ(k, λx)  (k - 1)!
    /// ```
    ///
    /// where `k` is the shape, `λ` is the rate, and `γ` is the lower incomplete gamma function
    fn cdf(&self, x: f64) -> f64 {
        self.g.cdf(x)
    }
}

impl Min<f64> for Erlang {
    /// Returns the minimum value in the domain of the
    /// erlang distribution representable by a double precision
    /// float
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    fn min(&self) -> f64 {
        self.g.min()
    }
}

impl Max<f64> for Erlang {
    /// Returns the maximum value in the domain of the
    /// erlang distribution representable by a double precision
    /// float
    ///
    /// # Formula
    ///
    /// ```ignore
    /// INF
    /// ```
    fn max(&self) -> f64 {
        self.g.max()
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use distribution::{Univariate, Continuous, Erlang};

    fn try_create(shape: u64, rate: f64) -> Erlang {
        let n = Erlang::new(shape, rate);
        assert!(n.is_ok());
        n.unwrap()
    }

    fn create_case(shape: u64, rate: f64) {
        let n = try_create(shape, rate);
        assert_eq!(shape, n.shape());
        assert_eq!(rate, n.rate());
    }

    fn bad_create_case(shape: u64, rate: f64) {
        let n = Erlang::new(shape, rate);
        assert!(n.is_err());
    }

    #[test]
    fn test_create() {
        create_case(1, 0.1);
        create_case(1, 1.0);
        create_case(10, 10.0);
        create_case(10, 1.0);
        create_case(10, f64::INFINITY);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(0, 1.0);
        bad_create_case(1, 0.0);
        bad_create_case(1, f64::NAN);
        bad_create_case(1, -1.0);
    }
}<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::io::{stdout, stderr, Error, Write};
    use std::process::exit;
    use coreutils::ArgParser;
    use extra::io::fail;
    use extra::option::OptionalExt;
    use syscall::data::StatVfs;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag("h", "help");
    parser.parse(env::args());

    if parser.found(&'h') || parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    if parser.args.is_empty() {
        fail("No arguments. Use --help to see the usage.", &mut stderr);
    }

    println!("{:<8}{:<8}{:<8}{:<5}", "Size", "Used", "Free", "Use%");
    for path in &parser.args {
        let mut stat = StatVfs::default();
        {
            let fd = syscall::open(&path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno)).try(&mut stderr);
            syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno)).try(&mut stderr);
            let _ = syscall::close(fd);
        }

        let size = stat.f_blocks * stat.f_bsize as u64 / 1024;
        let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64 / 1024;
        let free = stat.f_bavail * stat.f_bsize as u64 / 1024;
        let percent = (100.0 * used as f64 / size as f64) as u64;
        println!("{:<8}{:<8}{:<8}{:<5}", size, used, free, format!("{}%", percent));
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<commit_msg>Improve df<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn df(path: &str) -> ::std::io::Result<()> {
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64 / 1024;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64 / 1024;
    let free = stat.f_bavail * stat.f_bsize as u64 / 1024;
    let percent = (100.0 * used as f64 / size as f64) as u64;
    println!("{:<8}{:<8}{:<8}{:<8}{:<5}", path, size, used, free, format!("{}%", percent));

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use coreutils::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag("h", "help");
    parser.parse(env::args());

    if parser.found(&'h') || parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<8}{:<8}{:<8}{:<8}{:<5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)));
        }
    } else {
        for path in &parser.args {
            df(&path).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<|endoftext|>


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

macro_rules! assert_special {
    ($left:expr, $right:expr) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion_failed: `(left == right)`\
                            (left: `{:?}` right: `{:?}`)",
                    left_val, right_val)
                }

                true
            }
        }
    });
}

macro_rules! vector {
    ($elem:expr, $n:expr) => {
        ::std::vec::from_elem($elem, $n)
    };
    ($($x:expr),*) => {
        <[_]>::into_vec(Box::new([ $( $x ), *]))
    };
    // adds support for trailing comma
    ($($x:expr),+ ,) => {
        // delegate creation to second macro case
        vector![$($x), *]
    }
}

// Pattern language of regular expressions:

// $( ... )* Match 0 or more times with no separator

// $( ... ),* Match 0 or more times, separated by commas

// $( ... );* Match 0 or more times, separated by semicolons

// $( ... )+ Match 1 or more times with no separator

// $( ... ),+ Match 1 or more times, separated by commas

// $( ... );+ Match 1 or more times, separated by semicolons

#[derive(Clone, PartialEq, Debug)]
enum Json {
    Null,
    Boolean(bool),
    Number(f64),
    String(String),
    Array(Vec<Json>),
    Object(Box<HashMap<String, Json>>)
}

// Json macro:
macro_rules! json {
    (null) => {
        Json::Null
    };
    // expr does not work here, because in json! macro we need not Rust code, but very specific stuff
    // tt - token tree is very good for this, it matches either
    // a properly matched pair of brackets, (...) [...] or {...}, and everything in between,
    // including nested token trees;
    // or a single token that isn’t a bracket, like 1926 or "Knots".
    ([ $( $element:tt ), * ]) => {
        // let's convert some JSON stuff to Rust (will call our json! recursivly)
        Json::Array(vec![ $( json!($element)), * ])
    };
    ({ $( $key:tt : $value:tt ), * }) => {
        // don't forget to wrap ($key.to_string(), json!($value)) in parenthesis.
        Json::Object(Box::new(vec![$( ($key.to_string(), json!($value)) ), *].into_iter().collect()))
    };
    ($other:tt) => {
        Json::from($other)
    };
}

impl From<bool> for Json {
    fn from(b: bool) -> Json {
        Json::Boolean(b)
    }
}

impl From<String> for Json {
    fn from(s: String) -> Json {
        Json::String(s)
    }
}

impl<'a> From<&'a str> for Json {
    fn from(s: &'a str) -> Json {
        Json::String(s.to_string())
    }
}

macro_rules! impl_json_for {
    ( $( $t:ident ), * ) => {
        $(
            impl From<$t> for Json {
                fn from(number: $t) -> Json {
                    Json::Number(number as f64)
                }
            }
        )*
    }
}

fn main() {
    let val = assert_special!("hello", "hello");
    println!("{:?}", val);

    let some_vector = vector![10, 1];
    println!("{:?}", some_vector);

    // third case with trailing comma
    let some_vector_with_trailing_comma = vector![10, 1, 10,];
    println!("{:?}", some_vector_with_trailing_comma);

    // initialize Json structure without a macro
    let students = Json::Array(vec![
        Json::Object(Box::new(vec![
            ("name".to_string(), Json::String("Raventid".to_string())),
            ("age".to_string(), Json::Number(32.))
        ].into_iter().collect())),
        Json::Object(Box::new(vec![
            ("name".to_string(), Json::String("Raventida".to_string())),
            ("age".to_string(), Json::Number(26.))
        ].into_iter().collect()))
    ]);

    println!("{:?}", students);

    // Test for json macro:
    assert_eq!(json!(null), Json::Null);

    impl_json_for!(u8, i8, u16, u32, i32, u64, i64, usize, isize, f32, f64);

    let one_more_test = json!({
        "width": 10
        // "height": (10 * 2)
    });

    // let's delegate this code generation to macro
    // let students_with_macro = json!([{
    //     "name": "Raventid",
    //     "class_of": 32
    // },
    // {
    //     "name": "Raventida",
    //     "age": 26
    // }]);
}
<commit_msg>use local variable to generate json object in macro<commit_after>use std::collections::HashMap;

macro_rules! assert_special {
    ($left:expr, $right:expr) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion_failed: `(left == right)`\
                            (left: `{:?}` right: `{:?}`)",
                    left_val, right_val)
                }

                true
            }
        }
    });
}

macro_rules! vector {
    ($elem:expr, $n:expr) => {
        ::std::vec::from_elem($elem, $n)
    };
    ($($x:expr),*) => {
        <[_]>::into_vec(Box::new([ $( $x ), *]))
    };
    // adds support for trailing comma
    ($($x:expr),+ ,) => {
        // delegate creation to second macro case
        vector![$($x), *]
    }
}

// Pattern language of regular expressions:

// $( ... )* Match 0 or more times with no separator

// $( ... ),* Match 0 or more times, separated by commas

// $( ... );* Match 0 or more times, separated by semicolons

// $( ... )+ Match 1 or more times with no separator

// $( ... ),+ Match 1 or more times, separated by commas

// $( ... );+ Match 1 or more times, separated by semicolons

#[derive(Clone, PartialEq, Debug)]
enum Json {
    Null,
    Boolean(bool),
    Number(f64),
    String(String),
    Array(Vec<Json>),
    Object(Box<HashMap<String, Json>>)
}

// Json macro:
macro_rules! json {
    (null) => {
        Json::Null
    };
    // expr does not work here, because in json! macro we need not Rust code, but very specific stuff
    // tt - token tree is very good for this, it matches either
    // a properly matched pair of brackets, (...) [...] or {...}, and everything in between,
    // including nested token trees;
    // or a single token that isn’t a bracket, like 1926 or "Knots".
    ([ $( $element:tt ), * ]) => {
        // let's convert some JSON stuff to Rust (will call our json! recursivly)
        Json::Array(vec![ $( json!($element)), * ])
    };
    // ({ $( $key:tt : $value:tt ), * }) => {
    //     // don't forget to wrap ($key.to_string(), json!($value)) in parenthesis.
    //     Json::Object(Box::new(vec![$( ($key.to_string(), json!($value)) ), *].into_iter().collect()))
    // };

    // object macro with local variable instead of into_iter()
    ({ $( $key:tt : $value:tt ), * }) => {
        {
            let mut fields = Box::new(HashMap::new());
            $( fields.insert($key.to_string(), json!($value)); )*
                Json::Object(fields)
        }
    };

    ($other:tt) => {
        Json::from($other)
    };
}

impl From<bool> for Json {
    fn from(b: bool) -> Json {
        Json::Boolean(b)
    }
}

impl From<String> for Json {
    fn from(s: String) -> Json {
        Json::String(s)
    }
}

impl<'a> From<&'a str> for Json {
    fn from(s: &'a str) -> Json {
        Json::String(s.to_string())
    }
}

macro_rules! impl_json_for {
    ( $( $t:ident ), * ) => {
        $(
            impl From<$t> for Json {
                fn from(number: $t) -> Json {
                    Json::Number(number as f64)
                }
            }
        )*
    }
}

fn main() {
    let val = assert_special!("hello", "hello");
    println!("{:?}", val);

    let some_vector = vector![10, 1];
    println!("{:?}", some_vector);

    // third case with trailing comma
    let some_vector_with_trailing_comma = vector![10, 1, 10,];
    println!("{:?}", some_vector_with_trailing_comma);

    // initialize Json structure without a macro
    let students = Json::Array(vec![
        Json::Object(Box::new(vec![
            ("name".to_string(), Json::String("Raventid".to_string())),
            ("age".to_string(), Json::Number(32.))
        ].into_iter().collect())),
        Json::Object(Box::new(vec![
            ("name".to_string(), Json::String("Raventida".to_string())),
            ("age".to_string(), Json::Number(26.))
        ].into_iter().collect()))
    ]);

    println!("{:?}", students);

    // Test for json macro:
    assert_eq!(json!(null), Json::Null);

    impl_json_for!(u8, i8, u16, u32, i32, u64, i64, usize, isize, f32, f64);

    let one_more_test = json!({
        "width": 10
        // "height": (10 * 2)
    });

    // let's delegate this code generation to macro
    // let students_with_macro = json!([{
    //     "name": "Raventid",
    //     "class_of": 32
    // },
    // {
    //     "name": "Raventida",
    //     "age": 26
    // }]);
}
<|endoftext|>