#![cfg(target_os = "freebsd")]
extern crate pmc;
use event::Printable;
use std::fmt;
use error::Error;
use runner::Counter;
use separator::Separatable;
#[derive(Debug)]
pub struct PmcEvent<'a> {
spec: &'a str,
alias: Option<&'a str>,
value: Option<u64>,
counter: pmc::Counter<'a>,
}
impl<'a> PmcEvent<'a> {
pub fn new(spec: &'a str) -> Result<Self, Error> {
let counter = pmc::Counter::new(spec, &pmc::Scope::Process, pmc::CPU_ANY)?;
Ok(PmcEvent {
spec,
counter,
alias: None,
value: None,
})
}
pub fn alias(mut self, alias: &'a str) -> Self {
self.alias = Some(alias);
self
}
}
impl<'a> Counter for PmcEvent<'a> {
fn attach(&mut self, pid: u32) -> Result<(), Error> {
self.counter.attach(pid).map_err(Error::PmcError)?;
if let Ok(mut counter) =
pmc::Counter::new("LOCK.FAILED", &pmc::Scope::Process, pmc::CPU_ANY)
{
let _ = counter.attach(0);
let _ = counter.start();
let _ = counter.stop();
}
Ok(())
}
fn start(&mut self) -> Result<(), Error> {
self.counter.start().map_err(Error::PmcError)
}
fn stop(&mut self) -> Result<(), Error> {
self.counter.stop().map_err(Error::PmcError)
}
fn set(&mut self, value: u64) -> Result<u64, Error> {
self.counter
.set(value)
.and_then(|v| {
self.value = Some(v);
Ok(v)
})
.map_err(Error::PmcError)
}
}
impl<'a> fmt::Display for PmcEvent<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:>30}: {:>14}",
self.alias.unwrap_or(self.spec),
self.value.unwrap_or(0).separated_string(),
)
}
}
impl<'a> Printable for PmcEvent<'a> {
fn name(&self) -> &str {
self.alias.unwrap_or(self.spec)
}
fn value(&self) -> u64 {
self.value.unwrap_or(0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_event() {
let mut event = PmcEvent::new("instructions").unwrap();
assert_eq!(event.spec, "instructions");
assert_eq!(event.alias, None);
assert_eq!(event.value(), 0);
assert!(event.attach(0).is_ok());
assert!(event.start().is_ok());
assert!(event.stop().is_ok());
let v = event.set(0).unwrap();
assert!(v > 0);
assert_eq!(event.value(), v);
}
#[test]
#[ignore]
fn test_alias() {
let event = PmcEvent::new("instructions").unwrap().alias("alias");
assert_eq!(event.spec, "instructions");
assert_eq!(event.alias, Some("alias"));
}
}