00001 #include "EventFilter/EcalRawToDigi/interface/MatacqProducer.h"
00002 #include "EventFilter/EcalRawToDigi/src/Majority.h"
00003 #include "FWCore/Framework/interface/Event.h"
00004 #include "FWCore/Framework/interface/EventSetup.h"
00005 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00006 #include "FWCore/Framework/interface/ESHandle.h"
00007 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00008 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
00009 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00010 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00011 #include "DataFormats/EcalDigi/interface/EcalMatacqDigi.h"
00012 #include "DataFormats/EcalDigi/interface/EcalDigiCollections.h"
00013 #include <boost/algorithm/string.hpp>
00014 #include <boost/format.hpp>
00015
00016 #include <memory>
00017
00018 #include <stdio.h>
00019
00020 #include <fstream>
00021 #include <iomanip>
00022
00023 #include "DataFormats/EcalDigi/interface/EcalMatacqDigi.h"
00024
00025 #include <sys/types.h>
00026 #include <unistd.h>
00027 #include <signal.h>
00028 #include <sys/stat.h>
00029
00030 using namespace std;
00031 using namespace boost;
00032 using namespace edm;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 int MatacqProducer::orbitTolerance_ = 80;
00047
00048 MatacqProducer::stats_t MatacqProducer::stats_init = {0,0,0};
00049
00050 static std::string now(){
00051 struct timeval t;
00052 gettimeofday(&t, 0);
00053
00054 char buf[256];
00055 strftime(buf, sizeof(buf), "%F %R %S s", localtime(&t.tv_sec));
00056 buf[sizeof(buf)-1] = 0;
00057
00058 stringstream buf2;
00059 buf2 << buf << " " << ((t.tv_usec+500)/1000) << " ms";
00060
00061 return buf2.str();
00062 }
00063
00064
00065 MatacqProducer::MatacqProducer(const edm::ParameterSet& params):
00066 fileNames_(params.getParameter<std::vector<std::string> >("fileNames")),
00067 digiInstanceName_(params.getParameter<string>("digiInstanceName")),
00068 rawInstanceName_(params.getParameter<string>("rawInstanceName")),
00069 timing_(params.getUntrackedParameter<bool>("timing", false)),
00070 disabled_(params.getParameter<bool>("disabled")),
00071 verbosity_(params.getUntrackedParameter<int>("verbosity", 0)),
00072 produceDigis_(params.getParameter<bool>("produceDigis")),
00073 produceRaw_(params.getParameter<bool>("produceRaw")),
00074 inputRawCollection_(params.getParameter<InputTag>("inputRawCollection")),
00075 mergeRaw_(params.getParameter<bool>("mergeRaw")),
00076 ignoreTriggerType_(params.getParameter<bool>("ignoreTriggerType")),
00077 matacq_(0, 0),
00078 inFile_(0),
00079 data_(bufferSize),
00080 openedFileRunNumber_(0),
00081 lastOrb_(0),
00082 fastRetrievalThresh_(0),
00083 orbitOffsetFile_(params.getUntrackedParameter<std::string>("orbitOffsetFile",
00084 "")),
00085 inFileName_(""),
00086 stats_(stats_init),
00087 logFileName_(params.getUntrackedParameter<std::string>("logFileName",
00088 "matacqProducer.log")),
00089 eventSkipCounter_(0),
00090 onErrorDisablingEvtCnt_(params.getParameter<int>("onErrorDisablingEvtCnt")),
00091 timeLogFile_(params.getUntrackedParameter<std::string>("timeLogFile", "")),
00092 runNumber_(0)
00093 {
00094 if(verbosity_>=4) cout << "[Matacq " << now() << "] in MatacqProducer ctor" << endl;
00095
00096 gettimeofday(&timer_, 0);
00097
00098 if(timeLogFile_.size()>0){
00099 timeLog_.open(timeLogFile_.c_str());
00100 if(timeLog_.fail()){
00101 cout << "[LaserSorter " << now() << "] "
00102 << "Failed to open file " << timeLogFile_ << " to log timing.\n";
00103 logTiming_ = false;
00104 } else{
00105 logTiming_ = true;
00106 }
00107 }
00108
00109 posEstim_.verbosity(verbosity_);
00110
00111 logFile_.open(logFileName_.c_str(), ios::app | ios::out);
00112
00113 if(logFile_.bad()){
00114 throw cms::Exception("FileOpen") << "Failed to open file "
00115 << logFileName_ << " for logging.\n";
00116 }
00117
00118 if(produceDigis_){
00119 if(verbosity_>0) cout << "[Matacq " << now() << "] registering new "
00120 "EcalMatacqDigiCollection product with instance name '"
00121 << digiInstanceName_ << "'\n";
00122 produces<EcalMatacqDigiCollection>(digiInstanceName_);
00123 }
00124
00125 if(produceRaw_){
00126 if(verbosity_>0) cout << "[Matacq " << now() << "] registering new FEDRawDataCollection "
00127 "product with instance name '"
00128 << rawInstanceName_ << "'\n";
00129 produces<FEDRawDataCollection>(rawInstanceName_);
00130 }
00131
00132 startTime_.tv_sec = startTime_.tv_usec = 0;
00133 if(orbitOffsetFile_.size()>0){
00134 doOrbitOffset_ = true;
00135 loadOrbitOffset();
00136 } else{
00137 doOrbitOffset_ = false;
00138 }
00139 if(verbosity_>=4) cout << "[Matacq " << now() << "] exiting MatacqProducer ctor" << endl;
00140 }
00141
00142
00143 void
00144 MatacqProducer::produce(edm::Event& event, const edm::EventSetup& eventSetup){
00145 if(verbosity_>=4) cout << "[Matacq " << now() << "] in MatacqProducer::produce" << endl;
00146 if(logTiming_){
00147 timeval t;
00148 gettimeofday(&t, 0);
00149
00150 timeLog_ << t.tv_sec << "."
00151 << setfill('0') << setw(3) << (t.tv_usec+500)/1000 << setfill(' ')<< "\t"
00152 << (t.tv_usec - timer_.tv_usec)*1.
00153 + (t.tv_sec - timer_.tv_sec)*1.e6 << "\t";
00154 timer_ = t;
00155 }
00156
00157 if(startTime_.tv_sec==0) gettimeofday(&startTime_, 0);
00158 ++stats_.nEvents;
00159 if(disabled_) return;
00160 const uint32_t runNumber = getRunNumber(event);
00161 if(runNumber!=runNumber_){
00162 newRun(runNumber_, runNumber);
00163 }
00164 addMatacqData(event);
00165
00166 if(logTiming_){
00167 timeval t;
00168 gettimeofday(&t, 0);
00169 timeLog_ << (t.tv_usec - timer_.tv_usec)*1.
00170 + (t.tv_sec - timer_.tv_sec)*1.e6 << "\n";
00171 timer_ = t;
00172 }
00173 }
00174
00175 void
00176 MatacqProducer::addMatacqData(edm::Event& event){
00177 edm::Handle<FEDRawDataCollection> sourceColl;
00178 if(inputRawCollection_.label().size() == 0
00179 && inputRawCollection_.instance().size() == 0){
00180 event.getByType(sourceColl);
00181 } else{
00182 event.getByLabel(inputRawCollection_, sourceColl);
00183 }
00184
00185 std::auto_ptr<FEDRawDataCollection> rawColl;
00186 if(produceRaw_){
00187 if(mergeRaw_){
00188 rawColl = auto_ptr<FEDRawDataCollection>(new FEDRawDataCollection(*sourceColl));
00189 } else{
00190 rawColl = auto_ptr<FEDRawDataCollection>(new FEDRawDataCollection());
00191 }
00192 }
00193
00194 std::auto_ptr<EcalMatacqDigiCollection>
00195 digiColl(new EcalMatacqDigiCollection());
00196
00197 if(eventSkipCounter_==0){
00198 if(sourceColl->FEDData(matacqFedId_).size()>4 && !produceRaw_){
00199
00200 formatter_.interpretRawData(sourceColl->FEDData(matacqFedId_),
00201 *digiColl);
00202 } else{
00203 bool isLaserEvent = (getCalibTriggerType(event) == laserType);
00204
00205
00206
00207
00208 if(isLaserEvent || ignoreTriggerType_){
00209
00210 const uint32_t runNumber = getRunNumber(event);
00211 const uint32_t orbitId = getOrbitId(event);
00212
00213 LogInfo("Matacq") << "Run " << runNumber << "\t Orbit " << orbitId << "\n";
00214
00215 bool fileChange;
00216 if(doOrbitOffset_){
00217 map<uint32_t,uint32_t>::iterator it = orbitOffset_.find(runNumber);
00218 if(it == orbitOffset_.end()){
00219 LogWarning("Matacq") << "Orbit offset not found for run "
00220 << runNumber
00221 << ". No orbit correction will be applied.";
00222 }
00223 }
00224
00225 if(getMatacqFile(runNumber, orbitId, &fileChange)){
00226
00227 LogInfo("Matacq") << "Matacq data file found for "
00228 << "run " << runNumber << " orbit " << orbitId;
00229 if(getMatacqEvent(runNumber, orbitId, fileChange)){
00230 if(produceDigis_){
00231 formatter_.interpretRawData(matacq_, *digiColl);
00232 }
00233 if(produceRaw_){
00234 uint32_t dataLen64 = matacq_.getParsedLen();
00235 if(dataLen64 > bufferSize*8 || matacq_.getDccLen()!= dataLen64){
00236 LogWarning("Matacq") << " Error in Matacq event fragment length! "
00237 << "DCC len: " << matacq_.getDccLen()
00238 << "*8 Bytes, Parsed len: "
00239 << matacq_.getParsedLen() << "*8 Bytes. "
00240 << "Matacq data will not be included for this event.\n";
00241 } else{
00242 rawColl->FEDData(matacqFedId_).resize(dataLen64*8);
00243 copy(data_.begin(), data_.begin() + dataLen64*8,
00244 rawColl->FEDData(matacqFedId_).data());
00245 }
00246 }
00247 LogInfo("Matacq") << "Associating matacq data with orbit id "
00248 << matacq_.getOrbitId()
00249 << " to dcc event with orbit id "
00250 << orbitId << std::endl;
00251 if(isLaserEvent){
00252 ++stats_.nLaserEventsWithMatacq;
00253 } else{
00254 ++stats_.nNonLaserEventsWithMatacq;
00255 }
00256 } else{
00257 if(isLaserEvent){
00258 LogWarning("Matacq") << "No matacq data found for laser event "
00259 << "of run " << runNumber << " orbit "
00260 << orbitId;
00261 }
00262 }
00263 } else{
00264 LogWarning("Matacq") << "No matacq file found for event "
00265 << event.id();
00266 }
00267 }
00268 }
00269 if(eventSkipCounter_>0){
00270
00271
00272 LogInfo("Matacq") << " [" << now() << "] "
00273 << eventSkipCounter_
00274 << " next events will be skipped, following to an "
00275 << "error on the last processed event, "
00276 << "which is expected to be persistant.";
00277 }
00278 } else{
00279 --eventSkipCounter_;
00280 }
00281
00282 if(produceRaw_){
00283 if(verbosity_>1) cout << "[Matacq " << now() << "] "
00284 << "Adding FEDRawDataCollection collection "
00285 << " to event.\n";
00286 event.put(rawColl, rawInstanceName_);
00287 }
00288
00289 if(produceDigis_){
00290 if(verbosity_>1) cout << "[Matacq " << now() << "] "
00291 << "Adding EcalMatacqDigiCollection collection "
00292 << " to event.\n";
00293 event.put(digiColl, digiInstanceName_);
00294 }
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 bool
00344 MatacqProducer::getMatacqEvent(uint32_t runNumber,
00345 int32_t orbitId,
00346 bool fileChange){
00347 filepos_t startPos;
00348 if(!mtell(startPos)) return false;
00349
00350 int32_t startOrb = -1;
00351 const size_t headerSize = 8*8;
00352 if(mread((char*)&data_[0], headerSize, "Reading matacq header", true)){
00353 startOrb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00354 if(startOrb<0) startOrb = 0;
00355 } else{
00356 if(verbosity_>2){
00357 cout << "[Matacq " << now() << "] Failed to read matacq header. Moved to start of "
00358 " the file.\n";
00359 }
00360 mrewind();
00361 if(mread((char*)&data_[0], headerSize, "Reading matacq header", true)){
00362 startPos = 0;
00363 startOrb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00364 } else{
00365 if(verbosity_>2) cout << "[Matacq " << now() << "] Looks like matacq file is empty"
00366 << "\n";
00367 return false;
00368 }
00369 }
00370
00371 if(verbosity_>2) cout << "[Matacq " << now() << "] Last read orbit: " << lastOrb_
00372 << " looking for orbit " << orbitId
00373 << ". Current file position: " << startPos
00374 << " Orbit at current position: " << startOrb << "\n";
00375
00376
00377 bool didCoarseMove = false;
00378
00379
00380 if(!posEstim_.invalid()
00381 && (abs(lastOrb_-orbitId) > fastRetrievalThresh_)){
00382 filepos_t pos = posEstim_.pos(orbitId);
00383
00384
00385 filepos_t fsize;
00386
00387 if(msize(fsize)){
00388
00389 if(0!=posEstim_.eventLength() && pos > fsize){
00390
00391
00392 int64_t evtSize = posEstim_.eventLength()*sizeof(uint64_t);
00393 pos = ((int64_t)fsize/evtSize-1)*evtSize;
00394 if(verbosity_>2){
00395 cout << "[Matacq " << now() << "] Estimated position was beyond end of file. "
00396 "Changed to " << pos << "\n";
00397 }
00398 }
00399 } else{
00400 LogWarning("Matacq") << "Failed to access file " << inFileName_ << ".";
00401 }
00402 if(pos>=0){
00403 if(verbosity_>2) cout << "[Matacq " << now() << "] jumping to estimated position "
00404 << pos << "\n";
00405 mseek(pos, SEEK_SET, "Jumping to estimated event position");
00406 if(mread((char*)&data_[0], headerSize, "Reading matacq header", true)){
00407 didCoarseMove = true;
00408 } else{
00409
00410
00411 didCoarseMove = false;
00412 if(!mread((char*)&data_[0], headerSize, "Reading event header", true)){
00413 return false;
00414 }
00415 }
00416 } else{
00417 if(verbosity_) cout << "[Matacq " << now() << "] Event orbit outside of orbit range "
00418 "of matacq data file events\n";
00419 return false;
00420 }
00421 }
00422
00423 int32_t orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00424
00425 if(didCoarseMove){
00426
00427 if(abs(orb-orbitId) > fastRetrievalThresh_){
00428 if(verbosity_>2) cout << "[Matacq " << now() << "] Fast retrieval threshold increased from "
00429 << fastRetrievalThresh_;
00430 fastRetrievalThresh_ = 2*abs(orb-orbitId);
00431 if(verbosity_>2) cout << " to " << fastRetrievalThresh_ << "\n";
00432 }
00433
00434
00435 if(startOrb > 0
00436 && (abs(orb-orbitId) > abs(startOrb-orbitId))){
00437 if(verbosity_>2) cout << "[Matacq " << now() << "] Estimation (-> orbit " << orb << ") "
00438 "was worst than original position (-> orbit "
00439 << startOrb
00440 << "). Restoring position (" << startPos << ").\n";
00441 mseek(startPos, SEEK_SET);
00442 mread((char*)&data_[0], headerSize, "Reading event header", true);
00443 orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00444 }
00445 }
00446
00447 bool searchBackward = (orb>orbitId)?true:false;
00448
00449
00450 int len = (int)MatacqRawEvent::getDccLen(&data_[0], headerSize);
00451
00452 if(len==0){
00453 cout << "[Matacq " << now() << "] read DCC length is null! Cancels matacq event search "
00454 << " and move matacq file pointer to beginning of the file. "
00455 << "(" << __FILE__ << ":" << __LINE__ << ")."
00456 << "\n";
00457
00458 mrewind();
00459 return false;
00460 }
00461
00462 enum state_t { searching, found, failed } state = searching;
00463
00464 while(state == searching){
00465 orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00466 len = (int)MatacqRawEvent::getDccLen(&data_[0], headerSize);
00467 uint32_t run = MatacqRawEvent::getRunNum(&data_[0], headerSize);
00468 if(verbosity_>3){
00469 filepos_t pos;
00470 mtell(pos);
00471 cout << "[Matacq " << now() << "] Header read at file position "
00472 << pos
00473 << ": orbit = " << orb
00474 << " len = " << len << "x8 Byte"
00475 << " run = " << run << "\n";
00476 }
00477 if((abs(orb-orbitId) < orbitTolerance_)
00478 && (runNumber==0 || runNumber==run)){
00479 state = found;
00480 lastOrb_ = orb;
00481
00482 if((int)data_.size() < len*8){
00483 throw cms::Exception("Matacq") << "Buffer overflow";
00484 }
00485 if(verbosity_>2) cout << "[Matacq " << now() << "] Event found. Reading "
00486 " matacq event." << "\n";
00487 if(!mread((char*)&data_[0], len*8, "Reading matacq event")){
00488 if(verbosity_>2) cout << "[Matacq " << now() << "] Failed to read matacq event."
00489 << "\n";
00490 state = failed;
00491 }
00492 matacq_ = MatacqRawEvent((unsigned char*)&data_[0], len*8);
00493 } else {
00494 if((searchBackward && (orb < orbitId))
00495 || (!searchBackward && (orb > orbitId))){
00496 lastOrb_ = orb;
00497 state = failed;
00498 if(verbosity_>2) cout << "[Matacq " << now()
00499 << "] No matacq data found for run " << run
00500 << ", orbit ID " << orbitId << "." << "\n";
00501 } else{
00502 off_t offset = (searchBackward?-len:len)*8;
00503 lastOrb_ = orb;
00504 if(verbosity_>3){
00505 cout << "[Matacq " << now() << "] In matacq file, moving "
00506 << abs(offset) << " byte " << (offset>0?"forward":"backward")
00507 << ".\n";
00508 }
00509
00510 if(mseek(offset, SEEK_CUR,
00511 (searchBackward?"Moving to previous event":
00512 "Moving to next event"))
00513 && mread((char*)&data_[0], headerSize, "Reading event header",
00514 true)){
00515 } else{
00516 if(!searchBackward) mseek(-len*8, SEEK_CUR,
00517 "Moving to start of last complete event");
00518 state = failed;
00519 }
00520 }
00521 }
00522 }
00523
00524 if(state==found){
00525 filepos_t pos;
00526 filepos_t fsize;
00527 mtell(pos);
00528 msize(fsize);
00529 if(pos==fsize-1){
00530 if(verbosity_>2){
00531 cout << "[Matacq " << now() << "] Event found was at the end of the file. Moving "
00532 "stream position to beginning of this event."
00533 << "\n";
00534 }
00535 mseek(-(int)len*8-1, SEEK_CUR,
00536 "Moving to beginning of last matacq event");
00537 }
00538 }
00539 return (state==found);
00540 }
00541
00542
00543 bool
00544 MatacqProducer::getMatacqFile(uint32_t runNumber, uint32_t orbitId,
00545 bool* fileChange){
00546 if(openedFileRunNumber_!=0
00547 && openedFileRunNumber_==runNumber){
00548 if(fileChange!=0) *fileChange = false;
00549 return misOpened();
00550 }
00551
00552 if(fileNames_.size()==0) return 0;
00553
00554 const string runNumberFormat = "%08d";
00555 string sRunNumber = str(boost::format(runNumberFormat) % runNumber);
00556
00557 bool found = false;
00558 string fname;
00559 for(unsigned i=0; i < fileNames_.size() && !found; ++i){
00560 fname = fileNames_[i];
00561 boost::algorithm::replace_all(fname, "%run_subdir%",
00562 runSubDir(runNumber));
00563 boost::algorithm::replace_all(fname, "%run_number%", sRunNumber);
00564
00565 if(verbosity_>0) cout << "[Matacq " << now() << "] "
00566 << "Looking for a file with path "
00567 << fname << "\n";
00568
00569 if(mcheck(fname)){
00570 LogInfo("Matacq") << "Uses matacq data file: '" << fname << "'\n";
00571 found = true;
00572 }
00573 }
00574 if(!found){
00575 if(verbosity_>=0) cout << "[Matacq " << now() << "] no matacq file found "
00576 "for run " << runNumber << "\n";
00577 eventSkipCounter_ = onErrorDisablingEvtCnt_;
00578 openedFileRunNumber_ = 0;
00579 if(fileChange!=0) *fileChange = false;
00580 return 0;
00581 }
00582
00583 if(!mopen(fname)){
00584 LogWarning("Matacq") << "Failed to open file " << fname << "\n";
00585 eventSkipCounter_ = onErrorDisablingEvtCnt_;
00586 openedFileRunNumber_ = 0;
00587 if(fileChange!=0) *fileChange = false;
00588 return false;
00589 } else{
00590 openedFileRunNumber_ = runNumber;
00591 lastOrb_ = 0;
00592 posEstim_.init(this);
00593 if(fileChange!=0) *fileChange = true;
00594 return true;
00595 }
00596 }
00597
00598
00599 uint32_t MatacqProducer::getRunNumber(edm::Event& ev) const{
00600 return ev.run();
00601 }
00602
00603 uint32_t MatacqProducer::getOrbitId(edm::Event& ev) const{
00604
00605
00606
00607
00608 edm::Handle<FEDRawDataCollection> rawdata;
00609 if(!(ev.getByType(rawdata) && rawdata.isValid())){
00610 throw cms::Exception("NotFound")
00611 << "No FED raw data collection found. ECAL raw data are "
00612 "required to retrieve the orbit ID";
00613 }
00614
00615 int orbit = 0;
00616 for(int id=601; id<=654; ++id){
00617 if(!FEDNumbering::inRange(id)) continue;
00618 const FEDRawData& data = rawdata->FEDData(id);
00619 const int orbitIdOffset64 = 3;
00620 if(data.size()>=8*(orbitIdOffset64+1)){
00621 const unsigned char* pOrbit = data.data() + orbitIdOffset64*8;
00622 int thisOrbit = pOrbit[0]
00623 | (pOrbit[1] <<8)
00624 | (pOrbit[2] <<16)
00625 | (pOrbit[3] <<24);
00626 if(orbit!=0 && thisOrbit!=0 && abs(orbit-thisOrbit)>orbitTolerance_){
00627
00628
00629 LogWarning("EventCorruption")
00630 << "Orbit ID inconsitency in DCC headers";
00631 orbit = 0;
00632 break;
00633 }
00634 if(thisOrbit!=0) orbit = thisOrbit;
00635 }
00636 }
00637
00638 if(orbit==0){
00639
00640
00641 LogWarning("NotFound") << "Failed to retrieve orbit ID of event "
00642 << ev.id();
00643 }
00644 return orbit;
00645 }
00646
00647 int MatacqProducer::getCalibTriggerType(edm::Event& ev) const{
00648 edm::Handle<FEDRawDataCollection> rawdata;
00649 if(!(ev.getByType(rawdata) && rawdata.isValid())){
00650 throw cms::Exception("NotFound")
00651 << "No FED raw data collection found. ECAL raw data are "
00652 "required to retrieve the trigger type";
00653 }
00654
00655 Majority<int> stat;
00656 for(int id=601; id<=654; ++id){
00657 if(!FEDNumbering::inRange(id)) continue;
00658 const FEDRawData& data = rawdata->FEDData(id);
00659 const int detailedTrigger32 = 5;
00660 if(data.size()>=4*(detailedTrigger32+1)){
00661 const unsigned char* pTType = data.data() + detailedTrigger32*4;
00662 int tType = pTType[1] & 0x7;
00663 stat.add(tType);
00664 }
00665 }
00666 double p;
00667 int tType = stat.result(&p);
00668 if(p<0){
00669
00670 LogWarning("NotFound") << "No ECAL DCC data found\n";
00671 tType = -1;
00672 }
00673 if(p<.8){
00674
00675 LogWarning("EventCorruption") << "Inconsitency in detailed trigger type indicated in ECAL DCC data headers\n";
00676 tType = -1;
00677 }
00678 return tType;
00679 }
00680
00681 void MatacqProducer::PosEstimator::init(MatacqProducer* mp){
00682 mp->mrewind();
00683
00684 const size_t headerSize = 8*8;
00685 unsigned char data[headerSize];
00686 if(!mp->mread((char*)data, headerSize)){
00687 if(verbosity_) cout << "[Matacq " << now() << "] reached end of file!\n";
00688 firstOrbit_ = eventLength_ = orbitStepMean_ = 0;
00689 return;
00690 } else{
00691 firstOrbit_ = MatacqRawEvent::getOrbitId(data, headerSize);
00692 eventLength_ = MatacqRawEvent::getDccLen(data, headerSize);
00693 if(verbosity_>1) cout << "[Matacq " << now() << "] First event orbit: " << firstOrbit_
00694 << " event length: " << eventLength_
00695 << "*8 byte\n";
00696 }
00697
00698 mp->mrewind();
00699
00700 if(eventLength_==0){
00701 if(verbosity_) cout << "[Matacq " << now() << "] event length is null!" << endl;
00702 return;
00703 }
00704
00705 filepos_t s;
00706 mp->msize(s);
00707
00708
00709 const unsigned nEvents = s/eventLength_/8;
00710
00711 if(nEvents==0){
00712 if(verbosity_) cout << "[Matacq " << now() << "] File is empty!" << endl;
00713 orbitStepMean_ = 0;
00714 return;
00715 }
00716
00717 if(verbosity_>1) cout << "[Matacq " << now() << "] File size: " << s
00718 << " Number of events: " << nEvents << endl;
00719
00720
00721 off_t last = (nEvents-1)*(off_t)eventLength_*8;
00722 mp->mseek(last, SEEK_SET, "Moving to beginning of last complete "
00723 "matacq event");
00724 if(!mp->mread((char*) data, headerSize, "Reading matacq header", true)){
00725 LogWarning("Matacq") << "Fast matacq event retrieval failure. "
00726 "Falling back to safe retrieval mode.";
00727 orbitStepMean_ = 0;
00728 }
00729
00730 int32_t lastOrb = MatacqRawEvent::getOrbitId(data, headerSize);
00731 int32_t lastLen = MatacqRawEvent::getDccLen(data, headerSize);
00732
00733 if(verbosity_>1) cout << "[Matacq " << now() << "] Last event orbit: " << lastOrb
00734 << " last event length: " << lastLen << endl;
00735
00736
00737 if(lastLen!=eventLength_){
00738 LogWarning("Matacq")
00739
00740 << "Fast matacq event retrieval failure: it looks like "
00741 "the matacq file contains events of different sizes.";
00742
00743 invalid_ = false;
00744 orbitStepMean_ = 112;
00745 return;
00746 }
00747
00748 orbitStepMean_ = (lastOrb - firstOrbit_)/nEvents;
00749
00750 if(verbosity_>1) cout << "[Matacq " << now() << "] Orbit step mean: " << orbitStepMean_
00751 << "\n";
00752
00753 invalid_ = false;
00754 }
00755
00756 int64_t MatacqProducer::PosEstimator::pos(int orb) const{
00757 if(orb<firstOrbit_) return -1;
00758 uint64_t r = orbitStepMean_!=0?
00759 (((uint64_t)(orb-firstOrbit_))/orbitStepMean_)*eventLength_*8
00760 :0;
00761 if(verbosity_>2) cout << "[Matacq " << now() << "] Estimated Position for orbit " << orb
00762 << ": " << r << endl;
00763 return r;
00764 }
00765
00766 MatacqProducer::~MatacqProducer(){
00767 mclose();
00768 timeval t;
00769 gettimeofday(&t, 0);
00770 if(logTiming_ && startTime_.tv_sec!=0){
00771
00772 cout << "[Matacq " << now() << "] Time elapsed between first event and "
00773 "destruction of MatacqProducer: "
00774 << ((t.tv_sec-startTime_.tv_sec)*1.
00775 + (t.tv_usec-startTime_.tv_usec)*1.e-6) << "s\n";
00776 }
00777 }
00778
00779 void MatacqProducer::loadOrbitOffset(){
00780 ifstream f(orbitOffsetFile_.c_str());
00781 if(f.bad()){
00782 throw cms::Exception("Matacq")
00783 << "Failed to open orbit ID correction file '"
00784 << orbitOffsetFile_ << "'\n";
00785 }
00786
00787 cout << "[Matacq " << now() << "] "
00788 << "Offset to substract to Matacq events Orbit ID: \n"
00789 << "#Run Number\t Offset\n";
00790
00791 int iline = 0;
00792 string s;
00793 stringstream buf;
00794 while(f.eof()){
00795 getline(f, s);
00796 ++iline;
00797 if(s[0]=='#'){
00798
00799 f.ignore(numeric_limits<streamsize>::max(), '\n');
00800 continue;
00801 }
00802 buf.str("");
00803 buf << s;
00804 int run;
00805 int orbit;
00806 buf >> run;
00807 buf >> orbit;
00808 if(buf.bad()){
00809 throw cms::Exception("Matacq")
00810 << "Syntax error in Orbit offset file '"
00811 << orbitOffsetFile_ << "'";
00812 }
00813 cout << run << "\t" << orbit << "\n";
00814 orbitOffset_.insert(pair<int, int>(run, orbit));
00815 }
00816 }
00817
00818 #ifdef USE_STORAGE_MANAGER
00819 bool MatacqProducer::mseek(filepos_t offset, int whence, const char* mess){
00820 if(0==inFile_.get()) return false;
00821 try{
00822 Storage::Relative wh;
00823 if(whence==SEEK_SET) wh = Storage::SET;
00824 else if(whence==SEEK_CUR) wh = Storage::CURRENT;
00825 else if(whence==SEEK_END) wh = Storage::END;
00826 else throw cms::Exception("Bug") << "Bug found in "
00827 << __FILE__ << ": "<< __LINE__ << "\n";
00828
00829 inFile_->position(offset, wh);
00830 } catch(cms::Exception& e){
00831 if(verbosity_){
00832 cout << "[Matacq " << now() << "] ";
00833 if(mess) cout << mess << ". ";
00834 cout << "Random access error on input matacq file. ";
00835 if(whence==SEEK_SET) cout << "Failed to seek absolute position " << offset;
00836 else if(whence==SEEK_CUR) cout << "Failed to move " << offset << " bytes forward";
00837 else if(whence==SEEK_END) cout << "Failed to seek position at " << offset << " bytes before end of file";
00838 cout << ". Reopening file. " << e.what() << "\n";
00839 mopen(inFileName_);
00840 return false;
00841 }
00842 }
00843 return true;
00844 }
00845
00846 bool MatacqProducer::mtell(filepos_t& pos){
00847 if(0==inFile_.get()) return false;
00848 pos = inFile_->position();
00849 return true;
00850 }
00851
00852 bool MatacqProducer::mread(char* buf, size_t n, const char* mess, bool peek){
00853 if(0==inFile_.get()) return false;
00854
00855 filepos_t pos;
00856 if(!mtell(pos)) return false;
00857
00858 bool rc = false;
00859 try{
00860 rc = (n==inFile_->xread(buf, n));
00861 } catch(cms::Exception& e){
00862 if(verbosity_){
00863 cout << "[Matacq " << now() << "] ";
00864 if(mess) cout << mess << ". ";
00865 cout << "Read failure from input matacq file: "
00866 << e.what() << "\n";
00867 }
00868
00869 mopen(inFileName_);
00870 mseek(pos);
00871 return false;
00872 }
00873 if(peek){
00874 mseek(pos);
00875 }
00876 return rc;
00877 }
00878
00879 bool MatacqProducer::msize(filepos_t& s){
00880 if(inFile_.get()==0) return false;
00881 s = inFile_.get()->size();
00882 return true;
00883 }
00884
00885 bool MatacqProducer::mrewind(){
00886 Storage* file = inFile_.get();
00887 if(file==0) return false;
00888 try{
00889 file->rewind();
00890 } catch(cms::Exception e){
00891 if(verbosity_) cout << "Exception cautgh while rewinding file "
00892 << inFileName_ << ": " << e.what() << ". "
00893 << "File will be reopened.";
00894 return mopen(inFileName_);
00895 }
00896 return true;
00897 }
00898
00899 bool MatacqProducer::mcheck(const std::string& name){
00900 return StorageFactory::get()->check(name);
00901 }
00902
00903 bool MatacqProducer::mopen(const std::string& name){
00904
00905 mclose();
00906
00907 try{
00908 inFile_
00909 = auto_ptr<Storage>(StorageFactory::get()->open(name,
00910 IOFlags::OpenRead));
00911 inFileName_ = name;
00912 } catch(cms::Exception& e){
00913 LogWarning("Matacq") << e.what();
00914 inFile_.reset();
00915 inFileName_ = "";
00916 return false;
00917 }
00918 return true;
00919 }
00920
00921 void MatacqProducer::mclose(){
00922 if(inFile_.get()!=0){
00923 inFile_->close();
00924 inFile_.reset();
00925 }
00926 }
00927
00928 bool MatacqProducer::misOpened(){
00929 return inFile_.get()!=0;
00930 }
00931
00932 bool MatacqProducer::meof(){
00933 if(inFile_.get()==0) return true;
00934 return inFile_->eof();
00935 }
00936
00937 #else //USE_STORAGE_MANAGER not defined
00938 bool MatacqProducer::mseek(off_t offset, int whence, const char* mess){
00939 if(0==inFile_) return false;
00940 const int rc = fseeko(inFile_, offset, whence);
00941 if(rc!=0 && verbosity_){
00942 cout << "[Matacq " << now() << "] ";
00943 if(mess) cout << mess << ". ";
00944 cout << "Random access error on input matacq file. "
00945 "Rewind file.\n";
00946 mrewind();
00947 }
00948 return rc==0;
00949 }
00950
00951 bool MatacqProducer::mtell(filepos_t& pos){
00952 if(0==inFile_) return false;
00953 pos = ftello(inFile_);
00954 return pos != -1;
00955
00956 }
00957
00958 bool MatacqProducer::mread(char* buf, size_t n, const char* mess, bool peek){
00959 if(0==inFile_) return false;
00960 off_t pos = ftello(inFile_);
00961 bool rc = (pos!=-1) && (1==fread(buf, n, 1, inFile_));
00962 if(!rc){
00963 if(verbosity_){
00964 cout << "[Matacq " << now() << "] ";
00965 if(mess) cout << mess << ". ";
00966 cout << "Read failure from input matacq file.\n";
00967 }
00968 clearerr(inFile_);
00969 }
00970 if(peek || !rc){
00971 if(0!=fseeko(inFile_, pos, SEEK_SET)){
00972 if(verbosity_){
00973 cout << "[Matacq " << now() << "] ";
00974 if(mess) cout << mess << ". ";
00975 cout << "Failed to restore file position of "
00976 "before read error. Rewind file.\n";
00977 }
00978
00979 mrewind();
00980 lastOrb_ = 0;
00981 }
00982 }
00983 return rc;
00984 }
00985
00986 bool MatacqProducer::msize(filepos_t& s){
00987 if(0==inFile_) return false;
00988 struct stat buf;
00989 if(0!=fstat(fileno(inFile_), &buf)){
00990 s = 0;
00991 return false;
00992 } else{
00993 s = buf.st_size;
00994 return true;
00995 }
00996 }
00997
00998 bool MatacqProducer::mrewind(){
00999 if(0==inFile_) return false;
01000 clearerr(inFile_);
01001 return fseeko(inFile_, 0, SEEK_SET)!=0;
01002 }
01003
01004 bool MatacqProducer::mcheck(const std::string& name){
01005 struct stat dummy;
01006 return 0==stat(name.c_str(), &dummy);
01007
01008
01009
01010
01011
01012
01013
01014
01015 }
01016
01017 bool MatacqProducer::mopen(const std::string& name){
01018 if(inFile_!=0) mclose();
01019 inFile_ = fopen(name.c_str(), "r");
01020 if(inFile_!=0){
01021 inFileName_ = name;
01022 return true;
01023 } else{
01024 inFileName_ = "";
01025 return false;
01026 }
01027 }
01028
01029 void MatacqProducer::mclose(){
01030 if(inFile_!=0) fclose(inFile_);
01031 inFile_ = 0;
01032 }
01033
01034 bool MatacqProducer::misOpened(){
01035 return inFile_!=0;
01036 }
01037
01038 bool MatacqProducer::meof(){
01039 if(0==inFile_) return true;
01040 return feof(inFile_)==0;
01041 }
01042
01043 #endif //USE_STORAGE_MANAGER defined
01044
01045 std::string MatacqProducer::runSubDir(uint32_t runNumber){
01046 int millions = runNumber / (1000*1000);
01047 int thousands = (runNumber-millions*1000*1000) / 1000;
01048 int units = runNumber-millions*1000*1000 - thousands*1000;
01049 return str(boost::format("%03d/%03d/%03d") % millions % thousands % units);
01050 }
01051
01052 void MatacqProducer::newRun(int prevRun, int newRun){
01053 runNumber_ = newRun;
01054 eventSkipCounter_ = 0;
01055 logFile_ << "[" << now() << "] Event count for run "
01056 << runNumber_ << ": "
01057 << "total: " << stats_.nEvents << ", "
01058 << "Laser event with Matacq data: "
01059 << stats_.nLaserEventsWithMatacq << ", "
01060 << "Non laser event (according to DCC header) with Matacq data: "
01061 << stats_.nNonLaserEventsWithMatacq << "\n" << flush;
01062
01063 stats_.nEvents = 0;
01064 stats_.nLaserEventsWithMatacq = 0;
01065 stats_.nNonLaserEventsWithMatacq = 0;
01066
01067
01068 }