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