gondola_core/monitoring/heartbeats/
event_builder_hb.rs

1// This file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5use colored::Colorize;
6
7
8#[derive(Debug, Copy, Clone, PartialEq)]
9#[cfg_attr(feature="pybindings", pyclass)]
10pub struct EventBuilderHB {
11  pub version                 : ProtocolVersion,
12  /// Mission elapsed time in seconds
13  pub met_seconds             : u64,
14  /// Total number of received MasterTriggerEvents (from MTB)
15  pub n_mte_received_tot      : u32,
16  /// Total number of received RBEvents (from all RB)
17  pub n_rbe_received_tot      : u32,
18  /// Average number of RBEvents per each MTEvent
19  pub n_rbe_per_te            : u32,
20  /// Total number of discarded RBEvents (accross all boards)
21  pub n_rbe_discarded_tot     : u32,
22  /// TOtal number of missed MTEvents. "Skipped means" gaps in 
23  /// consecutive rising event ids
24  pub n_mte_skipped           : u32,
25  /// Total number of events that timed out, which means they 
26  /// got send before all RBEvents could be associated with 
27  /// this event
28  pub n_timed_out             : u32,
29  /// Total number of events that timed out for the secondary 
30  /// trigger, similar as n_timed out
31  pub n_timed_out_combo       : u32,
32  /// Total number of events passed on to the gloabl data sink 
33  /// thread
34  pub n_sent                  : u32,
35  /// ?
36  pub delta_mte_rbe           : u32,
37  /// The total size of the current event cache in number of events
38  pub event_cache_size        : u32,
39  /// In paralel to the event_cache, the event_id cache holds event ids.
40  /// This should be perfectly aligned to the event_cache by design.
41  pub event_id_cache_size     : u32, 
42  /// The total number of hits which we lost due to the DRS being busy
43  /// (this is on the Readoutboards)
44  pub drs_bsy_lost_hg_hits    : u32,
45  /// The total number of RBEvents which do not have a MasterTriggerEvent
46  pub rbe_wo_mte              : u32,
47  /// The current length of the channel which we use to send events from 
48  /// the MasterTrigger thread to the event builder
49  pub mte_receiver_cbc_len    : u32,
50  /// The current length of the channel whcih we use for all readoutboard
51  /// threads to send their events to the event builder
52  pub rbe_receiver_cbc_len    : u32,
53  /// the current length of the channel which we use to send built events 
54  /// to the global data sink thread
55  pub tp_sender_cbc_len       : u32,
56  /// The total number of RBEvents which have an event id which is SMALLER
57  /// than the smallest event id in the event cache. 
58  pub n_rbe_from_past         : u32,
59  pub n_rbe_orphan            : u32,
60  // let's deprecate this!
61  pub n_rbe_per_loop          : u32,
62  /// The totabl number of events with the "AnyDataMangling" flag set
63  pub data_mangled_ev         : u32,
64  // pub seen_rbevents         : HashMap<u8, usize>,
65  // this will not get serialized - can be filled by 
66  // gcu timestamp 
67  pub timestamp               : u64,
68  // possible new fields for ProtocolVersion::V1
69  // reserved_0 -> used for n_timed_out_sec
70  //pub reserved_0              : u32,
71  pub n_sent_trigger          : u32,
72  pub n_sent_combo_trigger    : u32,
73  pub reserved_3              : u32,
74  pub reserved_4              : u32,
75  pub reserved_5              : u32,
76  pub reserved_6              : u32,
77  pub reserved_7              : u32,
78  pub reserved_8              : u32,
79  pub reserved_9              : u32,
80  pub reserved_10             : u32,
81  pub reserved_11             : u32,
82  pub reserved_12             : u32,
83  pub reserved_13             : u32,
84  pub reserved_14             : u32,
85  pub reserved_15             : u32,
86  pub reserved_16             : u32,
87  pub reserved_17             : u32,
88  pub reserved_18             : u32,
89  pub reserved_19             : u32,
90}
91
92impl EventBuilderHB {
93  pub fn new() -> Self {
94    Self {
95      // from now on, set new heartbeats to version 
96      // V1. This allows to read the new fields
97      version              : ProtocolVersion::V1,
98      met_seconds          : 0,
99      n_mte_received_tot   : 0,
100      n_rbe_received_tot   : 0,
101      n_rbe_per_te         : 0,
102      n_rbe_discarded_tot  : 0,
103      n_mte_skipped        : 0,
104      n_timed_out          : 0,
105      n_timed_out_combo    : 0,
106      n_sent               : 0,
107      delta_mte_rbe        : 0,
108      event_cache_size     : 0,
109      event_id_cache_size  : 0,
110      drs_bsy_lost_hg_hits : 0,
111      rbe_wo_mte           : 0,
112      mte_receiver_cbc_len : 0,
113      rbe_receiver_cbc_len : 0,
114      tp_sender_cbc_len    : 0,
115      n_rbe_per_loop       : 0,
116      n_rbe_orphan         : 0,
117      n_rbe_from_past      : 0,
118      data_mangled_ev      : 0,
119      // seen_rbevents        : seen_rbevents, 
120      timestamp            : 0,
121      // used for n_timeout_combo
122      //reserved_0           : 0,
123      n_sent_trigger       : 0,
124      n_sent_combo_trigger : 0,
125      reserved_3           : 0,
126      reserved_4           : 0,
127      reserved_5           : 0,
128      reserved_6           : 0,
129      reserved_7           : 0,
130      reserved_8           : 0,
131      reserved_9           : 0,
132      reserved_10          : 0,
133      reserved_11          : 0,
134      reserved_12          : 0,
135      reserved_13          : 0,
136      reserved_14          : 0,
137      reserved_15          : 0,
138      reserved_16          : 0,
139      reserved_17          : 0,
140      reserved_18          : 0,
141      reserved_19          : 0
142    }
143  }
144
145  /// The average number of RBEvents per
146  /// TofEvent, tis is the average number
147  /// of active ReadoutBoards per TofEvent
148  pub fn get_average_rbe_te(&self) -> f64 {
149   if self.n_sent > 0 {
150     return self.n_rbe_per_te as f64 / self.n_sent as f64;
151   }
152   0.0
153  }
154
155  pub fn get_timed_out_frac(&self) -> f64 {
156    if self.n_sent > 0 {
157      return (self.n_timed_out + self.n_timed_out_combo) as f64  / self.n_sent as f64;
158    }
159    0.0
160  }
161  
162  pub fn get_timed_out_combo_frac(&self) -> f64 {
163    if self.n_sent > 0 {
164      return self.n_timed_out_combo as f64 / self.n_sent_combo_trigger as f64;
165    }
166    0.0
167  }
168  
169  pub fn get_timed_out_trigger_frac(&self) -> f64 {
170    if self.n_sent_trigger > 0 {
171      return self.n_timed_out as f64 / self.n_sent_trigger as f64;
172    }
173    0.0
174  }
175
176  // pub fn add_rbevent(&mut self, rb_id : u8) {
177  //   *self.seen_rbevents.get_mut(&rb_id).unwrap() += 1;
178  // }
179  
180  pub fn get_incoming_vs_outgoing_mte(&self) -> f64 {
181    if self.n_sent > 0 {
182      return self.n_mte_received_tot as f64 /  self.n_sent as f64;
183    }
184    0.0
185  }
186
187  pub fn get_nrbe_discarded_frac(&self) -> f64 {
188    if self.n_rbe_received_tot > 0 {
189     return self.n_rbe_discarded_tot as f64 / self.n_rbe_received_tot as f64;
190   }
191   0.0
192  }
193  
194  pub fn get_mangled_frac(&self) -> f64 {
195    if self.n_mte_received_tot > 0 {
196     return self.data_mangled_ev as f64 / self.n_mte_received_tot as f64;
197   }
198   0.0
199  }
200
201  pub fn get_drs_lost_frac(&self) -> f64 {
202    if self.n_rbe_received_tot > 0 {
203      return self.drs_bsy_lost_hg_hits as f64 / self.n_rbe_received_tot as f64;
204    }
205    0.0
206  }
207
208  pub fn pretty_print(&self) -> String {
209    let mut repr = String::from("");
210    repr += &(format!("\n \u{2B50} \u{2B50} \u{2B50} \u{2B50} \u{2B50} EVENTBUILDER HEARTBTEAT \u{2B50} \u{2B50} \u{2B50} \u{2B50} \u{2B50} "));
211    repr += &(format!("\n Mission elapsed time (MET) [s]             : {}", self.met_seconds).bright_purple());
212    repr += &(format!("\n Num. TofEvents sent                        : {}", self.n_sent).bright_purple());
213    repr += &(format!("\n"));
214    repr += &(format!("\n Size of event cache                        : {}", self.event_cache_size).bright_purple());
215    //repr += &(format!("\n Size of event ID cache                     : {}", self.event_id_cache_size).bright_purple());
216    repr += &(format!("\n"));
217    repr += &(format!("\n Num. TofEvents timed out                   : {}", self.n_timed_out).bright_purple());
218    repr += &(format!("\n Num. TofEvents timed out (combo)           : {}", self.n_timed_out_combo).bright_purple());
219    repr += &(format!("\n Percent events timed out                   : {:.2}%", self.get_timed_out_trigger_frac()*(100 as f64)).bright_purple());
220    repr += &(format!("\n Percent events timed out (combo)           : {:.2}%", self.get_timed_out_combo_frac()*(100 as f64)).bright_purple());
221    if self.n_mte_received_tot > 0{ 
222      repr += &(format!("\n \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504}"));
223      repr += &(format!("\n Num. evts with ANY data mangling           : {}"     , self.data_mangled_ev));
224      repr += &(format!("\n Per. evts with ANY data mangling           : {:.2}%" , self.get_mangled_frac()*(100 as f64)));
225    }
226    else {repr += &(format!("\n Percent events with data mangling: unable to calculate"));}
227    repr += &(format!("\n \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504}"));
228    repr += &(format!("\n Received MTEvents (from MTB)               : {}", self.n_mte_received_tot).bright_purple());
229    repr += &(format!("\n Skipped MTEvents (gaps in rising event ids): {}", self.n_mte_skipped).bright_purple());
230    repr += &(format!("\n Num. MTBEvevents / Num. TofEvents sent     : {:.2}", self.get_incoming_vs_outgoing_mte()).bright_purple());
231    repr += &(format!("\n \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504}"));
232    repr += &(format!("\n Received RBEvents                          : {}", self.n_rbe_received_tot).bright_purple());
233    repr += &(format!("\n RBEvents Discarded Total                   : {}", self.n_rbe_discarded_tot).bright_purple());
234    repr += &(format!("\n Percent RBEvents discarded                 : {:.2}%", self.get_nrbe_discarded_frac()*(100 as f64)).bright_purple());
235    repr += &(format!("\n DRS4 busy lost RBEvents                    : {}", self.drs_bsy_lost_hg_hits).bright_purple());
236    repr += &(format!("\n Percent DRS4 busy lost RBEvents            : {:.2}%", self.get_drs_lost_frac()*(100.0 as f64)).bright_purple());
237    repr += &(format!("\n"));
238    repr += &(format!("\n Num. RBEvents with evid from past          : {}",  self.n_rbe_from_past).bright_purple());
239    repr += &(format!("\n Num. RBEvents with evid from future        : {}",  self.n_rbe_orphan).bright_purple());
240    repr += &(format!("\n RBEvents which do not find their MTEvent \n
241                      in the channel on the first try                : {}", self.rbe_wo_mte).bright_blue());
242    if self.n_sent > 0 && self.n_mte_received_tot > 0 {
243        repr += &(format!("\n"));
244        repr += &(format!("\n num. RBEvents / num. TofEvts sent           : {:.2}", (self.n_rbe_received_tot as f64/ self.n_sent as f64)).bright_purple());
245        repr += &(format!("\n num. RBEvents / num. MTEvents received      : {:.2}", (self.n_rbe_received_tot as f64 / self.n_mte_received_tot as f64)).bright_purple()); }
246    repr += &(format!("\n n_rbe_per_loop                                  : {:.2}", self.n_rbe_per_loop).bright_purple());
247    repr += &(format!("\n \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504} \u{2504}"));
248    repr += &(format!("\n Ch. len MTE Receiver                      : {}", self.mte_receiver_cbc_len).bright_purple());
249    repr += &(format!("\n Ch. len RBE Receiver                      : {}", self.rbe_receiver_cbc_len).bright_purple());
250    repr += &(format!("\n Ch. len TP Sender                         : {}", self.tp_sender_cbc_len).bright_purple());
251    repr += &(format!("\n \u{2B50} \u{2B50} \u{2B50} \u{2B50} \u{2B50} END EVENTBUILDER HEARTBTEAT \u{2B50} \u{2B50} \u{2B50} \u{2B50} \u{2B50}"));
252    repr
253  }
254}
255
256
257impl MoniData for EventBuilderHB {
258  fn get_board_id(&self) -> u8 {
259    0
260  }
261 
262  fn get_timestamp(&self) -> u64 { 
263    if self.timestamp == 0 {
264      return self.met_seconds;
265    } else {  
266      return self.timestamp; 
267    }
268  }
269
270  fn set_timestamp(&mut self, ts : u64) {
271    self.timestamp = ts;
272  }
273
274  /// Access the (data) members by name 
275  fn get(&self, varname : &str) -> Option<f32> {
276    match varname {
277      "board_id"             => Some(0.0),
278      "met_seconds"          => Some(self.met_seconds as f32),
279      "n_mte_received_tot"   => Some(self.n_mte_received_tot as f32),
280      "n_rbe_received_tot"   => Some(self.n_rbe_received_tot as f32),
281      "n_rbe_per_te"         => Some(self.n_rbe_per_te as f32),
282      "n_rbe_discarded_tot"  => Some(self.n_rbe_discarded_tot as f32),
283      "n_mte_skipped"        => Some(self.n_mte_skipped as f32),
284      "n_timed_out"          => Some(self.n_timed_out as f32),
285      "n_timed_out_combo"    => Some(self.n_timed_out_combo as f32),
286      "n_sent"               => Some(self.n_sent as f32),
287      "delta_mte_rbe"        => Some(self.delta_mte_rbe as f32),
288      "event_cache_size"     => Some(self.event_cache_size as f32),
289      "event_id_cache_size"  => Some(self.event_id_cache_size as f32),
290      "drs_bsy_lost_hg_hits" => Some(self.drs_bsy_lost_hg_hits as f32),
291      "rbe_wo_mte"           => Some(self.rbe_wo_mte as f32),
292      "mte_receiver_cbc_len" => Some(self.mte_receiver_cbc_len as f32),
293      "rbe_receiver_cbc_len" => Some(self.rbe_receiver_cbc_len as f32),
294      "tp_sender_cbc_len"    => Some(self.tp_sender_cbc_len as f32),
295      "n_rbe_per_loop"       => Some(self.n_rbe_per_loop as f32),
296      "n_rbe_orphan"         => Some(self.n_rbe_orphan as f32),
297      "n_rbe_from_past"      => Some(self.n_rbe_from_past as f32),
298      "data_mangled_ev"      => Some(self.data_mangled_ev as f32),
299      "timestamp"            => Some(self.timestamp as f32),
300      _                      => None
301    }
302  }
303
304  /// A list of the variables in this MoniData
305  fn keys() -> Vec<&'static str> {
306    vec!["board_id", "met_seconds", "n_mte_received_tot",
307         "n_rbe_received_tot", "n_rbe_per_te", "n_rbe_discarded_tot",
308         "n_mte_skipped", "n_timed_out", "n_timed_out_combo", "n_sent", "delta_mte_rbe",
309         "n_sent_trigger", "n_sent_combo_trigger",
310         "event_cache_size", "event_id_cache_size","drs_bsy_lost_hg_hits",
311         "rbe_wo_mte", "mte_receiver_cbc_len", "rbe_receiver_cbc_len",
312         "tp_sender_cbc_len", "n_rbe_per_loop", "n_rbe_orphan", "n_rbe_from_past",
313         "data_mangled_ev", "timestamp"]
314  }
315}
316
317moniseries!(EventBuilderHBSeries,EventBuilderHB);
318
319#[cfg(feature="pybindings")]
320#[pymethods]
321impl EventBuilderHB {
322  /// The average number of RBEvents per
323  /// TofEvent, tis is the average number
324  /// of active ReadoutBoards per TofEvent
325  #[getter]
326  #[pyo3(name="average_rbe_te")]
327  fn get_average_rbe_te_py(&self) -> f64 {
328    self.get_average_rbe_te()
329  }
330
331  #[getter]
332  #[pyo3(name="timed_out_frac")]
333  pub fn get_timed_out_frac_py(&self) -> f64 {
334    self.get_timed_out_frac()
335  }
336  
337  #[getter]
338  #[pyo3(name="timed_out_combo_frac")]
339  pub fn get_timed_out_combo_frac_py(&self) -> f64 {
340    self.get_timed_out_combo_frac()
341  }
342 
343  #[getter]
344  #[pyo3(name="incoming_vs_outgoing_mte")]
345  pub fn get_incoming_vs_outgoing_mte_py(&self) -> f64 {
346    self.get_incoming_vs_outgoing_mte()
347  }
348
349  #[getter]
350  #[pyo3(name="nrbe_discarded_frac")]
351  pub fn get_nrbe_discarded_frac_py(&self) -> f64 {
352    self.get_nrbe_discarded_frac()
353  }
354  
355  #[getter]
356  #[pyo3(name="mangled_frac")]
357  pub fn get_mangled_frac_py(&self) -> f64 {
358    self.get_mangled_frac()
359  }
360
361  #[getter]
362  #[pyo3(name="drs_lost_frac")]
363  pub fn get_drs_lost_frac_py(&self) -> f64 {
364    self.get_drs_lost_frac()
365  }  
366}
367
368#[cfg(feature="pybindings")]
369pythonize_monidata!(EventBuilderHB);
370#[cfg(feature="pybindings")]
371pythonize_packable!(EventBuilderHB);
372
373//-----------------------------------------------------
374
375impl Default for EventBuilderHB {
376  fn default () -> Self {
377    Self::new()
378  }
379}
380
381impl TofPackable for EventBuilderHB {
382  const TOF_PACKET_TYPE : TofPacketType = TofPacketType::EventBuilderHB;
383}
384
385impl Serialization for EventBuilderHB {
386  const HEAD : u16 = 0xAAAA;
387  const TAIL : u16 = 0x5555;
388  const SIZE : usize = 156; //
389
390  fn from_bytestream(stream : &Vec<u8>, 
391                     pos        : &mut usize)
392    -> Result<Self, SerializationError>{
393    Self::verify_fixed(stream,pos)?;
394    let mut hb = EventBuilderHB::new();
395    let version_seconds     = parse_u64(stream,pos);
396    hb.version              = ProtocolVersion::from(((version_seconds & 0xC000000000000000) >> 56) as u8); 
397    let met_seconds         = version_seconds & 0x3FFFFFFFFFFFFFFF;
398    hb.met_seconds          = met_seconds;
399    //hb.met_seconds          = parse_u64(stream,pos);
400    if hb.version == ProtocolVersion::V1 {
401      hb.n_mte_received_tot   = parse_u32(stream,pos);
402      hb.n_rbe_received_tot   = parse_u32(stream,pos);
403      hb.n_rbe_per_te         = parse_u32(stream,pos);
404      hb.n_rbe_discarded_tot  = parse_u32(stream,pos);
405      hb.n_mte_skipped        = parse_u32(stream,pos);
406      hb.n_timed_out          = parse_u32(stream,pos);
407      hb.n_sent               = parse_u32(stream,pos);
408      hb.delta_mte_rbe        = parse_u32(stream,pos);
409      hb.event_cache_size     = parse_u32(stream,pos);
410      //hb.event_id_cache_size  = parse_u64(stream,pos);
411      hb.drs_bsy_lost_hg_hits = parse_u32(stream,pos);
412      hb.rbe_wo_mte           = parse_u32(stream,pos);
413      hb.mte_receiver_cbc_len = parse_u32(stream,pos);
414      hb.rbe_receiver_cbc_len = parse_u32(stream,pos);
415      hb.tp_sender_cbc_len    = parse_u32(stream,pos);
416      hb.n_rbe_per_loop       = parse_u32(stream,pos);
417      hb.n_rbe_from_past      = parse_u32(stream,pos);
418      hb.n_rbe_orphan         = parse_u32(stream,pos);
419      hb.data_mangled_ev      = parse_u32(stream,pos);
420      hb.n_timed_out_combo    = parse_u32(stream, pos);
421      hb.n_sent_trigger       = parse_u32(stream, pos);
422      hb.n_sent_combo_trigger = parse_u32(stream, pos);
423      hb.reserved_3           = parse_u32(stream, pos);
424      hb.reserved_4           = parse_u32(stream, pos);
425      hb.reserved_5           = parse_u32(stream, pos);
426      hb.reserved_6           = parse_u32(stream, pos);
427      hb.reserved_7           = parse_u32(stream, pos);
428      hb.reserved_8           = parse_u32(stream, pos);
429      hb.reserved_9           = parse_u32(stream, pos);
430      hb.reserved_10          = parse_u32(stream, pos);
431      hb.reserved_11          = parse_u32(stream, pos);
432      hb.reserved_12          = parse_u32(stream, pos);
433      hb.reserved_13          = parse_u32(stream, pos);
434      hb.reserved_14          = parse_u32(stream, pos);
435      hb.reserved_15          = parse_u32(stream, pos);
436      hb.reserved_16          = parse_u32(stream, pos);
437      hb.reserved_17          = parse_u32(stream, pos);
438      //hb.reserved_18          = parse_u32(stream, pos);
439      //hb.reserved_19          = parse_u32(stream, pos);
440    } else {
441      hb.n_mte_received_tot   = parse_u64(stream,pos) as u32;
442      hb.n_rbe_received_tot   = parse_u64(stream,pos) as u32;
443      hb.n_rbe_per_te         = parse_u64(stream,pos) as u32;
444      hb.n_rbe_discarded_tot  = parse_u64(stream,pos) as u32;
445      hb.n_mte_skipped        = parse_u64(stream,pos) as u32;
446      hb.n_timed_out          = parse_u64(stream,pos) as u32;
447      hb.n_sent               = parse_u64(stream,pos) as u32;
448      hb.delta_mte_rbe        = parse_u64(stream,pos) as u32;
449      hb.event_cache_size     = parse_u64(stream,pos) as u32;
450      //hb.event_id_cache_size  = parse_u64(stream,po as u32s);
451      hb.drs_bsy_lost_hg_hits = parse_u64(stream,pos) as u32;
452      hb.rbe_wo_mte           = parse_u64(stream,pos) as u32;
453      hb.mte_receiver_cbc_len = parse_u64(stream,pos) as u32;
454      hb.rbe_receiver_cbc_len = parse_u64(stream,pos) as u32;
455      hb.tp_sender_cbc_len    = parse_u64(stream,pos) as u32;
456      hb.n_rbe_per_loop       = parse_u64(stream,pos) as u32;
457      hb.n_rbe_from_past      = parse_u64(stream,pos) as u32;
458      hb.n_rbe_orphan         = parse_u64(stream,pos) as u32;
459      hb.data_mangled_ev      = parse_u64(stream,pos) as u32;
460    }
461    // hb.seen_rbevents        = HashMap::from(parse_u8(stream, pos));
462    *pos += 2;
463    Ok(hb)
464  }
465    
466  fn to_bytestream(&self) -> Vec<u8> {
467    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
468    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
469    let mut version_seconds = (self.version as u64) << 56; 
470    version_seconds = version_seconds | self.met_seconds;
471    //panic!("{}", ((version_seconds & 0xC000000000000000) >> 62) as u8);
472    bs.extend_from_slice(&version_seconds.to_le_bytes());
473    bs.extend_from_slice(&self.n_mte_received_tot.to_le_bytes());
474    bs.extend_from_slice(&self.n_rbe_received_tot.to_le_bytes());
475    bs.extend_from_slice(&self.n_rbe_per_te.to_le_bytes());
476    bs.extend_from_slice(&self.n_rbe_discarded_tot.to_le_bytes());
477    bs.extend_from_slice(&self.n_mte_skipped.to_le_bytes());
478    bs.extend_from_slice(&self.n_timed_out.to_le_bytes());
479    bs.extend_from_slice(&self.n_sent.to_le_bytes());
480    bs.extend_from_slice(&self.delta_mte_rbe.to_le_bytes());
481    bs.extend_from_slice(&self.event_cache_size.to_le_bytes());
482    //bs.extend_from_slice(&self.event_id_cache_size.to_le_bytes());
483    bs.extend_from_slice(&self.drs_bsy_lost_hg_hits.to_le_bytes());
484    bs.extend_from_slice(&self.rbe_wo_mte.to_le_bytes());
485    bs.extend_from_slice(&self.mte_receiver_cbc_len.to_le_bytes());
486    bs.extend_from_slice(&self.rbe_receiver_cbc_len.to_le_bytes());
487    bs.extend_from_slice(&self.tp_sender_cbc_len.to_le_bytes());
488    bs.extend_from_slice(&self.n_rbe_per_loop.to_le_bytes());
489    bs.extend_from_slice(&self.n_rbe_from_past.to_le_bytes());
490    bs.extend_from_slice(&self.n_rbe_orphan.to_le_bytes());
491    bs.extend_from_slice(&self.data_mangled_ev.to_le_bytes());
492    // bs.push(self.seen_rbevents.to_u8());
493    //if self.version == ProtocolVersion::V1 {
494    bs.extend_from_slice(&self.n_timed_out_combo.to_le_bytes());
495    bs.extend_from_slice(&self.n_sent_trigger.to_le_bytes());
496    bs.extend_from_slice(&self.n_sent_combo_trigger.to_le_bytes());
497    bs.extend_from_slice(&self.reserved_3.to_le_bytes());
498    bs.extend_from_slice(&self.reserved_4.to_le_bytes());
499    bs.extend_from_slice(&self.reserved_5.to_le_bytes());
500    bs.extend_from_slice(&self.reserved_6.to_le_bytes());
501    bs.extend_from_slice(&self.reserved_7.to_le_bytes());
502    bs.extend_from_slice(&self.reserved_8.to_le_bytes());
503    bs.extend_from_slice(&self.reserved_9.to_le_bytes());
504    bs.extend_from_slice(&self.reserved_10.to_le_bytes());
505    bs.extend_from_slice(&self.reserved_11.to_le_bytes());
506    bs.extend_from_slice(&self.reserved_12.to_le_bytes());
507    bs.extend_from_slice(&self.reserved_13.to_le_bytes());
508    bs.extend_from_slice(&self.reserved_14.to_le_bytes());
509    bs.extend_from_slice(&self.reserved_15.to_le_bytes());
510    bs.extend_from_slice(&self.reserved_16.to_le_bytes());
511    bs.extend_from_slice(&self.reserved_17.to_le_bytes());
512    //bs.extend_from_slice(&self.reserved_18.to_le_bytes());
513    //bs.extend_from_slice(&self.reserved_19.to_le_bytes());
514    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
515    bs
516  }
517}
518
519#[cfg(feature="random")]
520impl FromRandom for EventBuilderHB {
521  fn from_random() -> Self {
522    let mut rng              = rand::rng();
523    // this test can only do ProtocolVersion V1
524    let version = ProtocolVersion::V1;
525    Self {
526      // FIXME 
527      version                : version,
528      met_seconds            : rng.random::<u64>() & 0x3FFFFFFFFFFFFFFF,
529      n_rbe_received_tot     : rng.random::<u32>(),
530      n_rbe_per_te           : rng.random::<u32>(),
531      n_rbe_discarded_tot    : rng.random::<u32>(),
532      n_mte_skipped          : rng.random::<u32>(),
533      n_timed_out            : rng.random::<u32>(),
534      n_timed_out_combo      : rng.random::<u32>(),
535      n_sent                 : rng.random::<u32>(),
536      delta_mte_rbe          : rng.random::<u32>(),
537      event_cache_size       : rng.random::<u32>(),
538      // don't randomize this, since it 
539      // won't get serialized
540      event_id_cache_size    :                   0,
541
542      drs_bsy_lost_hg_hits   : rng.random::<u32>(),
543      rbe_wo_mte             : rng.random::<u32>(),
544      mte_receiver_cbc_len   : rng.random::<u32>(),
545      rbe_receiver_cbc_len   : rng.random::<u32>(),
546      tp_sender_cbc_len      : rng.random::<u32>(),
547      n_mte_received_tot     : rng.random::<u32>(),
548      n_rbe_per_loop         : rng.random::<u32>(),
549      n_rbe_from_past        : rng.random::<u32>(),
550      n_rbe_orphan           : rng.random::<u32>(),
551      data_mangled_ev        : rng.random::<u32>(),
552      timestamp              : 0, // this will get set later or 
553                                  // used by MoniSeries
554      
555      //reserved_0             : 0,
556      //reserved_1             : 0,
557      //reserved_2             : 0,
558      //reserved_3             : 0,
559      //reserved_4             : 0,
560      //reserved_5             : 0,
561      //reserved_6             : 0,
562      //reserved_7             : 0,
563      //reserved_8             : 0,
564      //reserved_9             : 0,
565      //reserved_10            : 0,
566      //reserved_11            : 0,
567      //reserved_12            : 0,
568      //reserved_13            : 0,
569      //reserved_14            : 0,
570      //reserved_15            : 0,
571      //reserved_16            : 0,
572      //reserved_17            : 0,
573      reserved_18            : 0,
574      reserved_19            : 0,
575      //reserved_0             : rng.random::<u32>(),
576      n_sent_trigger         : rng.random::<u32>(),
577      n_sent_combo_trigger   : rng.random::<u32>(),
578      reserved_3             : rng.random::<u32>(),
579      reserved_4             : rng.random::<u32>(),
580      reserved_5             : rng.random::<u32>(),
581      reserved_6             : rng.random::<u32>(),
582      reserved_7             : rng.random::<u32>(),
583      reserved_8             : rng.random::<u32>(),
584      reserved_9             : rng.random::<u32>(),
585      reserved_10            : rng.random::<u32>(),
586      reserved_11            : rng.random::<u32>(),
587      reserved_12            : rng.random::<u32>(),
588      reserved_13            : rng.random::<u32>(),
589      reserved_14            : rng.random::<u32>(),
590      reserved_15            : rng.random::<u32>(),
591      reserved_16            : rng.random::<u32>(),
592      reserved_17            : rng.random::<u32>(),
593      //reserved_18            : rng.random::<u32>(),
594      //reserved_19            : rng.random::<u32>(),
595    }
596  }
597} 
598
599impl fmt::Display for EventBuilderHB {
600  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
601    let mut repr = String::from("<EVTBLDRHearbeat:   ");
602    repr += &self.pretty_print();
603    write!(f, "{}>", repr)
604  }
605}  
606
607#[cfg(feature="random")]
608#[test]
609fn pack_eventbuilderhb() {
610  for _ in 0..100 {
611    let hb = EventBuilderHB::from_random();
612    let test : EventBuilderHB = hb.pack().unpack().unwrap();
613    assert_eq!(hb, test);
614  }
615}
616