<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 std::borrow::Cow;
use std::cell::RefCell;
use std::fmt::Display;
use std::path::Path;
use std::rc::Rc;
use std::io::ErrorKind;
use std::collections::BTreeMap;
use std::fmt;

use dbus;
use dbus::Connection;
use dbus::BusType;
use dbus::MessageItem;
use dbus::NameFlag;
use dbus::tree::Factory;
use dbus::tree::DataType;
use dbus::tree::MethodErr;
use dbus::tree::MTFn;
use dbus::tree::MethodResult;
use dbus::tree::MethodInfo;
use dbus::tree::Tree;

use dbus_consts::*;

use engine::Engine;
use types::{StratisResult, StratisError};

#[derive(Clone)]
pub struct DbusContext {
    pub next_index: u64,
    pub pools: BTreeMap<String, String>,
    pub engine: Rc<RefCell<Engine>>,
}

// engine doesn't impl Debug, so we can't derive
impl fmt::Debug for DbusContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{{DBusContext {:?}, {:?}}}", self.next_index, self.pools)
    }
}

impl DbusContext {
    pub fn new(engine: &Rc<RefCell<Engine>>) -> DbusContext {
        DbusContext {
            next_index: 0,
            pools: BTreeMap::new(),
            engine: engine.clone(),
        }
    }
    pub fn get_next_id(&mut self) -> u64 {
        self.next_index += 1;
        self.next_index
    }
}

#[derive(Copy, Clone, Default, Debug)]
struct TData;
impl DataType for TData {
    type ObjectPath = Rc<RefCell<DbusContext>>;
    type Property = ();
    type Interface = ();
    type Method = ();
    type Signal = ();
}

fn internal_to_dbus_err(err: &StratisError) -> StratisErrorEnum {
    match *err {
        StratisError::Stratis(_) => StratisErrorEnum::STRATIS_ERROR,
        StratisError::Io(ref err) => {
            match err.kind() {
                ErrorKind::NotFound => StratisErrorEnum::STRATIS_NOTFOUND,
                ErrorKind::AlreadyExists => StratisErrorEnum::STRATIS_ALREADY_EXISTS,
                _ => StratisErrorEnum::STRATIS_ERROR,
            }
        }
        _ => StratisErrorEnum::STRATIS_ERROR,
    }
}

fn list_pools(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {

    let dbus_context = m.path.get_data();
    let ref engine = dbus_context.borrow().engine;

    let result = engine.borrow().list_pools();

    let pool_tree = result.unwrap();

    let msg_vec = pool_tree.keys().map(|key| MessageItem::Str(format!("{}", key))).collect();
    let item_array = MessageItem::Array(msg_vec, Cow::Borrowed("s"));

    let code = StratisErrorEnum::STRATIS_OK;

    Ok(vec![m.msg.method_return().append3(item_array,
                                          MessageItem::UInt16(code.get_error_int()),
                                          MessageItem::Str(code.get_error_string().into()))])
}


fn create_volumes(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {

    Ok(vec![m.msg.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn destroy_volumes(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    Ok(vec![m.msg.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn list_volumes(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    Ok(vec![m.msg.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn list_devs(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {<commit_msg>Handle possibility of failure when listing pools.<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 std::borrow::Cow;
use std::cell::RefCell;
use std::fmt::Display;
use std::path::Path;
use std::rc::Rc;
use std::io::ErrorKind;
use std::collections::BTreeMap;
use std::fmt;

use dbus;
use dbus::Connection;
use dbus::BusType;
use dbus::MessageItem;
use dbus::NameFlag;
use dbus::tree::Factory;
use dbus::tree::DataType;
use dbus::tree::MethodErr;
use dbus::tree::MTFn;
use dbus::tree::MethodResult;
use dbus::tree::MethodInfo;
use dbus::tree::Tree;

use dbus_consts::*;

use engine::Engine;
use types::{StratisResult, StratisError};

#[derive(Clone)]
pub struct DbusContext {
    pub next_index: u64,
    pub pools: BTreeMap<String, String>,
    pub engine: Rc<RefCell<Engine>>,
}

// engine doesn't impl Debug, so we can't derive
impl fmt::Debug for DbusContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{{DBusContext {:?}, {:?}}}", self.next_index, self.pools)
    }
}

impl DbusContext {
    pub fn new(engine: &Rc<RefCell<Engine>>) -> DbusContext {
        DbusContext {
            next_index: 0,
            pools: BTreeMap::new(),
            engine: engine.clone(),
        }
    }
    pub fn get_next_id(&mut self) -> u64 {
        self.next_index += 1;
        self.next_index
    }
}

#[derive(Copy, Clone, Default, Debug)]
struct TData;
impl DataType for TData {
    type ObjectPath = Rc<RefCell<DbusContext>>;
    type Property = ();
    type Interface = ();
    type Method = ();
    type Signal = ();
}

fn internal_to_dbus_err(err: &StratisError) -> StratisErrorEnum {
    match *err {
        StratisError::Stratis(_) => StratisErrorEnum::STRATIS_ERROR,
        StratisError::Io(ref err) => {
            match err.kind() {
                ErrorKind::NotFound => StratisErrorEnum::STRATIS_NOTFOUND,
                ErrorKind::AlreadyExists => StratisErrorEnum::STRATIS_ALREADY_EXISTS,
                _ => StratisErrorEnum::STRATIS_ERROR,
            }
        }
        _ => StratisErrorEnum::STRATIS_ERROR,
    }
}

fn list_pools(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {

    let dbus_context = m.path.get_data();
    let ref engine = dbus_context.borrow().engine;

    let result = engine.borrow().list_pools();

    let return_message = m.msg.method_return();

    let msg = match result {
        Ok(pool_tree) => {
            let msg_vec =
                pool_tree.keys().map(|key| MessageItem::Str(format!("{}", key))).collect();
            let item_array = MessageItem::Array(msg_vec, Cow::Borrowed("s"));
            let code = StratisErrorEnum::STRATIS_OK;
            return_message.append3(item_array,
                                   MessageItem::UInt16(code.get_error_int()),
                                   MessageItem::Str(code.get_error_string().into()))
        }
        Err(x) => {
            let code = internal_to_dbus_err(&x);
            return_message.append3(MessageItem::ObjectPath("/".into()),
                                   MessageItem::UInt16(code.get_error_int()),
                                   MessageItem::Str(code.get_error_string().into()))
        }
    };
    Ok(vec![msg])
}


fn create_volumes(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {

    Ok(vec![m.msg.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn destroy_volumes(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    Ok(vec![m.msg.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn list_volumes(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    Ok(vec![m.msg.method_return().append3("/dbus/cache/path", 0, "Ok")])
}

fn list_devs(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
{'fraction_non_alphanumeric': 0.1561771561771562, 'fraction_numerical': 0.005621829151240916, 'mean_word_length': 3.1584948688711516, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6462170', 'n_tokens_mistral': 2493, 'n_tokens_neox': 2448, 'n_words': 501}