scst 0.3.4

iscsi-scst user interface implemention by rust
Documentation
use std::path::Path;

use anyhow::Result;
use regex::Regex;
use serde::{Deserialize, Serialize};

use crate::{Layer, read_dir, read_fl};
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct IOStat {
    bidi_cmd_count: usize,
    bidi_io_count_kb: usize,
    bidi_unaligned_cmd_count: usize,

    write_cmd_count: usize,
    write_io_count_kb: usize,
    write_unaligned_cmd_count: usize,

    read_cmd_count: usize,
    read_io_count_kb: usize,
    read_unaligned_cmd_count: usize,
}

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Session {
    #[serde(skip)]
    root: String,
    sid: String,
    thread_pid: String,
    initiator_name: String,

    ips: Vec<SessionIP>,
}

impl Session {
    pub fn sid(&self) -> &str {
        &self.sid
    }

    pub fn thread_pid(&self) -> &str {
        &self.thread_pid
    }

    pub fn initiator_name(&self) -> &str {
        &self.initiator_name
    }

    pub fn ips(&self) -> Vec<&SessionIP> {
        self.ips.iter().collect()
    }

    pub fn io_stat(&self) -> Result<IOStat> {
        read_stat(self.root())
    }
}

impl Layer for Session {
    fn root(&self) -> &Path {
        Path::new(&self.root)
    }

    fn load<P: AsRef<Path>>(&mut self, root: P) -> Result<()> {
        let root_ref = root.as_ref();
        self.root = root_ref.to_string_lossy().to_string();
        self.sid = read_fl(root_ref.join("sid"))?;
        self.thread_pid = read_fl(root_ref.join("thread_pid"))?;
        self.initiator_name = read_fl(root_ref.join("initiator_name"))?;

        let ip_re = Regex::new(r"^(?:\d{1,3}\.){3}\d{1,3}$")?;
        self.ips = read_dir(root_ref)?
            .filter_map(|res| res.ok())
            .filter(|entry| {
                entry.path().is_dir() && ip_re.is_match(&entry.file_name().to_string_lossy())
            })
            .filter_map(|entry| {
                let mut ip = SessionIP::default();
                ip.load(entry.path()).ok();
                Some(ip)
            })
            .collect();

        Ok(())
    }
}

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct SessionIP {
    #[serde(skip)]
    root: String,
    cid: String,
    ip: String,
    state: String,
    target_ip: String,
}

impl SessionIP {
    pub fn cid(&self) -> &str {
        &self.cid
    }

    pub fn ip(&self) -> &str {
        &self.ip
    }

    pub fn state(&self) -> &str {
        &self.state
    }

    pub fn target_ip(&self) -> &str {
        &self.target_ip
    }
}

impl Layer for SessionIP {
    fn root(&self) -> &Path {
        Path::new(&self.root)
    }

    fn load<P: AsRef<Path>>(&mut self, root: P) -> Result<()> {
        let root_ref = root.as_ref();
        self.root = root_ref.to_string_lossy().to_string();
        self.cid = read_fl(root_ref.join("cid"))?;
        self.ip = read_fl(root_ref.join("ip"))?;
        self.state = read_fl(root_ref.join("state"))?;
        self.target_ip = read_fl(root_ref.join("target_ip"))?;

        Ok(())
    }
}

pub fn read_stat<S: AsRef<Path>>(root: S) -> Result<IOStat> {
    let root_ref = root.as_ref();
    let bidi_cmd_count = read_fl(root_ref.join("bidi_cmd_count"))?.parse::<usize>()?;
    let bidi_io_count_kb = read_fl(root_ref.join("bidi_io_count_kb"))?.parse::<usize>()?;
    let bidi_unaligned_cmd_count =
        read_fl(root_ref.join("bidi_unaligned_cmd_count"))?.parse::<usize>()?;
    let write_cmd_count = read_fl(root_ref.join("write_cmd_count"))?.parse::<usize>()?;
    let write_io_count_kb = read_fl(root_ref.join("write_io_count_kb"))?.parse::<usize>()?;
    let write_unaligned_cmd_count =
        read_fl(root_ref.join("write_unaligned_cmd_count"))?.parse::<usize>()?;
    let read_cmd_count = read_fl(root_ref.join("read_cmd_count"))?.parse::<usize>()?;
    let read_io_count_kb = read_fl(root_ref.join("read_io_count_kb"))?.parse::<usize>()?;
    let read_unaligned_cmd_count =
        read_fl(root_ref.join("read_unaligned_cmd_count"))?.parse::<usize>()?;

    let stat = IOStat {
        bidi_cmd_count,
        bidi_io_count_kb,
        bidi_unaligned_cmd_count,
        write_cmd_count,
        write_io_count_kb,
        write_unaligned_cmd_count,
        read_cmd_count,
        read_io_count_kb,
        read_unaligned_cmd_count,
    };

    Ok(stat)
}