1extern crate libc;
2extern crate hbs_acc_pow_sys;
3
4use hbs_acc_pow_sys::*;
5use std::mem;
6use std::io::{self, Write};
7use std::fs::File;
8
9pub use hbs_acc_pow_sys::heartbeat_acc_pow_context as HeartbeatAccPowContext;
10pub use hbs_acc_pow_sys::heartbeat_acc_pow_record as HeartbeatAccPowRecord;
11pub use hbs_acc_pow_sys::heartbeat_acc_pow_window_complete as HeartbeatAccPowWindowComplete;
12
13pub struct HeartbeatAccPow {
15 pub hb: HeartbeatAccPowContext,
16 pub hbr: Vec<HeartbeatAccPowRecord>,
17 pub log: Option<File>,
18}
19
20impl HeartbeatAccPow {
21 pub fn new(window_size: usize,
23 hwc_callback: Option<HeartbeatAccPowWindowComplete>,
24 mut log: Option<File>) -> Result<HeartbeatAccPow, &'static str> {
25 let mut hbr: Vec<HeartbeatAccPowRecord> = Vec::with_capacity(window_size);
26 let hb: HeartbeatAccPowContext = unsafe {
27 hbr.set_len(window_size);
30 let mut hb = mem::uninitialized();
31 match heartbeat_acc_pow_init(&mut hb,
32 hbr.capacity() as u64,
33 hbr.as_mut_ptr(),
34 -1,
35 hwc_callback) {
36 0 => hb,
37 _ => return Err("Failed to initialize heartbeat")
38 }
39 };
40 if let Some(ref mut l) = log {
42 l.write_all(format!("{:6} {:6} \
43 {:11} {:11} {:11} \
44 {:15} {:15} {:20} {:20} \
45 {:15} {:15} {:15} \
46 {:15} {:15} {:15} \
47 {:15} {:15} {}\n",
48 "HB", "Tag",
49 "Global_Work", "Window_Work", "Work",
50 "Global_Time", "Window_Time", "Start_Time", "End_Time",
51 "Global_Perf", "Window_Perf", "Instant_Perf",
52 "Global_Acc", "Window_Acc", "Acc",
53 "Global_Acc_Rate", "Window_Acc_Rate", "Instant_Acc_Rate")
54 .as_bytes()).unwrap()
55 }
56 Ok(HeartbeatAccPow { hb: hb, hbr: hbr, log: log, })
57 }
58
59 pub fn heartbeat(&mut self,
61 tag: u64,
62 work: u64,
63 start_time: u64,
64 end_time: u64,
65 accuracy: u64,
66 start_energy: u64,
67 end_energy: u64) {
68 unsafe {
69 heartbeat_acc_pow(&mut self.hb,
70 tag,
71 work,
72 start_time,
73 end_time,
74 accuracy,
75 start_energy,
76 end_energy)
77 }
78 }
79
80 fn write_log(r: &HeartbeatAccPowRecord, l: &mut File) -> io::Result<usize> {
81 l.write(format!("{:<6} {:<6} \
82 {:<11} {:<11} {:<11} \
83 {:<15} {:<15} {:<20} {:<20} \
84 {:<15.6} {:<15.6} {:<15.6} \
85 {:<15} {:<15} {:<15} \
86 {:<15.6} {:<15.6} {:<.6}\n",
87 r.id, r.user_tag,
88 r.wd.global, r.wd.window, r.work,
89 r.td.global, r.td.window, r.start_time, r.end_time,
90 r.perf.global, r.perf.window, r.perf.instant,
91 r.ad.global, r.ad.window, r.accuracy,
92 r.acc.global, r.acc.window, r.acc.instant).as_bytes())
93 }
94
95 pub fn log_to_buffer_index(&mut self) -> io::Result<()> {
97 match self.log {
98 Some(ref mut l) => {
99 for i in 0..self.hb.ws.buffer_index {
100 match HeartbeatAccPow::write_log(self.hbr.get(i as usize).unwrap(), l) {
101 Ok(_) => (),
102 Err(e) => return Err(e),
103 }
104 }
105 l.flush()
106 }
107 None => Ok(())
108 }
109 }
110
111 pub fn get_window_size(&self) -> u64 {
112 unsafe {
113 hb_acc_pow_get_window_size(&self.hb)
114 }
115 }
116
117 pub fn get_user_tag(&self) -> u64 {
118 unsafe {
119 hb_acc_pow_get_user_tag(&self.hb)
120 }
121 }
122
123 pub fn get_global_time(&self) -> u64 {
124 unsafe {
125 hb_acc_pow_get_global_time(&self.hb)
126 }
127 }
128
129 pub fn get_window_time(&self) -> u64 {
130 unsafe {
131 hb_acc_pow_get_window_time(&self.hb)
132 }
133 }
134
135 pub fn get_global_work(&self) -> u64 {
136 unsafe {
137 hb_acc_pow_get_global_work(&self.hb)
138 }
139 }
140
141 pub fn get_window_work(&self) -> u64 {
142 unsafe {
143 hb_acc_pow_get_window_work(&self.hb)
144 }
145 }
146
147 pub fn get_global_perf(&self) -> f64 {
148 unsafe {
149 hb_acc_pow_get_global_perf(&self.hb)
150 }
151 }
152
153 pub fn get_window_perf(&self) -> f64 {
154 unsafe {
155 hb_acc_pow_get_window_perf(&self.hb)
156 }
157 }
158
159 pub fn get_instant_perf(&self) -> f64 {
160 unsafe {
161 hb_acc_pow_get_instant_perf(&self.hb)
162 }
163 }
164
165 pub fn get_global_accuracy(&self) -> u64 {
166 unsafe {
167 hb_acc_pow_get_global_accuracy(&self.hb)
168 }
169 }
170
171 pub fn get_window_accuracy(&self) -> u64 {
172 unsafe {
173 hb_acc_pow_get_window_accuracy(&self.hb)
174 }
175 }
176
177 pub fn get_global_accuracy_rate(&self) -> f64 {
178 unsafe {
179 hb_acc_pow_get_global_accuracy_rate(&self.hb)
180 }
181 }
182
183 pub fn get_window_accuracy_rate(&self) -> f64 {
184 unsafe {
185 hb_acc_pow_get_window_accuracy_rate(&self.hb)
186 }
187 }
188
189 pub fn get_instant_accuracy_rate(&self) -> f64 {
190 unsafe {
191 hb_acc_pow_get_instant_accuracy_rate(&self.hb)
192 }
193 }
194
195 pub fn get_global_energy(&self) -> u64 {
196 unsafe {
197 hb_acc_pow_get_global_energy(&self.hb)
198 }
199 }
200
201 pub fn get_window_energy(&self) -> u64 {
202 unsafe {
203 hb_acc_pow_get_window_energy(&self.hb)
204 }
205 }
206
207 pub fn get_global_power(&self) -> f64 {
208 unsafe {
209 hb_acc_pow_get_global_power(&self.hb)
210 }
211 }
212
213 pub fn get_window_power(&self) -> f64 {
214 unsafe {
215 hb_acc_pow_get_window_power(&self.hb)
216 }
217 }
218
219 pub fn get_instant_power(&self) -> f64 {
220 unsafe {
221 hb_acc_pow_get_instant_power(&self.hb)
222 }
223 }
224}
225
226#[cfg(test)]
227mod test {
228 use super::*;
229 use std::fs::File;
230
231 #[test]
232 fn test_simple() {
233 const TIME_INC: u64 = 1000000000;
234 const ENERGY_INC: u64 = 1000000;
235 let mut hb = HeartbeatAccPow::new(5, None, None).unwrap();
236 let mut start_time: u64 = 0;
237 let mut end_time: u64 = TIME_INC;
238 let mut start_energy: u64 = 0;
239 let mut end_energy: u64 = ENERGY_INC;
240 for tag in 0..10 {
241 hb.heartbeat(tag, 1, start_time, end_time, 1, start_energy, end_energy);
242 start_time = end_time;
243 end_time += TIME_INC;
244 start_energy = end_energy;
245 end_energy += ENERGY_INC;
246 }
247 }
248
249 #[test]
250 fn test_callback() {
251 static mut received_cb: bool = false;
252 extern fn callback(_hb: *const HeartbeatAccPowContext) {
253 unsafe {
254 received_cb = true;
255 }
256 }
257
258 let mut hb = HeartbeatAccPow::new(1, Some(callback), None).unwrap();
259 hb.heartbeat(0, 1, 0, 1000, 1, 0, 0);
260 unsafe {
261 assert!(received_cb);
262 }
263 }
264
265 #[test]
266 fn test_file() {
267 let mut hb = HeartbeatAccPow::new(5, None, Some(File::create("foo.log").unwrap())).unwrap();
268 hb.heartbeat(0, 1, 0, 1000, 1, 0, 0);
269 hb.log_to_buffer_index().unwrap();
270 }
271}