00001
00008 #include "DaqSource.h"
00009
00010 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00011 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00012 #include "EventFilter/FEDInterface/interface/GlobalEventNumber.h"
00013
00014 #include "IORawData/DaqSource/interface/DaqBaseReader.h"
00015 #include "IORawData/DaqSource/interface/DaqReaderPluginFactory.h"
00016
00017 #include "DataFormats/Provenance/interface/Timestamp.h"
00018 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00019 #include "FWCore/Framework/interface/EventPrincipal.h"
00020 #include "FWCore/Framework/interface/Event.h"
00021 #include "DataFormats/Provenance/interface/EventAuxiliary.h"
00022 #include "DataFormats/Provenance/interface/LuminosityBlockAuxiliary.h"
00023 #include "DataFormats/Provenance/interface/RunAuxiliary.h"
00024 #include "DataFormats/Provenance/interface/EventID.h"
00025 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00026
00027 #include <string>
00028 #include <iostream>
00029 #include <time.h>
00030 #include <sys/time.h>
00031 #include <sys/types.h>
00032
00033 #include "xgi/Method.h"
00034 #include "xgi/Utils.h"
00035
00036 #include "cgicc/Cgicc.h"
00037 #include "cgicc/FormEntry.h"
00038 #include "cgicc/HTMLClasses.h"
00039
00040 #include "boost/tokenizer.hpp"
00041
00042
00044
00046
00047
00048
00049 namespace edm {
00050 namespace daqsource{
00051 static unsigned int gtpEvmId_ = FEDNumbering::MINTriggerGTPFEDID;
00052 static unsigned int gtpeId_ = FEDNumbering::MINTriggerEGTPFEDID;
00053 }
00054
00055
00056 DaqSource::DaqSource(const ParameterSet& pset,
00057 const InputSourceDescription& desc)
00058 : InputSource(pset,desc)
00059 , evf::ModuleWeb("DaqSource")
00060 , reader_(0)
00061 , lumiSegmentSizeInEvents_(pset.getUntrackedParameter<unsigned int>("evtsPerLS",0))
00062 , useEventCounter_(pset.getUntrackedParameter<bool>("useEventCounter",false))
00063 , eventCounter_(0)
00064 , keepUsingPsidFromTrigger_(pset.getUntrackedParameter<bool>("keepUsingPsidFromTrigger",false))
00065 , fakeLSid_(lumiSegmentSizeInEvents_ != 0)
00066 , runNumber_(RunID::firstValidRun().run())
00067 , luminosityBlockNumber_(LuminosityBlockID::firstValidLuminosityBlock().luminosityBlock())
00068 , noMoreEvents_(false)
00069 , newRun_(true)
00070 , newLumi_(true)
00071 , eventCached_(false)
00072 , alignLsToLast_(false)
00073 , is_(0)
00074 , mis_(0)
00075 , thisEventLSid(0)
00076 , goToStopping(false)
00077 {
00078 count = 0;
00079 pthread_mutex_init(&mutex_,0);
00080 pthread_mutex_init(&signal_lock_,0);
00081 pthread_cond_init(&cond_,0);
00082 produces<FEDRawDataCollection>();
00083 setTimestamp(Timestamp::beginOfTime());
00084
00085
00086 std::string reader = pset.getUntrackedParameter<std::string>("readerPluginName");
00087
00088 try{
00089 reader_=
00090 DaqReaderPluginFactory::get()->create(reader,
00091 pset.getUntrackedParameter<ParameterSet>("readerPset"));
00092 reader_->setRunNumber(runNumber_);
00093 }
00094 catch(edm::Exception &e) {
00095 if(e.category() == "Configuration" && reader_ == 0) {
00096 reader_ = DaqReaderPluginFactoryU::get()->create(reader);
00097 if(reader_ == 0) throw;
00098 else reader_->setRunNumber(runNumber_);
00099 }
00100 else {
00101 throw;
00102 }
00103 }
00104 }
00105
00106
00107 DaqSource::~DaqSource() {
00108 delete reader_;
00109 }
00110
00111
00113
00115
00116
00117 InputSource::ItemType
00118 DaqSource::getNextItemType() {
00119
00120 if(goToStopping){noMoreEvents_ = true; goToStopping=false;}
00121 if (noMoreEvents_) {
00122 pthread_mutex_lock(&mutex_);
00123 pthread_cond_signal(&cond_);
00124 pthread_mutex_unlock(&mutex_);
00125 return IsStop;
00126 }
00127 if (newRun_) {
00128 return IsRun;
00129 }
00130 if (newLumi_ && luminosityBlockAuxiliary()) {
00131
00132 return IsLumi;
00133 }
00134 if (alignLsToLast_) {
00135
00136
00137
00138 signalWaitingThreadAndBlock();
00139 luminosityBlockNumber_++;
00140
00141
00142
00143 newLumi_ = true;
00144 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00145 resetLuminosityBlockAuxiliary();
00146 if(luminosityBlockNumber_ == thisEventLSid+1)
00147 {
00148 alignLsToLast_ = false;
00149 }
00150 if (!luminosityBlockAuxiliary() || luminosityBlockAuxiliary()->luminosityBlock() != luminosityBlockNumber_) {
00151 setLuminosityBlockAuxiliary(new LuminosityBlockAuxiliary(
00152 runNumber_, luminosityBlockNumber_, timestamp(), Timestamp::invalidTimestamp()));
00153
00154 readAndCacheLumi();
00155 setLumiPrematurelyRead();
00156
00157 }
00158 return IsLumi;
00159 }
00160 if (eventCached_) {
00161
00162 return IsEvent;
00163 }
00164 if(reader_ == 0) {
00165 throw edm::Exception(errors::LogicError)
00166 << "DaqSource is used without a reader. Check your configuration !";
00167 }
00168 EventID eventId;
00169 TimeValue_t time = 0LL;
00170 timeval stv;
00171 gettimeofday(&stv,0);
00172 time = stv.tv_sec;
00173 time = (time << 32) + stv.tv_usec;
00174 Timestamp tstamp(time);
00175
00176 int bunchCrossing = EventAuxiliary::invalidBunchXing;
00177 int orbitNumber = EventAuxiliary::invalidBunchXing;
00178
00179
00180 FEDRawDataCollection* fedCollection(0);
00181
00182 edm::EventAuxiliary::ExperimentType evttype = EventAuxiliary::Undefined;
00183
00184
00185 int retval = reader_->fillRawData(eventId, tstamp, fedCollection);
00186 if(retval==0) {
00187
00188 if (0 != fedCollection) delete fedCollection;
00189 noMoreEvents_ = true;
00190 pthread_mutex_lock(&mutex_);
00191 pthread_cond_signal(&cond_);
00192 pthread_mutex_unlock(&mutex_);
00193 return IsStop;
00194 }
00195 else if(retval<0)
00196 {
00197
00198 unsigned int nextLsFromSignal = (-1)*retval+1;
00199
00200
00201 if(luminosityBlockNumber_ < nextLsFromSignal)
00202 {
00203 if(lsToBeRecovered_->value_){
00204
00205 signalWaitingThreadAndBlock();
00206 luminosityBlockNumber_++;
00207 newLumi_ = true;
00208 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00209 resetLuminosityBlockAuxiliary();
00210 thisEventLSid = nextLsFromSignal - 1;
00211 if(luminosityBlockNumber_ != thisEventLSid+1)
00212 alignLsToLast_ = true;
00213
00214 }
00215 else{
00216
00217 luminosityBlockNumber_ = nextLsFromSignal;
00218 newLumi_ = true;
00219 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00220 resetLuminosityBlockAuxiliary();
00221 }
00222 }
00223
00224
00225 }
00226 else
00227 {
00228 if (eventId.event() == 0) {
00229 throw edm::Exception(errors::LogicError)
00230 << "The reader used with DaqSource has returned an invalid (zero) event number!\n"
00231 << "Event numbers must begin at 1, not 0.";
00232 }
00233 EventSourceSentry(*this);
00234 setTimestamp(tstamp);
00235
00236 unsigned char *gtpFedAddr = fedCollection->FEDData(daqsource::gtpEvmId_).size()!=0 ? fedCollection->FEDData(daqsource::gtpEvmId_).data() : 0;
00237 uint32_t gtpsize = 0;
00238 if(gtpFedAddr !=0) gtpsize = fedCollection->FEDData(daqsource::gtpEvmId_).size();
00239 unsigned char *gtpeFedAddr = fedCollection->FEDData(daqsource::gtpeId_).size()!=0 ? fedCollection->FEDData(daqsource::gtpeId_).data() : 0;
00240
00241 unsigned int nextFakeLs = 0;
00242 eventCounter_++;
00243 if(fakeLSid_ && luminosityBlockNumber_ !=
00244 (nextFakeLs = useEventCounter_ ? ((eventCounter_-1)/lumiSegmentSizeInEvents_ + 1) :
00245 ((eventId.event() - 1)/lumiSegmentSizeInEvents_ + 1))) {
00246 lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00247 prescaleSetIndex_->value_ = 0;
00248
00249 if(luminosityBlockNumber_ == nextFakeLs-1)
00250 signalWaitingThreadAndBlock();
00251 luminosityBlockNumber_ = nextFakeLs;
00252 thisEventLSid = nextFakeLs-1;
00253 newLumi_ = true;
00254 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00255 resetLuminosityBlockAuxiliary();
00256 if(keepUsingPsidFromTrigger_ &&
00257 gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00258 prescaleSetIndex_->value_ = (evf::evtn::getfdlpsc(gtpFedAddr) & 0xffff);
00259 }
00260 }
00261 else if(!fakeLSid_){
00262
00263 if(gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00264 lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00265 thisEventLSid = evf::evtn::getlbn(gtpFedAddr);
00266 prescaleSetIndex_->value_ = (evf::evtn::getfdlpsc(gtpFedAddr) & 0xffff);
00267 evttype = edm::EventAuxiliary::ExperimentType(evf::evtn::getevtyp(gtpFedAddr));
00268 if(luminosityBlockNumber_ != (thisEventLSid + 1)){
00269
00270
00271 if(lsToBeRecovered_->value_){
00272
00273 signalWaitingThreadAndBlock();
00274 luminosityBlockNumber_++;
00275 newLumi_ = true;
00276 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00277 resetLuminosityBlockAuxiliary();
00278 if(luminosityBlockNumber_ != thisEventLSid+1) alignLsToLast_ = true;
00279
00280 }
00281 else{
00282
00283 luminosityBlockNumber_ = thisEventLSid + 1;
00284 newLumi_ = true;
00285 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00286 resetLuminosityBlockAuxiliary();
00287 lsToBeRecovered_->value_ = true;
00288 }
00289 }
00290 }
00291 else if(gtpeFedAddr!=0 && evf::evtn::gtpe_board_sense(gtpeFedAddr)){
00292 lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00293 thisEventLSid = evf::evtn::gtpe_getlbn(gtpeFedAddr);
00294 prescaleSetIndex_->value_ = 0;
00295 evttype = edm::EventAuxiliary::PhysicsTrigger;
00296 if(luminosityBlockNumber_ != (thisEventLSid + 1)){
00297 if(luminosityBlockNumber_ == thisEventLSid)
00298 signalWaitingThreadAndBlock();
00299 luminosityBlockNumber_ = thisEventLSid + 1;
00300 newLumi_ = true;
00301 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00302 resetLuminosityBlockAuxiliary();
00303 }
00304 }
00305 }
00306 if(gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00307 bunchCrossing = int(evf::evtn::getfdlbx(gtpFedAddr));
00308 orbitNumber = int(evf::evtn::getorbit(gtpFedAddr));
00309 TimeValue_t time = evf::evtn::getgpshigh(gtpFedAddr);
00310 time = (time << 32) + evf::evtn::getgpslow(gtpFedAddr);
00311 Timestamp tstamp(time);
00312 setTimestamp(tstamp);
00313 }
00314 else if(gtpeFedAddr!=0 && evf::evtn::gtpe_board_sense(gtpeFedAddr)){
00315 bunchCrossing = int(evf::evtn::gtpe_getbx(gtpeFedAddr));
00316 orbitNumber = int(evf::evtn::gtpe_getorbit(gtpeFedAddr));
00317 }
00318 }
00319
00320
00321
00322 if (!luminosityBlockAuxiliary() || luminosityBlockAuxiliary()->luminosityBlock() != luminosityBlockNumber_) {
00323 newLumi_ = true;
00324 setLuminosityBlockAuxiliary(new LuminosityBlockAuxiliary(
00325 runNumber_, luminosityBlockNumber_, timestamp(), Timestamp::invalidTimestamp()));
00326
00327 readAndCacheLumi();
00328 setLumiPrematurelyRead();
00329
00330 }
00331
00332 if(retval<0){
00333
00334
00335 if(newLumi_) return IsLumi; else return getNextItemType();
00336 }
00337
00338
00339 eventId = EventID(runNumber_,thisEventLSid+1, eventId.event());
00340 std::auto_ptr<EventAuxiliary> eventAux(
00341 new EventAuxiliary(eventId, processGUID(),
00342 timestamp(),
00343 true,
00344 evttype,
00345 bunchCrossing,
00346 EventAuxiliary::invalidStoreNumber,
00347 orbitNumber));
00348 eventPrincipalCache()->fillEventPrincipal(eventAux, luminosityBlockPrincipal());
00349 eventCached_ = true;
00350
00351
00352 std::auto_ptr<FEDRawDataCollection> bare_product(fedCollection);
00353
00354 std::auto_ptr<Event> e(new Event(*eventPrincipalCache(), moduleDescription()));
00355
00356 e->put(bare_product);
00357
00358 e->commit_();
00359 if (newLumi_) {
00360 return IsLumi;
00361 }
00362 return IsEvent;
00363 }
00364
00365 void
00366 DaqSource::setRun(RunNumber_t r) {
00367 assert(!eventCached_);
00368 reset();
00369 newRun_ = newLumi_ = true;
00370 runNumber_ = r;
00371 if (reader_) reader_->setRunNumber(runNumber_);
00372 noMoreEvents_ = false;
00373 resetLuminosityBlockAuxiliary();
00374 }
00375
00376 boost::shared_ptr<RunAuxiliary>
00377 DaqSource::readRunAuxiliary_() {
00378 assert(newRun_);
00379 assert(!noMoreEvents_);
00380 newRun_ = false;
00381 return boost::shared_ptr<RunAuxiliary>(new RunAuxiliary(runNumber_, timestamp(), Timestamp::invalidTimestamp()));
00382 }
00383
00384 boost::shared_ptr<LuminosityBlockAuxiliary>
00385 DaqSource::readLuminosityBlockAuxiliary_() {
00386 assert(!newRun_);
00387 assert(newLumi_);
00388 assert(!noMoreEvents_);
00389 assert(luminosityBlockAuxiliary());
00390
00391
00392 newLumi_ = false;
00393 return luminosityBlockAuxiliary();
00394 }
00395
00396 EventPrincipal*
00397 DaqSource::readEvent_() {
00398
00399 assert(!newRun_);
00400
00401 assert(!newLumi_);
00402
00403 assert(!noMoreEvents_);
00404
00405 assert(eventCached_);
00406
00407 eventCached_ = false;
00408 return eventPrincipalCache();
00409 }
00410
00411 void
00412 DaqSource::setLumi(LuminosityBlockNumber_t) {
00413 throw edm::Exception(errors::LogicError,"DaqSource::setLumi(LuminosityBlockNumber_t lumiNumber)")
00414 << "The luminosity block number cannot be set externally for DaqSource.\n"
00415 << "Contact a Framework developer.\n";
00416 }
00417
00418 EventPrincipal*
00419 DaqSource::readIt(EventID const&) {
00420 throw edm::Exception(errors::LogicError,"DaqSource::readIt(EventID const& eventID)")
00421 << "Random access read cannot be used for DaqSource.\n"
00422 << "Contact a Framework developer.\n";
00423 }
00424
00425 void
00426 DaqSource::skip(int) {
00427 throw edm::Exception(errors::LogicError,"DaqSource::skip(int offset)")
00428 << "Random access skip cannot be used for DaqSource\n"
00429 << "Contact a Framework developer.\n";
00430 }
00431
00432 void DaqSource::publish(xdata::InfoSpace *is)
00433 {
00434 is_ = is;
00435 lumiSectionIndex_ = (xdata::UnsignedInteger32*)is_->find("lumiSectionIndex");
00436 prescaleSetIndex_ = (xdata::UnsignedInteger32*)is_->find("prescaleSetIndex");
00437 lastLumiPrescaleIndex_ = (xdata::UnsignedInteger32*)is_->find("lastLumiPrescaleIndex");
00438 lsTimedOut_ = (xdata::Boolean*)is_->find("lsTimedOut");
00439 lsToBeRecovered_ = (xdata::Boolean*)is_->find("lsToBeRecovered");
00440 }
00441 void DaqSource::publishToXmas(xdata::InfoSpace *is)
00442 {
00443 mis_ = is;
00444 }
00445
00446 void DaqSource::openBackDoor(unsigned int timeout_sec)
00447 {
00448 count++;
00449 if(count==2) throw;
00450 pthread_mutex_lock(&mutex_);
00451 pthread_mutex_unlock(&signal_lock_);
00452 timespec ts;
00453 #if _POSIX_TIMERS > 0
00454 clock_gettime(CLOCK_REALTIME, &ts);
00455 #else
00456 struct timeval tv;
00457 gettimeofday(&tv, NULL);
00458 ts.tv_sec = tv.tv_sec + 0;
00459 ts.tv_nsec = 0;
00460 #endif
00461 ts.tv_sec += timeout_sec;
00462
00463 int rc = pthread_cond_timedwait(&cond_, &mutex_, &ts);
00464 if(rc == ETIMEDOUT) lsTimedOut_->value_ = true;
00465 }
00466
00467 void DaqSource::closeBackDoor()
00468 {
00469 count--;
00470 pthread_cond_signal(&cond_);
00471 pthread_mutex_unlock(&mutex_);
00472 pthread_mutex_lock(&signal_lock_);
00473 lsTimedOut_->value_ = false;
00474 }
00475
00476 void DaqSource::signalWaitingThreadAndBlock()
00477 {
00478 pthread_mutex_lock(&signal_lock_);
00479 pthread_mutex_lock(&mutex_);
00480 pthread_mutex_unlock(&signal_lock_);
00481
00482 pthread_cond_signal(&cond_);
00483
00484 pthread_cond_wait(&cond_, &mutex_);
00485 pthread_mutex_unlock(&mutex_);
00486 ::usleep(1000);
00487 }
00488
00489 void DaqSource::defaultWebPage(xgi::Input *in, xgi::Output *out)
00490 {
00491 std::string path;
00492 std::string urn;
00493 std::string mname;
00494 std::string query;
00495 std::string original_referrer_;
00496 try
00497 {
00498 cgicc::Cgicc cgi(in);
00499 if ( xgi::Utils::hasFormElement(cgi,"gotostopping") )
00500 {
00501 goToStopping=true;
00502 }
00503 if ( xgi::Utils::hasFormElement(cgi,"module") )
00504 mname = xgi::Utils::getFormElement(cgi, "module")->getValue();
00505 cgicc::CgiEnvironment cgie(in);
00506 if(original_referrer_ == "")
00507 original_referrer_ = cgie.getReferrer();
00508 path = cgie.getPathInfo();
00509 query = cgie.getQueryString();
00510 }
00511 catch (const std::exception & e)
00512 {
00513
00514 }
00515
00516 using std::endl;
00517 *out << "<html>" << endl;
00518 *out << "<head>" << endl;
00519
00520
00521 *out << "<STYLE type=\"text/css\"> #T1 {border-width: 2px; border: solid blue; text-align: center} </STYLE> " << endl;
00522 *out << "<link type=\"text/css\" rel=\"stylesheet\"";
00523 *out << " href=\"/" << urn
00524 << "/styles.css\"/>" << endl;
00525
00526 *out << "<title>" << moduleName_
00527 << " MAIN</title>" << endl;
00528
00529 *out << "</head>" << endl;
00530 *out << "<body onload=\"loadXMLDoc()\">" << endl;
00531 *out << "<table border=\"0\" width=\"100%\">" << endl;
00532 *out << "<tr>" << endl;
00533 *out << " <td align=\"left\">" << endl;
00534 *out << " <img" << endl;
00535 *out << " align=\"middle\"" << endl;
00536 *out << " src=\"/evf/images/bugicon.jpg\"" << endl;
00537 *out << " alt=\"main\"" << endl;
00538 *out << " width=\"90\"" << endl;
00539 *out << " height=\"64\"" << endl;
00540 *out << " border=\"\"/>" << endl;
00541 *out << " <b>" << endl;
00542 *out << moduleName_ << endl;
00543 *out << " </b>" << endl;
00544 *out << " </td>" << endl;
00545 *out << " <td width=\"32\">" << endl;
00546 *out << " <a href=\"/urn:xdaq-application:lid=3\">" << endl;
00547 *out << " <img" << endl;
00548 *out << " align=\"middle\"" << endl;
00549 *out << " src=\"/hyperdaq/images/HyperDAQ.jpg\"" << endl;
00550 *out << " alt=\"HyperDAQ\"" << endl;
00551 *out << " width=\"32\"" << endl;
00552 *out << " height=\"32\"" << endl;
00553 *out << " border=\"\"/>" << endl;
00554 *out << " </a>" << endl;
00555 *out << " </td>" << endl;
00556 *out << " <td width=\"32\">" << endl;
00557 *out << " </td>" << endl;
00558 *out << " <td width=\"32\">" << endl;
00559 *out << " <a href=\"" << original_referrer_ << "\">" << endl;
00560 *out << " <img" << endl;
00561 *out << " align=\"middle\"" << endl;
00562 *out << " src=\"/evf/images/spoticon.jpg\"" << endl;
00563 *out << " alt=\"main\"" << endl;
00564 *out << " width=\"32\"" << endl;
00565 *out << " height=\"32\"" << endl;
00566 *out << " border=\"\"/>" << endl;
00567 *out << " </a>" << endl;
00568 *out << " </td>" << endl;
00569 *out << "</tr>" << endl;
00570 *out << "</table>" << endl;
00571
00572 *out << "<hr/>" << endl;
00573
00574 *out << cgicc::form().set("method","GET").set("action", path )
00575 << std::endl;
00576 boost::char_separator<char> sep("&");
00577 boost::tokenizer<boost::char_separator<char> > tokens(query, sep);
00578 for (boost::tokenizer<boost::char_separator<char> >::iterator tok_iter = tokens.begin();
00579 tok_iter != tokens.end(); ++tok_iter){
00580 size_t pos = (*tok_iter).find_first_of("=");
00581 if(pos != std::string::npos){
00582 std::string first = (*tok_iter).substr(0 , pos);
00583 std::string second = (*tok_iter).substr(pos+1, (*tok_iter).length()-pos-1);
00584 *out << cgicc::input().set("type","hidden").set("name",first).set("value", second)
00585 << std::endl;
00586 }
00587 }
00588
00589 *out << cgicc::input().set("type","hidden").set("name","gotostopping").set("value","true")
00590 << std::endl;
00591 *out << cgicc::input().set("type","submit").set("value","Go To Stopping") << std::endl;
00592 *out << cgicc::form() << std::endl;
00593
00594 *out << "</body>" << endl;
00595 *out << "</html>" << endl;
00596 }
00597 }