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