CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
LaserSorter.cc
Go to the documentation of this file.
1 //emacs settings:-*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 /*
3  * $Id: LaserSorter.cc,v 1.16 2012/02/26 21:20:28 pgras Exp $
4  */
5 
6 /***************************************************
7  * TODO: check Matacq *
8  * add DTT *
9  * completion of partial output file *
10  ***************************************************/
11 
12 
15 
16 #include <iostream>
17 //#include <fstream>
18 #include <iomanip>
19 //#include <limits>
20 #include <algorithm>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <errno.h>
25 
36 
37 using namespace std;
38 
39 const int LaserSorter::ecalDccFedIdMin_ = 601;
40 const int LaserSorter::ecalDccFedIdMax_ = 654;
41 
42 
43 static const int laserTrigger = 4;
44 static const int ledTrigger = 5;
45 static const int tpTrigger = 6;
46 static const int pedTrigger = 7;
47 
49 
50 static const char* const detailedTrigNames[] = {
51  "Inv0",//000
52  "Inv1",//001
53  "Inv2",//010
54  "Inv3",//011
55  "Las", //100
56  "Led", //101
57  "TP", //110
58  "Ped" //111
59 };
60 
61 static const char* const colorNames[] = {
62  "Blue",
63  "Green",
64  "Red",
65  "IR"
66 };
67 
69 const int LaserSorter::indexOffset32_ = 1;
70 
71 static std::string now(){
72  struct timeval t;
73  gettimeofday(&t, 0);
74 
75  char buf[256];
76  strftime(buf, sizeof(buf), "%F %R %S s", localtime(&t.tv_sec));
77  buf[sizeof(buf)-1] = 0;
78 
79  stringstream buf2;
80  buf2 << buf << " " << ((t.tv_usec+500)/1000) << " ms";
81 
82  return buf2.str();
83 }
84 
86  : lumiBlock_(0),
87  formatVersion_(5),
88  outputDir_(pset.getParameter<std::string>("outputDir")),
89  fedSubDirs_(pset.getParameter<std::vector<std::string> >("fedSubDirs")),
90  timeLogFile_(pset.getUntrackedParameter<std::string>("timeLogFile", "")),
91  disableOutput_(pset.getUntrackedParameter<bool>("disableOutput", false)),
92  runNumber_(0),
93  outputListFile_(pset.getUntrackedParameter<string>("outputListFile", "")),
94  doOutputList_(false),
95  verbosity_(pset.getUntrackedParameter<int>("verbosity", 0)),
96  iNoFullReadoutDccError_(0),
97  maxFullReadoutDccError_(pset.getParameter<int>("maxFullReadoutDccError")),
98  iNoEcalDataMess_(0),
99  maxNoEcalDataMess_(pset.getParameter<int>("maxNoEcalDataMess")),
100  lumiBlockSpan_(pset.getParameter<int>("lumiBlockSpan")),
101  stats_(stats_init)
102 {
103 
104  gettimeofday(&timer_, 0);
105  logFile_.open("eventSelect.log", ios::app | ios::out);
106 
107  const unsigned nEcalFeds= 54;
108  if(fedSubDirs_.size()!= nEcalFeds+1){
109  throw cms::Exception("LaserSorter")
110  << "Configuration error: "
111  << "fedSubDirs parameter must be a vector "
112  << " of " << nEcalFeds << " strings"
113  << " (subdirectory for unknown triggered FED followed by "
114  "subdirectories for FED ID 601 "
115  "to FED ID 654 in increasing FED ID order)";
116  }
117 
118  if(outputListFile_.size()!=0){
119  outputList_.open(outputListFile_.c_str(), ios::app);
120  if(outputList_.bad()){
121  throw cms::Exception("FileOpen")
122  << "Failed to open file '" << outputListFile_
123  << "' for logging of output file path list.";
124  }
125  doOutputList_ = true;
126  }
127 
128  if(timeLogFile_.size()>0){
129  timeLog_.open(timeLogFile_.c_str());
130  if(timeLog_.fail()){
131  cout << "[LaserSorter " << now() << "] "
132  << "Failed to open file " << timeLogFile_ << " to log timing.\n";
133  timing_ = false;
134  } else{
135  timing_ = true;
136  }
137  }
138 
139  struct stat fileStat;
140  if(0==stat(outputDir_.c_str(), &fileStat)){
141  if(!S_ISDIR(fileStat.st_mode)){
142  throw cms::Exception("[LaserSorter]")
143  << "File " << outputDir_ << " exists but is not a directory "
144  << " as expected.";
145  }
146  } else {//directory does not exists, let's try to create it
147  if(0!=mkdir(outputDir_.c_str(), 0755)){
148  throw cms::Exception("[LaserSorter]")
149  << "Failed to create directory " << outputDir_
150  << " for writing data.";
151  }
152  }
153 
154  logFile_ << "# "
155  "run\t"
156  "LB\t"
157  "event\t"
158  "trigType\t"
159  "FED\t"
160  "side\t"
161  "LB out\t"
162  "Written\t"
163  "ECAL data\n";
164 }
165 
167  logFile_ << "Summary. Event count: "
168  << stats_.nRead << " processed, "
169  << stats_.nWritten << " written, "
170  << stats_.nInvalidDccStrict << " with errors in DCC ID values, "
171  << stats_.nInvalidDccWeak << " with unusable DCC ID values, "
172  << stats_.nRestoredDcc << " restored DCC ID based on DCC block size\n";
173 }
174 
175 
176 // ------------ method called to analyze the data ------------
177 void
179  if(timing_){
180  timeval t;
181  gettimeofday(&t, 0);
182  timeLog_ << t.tv_sec << "."
183  << setfill('0') << setw(3) << (t.tv_usec+500)/1000 << setfill(' ')
184  << "\t"
185  << (t.tv_usec - timer_.tv_usec)*1.
186  + (t.tv_sec - timer_.tv_sec)*1.e6 << "\t";
187  timer_ = t;
188  }
189 
190  ++stats_.nRead;
191 
192  if(event.id().run()!=runNumber_){//run changed or first event
193  //for a new run, starts with a new output stream set.
194  closeAllStreams();
195  runNumber_ = event.id().run();
197  iNoEcalDataMess_ = 0;
198  }
199 
201  event.getByType(rawdata);
202 
203  //The "detailed trigger type DCC field content:
204  double dttProba = 0;
205  detailedTrigType_ = getDetailedTriggerType(rawdata, &dttProba);
206 
207  const int trigType = (detailedTrigType_ >>8 ) & 0x7;
208  const int color = (detailedTrigType_ >>6 ) & 0x3;
209  const int dccId = (detailedTrigType_ >>0 ) & 0x3F;
210  int triggeredFedId = (detailedTrigType_ == -2) ? -1 : (600 + dccId);
211  const int side = (detailedTrigType_ >>11) & 0x1;
212  //monitoring region extended id:
213  // const int lme = dcc2Lme(dccId, side);
214 
215  if(detailedTrigType_ > -2){
216  if(dttProba < 1. || triggeredFedId < ecalDccFedIdMin_
217  || triggeredFedId > ecalDccFedIdMax_){
219  }
220 
221  if(triggeredFedId<ecalDccFedIdMin_ || triggeredFedId > ecalDccFedIdMax_){
222  if(verbosity_) cout << "[LaserSorter " << now() << "] " << "DCC ID (" << dccId
223  << ") found in trigger type is out of range.";
225  vector<int> ids = getFullyReadoutDccs(*rawdata);
226  if(ids.size()==0){
228  cout << " No fully read-out DCC found\n";
230  }
231  } else if(ids.size()==1){
232  triggeredFedId = ids[0];
233  if(verbosity_) cout << " ID guessed from DCC payloads\n";
235  } else{ //ids.size()>1
236  if(verbosity_){
237  cout << " Several fully read-out Dccs:";
238  for(unsigned i=0; i < ids.size(); ++i) cout << " " << ids[i];
239  cout << "\n";
240  }
241  }
242  }
243 
244  if(verbosity_>1) cout << "\n----------------------------------------------------------------------\n"
245  << "Event id: "
246  << " " << event.id() << "\n"
247  << "Lumin block: " << event.luminosityBlock() << "\n"
248  << "TrigType: " << detailedTrigNames[trigType&0x7]
249  << " Color: " << colorNames[color&0x3]
250  << " FED: " << triggeredFedId
251  << " side:" << side << "\n"
252  << "\n----------------------------------------------------------------------\n";
253 
254  } else{ //NO ECAL DATA
255  if(verbosity_>1) cout << "\n----------------------------------------------------------------------\n"
256  << "Event id: "
257  << " " << event.id() << "\n"
258  << "Lumin block: " << event.luminosityBlock() << "\n"
259  << "No ECAL data\n"
260  << "\n----------------------------------------------------------------------\n";
261  }
262 
263  logFile_ << event.id().run() << "\t"
264  << event.luminosityBlock() << "\t"
265  << event.id().event() << "\t"
266  << trigType << "\t"
267  << triggeredFedId << "\t"
268  << side;
269 
270  bool written = false;
271  int assignedLB = -1;
272 
273  if(event.luminosityBlock()!=lumiBlock_){
274  //lumi block change => need for stream garbage collection
275  const int lb = event.luminosityBlock();
276  closeOldStreams(lb);
277  int minLumi = event.luminosityBlock() - lumiBlockSpan_;
278  int maxLumi = event.luminosityBlock() + lumiBlockSpan_;
279  for(int lb1 = minLumi; lb1 <= maxLumi; ++lb1){
281  }
282  }
283 
284 // if(event.luminosityBlock() < lumiBlock_){
285 // throw cms::Exception("LaserSorter")
286 // << "Process event has a lumi block (" << event.luminosityBlock() << ")"
287 // << "older than previous one (" << lumiBlock_ << "). "
288 // << "This can be due by wrong input file ordering or bad luminosity "
289 // << "block indication is the event header. "
290 // << "Event cannot be processed";
291 // }
292 
293  if(disableOutput_){
294  /* NO OP*/
295  } else{
296  OutStreamRecord* out = getStream(triggeredFedId, event.luminosityBlock());
297 
298  if(out!=0){
299  assignedLB = out->startingLumiBlock();
300  if(out->excludedOrbit().find(event.orbitNumber())
301  ==out->excludedOrbit().end()){
302  if(verbosity_ > 1) cout << "[LaserSorter " << now() << "] "
303  << "Writing out event from FED " << triggeredFedId
304  << " LB " << event.luminosityBlock()
305  << " orbit " << event.orbitNumber() << "\n";
306  int dtt = (detailedTrigType_ >=0) ? detailedTrigType_ : -1; //shall we use -1 or 0 for undefined value?
307  written = written
308  || writeEvent(*out, event, dtt, *rawdata);
309  ++stats_.nWritten;
310  } else{
311  if(verbosity_) cout << "[LaserSorter " << now() << "] "
312  << "File " << out->finalFileName() << " "
313  << "already contains calibration event from FED "
314  << triggeredFedId << ", LB = "
315  << event.luminosityBlock()
316  << " with orbit ID "
317  << event.orbitNumber() << ". Event skipped.\n";
318  }
319  }
320  }
321  lumiBlock_ = event.luminosityBlock();
322 
323  logFile_ << "\t";
324  if(assignedLB>=0) logFile_ << assignedLB; else logFile_ << "-";
325  logFile_ << "\t" << (written?"Y":"N") << "\n";
326  logFile_ << "\t" << (detailedTrigType_==-2?"N":"Y") << "\n";
327 
328  if(timing_){
329  timeval t;
330  gettimeofday(&t, 0);
331  timeLog_ << (t.tv_usec - timer_.tv_usec)*1.
332  + (t.tv_sec - timer_.tv_sec)*1.e6 << "\n";
333  timer_ = t;
334  }
335 }
336 
337 int LaserSorter::dcc2Lme(int dcc, int side){
338  int fedid = (dcc%600) + 600; //to handle both FED and DCC id.
339  vector<int> lmes;
340  // EE -
341  if( fedid <= 609 ) {
342  if ( fedid <= 607 ) {
343  lmes.push_back(fedid-601+83);
344  } else if ( fedid == 608 ) {
345  lmes.push_back(90);
346  lmes.push_back(91);
347  } else if ( fedid == 609 ) {
348  lmes.push_back(92);
349  }
350  } //EB
351  else if ( fedid >= 610 && fedid <= 645 ) {
352  lmes.push_back(2*(fedid-610)+1);
353  lmes.push_back(lmes[0]+1);
354  } // EE+
355  else if ( fedid >= 646 ) {
356  if ( fedid <= 652 ) {
357  lmes.push_back(fedid-646+73);
358  } else if ( fedid == 653 ) {
359  lmes.push_back(80);
360  lmes.push_back(81);
361  } else if ( fedid == 654 ) {
362  lmes.push_back(82);
363  }
364  }
365  return lmes.size()==0?-1:lmes[min(lmes.size(), (size_t)side)];
366 }
367 
369  double* proba){
370  Majority<int> stat;
371  bool ecalData = false;
372  for(int id=ecalDccFedIdMin_; id<=ecalDccFedIdMax_; ++id){
373  if(!FEDNumbering::inRange(id)) continue;
374  const FEDRawData& data = rawdata->FEDData(id);
375  const int detailedTrigger32 = 5;
376  if(verbosity_>3) cout << "[LaserSorter " << now() << "] "
377  << "FED " << id << " data size: "
378  << data.size() << "\n";
379  if(data.size()>=4*(detailedTrigger32+1)){
380  ecalData = true;
381  const uint32_t* pData32 = (const uint32_t*) data.data();
382  int tType = pData32[detailedTrigger32] & 0xFFF;
383  if(verbosity_>3) cout << "[LaserSorter " << now() << "] "
384  << "Trigger type " << tType << "\n";
385  stat.add(tType);
386  }
387  }
388  if(!ecalData) return -2;
389  double p;
390  int tType = stat.result(&p);
391  if(p<0){
392  //throw cms::Exception("NotFound") << "No ECAL DCC data found\n";
394  edm::LogWarning("NotFound") << "No ECAL DCC data found. "
395  "(This warning will be disabled for the current run after "
396  << maxNoEcalDataMess_ << " occurences.)";
398  }
399  tType = -1;
400  } else if(p<.8){
401  //throw cms::Exception("EventCorruption") << "Inconsitency in detailed trigger type indicated in ECAL DCC data headers\n";
402  edm::LogWarning("EventCorruption") << "Inconsitency in detailed trigger type indicated in ECAL DCC data headers\n";
403  tType = -1;
404  }
405  if(proba) *proba = p;
406  return tType;
407 }
408 
410  for(OutStreamList::iterator it = outStreamList_.begin();
411  it != outStreamList_.end();/*NOOP*/){
412  it = closeOutStream(it);
413  }
414 }
415 
417  const edm::LuminosityBlockNumber_t minLumiBlock = lumiBlock - lumiBlockSpan_;
418  const edm::LuminosityBlockNumber_t maxLumiBlock = lumiBlock + lumiBlockSpan_;
419  //If container type is ever changed, beware that
420  //closeOutStream call in the loop removes it from outStreamList
421  for(boost::ptr_list<OutStreamRecord>::iterator it = outStreamList_.begin();
422  it != outStreamList_.end();
423  /*NOOP*/){
424  if(it->startingLumiBlock() < minLumiBlock
425  || it->startingLumiBlock() > maxLumiBlock){
426  //event older than 2 lumi block => stream can be closed
427  if(verbosity_) cout << "[LaserSorter " << now() << "] "
428  << "Closing file for "
429  << "FED "
430  << it->fedId()
431  << " LB " << it->startingLumiBlock()
432  << "\n";
433  it = closeOutStream(it);
434  } else{
435  ++it;
436  }
437  }
438 }
439 
442  edm::LuminosityBlockNumber_t lumiBlock){
443 
444  if((fedId != -1) &&
445  (fedId < ecalDccFedIdMin_ || fedId > ecalDccFedIdMax_)) fedId = -1;
446 
447  if(verbosity_>1) cout << "[LaserSorter " << now() << "] "
448  << "Looking for an opened output file for FED "
449  << fedId << " LB " << lumiBlock
450  << "\n";
451 
452  //first look if stream is already open:
453  for(OutStreamList::iterator it = outStreamList_.begin();
454  it != outStreamList_.end();
455  ++it){
456  if(it->fedId()==fedId &&
457  (abs((int)it->startingLumiBlock()-(int)lumiBlock)<=lumiBlockSpan_)){
458  //stream found!
459  return &(*it);
460  }
461  }
462  //stream was not found. Let's create one
463 
464  if(verbosity_) cout << "[LaserSorter " << now() << "] "
465  << "File not yet opened. Opening it.\n";
466 
467  OutStreamList::iterator streamRecord = createOutStream(fedId, lumiBlock);
468  return streamRecord!=outStreamList_.end()?&(*streamRecord):0;
469 }
470 
472  int dtt,
473  const FEDRawDataCollection& data){
474 
475  ofstream& out = *outRcd.out();
476  bool rc = true;
477  vector<unsigned> fedIds;
478  getOutputFedList(event, data, fedIds);
479 
480  out.clear();
481  uint32_t evtStart = out.tellp();
482  if(out.bad()) evtStart = 0;
483  // cout << "------> fedIds.size() = " << fedIds.size() << endl;
484  rc &= writeEventHeader(out, event, dtt, fedIds.size());
485 
486  for(unsigned iFed = 0; iFed < fedIds.size() && rc; ++iFed){
487 // cout << "------> data.FEDData(" << fedIds[iFed] << ").size = "
488 // << data.FEDData(fedIds[iFed]).size() << "\n";
489  rc &= writeFedBlock(out, data.FEDData(fedIds[iFed]));
490  }
491 
492  if(rc){
493  //update index table for this file:
494  vector<IndexRecord>& indices = *outRcd.indices();
495  IndexRecord indexRcd = {static_cast<unsigned int>(event.orbitNumber()), evtStart};
496  indices.push_back(indexRcd);
497  }
498  return rc;
499 }
500 
501 bool LaserSorter::writeFedBlock(std::ofstream& out,
502  const FEDRawData& data){
503  bool rc = false;
504  if (data.size()>4){
505  const uint32_t * pData
506  = reinterpret_cast<uint32_t*>(const_cast<unsigned char*> ( data.data()));
507 
508  uint32_t dccLen64 = pData[2] & 0x00FFFFFF; //in 32-byte unit
509 
510  if(data.size() != dccLen64*sizeof(uint64_t)){
511 // throw cms::Exception("Bug") << "Bug found in "
512 // << __FILE__ << ":" << __LINE__ << ".";
513  throw cms::Exception("LaserSorter")
514  << "Mismatch between FED fragment size indicated in header "
515  << "(" << dccLen64 << "*8 Byte) "
516  << "and actual size (" << data.size() << " Byte) "
517  << "for FED ID " << ((pData[0] >>8) & 0xFFF) << "!\n";
518  }
519 
520  if(verbosity_>3) cout << "[LaserSorter " << now() << "] " << "Event fragment size: "
521  << data.size() << " Byte"
522  << "\t From Dcc header: " << dccLen64*8 << " Byte\n";
523 
524  const size_t nBytes = data.size();
525  // cout << "[LaserSorter " << now() << "] "
526  // << "Writing " << nBytes << " byte from adress "
527  // << (void*) data.data() << " to file.\n";
528  if(out.fail()) cout << "[LaserSorter " << now() << "] " << "Problem with stream!\n";
529  out.write((char*)data.data(), nBytes);
530  rc = true;
531  } else{
532  throw cms::Exception("Bug") << "Bug found in "
533  << __FILE__ << ":" << __LINE__ << ".\n";
534  }
535  return rc;
536 }
537 
538 bool LaserSorter::renameAsBackup(const std::string& fileName,
539  std::string& newFileName){
540  int i = 0;
541  int err;
542  static int maxTries = 100;
543  stringstream newFileName_;
544  do{
545  newFileName_.str("");
546  newFileName_ << fileName << "~";
547  if(i>0) newFileName_ << i;
548  err = link(fileName.c_str(), newFileName_.str().c_str());
549  if(err==0){
550  newFileName = newFileName_.str();
551  err = unlink(fileName.c_str());
552  }
553  ++i;
554  } while((err!=0) && (errno == EEXIST) && (i < maxTries));
555  return err==0;
556 }
557 
558 LaserSorter::OutStreamList::iterator
560  edm::LuminosityBlockNumber_t lumiBlock){
561  if(verbosity_) cout << "[LaserSorter " << now() << "] " << "Creating a stream for FED " << fedId
562  << " lumi block " << lumiBlock << ".\n";
563  std::string tmpName;
564  std::string finalName;
565 
566  streamFileName(fedId, lumiBlock, tmpName, finalName);
567 
568  errno = 0;
569 
570  //checks if a file with tmpName name already exists:
571  ofstream* out = new ofstream(tmpName.c_str(), ios::out | ios::in);
572  if(out->is_open()){//temporary file already exists. Making a backup:
573  string newName;
574  if(!renameAsBackup(tmpName, newName)){
575  throw cms::Exception("LaserSorter")
576  << "Failed to rename file " << tmpName
577  << " to " << newName << "\n";
578  }
579  if(verbosity_) cout << "[LaserSorter " << now() << "] "
580  << "Already existing File " << tmpName
581  << " renamed to "
582  << newName << "\n";
583  out->close();
584  }
585 
586  out->clear();
587  out->open(tmpName.c_str(), ios::out | ios::trunc);
588 
589  if(out->fail()){//failed to create file
590  delete out;
591  throw cms::Exception("LaserSorter")
592  << "Failed to create file "
593  << tmpName << " for writing event from FED " << fedId
594  << " lumi block " << lumiBlock
595  << ": " << strerror(errno) << "\n.";
596  }
597 
598  ifstream in(finalName.c_str());
599  bool newFile = true;
600  if(in.good()){//file already exists with final name.
601  if(verbosity_) cout << "[LaserSorter " << now() << "] " << "File "
602  << finalName
603  << " already exists. It will be updated if needed.\n";
604  //Copying its contents:
605  char buffer[256];
606  streamsize nread = -1;
607  int vers = readFormatVersion(in, finalName);
608  if(vers==-1){
609  edm::LogWarning("LaserSorter") << "File " << tmpName.c_str()
610  << " is not an LMF file despite its extension or "
611  << "it is corrupted.\n";
612  } else if(vers!=formatVersion_){
613  edm::LogWarning("LaserSorter") << "Cannot include events already in file "
614  << tmpName.c_str()
615  << " because of version "
616  << "mismatch (found version "
617  << (int)vers << " while "
618  << "only version "
619  << (int)formatVersion_
620  << " is supported).\n";
621  } else{
622  newFile = false;
623  //read index table offset value:
624  const int indexTableOffsetPos8 = 1*sizeof(uint32_t);
625  uint32_t indexTableOffsetValue = 0;
626  in.clear();
627  in.seekg(indexTableOffsetPos8, ios::beg);
628  in.read((char*) &indexTableOffsetValue,
629  sizeof(indexTableOffsetValue));
630  if(in.fail()){
631  cout << "[LaserSorter " << now() << "] " << "Failed to read offset of index table "
632  " in the existing file " << finalName << "\n";
633  } else{
634  if(verbosity_>2) cout << "[LaserSorter " << now() << "] " << "Index table offset of "
635  "original file " << finalName << ": 0x"
636  << hex << setfill('0')
637  << setw(8) << indexTableOffsetValue
638  << dec << setfill(' ') << "\n";
639  }
640  in.clear();
641  in.seekg(0, ios::beg);
642 
643  //copy legacy file contents except the index table
644  uint32_t toRead = indexTableOffsetValue;
645  cout << "[LaserSorter " << now() << "] " << "Copying " << finalName << " to " << tmpName << endl;
646  while(!in.eof()
647  && (toRead > 0)
648  && (nread=in.readsome(buffer, min(toRead, (uint32_t)sizeof(buffer))))!=0){
649  // cout << "Writing " << nread << " bytes to file "
650  // << tmpName.c_str() << "\n";
651  toRead -= nread;
652  // out->seekp(0, ios::end);
653  out->write(buffer, nread);
654  if(out->bad()){
655  throw cms::Exception("LaserSorter") << "Error while writing to file "
656  << tmpName
657  << ". Check if there is enough "
658  << "space on the device.\n";
659  }
660  }
661 
662  //resets index table offset field:
663  indexTableOffsetValue = 0 ;
664  out->clear();
665  out->seekp(indexTableOffsetPos8, ios::beg);
666  out->write((char*)&indexTableOffsetValue, sizeof(uint32_t));
667  out->clear();
668  out->seekp(0, ios::end);
669  }
670  }
671 
672 #if 0
673  out->flush();
674  cout << "Press enter... file name was " << tmpName << endl;
675  char c;
676  cin >> c;
677 #endif
678 
679  OutStreamRecord* outRcd = new OutStreamRecord(fedId, lumiBlock,
680  out,
681  tmpName, finalName);
682 
683  if(newFile){
684  writeFileHeader(*out);
685  } else{
686  std::string errMsg;
687  if(!readIndexTable(in, finalName, *outRcd, &errMsg)){
688  throw cms::Exception("LaserSorter") << errMsg << "\n";
689  }
690  }
691 
692  return outStreamList_.insert(outStreamList_.end(), outRcd);
693 }
694 
695 void LaserSorter::writeFileHeader(std::ofstream& out){
696  out.clear();
697 
698  uint32_t id = 'L' | ('M' <<8) | ('F' <<16) | (formatVersion_<<24);
699 
700  out.write((char*)&id, sizeof(uint32_t));
701 
702  //index position (to be filled at end of writing)
703  uint32_t zero = 0;
704  out.write((char*)&zero, sizeof(uint32_t));
705 
706  if(out.fail()){
707  throw cms::Exception("LaserSorter")
708  << "Failed to write file header.\n";
709  }
710 }
711 
712 bool LaserSorter::writeEventHeader(std::ofstream& out,
713  const edm::Event& evt,
714  int dtt,
715  unsigned nFeds){
716  uint32_t data[10];
717 
718  data[0] = evt.time().value() & 0xFFFFFFFF;
719  data[1] = evt.time().value() >>32;
720  data[2] = evt.luminosityBlock();
721  data[3] = evt.run();
722  data[4] = evt.orbitNumber();
723  data[5] = evt.bunchCrossing();
724  data[6] = evt.id().event();
725  data[7] = dtt;
726  data[8] = nFeds;
727  data[9] = 0; //reserved (to be aligned on 64-bits)
728 
729  if(verbosity_>1){
730  cout << "[LaserSorter " << now() << "] " << "Write header of event: "
731  << "Time: " << toString(evt.time().value())
732  << ", LB: " << evt.luminosityBlock()
733  << ", Run: " << evt.run()
734  << ", Bx: " << evt.bunchCrossing()
735  << ", Event ID: " << evt.id().event()
736  << ", Detailed trigger type: 0x" << hex << dtt << dec
737  << " (" << detailedTrigNames[(dtt>>8)&0x7] << ", "
738  << colorNames[(dtt>>6)&0x3] << ", DCC " << (dtt&0x3f)
739  << ", side " << ((dtt>>10) &0x1) << ")"
740  << ", number of FEDs: " << nFeds
741  << "\n";
742  }
743 
744  out.clear();
745  out.write((char*)data, sizeof(data));
746  return !out.bad();
747 }
748 
750  edm::LuminosityBlockNumber_t lumiBlock,
751  std::string& tmpName, std::string& finalName){
752  int iFed;
753  if(fedId >= ecalDccFedIdMin_ && fedId <= ecalDccFedIdMax_){
754  iFed = fedId - ecalDccFedIdMin_ + 1;
755  } else if(fedId < 0){
756  iFed = -1; //event w/o ECAL data
757  } else {
758  iFed = 0;
759  }
760  if(iFed < -1 || iFed >= (int)fedSubDirs_.size()){
761  throw cms::Exception("LaserSorter")
762  << "Bug found at " << __FILE__ << ":" << __LINE__
763  << ". FED ID is out of index!";
764  }
765 
766 
767  struct stat fileStat;
768 
769  stringstream buf;
770  buf << outputDir_ << "/"
771  << (iFed<0 ? "Empty" : fedSubDirs_[iFed]);
772 
773  string dir = buf.str();
774  if(0==stat(dir.c_str(), &fileStat)){
775  if(!S_ISDIR(fileStat.st_mode)){
776  throw cms::Exception("[LaserSorter]")
777  << "File " << dir << " exists but is not a directory "
778  << " as expected.";
779  }
780  } else {//directory does not exists, let's try to create it
781  if(0!=mkdir(dir.c_str(), 0755)){
782  throw cms::Exception("[LaserSorter]")
783  << "Failed to create directory " << dir
784  << " for writing data.";
785  }
786  }
787 
788  buf.str("");
789  buf << "Run" << runNumber_
790  << "_LB" << setfill('0') << setw(4) << lumiBlock
791  << ".lmf";
792  string fileName = buf.str();
793  string tmpFileName = fileName + ".part";
794 
795  finalName = dir + "/" + fileName;
796  tmpName = dir + "/" + tmpFileName;
797 
798  if(verbosity_>3) cout << "[LaserSorter " << now() << "] " << "File path: "
799  << finalName << "\n";
800 }
801 
802 LaserSorter::OutStreamList::iterator
803 LaserSorter::closeOutStream(LaserSorter::OutStreamList::iterator
804  streamRecord){
805  if(streamRecord==outStreamList_.end()) return outStreamList_.end();
806 
807  if(verbosity_) cout << "[LaserSorter " << now() << "] " << "Writing Index table of file "
808  << streamRecord->finalFileName() << "\n";
809  ofstream& out = *streamRecord->out();
810  out.clear();
811  if(!writeIndexTable(out, *streamRecord->indices())){
812  cout << "Error while writing index table for file "
813  << streamRecord->finalFileName() << ". "
814  << "Resulting file might be corrupted. "
815  << "The error can be due to a lack of disk space.";
816  }
817 
818  if(verbosity_) cout << "[LaserSorter " << now() << "] " << "Closing file "
819  << streamRecord->finalFileName() << ".\n";
820  out.close();
821 
822  const std::string& tmpFileName = streamRecord->tmpFileName();
823  const std::string& finalFileName = streamRecord->finalFileName();
824 
825  if(verbosity_) cout << "[LaserSorter " << now() << "] " << "Renaming " << tmpFileName
826  << " to " << finalFileName << ".\n";
827 
828  if(0!=rename(tmpFileName.c_str(), finalFileName.c_str())){
829  cout << "[LaserSorter " << now() << "] "
830  << " Failed to rename output file from "
831  << tmpFileName << " to " << finalFileName
832  << ". " << strerror(errno) << "\n";
833  }
834 
835  if(doOutputList_){
836  char buf[256];
837  time_t t = time(0);
838  strftime(buf, sizeof(buf), "%F %R:%S", localtime(&t));
839 
840  ifstream f(".watcherfile");
841  string inputFile;
842  f >> inputFile;
843  outputList_ << finalFileName << "\t" << buf
844  << "\t" << inputFile
845  << endl;
846  }
847 
848  return outStreamList_.erase(streamRecord);
849 }
850 
852  //TODO: better treatement of last files:
853  //they might be imcomplete...
854  closeAllStreams();
855 }
856 
858 }
859 
860 bool LaserSorter::isDccEventEmpty(const FEDRawData& data, size_t* dccLen,
861  int* nTowerBlocks) const{
862  if(nTowerBlocks) *nTowerBlocks = 0;
863  //DCC event is considered empty if it does not contains any Tower block
864  //( = FE data)
865  bool rc = true;
866  if(dccLen) *dccLen = 0;
867  const unsigned nWord32 = data.size()/sizeof(uint32_t);
868  if(nWord32==0){
869  //cout << "[LaserSorter " << now() << "] " << "FED block completly empty\n";
870  return true;
871  }
872  for(unsigned iWord32 = 0; iWord32 < nWord32; iWord32 += 2){
873  uint32_t* data32 = ((uint32_t*)(data.data())) + iWord32;
874  int dataType = (data32[1] >>28) & 0xF;
875  // cout << hex << "0x" << setfill('0')
876  // << setw(8) << data32[1] << "'" << setw(8) << data32[0]
877  // << " dataType: 0x" << dataType
878  // << dec << setfill(' ') << "\n";
879  if(0==(dataType>>2)){//in DCC header
880  const int dccHeaderId = (data32[1] >>24) & 0x3F;
881  if(dccHeaderId==1){
882  if(dccLen) *dccLen=((data32[0] >>0 ) & 0xFFFFFF);
883  }
884  } if((dataType>>2)==3){//Tower block
885  rc = false;
886  if(nTowerBlocks){//number of tower block must be counted
887  ++(*nTowerBlocks);
888  } else{
889  break;
890  }
891  }
892  }
893  // cout << "[LaserSorter " << now() << "] " << "DCC Len: ";
894 
895  // if(dccLen){
896  // cout << (*dccLen) << " event ";
897  // }
898  // cout << (rc?"":"non") << " empty"
899  // << endl;
900  return rc;
901 }
902 
904  const FEDRawDataCollection& data,
905  std::vector<unsigned>& fedIds) const{
906  fedIds.erase(fedIds.begin(), fedIds.end());
907  for(int id=ecalDccFedIdMin_; id<=ecalDccFedIdMax_; ++id){
908  size_t dccLen;
909  const FEDRawData& dccEvent = data.FEDData(id);
910  if(id==matacqFedId_
911  || !isDccEventEmpty(dccEvent, &dccLen)){
912  fedIds.push_back(id);
913  }
914  if(dccLen*sizeof(uint64_t)!=dccEvent.size()){
915  edm::LogWarning("LaserSorter")
916  << "Length error in data of FED " << id
917  << " in event " << event.id()
918  << ", Data of this FED dropped.";
919  }
920  }
921  // cout << __FILE__ << ":" << __LINE__ << ": "
922  // << "data.FEDData(" << matacqFedId_ << ").size() = "
923  // << data.FEDData(matacqFedId_).size() << "\n";
924  if(data.FEDData(matacqFedId_).size()>4){//matacq block present
925  // cout << __FILE__ << ":" << __LINE__ << ": "
926  // << "Adding matacq to list of FEDs\n";
927  fedIds.push_back(matacqFedId_);
928  }
929 }
930 
931 std::vector<int>
933  int nTowers;
934  vector<int> result;
935  for(int fed = ecalDccFedIdMin_; fed < ecalDccFedIdMax_; ++fed){
936  const FEDRawData& fedData = data.FEDData(fed);
937  isDccEventEmpty(fedData, 0, &nTowers);
938  if(nTowers>=68) result.push_back(fed);
939  }
940  return result;
941 }
942 
943 
944 bool LaserSorter::writeIndexTable(std::ofstream& out,
945  std::vector<IndexRecord>& indices){
946  uint32_t indexTablePos = out.tellp();
947  uint32_t nevts = indices.size();
948 
949  out.clear();
950  out.write((char*)&nevts, sizeof(nevts));
951  const uint32_t reserved = 0;
952  out.write((char*)&reserved, sizeof(reserved));
953 
954  if(out.bad()) return false;
955 
956  sort(indices.begin(), indices.end());
957 
958  for(unsigned i = 0; i < indices.size(); ++i){
959  uint32_t data[2];
960  data[0] = indices[i].orbit;
961  data[1] = indices[i].filePos;
962  out.write((char*)data, sizeof(data));
963  }
964 
965  if(out.bad()) return false; //intial 0 valur for index table position
966  // is left to indicate corrupted table.
967 
968  //writes index table position:x
969  out.clear();
970  out.seekp(indexOffset32_*sizeof(uint32_t));
971  // cout << "[LaserSorter] Index table position: 0x" << hex << indexTablePos
972  // << dec << "\n";
973  if(!out.bad()) out.write((char*)&indexTablePos, sizeof(uint32_t));
974 
975  bool rc = !out.bad();
976 
977  //reposition pointer to eof:
978  out.seekp(0, ios::end);
979 
980  return rc;
981 }
982 
983 //beware this method change the pointer position in the ifstream in
984 bool LaserSorter::readIndexTable(std::ifstream& in,
985  std::string& inName,
986  OutStreamRecord& outRcd,
987  std::string* err){
988  stringstream errMsg;
989 
990  ifstream* s = &in;
991 
992  //streampos pos = s->tellg();
993  s->clear();
994  s->seekg(0);
995 
996  uint32_t fileHeader[2];
997  s->read((char*)&fileHeader[0], sizeof(fileHeader));
998  uint32_t indexTablePos = fileHeader[1];
999 
1000  if(s->eof()){
1001  s->clear();
1002  s->seekg(0);
1003  errMsg << "Failed to read header of file " << inName
1004  << ".";
1005  if(err) *err = errMsg.str();
1006  return false;
1007  }
1008 
1009  s->seekg(indexTablePos);
1010 
1011  uint32_t nevts = 0;
1012  s->read((char*)&nevts, sizeof(nevts));
1013  s->ignore(4);
1014  if(s->bad()){
1015  errMsg << "Failed to read index table from file "
1016  << inName << ".";
1017  if(err) *err = errMsg.str();
1018  return false;
1019  }
1020  if(nevts>maxEvents_){
1021  errMsg << "Number of events indicated in event index of file "
1022  << inName << " (" << nevts << ") "
1023  << "is unexpectively large.";
1024  if(err) *err = errMsg.str();
1025  return false;
1026  }
1027  outRcd.indices()->resize(nevts);
1028  s->read((char*)&(*outRcd.indices())[0], nevts*sizeof(IndexRecord));
1029  if(s->bad()){
1030  outRcd.indices()->clear();
1031  errMsg << "Failed to read index table from file "
1032  << inName << ".";
1033  if(err) *err = errMsg.str();
1034  return false;
1035  }
1036  if(nevts>maxEvents_){
1037  errMsg << "Number of events indicated in event index of file "
1038  << inName << " is unexpectively large.";
1039  if(err) *err = errMsg.str();
1040  outRcd.indices()->clear();
1041  return false;
1042  }
1043 
1044  if(verbosity_ > 1) cout << "[LaserSorter " << now() << "] " << "Orbit IDs of events "
1045  << "already contained in the file "
1046  << inName << ":";
1047  for(unsigned i = 0; i < outRcd.indices()->size(); ++i){
1048  if(verbosity_>1){
1049  cout << " " << setw(9) << (*outRcd.indices())[i].orbit;
1050  }
1051  outRcd.excludedOrbit().insert((*outRcd.indices())[i].orbit);
1052  }
1053  if(verbosity_>1) cout << "\n";
1054 
1055  return true;
1056 }
1057 
1059  const std::string& fileName){
1060  int vers = -1;
1061  streampos p = in.tellg();
1062 
1063  uint32_t data;
1064 
1065  in.read((char*)&data, sizeof(data));
1066 
1067  char magic[4];
1068 
1069  magic[0] = data & 0xFF;
1070  magic[1] = (data >>8) & 0xFF;
1071  magic[2] = (data >>16) & 0xFF;
1072  magic[3] = 0;
1073 
1074 
1075  const string lmf = string("LMF");
1076 
1077  if(in.good() && lmf.compare(magic)==0){
1078  vers = (data >>24) & 0xFF;
1079  }
1080 
1081  if(lmf.compare(magic)!=0){
1082  edm::LogWarning("LaserSorter") << "File " << fileName
1083  << "is not an LMF file.\n";
1084  }
1085 
1086  in.clear();
1087  in.seekg(p);
1088  return vers;
1089 }
1090 
1092  char buf[256];
1093 
1094  time_t tsec = t>>32;
1095 
1096  uint32_t tusec = t & 0xFFFFFFFF;
1097  strftime(buf, sizeof(buf), "%F %R %S s", localtime(&tsec));
1098  buf[sizeof(buf)-1] = 0;
1099 
1100  stringstream buf2;
1101  buf2 << (tusec+500)/1000;
1102 
1103  return string(buf) + " " + buf2.str() + " ms";
1104 }
1105 
1107  string dummy;
1108  string fileName;
1109 
1110  for(int fedId = ecalDccFedIdMin_-2; fedId <= ecalDccFedIdMax_; ++fedId){
1111  int fedId_;
1112  if(fedId == ecalDccFedIdMin_-2) fedId_ = -1; //stream for event w/o ECAL data
1113  else fedId_ = fedId;
1114  streamFileName(fedId_, lumiBlock, dummy, fileName);
1115  struct stat s;
1116  //TODO: could be optimized by adding an option to get stream
1117  //to open only existing file: would avoid double call to streamFileName.
1118  if(stat(fileName.c_str(), &s)==0){//file exists
1119  getStream(fedId_, lumiBlock);
1120  }
1121  }
1122 }
RunNumber_t run() const
Definition: EventID.h:42
static const char runNumber_[]
EventNumber_t event() const
Definition: EventID.h:44
OutStreamRecord * getStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock)
Definition: LaserSorter.cc:441
int i
Definition: DBlmapReader.cc:9
int lumiBlockSpan_
Definition: LaserSorter.h:428
bool disableOutput_
Definition: LaserSorter.h:346
std::vector< int > getFullyReadoutDccs(const FEDRawDataCollection &data) const
Definition: LaserSorter.cc:932
int maxFullReadoutDccError_
Definition: LaserSorter.h:406
double nRestoredDcc
number of events whose DCC ID was restored based on FED block sizes
Definition: LaserSorter.h:457
static const char *const detailedTrigNames[]
Definition: LaserSorter.cc:50
static const int tpTrigger
Definition: LaserSorter.cc:45
static std::string toString(uint64_t t)
size_t size() const
Definition: Event.cc:185
static const int laserTrigger
Definition: LaserSorter.cc:43
static const int ecalDccFedIdMin_
Definition: LaserSorter.h:305
static const int indexOffset32_
Definition: LaserSorter.h:436
virtual void beginJob()
Definition: LaserSorter.cc:857
bool writeIndexTable(std::ofstream &out, std::vector< IndexRecord > &indices)
Definition: LaserSorter.cc:944
bool readIndexTable(std::ifstream &in, std::string &inName, OutStreamRecord &outRcd, std::string *err)
Definition: LaserSorter.cc:984
bool writeEvent(OutStreamRecord &out, const edm::Event &event, int detailedTriggerType, const FEDRawDataCollection &data)
Definition: LaserSorter.cc:471
edm::RunNumber_t runNumber_
Definition: LaserSorter.h:350
bool isDccEventEmpty(const FEDRawData &data, size_t *dccLen=0, int *nTowerBlocks=0) const
Definition: LaserSorter.cc:860
virtual void endJob()
Definition: LaserSorter.cc:851
void writeFileHeader(std::ofstream &out)
Definition: LaserSorter.cc:695
int bunchCrossing() const
Definition: EventBase.h:62
std::ofstream * out() const
Definition: LaserSorter.h:73
#define abs(x)
Definition: mlp_lapack.h:159
edm::LuminosityBlockNumber_t luminosityBlock() const
Definition: EventBase.h:59
void streamFileName(int fedId, edm::LuminosityBlockNumber_t lumiBlock, std::string &tmpName, std::string &finalName)
Definition: LaserSorter.cc:749
unsigned dccId(const DetId &)
#define min(a, b)
Definition: mlp_lapack.h:161
edm::LuminosityBlockNumber_t lumiBlock_
Definition: LaserSorter.h:321
std::set< uint32_t > & excludedOrbit()
Definition: LaserSorter.h:83
void getOutputFedList(const edm::Event &event, const FEDRawDataCollection &data, std::vector< unsigned > &fedIds) const
Definition: LaserSorter.cc:903
static const int pedTrigger
Definition: LaserSorter.cc:46
static const int matacqFedId_
Definition: LaserSorter.h:432
OutStreamList::iterator closeOutStream(OutStreamList::iterator streamRecord)
Definition: LaserSorter.cc:803
unsigned int LuminosityBlockNumber_t
Definition: EventID.h:31
std::string finalFileName() const
Definition: LaserSorter.h:74
void closeAllStreams()
Definition: LaserSorter.cc:409
size_t size() const
Lenght of the data buffer in bytes.
Definition: FEDRawData.h:49
std::vector< std::string > fedSubDirs_
Definition: LaserSorter.h:338
edm::LuminosityBlockNumber_t startingLumiBlock() const
Definition: LaserSorter.h:70
std::string link(std::string &nm, std::string &ns)
Definition: hierarchy.cc:47
void add(const T &value)
Definition: Majority.h:25
const FEDRawData & FEDData(int fedid) const
retrieve data for fed
double nRead
number of events read out
Definition: LaserSorter.h:447
static const int ledTrigger
Definition: LaserSorter.cc:44
unsigned char formatVersion_
Definition: LaserSorter.h:330
std::vector< IndexRecord > * indices()
Definition: LaserSorter.h:76
tuple result
Definition: query.py:137
RunNumber_t run() const
Definition: Event.h:67
int dcc2Lme(int dccNum, int dccSide)
Definition: LaserSorter.cc:337
std::string outputDir_
Definition: LaserSorter.h:334
timeval timer_
Definition: LaserSorter.h:354
bool writeFedBlock(std::ofstream &out, const FEDRawData &data)
Definition: LaserSorter.cc:501
double f[11][100]
std::string outputListFile_
Definition: LaserSorter.h:366
#define end
Definition: vmac.h:38
int orbitNumber() const
Definition: EventBase.h:63
std::string timeLogFile_
Definition: LaserSorter.h:342
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
int iNoEcalDataMess_
Definition: LaserSorter.h:411
static const unsigned maxEvents_
Definition: LaserSorter.h:441
void closeOldStreams(edm::LuminosityBlockNumber_t lumiBlock)
Definition: LaserSorter.cc:416
tuple out
Definition: dbtoconf.py:99
TimeValue_t value() const
Definition: Timestamp.cc:72
int getDetailedTriggerType(const edm::Handle< FEDRawDataCollection > &rawdata, double *proba=0)
Definition: LaserSorter.cc:368
LaserSorter(const edm::ParameterSet &)
Definition: LaserSorter.cc:85
int detailedTrigType_
Definition: LaserSorter.h:313
unsigned long long uint64_t
Definition: Time.h:15
static const int ecalDccFedIdMax_
Definition: LaserSorter.h:309
static std::string now()
Definition: LaserSorter.cc:71
std::ofstream outputList_
Definition: LaserSorter.h:378
int readFormatVersion(std::ifstream &in, const std::string &fileName)
std::ofstream logFile_
Definition: LaserSorter.h:317
list nevts
Definition: launcher.py:16
struct LaserSorter::stats_t stats_
static bool inRange(int)
edm::EventID id() const
Definition: EventBase.h:56
static stats_t stats_init
Definition: LaserSorter.h:459
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
bool writeEventHeader(std::ofstream &out, const edm::Event &evt, int fedId, unsigned nFeds)
Definition: LaserSorter.cc:712
const unsigned char * data() const
Return a const pointer to the beginning of the data buffer.
Definition: FEDRawData.cc:29
OutStreamList::iterator createOutStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock)
Definition: LaserSorter.cc:559
tuple cout
Definition: gather_cfg.py:121
int maxNoEcalDataMess_
Definition: LaserSorter.h:415
static const char *const colorNames[]
Definition: LaserSorter.cc:61
int iNoFullReadoutDccError_
Definition: LaserSorter.h:401
void restoreStreamsOfLumiBlock(int lumiBlock)
dbl *** dir
Definition: mlp_gen.cc:35
dictionary rawdata
Definition: lumiPlot.py:393
virtual void analyze(const edm::Event &, const edm::EventSetup &)
Definition: LaserSorter.cc:178
T result(double *proba) const
Definition: Majority.h:30
bool doOutputList_
Definition: LaserSorter.h:370
double nWritten
number of events written out
Definition: LaserSorter.h:449
OutStreamList outStreamList_
Definition: LaserSorter.h:326
std::ofstream timeLog_
Definition: LaserSorter.h:358
edm::Timestamp time() const
Definition: EventBase.h:57
bool renameAsBackup(const std::string &fileName, std::string &newFileName)
Definition: LaserSorter.cc:538