Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEventWriterEVIO.cc
Go to the documentation of this file.
1 #include "DEventWriterEVIO.h"
2 #include "DAQ/DL1Info.h"
3 
5 
6 
8 {
9  // must be read/used entirely in "EVIOWriter" lock
10  static size_t locEVIONumOutputThreads = 0;
11  return locEVIONumOutputThreads;
12 }
13 
14 map<string, HDEVIOWriter*>& DEventWriterEVIO::Get_EVIOOutputters(void) const
15 {
16  // must be read/used entirely in "EVIOWriter" lock
17  static map<string, HDEVIOWriter*> locEVIOOutputters;
18  return locEVIOOutputters;
19 }
20 
21 map<string, DEVIOBufferWriter*>& DEventWriterEVIO::Get_EVIOBufferWriters(void) const
22 {
23  // must be read/used entirely in "EVIOWriter" lock
24  static map<string, DEVIOBufferWriter*> locEVIOBufferWriters;
25  return locEVIOBufferWriters;
26 }
27 
28 map<string, pthread_t>& DEventWriterEVIO::Get_EVIOOutputThreads(void) const
29 {
30  // must be read/used entirely in "EVIOWriter" lock
31  static map<string, pthread_t> locEVIOOutputThreads;
32  return locEVIOOutputThreads;
33 }
34 
35 DEventWriterEVIO::DEventWriterEVIO(JEventLoop* locEventLoop)
36 {
37  COMPACT = true;
38  PREFER_EMULATED = false;
39  DEBUG_FILES = false; // n.b. also defined in HDEVIOWriter
40  dMergeFiles = false;
41  dMergedFilename = "merged.evio";
42 
43  ofs_debug_input = NULL;
44  ofs_debug_output = NULL;
45 
46  gPARMS->SetDefaultParameter("EVIOOUT:COMPACT" , COMPACT, "Drop words where we can to reduce output file size. This shouldn't loose any vital information, but can be turned off to help with debugging.");
47  gPARMS->SetDefaultParameter("EVIOOUT:PREFER_EMULATED" , PREFER_EMULATED, "If true, then sample data will not be written to output, but emulated hits will. Otherwise, do exactly the opposite.");
48  gPARMS->SetDefaultParameter("EVIOOUT:DEBUG_FILES" , DEBUG_FILES, "Write input and output debug files in addition to the standard output.");
49 
50  //buffer_writer = new DEVIOBufferWriter(COMPACT, PREFER_EMULATED);
51 
52  // save a pointer to the translation table
53  ttab = NULL;
54  locEventLoop->GetSingle(ttab);
55 
56  // initialize file-level variables
57  japp->WriteLock("EVIOWriter");
58  {
60  }
61  japp->Unlock("EVIOWriter");
62 
63  if(DEBUG_FILES){
64  ofs_debug_input = new ofstream("hdevio_debug_input.evio");
65  if( !ofs_debug_input->is_open() ){
66  jerr << "Unable to open \"hdevio_debug_input.evio\"!" << endl;
67  delete ofs_debug_input;
68  ofs_debug_input = NULL;
69  }else{
70  jout << "Opened \"hdevio_debug_input.evio\" for debug output" << endl;
71  }
72 
73  ofs_debug_output = new ofstream("hdevio_debug_output_preswap.evio");
74  if( !ofs_debug_output->is_open() ){
75  jerr << "Unable to open \"hdevio_debug_output_preswap.evio\"!" << endl;
76  delete ofs_debug_output;
77  ofs_debug_output = NULL;
78  }else{
79  jout << "Opened \"hdevio_debug_output_preswap.evio\" for debug output" << endl;
80  }
81  }
82 }
83 
84 
85 void DEventWriterEVIO::SetDetectorsToWriteOut(string detector_list, string locOutputFileNameSubString) const
86 {
87  // Allow users to set only some detectors to be written out
88  // The list of detectors is set on a per-file basis
89  // and the list is the same as given in DTranslationTable
90 
91  if(ttab == NULL) {
92  jerr << "Tried to set values in DEventWriterEVIO::SetDetectorsToWriteOut() but translation table not loaded!" << endl;
93  return;
94  }
95 
96  // sanity check
97  japp->WriteLock("EVIOWriter");
98  if(Get_EVIOBufferWriters().find(locOutputFileNameSubString) == Get_EVIOBufferWriters().end()) {
99  japp->Unlock("EVIOWriter");
100  // file must not have been created?
101  return;
102  }
103  japp->Unlock("EVIOWriter");
104 
105 
106  // create new roc output list
107  set<uint32_t> rocs_to_write_out;
108 
109  // if given a blank list, assume we should write everything out
110  if(detector_list == "") {
111  japp->WriteLock("EVIOWriter");
112  Get_EVIOBufferWriters()[locOutputFileNameSubString]->SetROCsToWriteOut(rocs_to_write_out);
113  japp->Unlock("EVIOWriter");
114  return;
115  }
116 
117  // set up some information
118  map<string, DTranslationTable::Detector_t> name_to_id;
119  for(uint32_t dettype=DTranslationTable::UNKNOWN_DETECTOR; dettype<DTranslationTable::NUM_DETECTOR_TYPES; dettype++){
121  }
122 
123  // Parse string of system names
124  std::istringstream ss(detector_list);
125  std::string token;
126  while(std::getline(ss, token, ',')) {
127 
128  // Get initial list of rocids based on token
129  set<uint32_t> rocids = ttab->Get_ROCID_By_System()[name_to_id[token]];
130 
131  // Let "FDC" be an alias for both cathode strips and wires
132  if(token == "FDC"){
133  set<uint32_t> rocids1 = ttab->Get_ROCID_By_System()[name_to_id["FDC_CATHODES"]];
134  set<uint32_t> rocids2 = ttab->Get_ROCID_By_System()[name_to_id["FDC_WIRES"]];
135  rocids.insert(rocids1.begin(), rocids1.end());
136  rocids.insert(rocids2.begin(), rocids2.end());
137  }
138 
139  // More likely than not, someone specifying "PS" will also want "PSC"
140  if(token == "PS"){
141  set<uint32_t> rocids1 = ttab->Get_ROCID_By_System()[name_to_id["PSC"]];
142  rocids.insert(rocids1.begin(), rocids1.end());
143  }
144 
145  // Finally, add the ROCs to the list
146  rocs_to_write_out.insert( rocids.begin(), rocids.end() );
147  }
148 
149  // save results
150  japp->WriteLock("EVIOWriter");
151  Get_EVIOBufferWriters()[locOutputFileNameSubString]->SetROCsToWriteOut(rocs_to_write_out);
152  japp->Unlock("EVIOWriter");
153 }
154 
155 
156 bool DEventWriterEVIO::Write_EVIOEvent(JEventLoop* locEventLoop, string locOutputFileNameSubString) const
157 {
158  vector<const JObject *> locObjectsToSaveNull;
159  return Write_EVIOEvent(locEventLoop, locOutputFileNameSubString, locObjectsToSaveNull);
160 }
161 
162 
163 bool DEventWriterEVIO::Write_EVIOEvent(JEventLoop* locEventLoop, string locOutputFileNameSubString,
164  vector<const JObject *> &locObjectsToSave) const
165 {
166  JEvent& locEvent = locEventLoop->GetJEvent();
167 
168  // Get pointer to JEventSource and make sure it is the right type
169  JEventSource* locEventSource = locEvent.GetJEventSource();
170  if(locEventSource == NULL)
171  return false;
172 
173  // Optionally write input buffer to a debug file
174  // Note that this only works with JEventSource_EVIO (old-style parser)
175  // since JEventSource_EVIOpp (new parser) doesn't have access to the
176  // raw EVIO buffer
177  if(DEBUG_FILES){
178  JEvent &jevent = locEventLoop->GetJEvent();
179  JEventSource *jes = jevent.GetJEventSource();
180  JEventSource_EVIO *jesevio = dynamic_cast<JEventSource_EVIO*>(jes);
181  if(!jesevio){
182  static bool warned = false;
183  if(!warned) jerr << "Event source not a JEventSource_EVIO type!" << endl;
184  warned = true;
185  }else{
186  uint32_t *buff;
187  uint32_t buff_size;
188  jesevio->GetEVIOBuffer(jevent, buff, buff_size);
189  if(ofs_debug_input) ofs_debug_input->write((char*)buff, buff_size*sizeof(uint32_t));
190  }
191  }
192 
193  string locOutputFileName = Get_OutputFileName(locEventLoop, locOutputFileNameSubString);
194  japp->WriteLock("EVIOWriter");
195  {
196  //check to see if the EVIO file is open
197  if(Get_EVIOOutputters().find(locOutputFileName) == Get_EVIOOutputters().end()) {
198  //not open, open it
199  if(!Open_OutputFile(locEventLoop, locOutputFileName))
200  return false; //failed to open
201  }
202 
203  //open: get handle, write event
204  HDEVIOWriter *locEVIOWriter = Get_EVIOOutputters()[locOutputFileName];
205  DEVIOBufferWriter *locBufferWriter = Get_EVIOBufferWriters()[locOutputFileName];
206  // Write event into buffer
207  vector<uint32_t> *buff = locEVIOWriter->GetBufferFromPool();
208  if(locObjectsToSave.size() == 0)
209  locBufferWriter->WriteEventToBuffer(locEventLoop, *buff);
210  else
211  locBufferWriter->WriteEventToBuffer(locEventLoop, *buff, locObjectsToSave);
212 
213  // Optionally write buffer to output file
214  if(ofs_debug_output) ofs_debug_output->write((const char*)&(*buff)[0], buff->size()*sizeof(uint32_t));
215 
216  // Add event to output queue
217  locEVIOWriter->AddBufferToOutput(buff);
218  }
219  japp->Unlock("EVIOWriter");
220 
221  return true;
222 }
223 
224 bool DEventWriterEVIO::Write_EVIOBuffer(JEventLoop* locEventLoop, uint32_t *locOutputBuffer, uint32_t locOutputBufferSize, string locOutputFileNameSubString) const
225 {
226  vector<uint32_t> *locOutputBufferVec = new vector<uint32_t>();
227  locOutputBufferVec->reserve(locOutputBufferSize);
228  // buffer size is passed to us as number of bytes, but we are copying words, so do the unit conversion
229  double locOutputBufferWords = locOutputBufferSize/4;
230 
231  //cout << "event" << endl;
232 
233  // build ouptut buffer from C-style array
234  for(uint32_t i=0; i<locOutputBufferWords; i++) {
235  //if(i<8)
236  // cout << "0x" << hex << locOutputBuffer[i] << endl;
237  locOutputBufferVec->push_back(locOutputBuffer[i]);
238  }
239 
240  //cout << "Write_EVIOBuffer() locOutputBufferSize = " << locOutputBufferSize << " vector size = " << locOutputBufferVec->size() << endl;
241 
242  return Write_EVIOBuffer(locEventLoop, locOutputBufferVec, locOutputFileNameSubString);
243 }
244 
245 
246 bool DEventWriterEVIO::Write_EVIOBuffer(JEventLoop* locEventLoop, vector<uint32_t> *locOutputBuffer, string locOutputFileNameSubString) const
247 {
248  // write out raw EVIO buffer
249 
250  JEvent& locEvent = locEventLoop->GetJEvent();
251 
252  // Get pointer to JEventSource and make sure it is the right type
253  JEventSource* locEventSource = locEvent.GetJEventSource();
254  if(locEventSource == NULL)
255  return false;
256 
257  JEventSource_EVIO* locEvioSource = dynamic_cast<JEventSource_EVIO*>(locEventSource);
258  if(locEvioSource == NULL) {
259  jerr << "WARNING!!! You MUST use this only with EVIO formatted data!!!" << endl;
260  return false;
261  }
262 
263  string locOutputFileName = Get_OutputFileName(locEventLoop, locOutputFileNameSubString);
264  japp->WriteLock("EVIOWriter");
265  {
266  //check to see if the EVIO file is open
267  if(Get_EVIOOutputters().find(locOutputFileName) == Get_EVIOOutputters().end()) {
268  //not open, open it
269  if(!Open_OutputFile(locEventLoop, locOutputFileName)){
270  jerr << "Unable to open EVIO file \""<< locOutputFileName << "\" for writing!" << endl;
271  japp->Quit();
272  japp->Unlock("EVIOWriter");
273  return false; //failed to open
274  }
275  }
276 
277  //open: get handle, write event
278  HDEVIOWriter *locEVIOWriter = Get_EVIOOutputters()[locOutputFileName];
279  // Add event to output queue
280  locEVIOWriter->AddBufferToOutput(locOutputBuffer);
281  }
282  japp->Unlock("EVIOWriter");
283 
284  return true;
285 }
286 
287 string DEventWriterEVIO::Get_OutputFileName(JEventLoop* locEventLoop, string locOutputFileNameSubString) const
288 {
289  // if we're merging input files, write everything to the specified file
290  if(dMergeFiles) {
291  return dMergedFilename;
292  }
293 
294  //get the event source
295  JEvent& locEvent = locEventLoop->GetJEvent();
296  JEventSource* locEventSource = locEvent.GetJEventSource();
297  if(locEventSource == NULL)
298  return "no_name.evio";
299 
300  //get the source file name (strip the path)
301  string locSourceFileName = locEventSource->GetSourceName();
302  size_t locSlashIndex = locSourceFileName.find_last_of("/");
303  string locSourceFileName_Pathless = (locSlashIndex != string::npos) ? locSourceFileName.substr(locSlashIndex + 1) : locSourceFileName;
304 
305  //strip the file extension (if present and if is a known format: .root, .evio, or .hddm)
306  size_t locDotIndex = locSourceFileName_Pathless.find_last_of(".");
307  if(locDotIndex != string::npos)
308  {
309  string locSuffix = locSourceFileName_Pathless.substr(locDotIndex + 1);
310  if((locSuffix == "root") || (locSuffix == "evio") || (locSuffix == "hddm"))
311  locSourceFileName_Pathless = locSourceFileName_Pathless.substr(0, locDotIndex);
312  }
313 
314  return (locSourceFileName_Pathless + string(".") + locOutputFileNameSubString + string(".evio"));
315 }
316 
317 bool DEventWriterEVIO::Open_OutputFile(JEventLoop* locEventLoop, string locOutputFileName) const
318 {
319  //ASSUMES A LOCK HAS ALREADY BEEN ACQUIRED (by WriteEVIOEvent)
320  // and assume that it doesn't exist
321 
322  // Create object to write the selected events to a file or ET system
323  // Run each connection in their own thread
324  HDEVIOWriter *locEVIOout = new HDEVIOWriter(locOutputFileName);
326  pthread_t locEVIOout_thr;
327  int result = pthread_create(&locEVIOout_thr, NULL, HDEVIOOutputThread, locEVIOout);
328  bool success = (result == 0);
329 
330  //evaluate status
331  if(!success)
332  jerr << "Unable to open EVIO file: error code = " << result << endl;
333  else
334  {
335  jout << "Output EVIO file " << locOutputFileName << " created." << endl;
336  Get_EVIOOutputters()[locOutputFileName] = locEVIOout; //store the handle
337  Get_EVIOOutputThreads()[locOutputFileName] = locEVIOout_thr; //store the thread
338  Get_EVIOBufferWriters()[locOutputFileName] = locEVIOwriter; //store the buffer creator
339  }
340 
341  return success;
342 }
343 
345 {
346  japp->WriteLock("EVIOWriter");
347  {
349  if(Get_NumEVIOOutputThreads() > 0)
350  {
351  japp->Unlock("EVIOWriter");
352  return; //not the last thread writing to EVIO files
353  }
354 
355  //last thread writing to EVIO files: close all files and free all memory
356  map<string, HDEVIOWriter *>::iterator locIterator = Get_EVIOOutputters().begin();
357  for(; locIterator != Get_EVIOOutputters().end(); ++locIterator)
358  {
359  string locOutputFileName = locIterator->first;
360  HDEVIOWriter *locEVIOOutputter = locIterator->second;
361  pthread_t locEVIOOutputThread = Get_EVIOOutputThreads()[locOutputFileName];
362 
363  // finish writing out to the event source
364  locEVIOOutputter->Quit();
365  // clean up the output thread
366  void *retval=NULL;
367  int result = pthread_join(locEVIOOutputThread, &retval);
368  if(result!=0)
369  jerr << "Problem closing EVIO file: error code = " << result << endl;
370  delete locEVIOOutputter;
371  std::cout << "Closed EVIO file " << locOutputFileName << std::endl;
372  }
373  Get_EVIOOutputters().clear();
374  Get_EVIOOutputThreads().clear();
375  }
376  japp->Unlock("EVIOWriter");
377 }
378 
void * HDEVIOOutputThread(void *evioout)
void GetEVIOBuffer(jana::JEvent &jevent, uint32_t *&buff, uint32_t &size) const
std::ofstream * ofs_debug_input
char string[256]
static map< DTranslationTable::Detector_t, set< uint32_t > > & Get_ROCID_By_System(void)
map< string, pthread_t > & Get_EVIOOutputThreads(void) const
JApplication * japp
size_t & Get_NumEVIOOutputThreads(void) const
map< string, DEVIOBufferWriter * > & Get_EVIOBufferWriters(void) const
void AddBufferToOutput(vector< uint32_t > *buff)
DEventWriterEVIO(JEventLoop *locEventLoop)
vector< uint32_t > * GetBufferFromPool(void)
void Quit(void)
string Get_OutputFileName(JEventLoop *locEventLoop, string locOutputFileNameSubString) const
bool Write_EVIOBuffer(JEventLoop *locEventLoop, vector< uint32_t > *locOutputBuffer, string locOutputFileNameSubString) const
void SetDetectorsToWriteOut(string detector_list, string locOutputFileNameSubString) const
bool Write_EVIOEvent(JEventLoop *locEventLoop, string locOutputFileNameSubString) const
std::ofstream * ofs_debug_output
const DTranslationTable * ttab
void WriteEventToBuffer(JEventLoop *loop, vector< uint32_t > &buff, vector< const JObject * > objects_to_save) const
map< string, HDEVIOWriter * > & Get_EVIOOutputters(void) const
bool Open_OutputFile(JEventLoop *locEventLoop, string locOutputFileName) const
The JEventSource_EVIO class implements a JEventSource capable of reading in EVIO data from raw data f...
static string DetectorName(Detector_t type)