Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upstream various patches from tikv's fork #244

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ build = "build.rs"
cfg-if = "0.1"
rayon = "^1.0"
doc-comment = "0.3"
walkdir = "2.2.9"
pnet_datalink = "0.23.0"
num_cpus = "1.11.1"
cache-size = "0.4.0"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["fileapi", "handleapi", "ioapiset", "minwindef", "pdh", "psapi", "synchapi", "sysinfoapi", "winbase", "winerror", "winioctl", "winnt", "oleauto", "wbemcli", "rpcdce", "combaseapi", "objidl", "objbase"] }
Expand Down
93 changes: 93 additions & 0 deletions src/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;

/// IOLoad represents current system block devices IO statistics
#[derive(Debug)]
pub struct IOLoad {
/// number of read I/Os processed
/// units: requests
pub read_io: f64,
/// number of read I/Os merged with in-queue I/O
/// units: requests
pub read_merges: f64,
/// number of sectors read
/// units: sectors
pub read_sectors: f64,
/// total wait time for read requests
/// units: milliseconds
pub read_ticks: f64,
/// number of write I/Os processed
/// units: requests
pub write_io: f64,
/// number of write I/Os merged with in-queue I/O
/// units: requests
pub write_merges: f64,
/// number of sectors written
/// units: sectors
pub write_sectors: f64,
/// total wait time for write requests
/// units: milliseconds
pub write_ticks: f64,
/// number of I/Os currently in flight
/// units: requests
pub in_flight: f64,
/// total time this block device has been active
/// units: milliseconds
pub io_ticks: f64,
/// total wait time for all requests
/// units: milliseconds
pub time_in_queue: f64,
}

impl IOLoad {
/// Returns the current IO statistics
///
/// # Notes
///
/// Current don't support non-unix operating system
#[cfg(not(unix))]
pub fn snapshot() -> HashMap<String, NICLoad> {
HashMap::new()
}

/// Returns the current IO statistics
#[cfg(unix)]
pub fn snapshot() -> HashMap<String, IOLoad> {
let mut result = HashMap::new();
// https://www.kernel.org/doc/Documentation/block/stat.txt
if let Ok(dir) = std::fs::read_dir("/sys/block/") {
for entry in dir {
if let Ok(entry) = entry {
let stat = entry.path().join("stat");
let mut s = String::new();
if let Err(_) = File::open(stat).and_then(|mut f| f.read_to_string(&mut s)) {
continue;
};
let parts = s
.split_whitespace()
.map(|w| w.parse().unwrap_or_default())
.collect::<Vec<f64>>();
if parts.len() < 11 {
continue;
}
let load = IOLoad {
read_io: parts[0],
read_merges: parts[1],
read_sectors: parts[2],
read_ticks: parts[3],
write_io: parts[4],
write_merges: parts[5],
write_sectors: parts[6],
write_ticks: parts[7],
in_flight: parts[8],
io_ticks: parts[9],
time_in_queue: parts[10],
};
result.insert(format!("{:?}", entry.file_name()), load);
}
}
}
result
}
}
2 changes: 1 addition & 1 deletion src/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ pub use self::component::Component;
pub use self::disk::{Disk, DiskType};
pub use self::network::NetworkData;
pub use self::process::{Process, ProcessStatus};
pub use self::processor::Processor;
pub use self::processor::{get_avg_load, get_cpu_frequency, get_vendor_id, Processor};
pub use self::system::System;
59 changes: 59 additions & 0 deletions src/linux/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

#![allow(clippy::too_many_arguments)]

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

use LoadAvg;
use ProcessorExt;

/// Struct containing values to compute a CPU usage.
Expand Down Expand Up @@ -249,3 +254,57 @@ pub fn set_processor(
pub fn get_raw_times(p: &Processor) -> (u64, u64) {
(p.new_values.total_time(), p.old_values.total_time())
}

/// get_cpu_frequency returns the CPU frequency in MHz
pub fn get_cpu_frequency() -> u64 {
// /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
let mut s = String::new();
if let Err(_) = File::open("/proc/cpuinfo").and_then(|mut f| f.read_to_string(&mut s)) {
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() -> String {
let mut s = String::new();
if let Err(_) = File::open("/proc/cpuinfo").and_then(|mut f| f.read_to_string(&mut s)) {
return String::new();
}

s.split('\n').find(|line| line.starts_with("vendor_id\t"))
.and_then(|line| line.split(':').last())
.map(|s| s.trim().to_owned())
.unwrap_or_default()
}

/// get_avg_load returns the system load average value.
pub fn get_avg_load() -> LoadAvg {
let mut s = String::new();
if let Err(_) = File::open("/proc/loadavg").and_then(|mut f| f.read_to_string(&mut s)) {
return LoadAvg::default();
}
let loads = s
.trim()
.split(' ')
.take(3)
.map(|val| val.parse::<f64>().unwrap())
.collect::<Vec<f64>>();
LoadAvg {
one: loads[0],
five: loads[1],
fifteen: loads[2],
}
}
8 changes: 8 additions & 0 deletions src/mac/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ extern "C" {
//pub fn host_statistics(host_priv: u32, flavor: u32, host_info: *mut c_void,
// host_count: *const u32) -> u32;
pub fn vm_deallocate(target_task: u32, address: *mut i32, size: u32) -> kern_return_t;
pub fn sysctlbyname(
name: *const c_char,
oldp: *mut u64,
oldlenp: *mut usize,
newp: *mut c_void,
newlen: usize,
) -> kern_return_t;
pub fn getloadavg(loads: *const f64, size: c_int);

// pub fn proc_pidpath(pid: i32, buf: *mut i8, bufsize: u32) -> i32;
// pub fn proc_name(pid: i32, buf: *mut i8, bufsize: u32) -> i32;
Expand Down
2 changes: 1 addition & 1 deletion src/mac/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ pub use self::component::Component;
pub use self::disk::{Disk, DiskType};
pub use self::network::NetworkData;
pub use self::process::{Process, ProcessStatus};
pub use self::processor::Processor;
pub use self::processor::{get_avg_load, get_cpu_frequency, get_vendor_id, Processor};
pub use self::system::System;
38 changes: 38 additions & 0 deletions src/mac/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
// Copyright (c) 2015 Guillaume Gomez
//

use libc::c_char;
use std::ops::Deref;
use std::sync::Arc;
use sys::ffi;

use LoadAvg;
use ProcessorExt;

pub struct UnsafePtr<T>(*mut T);
Expand Down Expand Up @@ -96,3 +98,39 @@ pub fn set_cpu_proc(p: &mut Processor, cpu_usage: f32) {
pub fn get_processor_data(p: &Processor) -> Arc<ProcessorData> {
Arc::clone(&p.processor_data)
}

/// get_cpu_frequency returns the CPU frequency in MHz
pub fn get_cpu_frequency() -> u64 {
let mut speed: u64 = 0;
let mut len = std::mem::size_of::<u64>();
unsafe {
ffi::sysctlbyname(
"hw.cpufrequency".as_ptr() as *const c_char,
&mut speed,
&mut len,
std::ptr::null_mut(),
0,
);
}
speed /= 1000000;
speed
}

/// Returns the brand/vendor string for the first CPU (which should be the same for all CPUs).
pub fn get_vendor_id() -> String {
// TODO: support Mac
"".to_owned()
}

/// get_avg_load returns the system load average value.
pub fn get_avg_load() -> LoadAvg {
let loads = vec![0f64; 3];
unsafe {
ffi::getloadavg(loads.as_ptr() as *const f64, 3);
}
LoadAvg {
one: loads[0],
five: loads[1],
fifteen: loads[2],
}
}
72 changes: 72 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::collections::HashMap;

/// NICLoad represents the network interface card load informations
#[derive(Debug)]
pub struct NICLoad {
/// a total number of bytes received over interface.
pub rx_bytes: usize,
/// a total number of bytes transmitted over interface.
pub tx_bytes: usize,
/// a total number of packets received.
pub rx_packets: usize,
/// a total number of packets transmitted.
pub tx_packets: usize,
/// shows a total number of packets received with error. This includes
/// too-long-frames errors, ring-buffer overflow errors, CRC errors,
/// frame alignment errors, fifo overruns, and missed packets.
pub rx_errors: usize,
/// similar to `rx_errors`
pub tx_errors: usize,
/// Indicates the number of compressed packets received by this
/// network device. This value might only be relevant for interfaces
/// that support packet compression (e.g: PPP).
pub rx_compressed: usize,
/// Indicates the number of transmitted compressed packets. Note
/// this might only be relevant for devices that support
/// compression (e.g: PPP).
pub tx_compressed: usize,
}

impl NICLoad {
/// Returns the current network interfaces card statistics
///
/// # Notes
///
/// Current don't support non-unix operating system
#[cfg(not(unix))]
pub fn snapshot() -> HashMap<String, NICLoad> {
HashMap::new()
}

/// Returns the current network interfaces card statistics
#[cfg(unix)]
pub fn snapshot() -> HashMap<String, NICLoad> {
let mut result = HashMap::new();
if let Ok(dir) = std::fs::read_dir("/sys/class/net/") {
for entry in dir {
if let Ok(entry) = entry {
let parent = entry.path().join("statistics");
let read = |path: &str| -> usize {
std::fs::read_to_string(parent.join(path))
.unwrap_or_default()
.trim()
.parse()
.unwrap_or_default()
};
let load = NICLoad {
rx_bytes: read("rx_bytes"),
tx_bytes: read("tx_bytes"),
rx_packets: read("rx_packets"),
tx_packets: read("tx_packets"),
rx_errors: read("rx_errors"),
tx_errors: read("tx_errors"),
rx_compressed: read("rx_compressed"),
tx_compressed: read("tx_compressed"),
};
result.insert(format!("{:?}", entry.file_name()), load);
}
}
}
result
}
}
Loading