1extern crate inotify;
2
3use std::time::{SystemTime};
4use std::fs;
5use std::fs::File;
6use std::io::Write;
7use subprocess::Exec;
8
9use inotify::{
10 Inotify,
11 WatchMask,
12};
13
14
15pub mod vjoule_api;
16use crate::vjoule_api::stamp::{ConsumptionStamp};
17use crate::vjoule_api::error::VJouleError;
18use crate::vjoule_api::constants::{VJOULE_RES_PATH, VJOULE_PATH};
19
20pub struct VJouleAPI {
24}
25
26impl VJouleAPI {
27
28 pub fn new ()-> Result <VJouleAPI, VJouleError> {
45 let p = Exec::shell ("systemctl is-active --quiet vjoule_service.service").capture ().map_err (|_e| "Failed to execute bash command")?;
46 match p.exit_status {
47 subprocess::ExitStatus::Exited (0) => {}
48 _ => {
49 return Err ("vJoule service is not started. sudo systemctl start vjoule_service.service");
50 }
51 }
52
53 Ok (VJouleAPI {})
54 }
55
56 pub fn get_current_machine_consumption (&mut self)-> Result<ConsumptionStamp, VJouleError> {
67 self.force_signal ();
68 self.get_current_machine_consumption_no_force ()
69 }
70
71 pub fn get_current_machine_consumption_no_force (&mut self)-> Result<ConsumptionStamp, VJouleError> {
77 let cpu_path = format!("{}/cpu", VJOULE_RES_PATH);
78 let ram_path = format!("{}/ram", VJOULE_RES_PATH);
79 let gpu_path = format!("{}/gpu", VJOULE_RES_PATH);
80 let pdu_e_path = format!("{}/pdu_energy", VJOULE_RES_PATH);
81 let pdu_p_path = format!("{}/pdu_power", VJOULE_RES_PATH);
82
83 let cpu = self.read_value (&cpu_path[..]);
84 let ram = self.read_value (&ram_path[..]);
85 let gpu = self.read_value (&gpu_path[..]);
86 let pdu_e = self.read_value (&pdu_e_path[..]);
87 let pdu_p = self.read_value (&pdu_p_path[..]);
88
89 Ok (ConsumptionStamp {
90 time : SystemTime::now (),
91 pdu_watts : pdu_p,
92 pdu : pdu_e,
93 cpu : cpu,
94 ram : ram,
95 gpu : gpu
96 })
97 }
98
99 fn read_value (&mut self, file : &str)-> f64 {
104 match fs::read_to_string (&file) {
105 Ok (content) => {
106 match content[..content.len () - 1].parse::<f64> () {
107 Ok (result) => {
108 return result;
109 }
110 _ => {
111 return 0.0;
112 }
113 }
114 }
115 _ => {
116 return 0.0;
117 }
118 }
119
120 }
121
122 fn force_signal (&mut self) {
127 let mut inotif = Inotify::init ().expect ("Error while initializing inotify instance");
128 inotif.watches ().add (
129 format!("{}/cpu", VJOULE_RES_PATH),
130 WatchMask::MODIFY
131 ).expect ("Failed to add watch");
132
133 for _i in 0 .. 2 {
134 let file = File::create (format!("{}/signal", VJOULE_PATH));
135 match file {
136 Ok (mut f) => {
137 f.write_all (b"1").expect ("Failed to write in signal file");
138 f.sync_all ().expect ("Failed to close signal file");
139 }
140 _ => {
141 }
142 }
143
144 let mut buffer = [0 ; 1024];
145 inotif.read_events_blocking (&mut buffer)
146 .expect ("Error while reading events");
147 }
148 }
149
150}