gondola_core/io/
tof_writer.rs

1// The following file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5
6/// Write TofPackets to disk.
7///
8/// Operates sequentially, packets can 
9/// be added one at a time, then will
10/// be synced to disk.
11pub struct TofPacketWriter {
12
13  pub file            : File,
14  /// location to store the file
15  pub file_path       : String,
16  /// The maximum number of packets 
17  /// for a single file. Ater this 
18  /// number is reached, a new 
19  /// file is started.
20  pub pkts_per_file   : usize,
21  /// The maximum number of (Mega)bytes
22  /// per file. After this a new file 
23  /// is started
24  pub mbytes_per_file : usize,
25  /// add timestamps to filenames
26  pub file_type       : FileType,
27  pub file_name       : String,
28
29  file_id             : usize,
30  /// internal packet counter, number of 
31  /// packets which went through the writer
32  n_packets           : usize,
33  /// internal counter for bytes written in 
34  /// this file
35  file_nbytes_wr      : usize,
36}
37
38impl TofPacketWriter {
39
40  /// Instantiate a new PacketWriter 
41  ///
42  /// # Arguments
43  ///
44  /// * file_prefix     : Prefix file with this string. A continuous number will get 
45  ///                     appended to control the file size.
46  /// * file_type       : control the behaviour of how the filename is
47  ///                     assigned.
48  pub fn new(mut file_path : String, file_type : FileType) -> Self {
49    //let filename = file_prefix.clone() + "_0.tof.gaps";
50    let file : File;
51    let file_name : String;
52    if !file_path.ends_with("/") {
53      file_path += "/";
54    }
55    match file_type {
56      FileType::Unknown => {
57        let filename = file_path.clone() + "Data.tof.gaps";
58        let path     = Path::new(&filename); 
59        info!("Writing to file {filename}");
60        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
61        file_name = filename;
62      }
63      FileType::RunFile(runid) => {
64        let filename = format!("{}{}", file_path, get_runfilename(runid, 0, None, None));
65        let path     = Path::new(&filename); 
66        println!("Writing to file {filename}");
67        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
68        file_name = filename;
69      }
70      FileType::CalibrationFile(rbid) => {
71        let filename = format!("{}{}", file_path, get_califilename(rbid, false));
72        //let filename = file_path.clone() + &get_califilename(rbid,false);
73        let path     = Path::new(&filename); 
74        info!("Writing to file {filename}");
75        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
76        file_name = filename;
77      }
78      FileType::SummaryFile(ref fname) => {
79        let filename = fname.replace(".tof.", ".tofsum.");
80        let path     = Path::new(&filename);
81        info!("Writing to file {filename}");
82        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
83        file_name = filename;
84      }
85    }
86    Self {
87      file,
88      file_path        : file_path,
89      pkts_per_file    : 0,
90      mbytes_per_file  : 420,
91      file_nbytes_wr   : 0,    
92      file_type        : file_type,
93      file_id          : 1,
94      n_packets        : 0,
95      file_name        : file_name,
96    }
97  }
98
99  pub fn get_file(&self) -> File { 
100    let file : File;
101    match &self.file_type {
102      FileType::Unknown => {
103        let filename = self.file_path.clone() + "Data.tof.gaps";
104        let path     = Path::new(&filename); 
105        info!("Writing to file {filename}");
106        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
107      }
108      FileType::RunFile(runid) => {
109        let filename = format!("{}{}", self.file_path, get_runfilename(*runid, self.file_id as u64, None, None));
110        //let filename = self.file_path.clone() + &get_runfilename(runid,self.file_id as u64, None);
111        let path     = Path::new(&filename); 
112        info!("Writing to file {filename}");
113        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
114      }
115      FileType::CalibrationFile(rbid) => {
116        //let filename = self.file_path.clone() + &get_califilename(rbid,false);
117        let filename = format!("{}{}", self.file_path, get_califilename(*rbid, false));
118        let path     = Path::new(&filename); 
119        info!("Writing to file {filename}");
120        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
121      }
122      FileType::SummaryFile(fname) => {
123        let filename = fname.replace(".tof.", ".tofsum.");
124        let path     = Path::new(&filename);
125        info!("Writing to file {filename}");
126        file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
127      }
128    }
129    file
130  }
131
132  /// Induce serialization to disk for a TofPacket
133  ///
134  ///
135  pub fn add_tof_packet(&mut self, packet : &TofPacket) {
136    let buffer = packet.to_bytestream();
137    self.file_nbytes_wr += buffer.len();
138    match self.file.write_all(buffer.as_slice()) {
139      Err(err) => error!("Writing to file to path {} failed! {}", self.file_path, err),
140      Ok(_)    => ()
141    }
142    self.n_packets += 1;
143    let mut newfile = false;
144    if self.pkts_per_file != 0 {
145      if self.n_packets == self.pkts_per_file {
146        newfile = true;
147        self.n_packets = 0;
148      }
149    } else if self.mbytes_per_file != 0 {
150      // multiply by mebibyte
151      if self.file_nbytes_wr >= self.mbytes_per_file * 1_048_576 {
152        newfile = true;
153        self.file_nbytes_wr = 0;
154      }
155    }
156    if newfile {
157        //let filename = self.file_prefix.clone() + "_" + &self.file_id.to_string() + ".tof.gaps";
158        match self.file.sync_all() {
159          Err(err) => {
160            error!("Unable to sync file to disc! {err}");
161          },
162          Ok(_) => ()
163        }
164        self.file = self.get_file();
165        self.file_id += 1;
166        //let path  = Path::new(&filename);
167        //println!("==> [TOFPACKETWRITER] Will start a new file {}", path.display());
168        //self.file = OpenOptions::new().create(true).append(true).open(path).expect("Unable to open file {filename}");
169        //self.n_packets = 0;
170        //self.file_id += 1;
171      }
172  debug!("TofPacket written!");
173  }
174}
175
176impl Default for TofPacketWriter {
177  fn default() -> TofPacketWriter {
178    TofPacketWriter::new(String::from(""), FileType::Unknown)
179  }
180}
181