CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/IORawData/DaqSource/plugins/DaqSource.cc

Go to the documentation of this file.
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/MessageLogger/interface/MessageLogger.h"
00021 #include "DataFormats/Provenance/interface/LuminosityBlockAuxiliary.h"
00022 #include "DataFormats/Provenance/interface/RunAuxiliary.h"
00023 #include "DataFormats/Provenance/interface/EventID.h"
00024 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00025 
00026 #include <string>
00027 #include <iostream>
00028 #include <time.h>
00029 #include <sys/time.h>
00030 #include <sys/types.h>
00031 
00032 #include "xgi/Method.h"
00033 #include "xgi/Utils.h"
00034 
00035 #include "cgicc/Cgicc.h"
00036 #include "cgicc/FormEntry.h"
00037 #include "cgicc/HTMLClasses.h"
00038 
00039 #include "boost/tokenizer.hpp"
00040 
00041 
00043 // construction/destruction
00045 
00046 
00047 
00048 namespace edm {
00049  namespace daqsource{
00050   constexpr unsigned int gtpEvmId_ =  FEDNumbering::MINTriggerGTPFEDID;
00051   constexpr unsigned int gtpeId_ =  FEDNumbering::MINTriggerEGTPFEDID;
00052  }
00053 
00054   //______________________________________________________________________________
00055   DaqSource::DaqSource(const ParameterSet& pset, 
00056                      const InputSourceDescription& desc) 
00057     : InputSource(pset,desc)
00058     , evf::ModuleWeb("DaqSource")
00059     , reader_(0)
00060     , lumiSegmentSizeInEvents_(pset.getUntrackedParameter<unsigned int>("evtsPerLS",0))
00061     , lumiSegmentSizeInSeconds_(pset.getUntrackedParameter<unsigned int>("secondsPerLS",0))
00062     , useEventCounter_(pset.getUntrackedParameter<bool>("useEventCounter",false))
00063     , useTimer_(lumiSegmentSizeInSeconds_!=0)
00064     , eventCounter_(0)
00065     , keepUsingPsidFromTrigger_(pset.getUntrackedParameter<bool>("keepUsingPsidFromTrigger",false))
00066     , fakeLSid_(lumiSegmentSizeInEvents_ != 0 || lumiSegmentSizeInSeconds_ != 0)
00067     , runNumber_(pset.getUntrackedParameter<unsigned int>("runNumber",RunID::firstValidRun().run()))
00068     , luminosityBlockNumber_(LuminosityBlockID::firstValidLuminosityBlock().luminosityBlock())
00069     , daqProvenanceHelper_(TypeID(typeid(FEDRawDataCollection)))
00070     , noMoreEvents_(false)
00071     , alignLsToLast_(false)
00072     , lumiSectionIndex_(0)
00073     , prescaleSetIndex_(0)
00074     , lastLumiPrescaleIndex_(0)
00075     , lastLumiUsingEol_(0)
00076     , lsTimedOut_(0)
00077     , lsToBeRecovered_(0)
00078     , is_(0)
00079     , mis_(0)
00080     , thisEventLSid(0)
00081     , goToStopping(false)
00082     , immediateStop(false)
00083     , forkInfo_(nullptr)
00084     , runFork_(false)
00085     , beginRunTiming_(false)
00086     , bunchCrossing_(EventAuxiliary::invalidBunchXing)
00087     , orbitNumber_(EventAuxiliary::invalidBunchXing)
00088     , evttype_(EventAuxiliary::Undefined)
00089     , eventID_(0,0,0)
00090     , fedCollection_(nullptr)
00091   {
00092     count = 0;
00093     pthread_mutex_init(&mutex_,0);
00094     pthread_mutex_init(&signal_lock_,0);
00095     pthread_cond_init(&cond_,0);
00096 
00097     std::cout << " DaqSourceFake will use fake ls id ? " << fakeLSid_ << std::endl; 
00098     if(fakeLSid_) std::cout << " DaqSourceFake set to make a new ls every " << lumiSegmentSizeInEvents_ << " events " << std::endl;
00099     if(fakeLSid_) std::cout << " DaqSourceFake set to make a new ls every " << lumiSegmentSizeInSeconds_ << " seconds " << std::endl;
00100 
00101     setTimestamp(Timestamp::beginOfTime());
00102     
00103     // Instantiate the requested data source
00104     std::string reader = pset.getUntrackedParameter<std::string>("readerPluginName");
00105     
00106     try{
00107       reader_=
00108         DaqReaderPluginFactory::get()->create(reader,
00109                                             pset.getUntrackedParameter<ParameterSet>("readerPset"));
00110       reader_->setRunNumber(runNumber_);
00111     }
00112     catch(edm::Exception &e) {
00113       if(e.category() == "Configuration" && reader_ == 0) {
00114         reader_ = DaqReaderPluginFactoryU::get()->create(reader);
00115         if(reader_ == 0) throw;
00116         else reader_->setRunNumber(runNumber_);
00117       }
00118       else {
00119         throw;
00120       }
00121     }
00122 
00123     // Initialize LS timer if requested
00124     if(lumiSegmentSizeInSeconds_ != 0) gettimeofday(&startOfLastLumi,0);
00125 
00126     // Initialize metadata, and save the process history ID for use every event.
00127     phid_ = daqProvenanceHelper_.daqInit(productRegistryUpdate());
00128 
00129   }
00130   
00131   //______________________________________________________________________________
00132   DaqSource::~DaqSource() {
00133     delete reader_;
00134   }
00135   
00136   void DaqSource::publishForkInfo(evf::moduleweb::ForkInfoObj * forkInfoObj) {
00137     forkInfo_ = forkInfoObj;
00138     runFork_=true;
00139     immediateStop=false;
00140     noMoreEvents_=false;
00141   }
00142   
00144   // implementation of member functions
00146 
00147 
00148   //______________________________________________________________________________
00149   int DaqSource::doMyBeginRun() {
00150 
00151     if (forkInfo_) {
00152       while (!immediateStop) {
00153         //queue new run to Framework (causes EP beginRun to be executed)
00154         if (newRun()) {
00155           beginRunTiming_=true;
00156           gettimeofday(&tvStat_, NULL);
00157           return 2;
00158         }
00159         //measure time in fwk beginRun
00160         if (beginRunTiming_) {
00161           timeval tsTmp;
00162           gettimeofday(&tsTmp,NULL);
00163           long tusecs = (tsTmp.tv_sec-tvStat_.tv_sec)*1000000 + tsTmp.tv_usec - tvStat_.tv_usec;
00164           double tsecs = ((double)(tusecs/10000))/100.;
00165           std::cout << "DaqSource: FWK beginRun elapsed time: " << tsecs << " seconds in master EP"<< std::endl;
00166           edm::LogInfo("DaqSource") << "FWK beginRun elapsed time: " << tsecs << " seconds in master EP";
00167           beginRunTiming_=false;
00168           usleep(10000);//short sleep before fork
00169         }
00170         //first or new run init
00171         if (forkInfo_->forkParams.isMaster==-1) {
00172           forkInfo_->lock();//keeping it locked during init!
00173           forkInfo_->forkHandler(forkInfo_->fuAddr); //fork all slaves
00174         }
00175         if (forkInfo_->forkParams.isMaster==-1) {
00176           forkInfo_->unlock();
00177           std::cout << "ERROR (DaqSource): not notified to be either in  master or slave process after fork" << std::endl;
00178           return -2;
00179         }
00180 
00181         //slave process after fork: exit all this
00182         if (forkInfo_->forkParams.isMaster==0) {
00183           forkInfo_->unlock();
00184           return 1;
00185         }
00186 
00187         //master process after fork:
00188         if (forkInfo_->forkParams.isMaster==1) {
00189             forkInfo_->unlock();
00190             int slotToRestart=-1;
00191             sem_wait(forkInfo_->control_sem_);
00192             forkInfo_->lock();
00193 
00194             //got unblocked due to next run
00195             if (forkInfo_->forkParams.isMaster==-1) {
00196                     forkInfo_->unlock();
00197                     continue; // check here for newRun()?
00198             }
00199             //check if asked to stop
00200             immediateStop=forkInfo_->stopCondition;
00201             if (immediateStop) {
00202               forkInfo_->receivedStop_=true;
00203               break;
00204             }
00205             
00206             //check if asked to restart
00207             slotToRestart = forkInfo_->forkParams.slotId;
00208 
00209           if (slotToRestart==-1 && forkInfo_->forkParams.restart==0) {
00210             //this will deal with spurious semaphore signals when slave is killed
00211             forkInfo_->unlock();
00212             continue;
00213           }
00214           //restart single slave
00215           forkInfo_->forkHandler(forkInfo_->fuAddr);
00216         }
00217       }
00218       //loop exit
00219       forkInfo_->unlock();
00220       return 0;
00221     }
00222     return -1; //no forkInfo_
00223   }
00224 
00225 
00226   //______________________________________________________________________________
00227   InputSource::ItemType 
00228   DaqSource::getNextItemType() {
00229     //    std::cout << getpid() << " enter getNextItemType " << std::endl;
00230     if (runFork_) {
00231       runFork_=false;
00232       int queueNext = doMyBeginRun();
00233       //check if new run (requires returning IsRun once)
00234       if (queueNext == 2) runFork_=true;
00235     }
00236 
00237     //get initial time before beginRun (used with old forking)
00238     if (!forkInfo_ && newRun()) {
00239       beginRunTiming_=true;
00240       gettimeofday(&tvStat_, NULL);
00241     }
00242 
00243     if (immediateStop) return IsStop;
00244 
00245     // --------------
00246     if(goToStopping){noMoreEvents_ = true; goToStopping=false;}
00247     if (noMoreEvents_) {
00248       pthread_mutex_lock(&mutex_);
00249       pthread_cond_signal(&cond_);
00250       pthread_mutex_unlock(&mutex_);
00251       return IsStop;
00252     }
00253     if (newRun()) {
00254       return IsRun;
00255     }
00256 
00257     //calculate and print the beginRun the timing
00258     if (beginRunTiming_) {
00259       timeval tsTmp;
00260       gettimeofday(&tsTmp,NULL);
00261       long tusecs = (tsTmp.tv_sec-tvStat_.tv_sec)*1000000 + tsTmp.tv_usec - tvStat_.tv_usec;
00262       double tsecs = ((double)(tusecs/10000))/100.;
00263       std::cout << "DaqSource (slave pid "<< getpid() << " ): FWK beginRun elapsed time: " 
00264                 << tsecs << " seconds "<< std::endl;
00265       edm::LogInfo("DaqSource") << "DaqSource (slave pid "<< getpid() << " ): FWK beginRun elapsed time: " 
00266                 << tsecs << " seconds ";
00267       beginRunTiming_=false;
00268     }
00269 
00270     if (newLumi() && luminosityBlockAuxiliary()) {
00271       //      std::cout << "newLumi & lumiblock valid " << std::endl;
00272       return IsLumi;
00273     }
00274     if (alignLsToLast_) { //here we are recovering from a gap in Ls number so an event may already be cached but 
00275       // we hold onto it until we have issued all the necessary endLumi/beginLumi
00276       //       std::cout << getpid() << "alignLsToLast was set and ls number is " 
00277       //                << luminosityBlockNumber_ << " before signaling" << std::endl;
00278       signalWaitingThreadAndBlock();
00279       luminosityBlockNumber_++;
00280       //       std::cout << getpid() << "alignLsToLast signaled and incremented " 
00281       //                << luminosityBlockNumber_ << " eventcached " 
00282       //                << eventCached() << std::endl;
00283       setNewLumi();
00284       if (lumiSectionIndex_!=0)
00285         lumiSectionIndex_->value_ = luminosityBlockNumber_;
00286       resetLuminosityBlockAuxiliary();
00287       if(luminosityBlockNumber_ == thisEventLSid+1) 
00288       {
00289         alignLsToLast_ = false;
00290       }
00291       if (!luminosityBlockAuxiliary() || luminosityBlockAuxiliary()->luminosityBlock() != luminosityBlockNumber_) {
00292         setLuminosityBlockAuxiliary(new LuminosityBlockAuxiliary(
00293               runNumber_, luminosityBlockNumber_, timestamp(), Timestamp::invalidTimestamp()));
00294         luminosityBlockAuxiliary()->setProcessHistoryID(phid_);
00295 
00296         //      std::cout << "nextItemType: dealt with new lumi block principal, retval is " << retval << std::endl;
00297       }
00298       return IsLumi;
00299     }
00300     if (eventCached()) {
00301       //      std::cout << "read event already cached " << std::endl;
00302       return IsEvent;
00303     }
00304 
00305     if(reader_ == 0) {
00306       throw edm::Exception(errors::LogicError)
00307           << "DaqSource is used without a reader. Check your configuration !";
00308     }
00309     TimeValue_t time = 0LL;
00310     timeval stv;
00311     gettimeofday(&stv,0);
00312     time = stv.tv_sec;
00313     time = (time << 32) + stv.tv_usec;
00314     Timestamp tstamp(time);
00315 
00316     bunchCrossing_ = EventAuxiliary::invalidBunchXing;
00317     orbitNumber_   = EventAuxiliary::invalidBunchXing;
00318     evttype_ = EventAuxiliary::Undefined;
00319     
00320     // pass a null pointer to fillRawData()!
00321     fedCollection_ = nullptr ;
00322 
00323   
00324     // let reader_ fill the fedCollection 
00325     int retval = reader_->fillRawData(eventID_, tstamp, fedCollection_);
00326     if(retval==0) {
00327       // fillRawData() failed, clean up the fedCollection in case it was allocated!
00328       if (nullptr != fedCollection_) delete fedCollection_;
00329       noMoreEvents_ = true;
00330       pthread_mutex_lock(&mutex_);
00331       pthread_cond_signal(&cond_);
00332       pthread_mutex_unlock(&mutex_);
00333       return IsStop;
00334     }
00335     else if(retval<0)
00336       {
00337  
00338         unsigned int nextLsFromSignal = (-1)*retval+1;
00339 //      std::cout << getpid() << "::got end-of-lumi for " << (-1)*retval
00340 //                << " was " << luminosityBlockNumber_ << std::endl;
00341         if(luminosityBlockNumber_ == (nextLsFromSignal-1) )
00342           {
00343             if (lastLumiUsingEol_ != 0)
00344               lastLumiUsingEol_->value_ = nextLsFromSignal;
00345             if(lsToBeRecovered_ != 0 && lsToBeRecovered_->value_){
00346 //            std::cout << getpid() << "eol::recover ls::for " << (-1)*retval << std::endl;
00347               signalWaitingThreadAndBlock();
00348               luminosityBlockNumber_++;
00349               setNewLumi();
00350               if (lumiSectionIndex_ != 0)
00351                 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00352               resetLuminosityBlockAuxiliary();
00353               thisEventLSid = nextLsFromSignal - 1;
00354               if(luminosityBlockNumber_ != thisEventLSid+1) 
00355                 alignLsToLast_ = true;
00356               //              std::cout << getpid() << "eol::::alignLsToLast_ " << alignLsToLast_ << std::endl;
00357             }
00358             else{
00359               //              std::cout << getpid() << "eol::realign ls::for " << (-1)*retval << std::endl;
00360               luminosityBlockNumber_ = nextLsFromSignal;
00361               setNewLumi();
00362               if (lumiSectionIndex_ != 0)
00363                 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00364               resetLuminosityBlockAuxiliary();
00365             }
00366           }
00367         else {
00368           if(nextLsFromSignal >(luminosityBlockNumber_+100) ) {
00369             edm::LogError("DaqSource") << "Got EOL event with value " << retval 
00370                                        << " nextLS would be " << nextLsFromSignal 
00371                                        << " while we expected " << luminosityBlockNumber_+1 << " - disregarding... ";
00372           }
00373           if (nextLsFromSignal > luminosityBlockNumber_+2) //recover on delta > 2
00374           {
00375               if (lastLumiUsingEol_ != 0)
00376                 lastLumiUsingEol_->value_ = nextLsFromSignal;
00377               thisEventLSid=nextLsFromSignal-1;//set new LS
00378               signalWaitingThreadAndBlock();
00379               luminosityBlockNumber_++;
00380               setNewLumi();
00381               if (lumiSectionIndex_ != 0)
00382               lumiSectionIndex_->value_ = luminosityBlockNumber_;
00383               alignLsToLast_ = true;
00384 
00385               //set new lumi block
00386               resetLuminosityBlockAuxiliary();
00387               setLuminosityBlockAuxiliary(new LuminosityBlockAuxiliary(
00388                 runNumber_, luminosityBlockNumber_, timestamp(), Timestamp::invalidTimestamp()));
00389               luminosityBlockAuxiliary()->setProcessHistoryID(phid_);
00390           }
00391 
00392         }
00393         //      else
00394         //        std::cout << getpid() << "::skipping end-of-lumi for " << (-1)*retval << std::endl;
00395       }
00396     else
00397       {
00398         if (eventID_.event() == 0) {
00399           throw edm::Exception(errors::LogicError)
00400             << "The reader used with DaqSource has returned an invalid (zero) event number!\n"
00401             << "Event numbers must begin at 1, not 0.";
00402         }
00403         EventSourceSentry(*this);
00404         setTimestamp(tstamp);
00405     
00406         unsigned char *gtpFedAddr = fedCollection_->FEDData(daqsource::gtpEvmId_).size()!=0 ? fedCollection_->FEDData(daqsource::gtpEvmId_).data() : 0;
00407         uint32_t gtpsize = 0;
00408         if(gtpFedAddr !=0) gtpsize = fedCollection_->FEDData(daqsource::gtpEvmId_).size();
00409         unsigned char *gtpeFedAddr = fedCollection_->FEDData(daqsource::gtpeId_).size()!=0 ? fedCollection_->FEDData(daqsource::gtpeId_).data() : 0; 
00410 
00411         unsigned int nextFakeLs = 0;
00412         eventCounter_++;
00413         if (fakeLSid_)
00414             evttype_ =  edm::EventAuxiliary::PhysicsTrigger;
00415         bool fakeLSFromEventCount = fakeLSid_ && (lumiSegmentSizeInEvents_ != 0);
00416         bool fakeLSFromTimer = fakeLSid_ && (lumiSegmentSizeInSeconds_ != 0);
00417         if(fakeLSFromEventCount && luminosityBlockNumber_ != 
00418            (nextFakeLs = useEventCounter_ ? ((eventCounter_-1)/lumiSegmentSizeInEvents_ + 1) :
00419             ((eventID_.event() - 1)/lumiSegmentSizeInEvents_ + 1))) {
00420             if (prescaleSetIndex_ != 0 && lastLumiPrescaleIndex_!= 0) {
00421               lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00422               prescaleSetIndex_->value_ = 0; // since we do not know better but we want to be able to run
00423             }
00424           if(luminosityBlockNumber_ == nextFakeLs-1)
00425             signalWaitingThreadAndBlock();
00426           luminosityBlockNumber_ = nextFakeLs;
00427           thisEventLSid = nextFakeLs-1;
00428           setNewLumi();
00429           if (lumiSectionIndex_ != 0)
00430             lumiSectionIndex_->value_ = luminosityBlockNumber_;
00431           resetLuminosityBlockAuxiliary();
00432           if(keepUsingPsidFromTrigger_ && 
00433              gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00434             if (prescaleSetIndex_ != 0)
00435               prescaleSetIndex_->value_  = (evf::evtn::getfdlpsc(gtpFedAddr) & 0xffff);
00436           }       
00437         }
00438         else if(fakeLSFromTimer){
00439           struct timeval tv;
00440           gettimeofday(&tv,0);
00441           unsigned int elapsed_time = tv.tv_sec - startOfLastLumi.tv_sec;
00442           //      std::cout << "daqsource elapsed time " << elapsed_time << std::endl;
00443           if(luminosityBlockNumber_ != 
00444              (nextFakeLs = elapsed_time/lumiSegmentSizeInSeconds_ + 1)) {
00445             if(prescaleSetIndex_ != 0){
00446               lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00447               prescaleSetIndex_->value_ = 0; // since we do not know better but we want to be able to run
00448             }
00449             if(luminosityBlockNumber_ == (nextFakeLs-1))
00450               signalWaitingThreadAndBlock();
00451             luminosityBlockNumber_ = nextFakeLs;
00452             thisEventLSid = nextFakeLs-1;
00453             setNewLumi();
00454             if(lumiSectionIndex_!=0)
00455               lumiSectionIndex_->value_ = luminosityBlockNumber_;
00456             resetLuminosityBlockAuxiliary();
00457             if(keepUsingPsidFromTrigger_ && 
00458                gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00459               if(prescaleSetIndex_ != 0)
00460                 prescaleSetIndex_->value_  = (evf::evtn::getfdlpsc(gtpFedAddr) & 0xffff);
00461             }     
00462           }
00463         } 
00464         else if(!fakeLSid_){ 
00465 
00466           if(gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00467             if (lastLumiPrescaleIndex_ != 0 && prescaleSetIndex_ != 0)
00468               lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00469             thisEventLSid = evf::evtn::getlbn(gtpFedAddr);
00470             if (prescaleSetIndex_ != 0)
00471               prescaleSetIndex_->value_  = (evf::evtn::getfdlpsc(gtpFedAddr) & 0xffff);
00472             evttype_ =  edm::EventAuxiliary::ExperimentType(evf::evtn::getevtyp(gtpFedAddr));
00473             if(luminosityBlockNumber_ > (thisEventLSid + 1))
00474             {
00475               //late event,throw fwk exception
00476               std::ostringstream excptmsg;
00477               excptmsg << "DaqSource::event with late LS (" << thisEventLSid + 1 << ")received.";
00478               throw edm::Exception(errors::LogicError,excptmsg.str());
00479             }
00480             if(luminosityBlockNumber_ != (thisEventLSid + 1)){
00481               // we got here in a running process and some Ls might have been skipped so set the flag, 
00482               // increase by one, check and if appropriate set the flag then continue
00483               if(lsToBeRecovered_!=0 && lsToBeRecovered_->value_){
00484                 //              std::cout << getpid() << "eve::recover ls::for " << thisEventLSid << std::endl;
00485                 signalWaitingThreadAndBlock();
00486                 luminosityBlockNumber_++;
00487                 setNewLumi();
00488                 if (lumiSectionIndex_ !=0 )
00489                   lumiSectionIndex_->value_ = luminosityBlockNumber_;
00490                 resetLuminosityBlockAuxiliary();
00491                 if(luminosityBlockNumber_ != thisEventLSid+1) alignLsToLast_ = true;
00492                 //              std::cout << getpid() << "eve::::alignLsToLast_ " << alignLsToLast_ << std::endl;
00493               }
00494               else{ // we got here because the process was restarted. just realign the ls id and proceed with this event
00495                 //              std::cout << getpid() << "eve::realign ls::for " << thisEventLSid << std::endl;
00496                 luminosityBlockNumber_ = thisEventLSid + 1;
00497                 setNewLumi();
00498                 if (lumiSectionIndex_ !=0)
00499                   lumiSectionIndex_->value_ = luminosityBlockNumber_;
00500                 resetLuminosityBlockAuxiliary();
00501                 if (lsToBeRecovered_ !=0)
00502                   lsToBeRecovered_->value_ = true;
00503               }
00504             }
00505           }
00506           else if(gtpeFedAddr!=0 && evf::evtn::gtpe_board_sense(gtpeFedAddr)){
00507             if (lastLumiPrescaleIndex_ != 0 && prescaleSetIndex_ != 0)
00508               lastLumiPrescaleIndex_->value_ = prescaleSetIndex_->value_;
00509             thisEventLSid = evf::evtn::gtpe_getlbn(gtpeFedAddr);
00510             if (prescaleSetIndex_ != 0)
00511               prescaleSetIndex_->value_ = 0; //waiting to get a PS index from gtpe
00512             evttype_ =  edm::EventAuxiliary::PhysicsTrigger; 
00513             if(luminosityBlockNumber_ != (thisEventLSid + 1)){
00514               if(luminosityBlockNumber_ == thisEventLSid)
00515                 signalWaitingThreadAndBlock();
00516               luminosityBlockNumber_ = thisEventLSid + 1;
00517               setNewLumi();
00518               if (lumiSectionIndex_ !=0 )
00519                 lumiSectionIndex_->value_ = luminosityBlockNumber_;
00520               resetLuminosityBlockAuxiliary();
00521             }
00522           }
00523         }
00524         if(gtpFedAddr!=0 && evf::evtn::evm_board_sense(gtpFedAddr,gtpsize)){
00525           bunchCrossing_ =  int(evf::evtn::getfdlbx(gtpFedAddr));
00526           orbitNumber_ =  int(evf::evtn::getorbit(gtpFedAddr));
00527           TimeValue_t time = evf::evtn::getgpshigh(gtpFedAddr);
00528           time = (time << 32) + evf::evtn::getgpslow(gtpFedAddr);
00529           Timestamp tstamp(time);
00530           setTimestamp(tstamp);      
00531         }
00532         else if(gtpeFedAddr!=0 && evf::evtn::gtpe_board_sense(gtpeFedAddr)){
00533           bunchCrossing_ =  int(evf::evtn::gtpe_getbx(gtpeFedAddr));
00534           orbitNumber_ =  int(evf::evtn::gtpe_getorbit(gtpeFedAddr));
00535         }
00536       }    
00537           
00538     //    std::cout << "lumiblockaux = " << luminosityBlockAuxiliary() << std::endl;
00539     // If there is no luminosity block principal, make one.
00540     if (!luminosityBlockAuxiliary() || luminosityBlockAuxiliary()->luminosityBlock() != luminosityBlockNumber_) {
00541       setNewLumi();
00542       setLuminosityBlockAuxiliary(new LuminosityBlockAuxiliary(
00543         runNumber_, luminosityBlockNumber_, timestamp(), Timestamp::invalidTimestamp()));
00544       luminosityBlockAuxiliary()->setProcessHistoryID(phid_);
00545 
00546       //      std::cout << "nextItemType: dealt with new lumi block principal, retval is " << retval << std::endl;
00547     }
00548     //    std::cout << "here retval = " << retval << std::endl;
00549     if(retval<0){
00550       //      std::cout << getpid() << " returning from getnextitem because retval < 0 - IsLumi "
00551       //                << IsLumi << std::endl;
00552       if(newLumi()) return IsLumi; else return getNextItemType();
00553     }
00554     if (newLumi()) {
00555       return IsLumi;
00556     }
00557     setEventCached();
00558     return IsEvent;
00559   }
00560 
00561   void
00562   DaqSource::setRun(RunNumber_t r) {
00563     assert(!eventCached());
00564     reset();
00565     setNewRun();
00566     runNumber_ = r;
00567     if (reader_) reader_->setRunNumber(runNumber_);
00568     noMoreEvents_ = false;
00569     resetLuminosityBlockAuxiliary();
00570   }
00571 
00572   boost::shared_ptr<RunAuxiliary>
00573   DaqSource::readRunAuxiliary_() {
00574     assert(newRun());
00575     assert(!noMoreEvents_);
00576     resetNewRun();
00577     boost::shared_ptr<RunAuxiliary> ra(new RunAuxiliary(runNumber_, timestamp(), Timestamp::invalidTimestamp()));
00578     ra->setProcessHistoryID(phid_);
00579     return ra;
00580   }
00581 
00582   boost::shared_ptr<LuminosityBlockAuxiliary>
00583   DaqSource::readLuminosityBlockAuxiliary_() {
00584     assert(!newRun());
00585     assert(newLumi());
00586     assert(!noMoreEvents_);
00587     assert(luminosityBlockAuxiliary());
00588     resetNewLumi();
00589     return luminosityBlockAuxiliary();
00590   }
00591 
00592   EventPrincipal*
00593   DaqSource::readEvent_(EventPrincipal& eventPrincipal) {
00594     //    std::cout << "assert not newRun " << std::endl;
00595     assert(!newRun());
00596     //    std::cout << "assert not newLumi " << std::endl;
00597     assert(!newLumi());
00598     //    std::cout << "assert not noMoreEvents " << std::endl;
00599     assert(!noMoreEvents_);
00600     //    std::cout << "assert eventCached " << std::endl;
00601     assert(eventCached());
00602     //    std::cout << "asserts done " << std::endl;
00603 
00604     resetEventCached();
00605 
00606     // make a brand new event principal
00607     eventID_ = EventID(runNumber_,thisEventLSid+1, eventID_.event());
00608     EventAuxiliary eventAux(eventID_, processGUID(),
00609                             timestamp(),
00610                             true,
00611                             evttype_,
00612                             bunchCrossing_,
00613                             EventAuxiliary::invalidStoreNumber,
00614                             orbitNumber_);
00615     eventAux.setProcessHistoryID(phid_);
00616     eventPrincipal.fillEventPrincipal(eventAux);
00617     
00618     // have fedCollection managed by a std::auto_ptr<>
00619     std::auto_ptr<FEDRawDataCollection> bare_product(fedCollection_);
00620 
00621     WrapperOwningHolder edp(new Wrapper<FEDRawDataCollection>(bare_product), Wrapper<FEDRawDataCollection>::getInterface());
00622     eventPrincipal.put(daqProvenanceHelper_.constBranchDescription_, edp, daqProvenanceHelper_.dummyProvenance_);
00623 
00624 /*
00625     Event e(eventPrincipal, md_);
00626     // put the fed collection into the transient event store
00627     e.put(bare_product);
00628     // The commit is needed to complete the "put" transaction.
00629     e.commit_();
00630 */
00631     return &eventPrincipal;
00632   }
00633 
00634   void
00635   DaqSource::setLumi(LuminosityBlockNumber_t) {
00636       throw edm::Exception(errors::LogicError,"DaqSource::setLumi(LuminosityBlockNumber_t lumiNumber)")
00637         << "The luminosity block number cannot be set externally for DaqSource.\n"
00638         << "Contact a Framework developer.\n";
00639   }
00640 
00641   EventPrincipal*
00642   DaqSource::readIt(EventID const&) {
00643       throw edm::Exception(errors::LogicError,"DaqSource::readIt(EventID const& eventID)")
00644         << "Random access read cannot be used for DaqSource.\n"
00645         << "Contact a Framework developer.\n";
00646   }
00647 
00648   void
00649   DaqSource::skip(int) {
00650       throw edm::Exception(errors::LogicError,"DaqSource::skip(int offset)")
00651         << "Random access skip cannot be used for DaqSource\n"
00652         << "Contact a Framework developer.\n";
00653   }
00654 
00655   void DaqSource::publish(xdata::InfoSpace *is)
00656   {
00657     is_ = is;
00658     lumiSectionIndex_      = (xdata::UnsignedInteger32*)is_->find("lumiSectionIndex");
00659     prescaleSetIndex_      = (xdata::UnsignedInteger32*)is_->find("prescaleSetIndex");
00660     lastLumiPrescaleIndex_ = (xdata::UnsignedInteger32*)is_->find("lastLumiPrescaleIndex");
00661     lastLumiUsingEol_ = (xdata::UnsignedInteger32*)is_->find("lastLumiUsingEol");
00662     lsTimedOut_            = (xdata::Boolean*)is_->find("lsTimedOut");
00663     lsToBeRecovered_       = (xdata::Boolean*)is_->find("lsToBeRecovered");
00664   }
00665   void DaqSource::publishToXmas(xdata::InfoSpace *is)
00666   {
00667     mis_ = is;
00668   }
00669 
00670   void DaqSource::openBackDoor(unsigned int timeout_sec, bool *running)
00671   {
00672     count++;
00673     if(count==2) throw;
00674     pthread_mutex_lock(&mutex_);
00675     if (running) *running=true;
00676     pthread_mutex_unlock(&signal_lock_);
00677     timespec ts;
00678 #if _POSIX_TIMERS > 0
00679     clock_gettime(CLOCK_REALTIME, &ts);
00680 #else
00681     struct timeval tv; 
00682     gettimeofday(&tv, NULL);
00683     ts.tv_sec = tv.tv_sec + 0;
00684     ts.tv_nsec = 0;
00685 #endif
00686     ts.tv_sec += timeout_sec;
00687 
00688     int rc = pthread_cond_timedwait(&cond_, &mutex_, &ts);
00689     if(rc == ETIMEDOUT && lsTimedOut_ != 0) lsTimedOut_->value_ = true; 
00690   }
00691   
00692   void DaqSource::closeBackDoor()
00693   {
00694     count--;
00695     pthread_cond_signal(&cond_);
00696     pthread_mutex_unlock(&mutex_);
00697     pthread_mutex_lock(&signal_lock_);
00698     if (lsTimedOut_ != 0)
00699       lsTimedOut_->value_ = false; 
00700   }
00701 
00702   void DaqSource::signalWaitingThreadAndBlock()
00703   {
00704     //check if we are running offline, in which case return immediately
00705     if(is_ == 0) return;
00706     pthread_mutex_lock(&signal_lock_);
00707     pthread_mutex_lock(&mutex_);
00708     pthread_mutex_unlock(&signal_lock_);
00709     //    std::cout << getpid() << " DS::signal from evloop " << std::endl;
00710     pthread_cond_signal(&cond_);
00711     //    std::cout << getpid() << " DS::go to wait for scalers wl " << std::endl;
00712     pthread_cond_wait(&cond_, &mutex_);
00713     pthread_mutex_unlock(&mutex_);
00714     ::usleep(1000);//allow other thread to lock
00715   }  
00716 
00717   void DaqSource::defaultWebPage(xgi::Input *in, xgi::Output *out)
00718   {
00719       std::string path;
00720       std::string urn;
00721       std::string mname;
00722       std::string query;
00723       std::string original_referrer_;
00724       try 
00725         {
00726           cgicc::Cgicc cgi(in);
00727           if ( xgi::Utils::hasFormElement(cgi,"gotostopping") )
00728             {
00729               goToStopping=true;
00730             }
00731           if ( xgi::Utils::hasFormElement(cgi,"module") )
00732             mname = xgi::Utils::getFormElement(cgi, "module")->getValue();
00733           cgicc::CgiEnvironment cgie(in);
00734           if(original_referrer_ == "")
00735             original_referrer_ = cgie.getReferrer();
00736           path = cgie.getPathInfo();
00737           query = cgie.getQueryString();
00738         }
00739       catch (const std::exception & e) 
00740         {
00741           // don't care if it did not work
00742         }
00743 
00744       using std::endl;
00745       *out << "<html>"                                                   << endl;
00746       *out << "<head>"                                                   << endl;
00747 
00748 
00749       *out << "<STYLE type=\"text/css\"> #T1 {border-width: 2px; border: solid blue; text-align: center} </STYLE> "                                      << endl; 
00750       *out << "<link type=\"text/css\" rel=\"stylesheet\"";
00751       *out << " href=\"/" <<  urn
00752            << "/styles.css\"/>"                   << endl;
00753 
00754       *out << "<title>" << moduleName_
00755            << " MAIN</title>"                                            << endl;
00756 
00757       *out << "</head>"                                                  << endl;
00758       *out << "<body onload=\"loadXMLDoc()\">"                           << endl;
00759       *out << "<table border=\"0\" width=\"100%\">"                      << endl;
00760       *out << "<tr>"                                                     << endl;
00761       *out << "  <td align=\"left\">"                                    << endl;
00762       *out << "    <img"                                                 << endl;
00763       *out << "     align=\"middle\""                                    << endl;
00764       *out << "     src=\"/evf/images/bugicon.jpg\""                     << endl;
00765       *out << "     alt=\"main\""                                        << endl;
00766       *out << "     width=\"90\""                                        << endl;
00767       *out << "     height=\"64\""                                       << endl;
00768       *out << "     border=\"\"/>"                                       << endl;
00769       *out << "    <b>"                                                  << endl;
00770       *out <<             moduleName_                                    << endl;
00771       *out << "    </b>"                                                 << endl;
00772       *out << "  </td>"                                                  << endl;
00773       *out << "  <td width=\"32\">"                                      << endl;
00774       *out << "    <a href=\"/urn:xdaq-application:lid=3\">"             << endl;
00775       *out << "      <img"                                               << endl;
00776       *out << "       align=\"middle\""                                  << endl;
00777       *out << "       src=\"/hyperdaq/images/HyperDAQ.jpg\""             << endl;
00778       *out << "       alt=\"HyperDAQ\""                                  << endl;
00779       *out << "       width=\"32\""                                      << endl;
00780       *out << "       height=\"32\""                                     << endl;
00781       *out << "       border=\"\"/>"                                     << endl;
00782       *out << "    </a>"                                                 << endl;
00783       *out << "  </td>"                                                  << endl;
00784       *out << "  <td width=\"32\">"                                      << endl;
00785       *out << "  </td>"                                                  << endl;
00786       *out << "  <td width=\"32\">"                                      << endl;
00787       *out << "    <a href=\"" << original_referrer_  << "\">"           << endl;
00788       *out << "      <img"                                               << endl;
00789       *out << "       align=\"middle\""                                  << endl;
00790       *out << "       src=\"/evf/images/spoticon.jpg\""                  << endl;
00791       *out << "       alt=\"main\""                                      << endl;
00792       *out << "       width=\"32\""                                      << endl;
00793       *out << "       height=\"32\""                                     << endl;
00794       *out << "       border=\"\"/>"                                     << endl;
00795       *out << "    </a>"                                                 << endl;
00796       *out << "  </td>"                                                  << endl;
00797       *out << "</tr>"                                                    << endl;
00798       *out << "</table>"                                                 << endl;
00799 
00800       *out << "<hr/>"                                                    << endl;
00801   
00802       *out << cgicc::form().set("method","GET").set("action", path ) 
00803            << std::endl;
00804       boost::char_separator<char> sep("&");
00805       boost::tokenizer<boost::char_separator<char> > tokens(query, sep);
00806       for (boost::tokenizer<boost::char_separator<char> >::iterator tok_iter = tokens.begin();
00807            tok_iter != tokens.end(); ++tok_iter){
00808         size_t pos = (*tok_iter).find_first_of("=");
00809         if(pos != std::string::npos){
00810           std::string first  = (*tok_iter).substr(0    ,                        pos);
00811           std::string second = (*tok_iter).substr(pos+1, (*tok_iter).length()-pos-1);
00812           *out << cgicc::input().set("type","hidden").set("name",first).set("value", second) 
00813                << std::endl;
00814         }
00815       }
00816 
00817       *out << cgicc::input().set("type","hidden").set("name","gotostopping").set("value","true")
00818            << std::endl;
00819       *out << cgicc::input().set("type","submit").set("value","Go To Stopping")              << std::endl;
00820       *out << cgicc::form()                                                << std::endl;  
00821 
00822       *out << "</body>"                                                  << endl;
00823       *out << "</html>"                                                  << endl;
00824   }
00825 }