//-------------------------------------------------------------------------- // File and Version Information: // $Id: APPLevel3GenericOutputModule.cc,v 1.90 2005/01/12 00:04:11 boisvert Exp $ // // Description: // Class APPLevel3GenericOutputModule. This class derives from StreamsOutput // and adds functionality generic to Level3 and Level3 testing, independent // of event I/O method. // // This output module may be run in a stand-alone // mode to produce file output with Level3 result banks. // // Environment: // CDF Run II Level-3 Trigger // // Author List: // Kevin McFarland/Mike Carew Original Authors // // Copyright Information: // //------------------------------------------------------------------------ #include "Experiment/Experiment.hh" //----------------------- // This Class's Header -- //----------------------- #include "Level3Mods/APPLevel3GenericOutputModule.hh" //------------- // C Headers -- //------------- #include #include using namespace std; //------------------------------- // Collaborating Class Headers -- //------------------------------- class AbsEvent; #include "Framework/APPJob.hh" #include "Framework/AppStream.hh" #include "Framework/APPFramework.hh" #include "Framework/APPPath.hh" #include "Framework/APPList.hh" #include "Framework/APPListIterator.hh" #include "HeaderObjects/LRIH_StorableBank.hh" #include "StorableBanks/LRID_StorableBank.hh" #include "StorableBanks/LRID_StorableBank_utilities.hh" #include "StorableBanks/IterableBankI2s1.hh" #include "TriggerObjects/TFRD_StorableBank.hh" #include "StorableBanks/EVCL_StorableBank.hh" #include "TriggerObjects/TL2D_StorableBank.hh" #include "Edm/EventRecord.hh" #include "Edm/ConstHandle.hh" #include "Edm/GenericConstHandle.hh" #include "AbsEnv/AbsEnv.hh" #include "ErrorLogger/ELadministrator.h" #include "ErrorLogger/ELstring.h" #include "Level3Mods/Level3Accountant.hh" // here it gets used for encoding the native byte order to send to CSL #include "Trybos/private/TRY_Ybos_Physrec_Format.hh" // for definitions of default tags #include "Level3Control/Abs_Level3Interface.hh" // error summary #include "ErrorLogger_i/CDF_ELContext.hh" #include "ErrorLogger/ELadministrator.h" #include "ErrorLogger/ELdestControl.h" #include "ErrorLogger/ELerrorList.h" #include "HeaderObjects/ErrorSummary.hh" #include "FrameMods/ErrorSummaryUtilities.hh" #include //---------------------------------- // Online System headers -- //---------------------------------- extern "C" { #include "ConsumerInterface/l3_cs_pointer_space.h" } // for gettimeofday calls extern "C" { #if defined( IRIX6_2 ) #define __vfork vfork #endif #include #include } static const char rcsid[] = "$Id: APPLevel3GenericOutputModule.cc,v 1.90 2005/01/12 00:04:11 boisvert Exp $"; // ---------------------------------------- // -- Public Function Member Definitions -- // ---------------------------------------- //---------------- // Constructors -- //---------------- APPLevel3GenericOutputModule ::APPLevel3GenericOutputModule(const char* const theName, const char* const theDescription, const int4 exeTag ) : AppStreamsOutputModule( theName, theDescription ), _storedErrorCount(0), _exeTag(exeTag), _theLevel3Accountant(NULL), _nCrossingTrigger(-1), _noLevel3Accountant("noLevel3Accountant",this,false), _noLevel3CpuMonitor("noLevel3CpuMonitor",this,false), _enableOldTL3("enableOldTL3",this,false), _enableNewTL3("enableNewTL3",this,true), _disableNewLRIH("disableNewLRIH",this,false), _passFailedEvents ( "passFailedEvents",this,false ), _passFailedSummary ( "passFailedSummary",this,false ), _zeroStreamMask ( "zeroStreamMask",this,false ), _sentBeginRun(false), _sentEndRun(false), _initdone(false), _dumpResultMasks ( "dumpResultMasks",this,false), _debug("debug",this,false), _tclTag("tclTag",this, TL3D_Identifier::undefinedIdentifier, Abs_Level3Interface::defaultTag), _calibTag("calibTag",this, TL3D_Identifier::undefinedIdentifier, Abs_Level3Interface::defaultTag), _createRunSection("createRunSection",this,false), _crossingsPerRunSection ("crossingsPerRunSection",this,30), _initialRunSection ("initialRunSection",this,1), _fakeCrossingTrigger("fakeCrossingTrigger",this,false), _fakeRunNumber("fakeRunNumber",this,-1), _fakeEventNumber("fakeEventNumber",this,false), _nodeEventOffset("nodeEventOffset",this,0), _maxNodeEventOffset("maxNodeEventOffset",this,16), _timeGranularity("timeGranularity",this,100), _crossingTriggerPeriod("crossingTriggerPeriod",this,1), _useErrorEventStream("useErrorEventStream", this, true), _preferTFRDLevel1Bits("preferTFRDLevel1Bits",this,true), _streamByName("streamByName", this, true), _errorStreamName("errorStreamName",this,""), _L1TriggerNames("L1TriggerNames",this,0,1000," "), _L1TriggerBits("L1TriggerBits",this,0,1000,-1), _L1TriggerIds("L1TriggerIds",this,0,1000,-1), _L2TriggerNames("L2TriggerNames",this,0,1000," "), _L2TriggerBits("L2TriggerBits",this,0,1000,-1), _L2TriggerIds("L2TriggerIds",this,0,1000,-1), _L3PathNames("L3PathNames",this,0,1000," "), _L3PathBits("L3PathBits",this,0,1000,-1), _L3PathIds("L3PathIds",this,0,1000,-1), _L3PathDatasetNames("L3PathDatasetNames",this,0,1000," "), _L3PathDatasetIds("L3PathDatasetIds",this,0,1000,-1), _useEvclBits("useEvclBits",this,false) { _noLevel3Accountant.addDescription(" \tDon't call Level-3 Accountant in output moule (default false)"); _noLevel3CpuMonitor.addDescription(" \tDon't let the Level-3 Accountant Monitor CPU time (default false)"); _enableOldTL3.addDescription(" \tEnable testing of new TL3 objects (default false)"); _enableNewTL3.addDescription(" \tEnable testing of new TL3 objects (default true)"); _disableNewLRIH.addDescription(" \tDisable adding the new LRIH bank to the event (default false)"); _passFailedEvents.addDescription(" \tOutput all events, even if they do not pass any trigger (default false)"); _passFailedSummary.addDescription(" \tOutput summary of events that failed (default false)"); _zeroStreamMask.addDescription(" \tIf true, all stream bits will be set to zero and events won't be logged to disk by CSL (default false)"); _dumpResultMasks.addDescription(" \tVerbose dumping of L1/L2/L3/stream masks used by Consumer-Server (default false)"); _tclTag.addDescription(" \tInt4 tag for the tcl file"); _calibTag.addDescription(" \tInt4 identifier for the calibration tag"); _useErrorEventStream.addDescription( " \tIf set true, error events (not BOR or EOR) will be sent to the CSL using a special error message type (default is true)"); _streamByName.addDescription( " \tUse the name of the stream instead of the framework stream index to set the stream Mask for the CSL (default is true)"); _errorStreamName.addDescription( " \tName of a stream to send error events to (default is no stream)"); commands()->append(&_dumpResultMasks); commands()->append(&_noLevel3Accountant); commands()->append(&_noLevel3CpuMonitor); commands()->append(&_enableOldTL3); commands()->append(&_enableNewTL3); commands()->append(&_disableNewLRIH); commands()->append(&_passFailedEvents); commands()->append(&_passFailedSummary); commands()->append(&_zeroStreamMask); commands()->append(&_tclTag); commands()->append(&_calibTag); commands()->append(&_useErrorEventStream); commands()->append(&_streamByName); commands()->append(&_errorStreamName); _createRunSection.addDescription(" \tSet the run section number based on the crossing trigger number if true; otherwise run section comes from reformatter (default false)"); _crossingsPerRunSection.addDescription(" \tThe number of crossing triggers per run section; irrelevant if createRunSection is false (default 30)"); _initialRunSection.addDescription(" \tFirst run section for start of event; irrelevant if createRunSection is false (default 0)"); _fakeCrossingTrigger.addDescription(" \tSets the L3_CS_POINTER_SPACE crossing trigger number to a faked value instead of getting it from the TFRD bank (default false)"); _fakeRunNumber.addDescription(" \tSets the L3_CS_POINTER_SPACE run number to be a fake value (e.g., not from LRIH) if greater-equal zero (default -1)"); _fakeEventNumber.addDescription(" \tSets the L3_CS_POINTER_SPACE event number to a locally generated value instead of reading from LRIH (default false)"); _nodeEventOffset.addDescription(" \tOffset to event number from the executable ID (default 0)"); _maxNodeEventOffset.addDescription(" \tMaximum offset to event number from the executable ID (default 16)"); _timeGranularity.addDescription(" \tTime steps per second used in generating a time-based fake event number (default 100)"); _crossingTriggerPeriod.addDescription(" \tPeriod of fake crossing triggers in seconds (default 1)"); commands()->append(&_createRunSection); commands()->append(&_crossingsPerRunSection); commands()->append(&_initialRunSection); commands()->append(&_crossingTriggerPeriod); commands()->append(&_fakeCrossingTrigger); commands()->append(&_fakeRunNumber); commands()->append(&_fakeEventNumber); commands()->append(&_nodeEventOffset); commands()->append(&_maxNodeEventOffset); commands()->append(&_timeGranularity); _debug.addDescription(" \tPrint debugging output? (default false)"); commands()->append(&_debug); _useEvclBits.addDescription( " \tUse trigger summary bits from EVCL instead of TL2D, implemented for backwords compatibility (default false)"); _preferTFRDLevel1Bits.addDescription( " \tUse TFRD version of Level-1 bits instead of TL2D when both are present (default true)"); commands()->append(&_preferTFRDLevel1Bits); _L1TriggerNames.addDescription("\tOrdered list of L1 Trigger Names"); _L1TriggerBits.addDescription("\tOrdered list of L1 Trigger Bits"); _L1TriggerIds.addDescription("\tOrdered list of L1 Trigger Unique Ids"); _L2TriggerNames.addDescription("\tOrdered list of L2 Trigger Names"); _L2TriggerBits.addDescription("\tOrdered list of L2 Trigger Bits"); _L2TriggerIds.addDescription("\tOrdered list of L2 Trigger Unique Ids"); _L3PathNames.addDescription("\tOrdered list of L3 Path Names"); _L3PathBits.addDescription("\tOrdered list of L3 Path Bits"); _L3PathIds.addDescription("\tOrdered list of L3 Path Unique Ids"); _L3PathDatasetNames.addDescription("\tOrdered list of Names of Datasets that own L3 Paths"); _L3PathDatasetIds.addDescription("\tOrdered list of Unique Ids of Datasets that own L3 Paths"); commands()->append(&_L1TriggerNames); commands()->append(&_L1TriggerBits); commands()->append(&_L1TriggerIds); commands()->append(&_L2TriggerNames); commands()->append(&_L2TriggerBits); commands()->append(&_L2TriggerIds); commands()->append(&_L3PathNames); commands()->append(&_L3PathBits); commands()->append(&_L3PathIds); commands()->append(&_L3PathDatasetNames); commands()->append(&_L3PathDatasetIds); // // _realStartTime = whatTime(1,0); _lastEvent = 0; // establish error local logger list and control of the list // zero the list & set the threshold _localElBuffer = new ELerrorList(_localErrorList); _localElControl = new ELdestControl( ELadministrator::instance()->attach(*_localElBuffer) ); _localElControl->setThreshold(ELsevere); //FAILS with development, 4/12/01 _localElControl->wipe(); _localElControl->suppressContext(); _localElControl->suppressTime(); // Make sure raw data is kept by default _combinedProcKeepList.push_back( "RAW" ); // // create errorSummary buffer (a la FileOutputModule) // fwk::createErrorSummaryBuffer(&_errorBuffer); } //-------------- // Destructor -- //-------------- APPLevel3GenericOutputModule::~APPLevel3GenericOutputModule( ) { if ( _localElControl ) delete _localElControl; if ( _localElBuffer ) delete _localElBuffer; } //-------------- // Operations -- //-------------- AppResult APPLevel3GenericOutputModule::beginJob( AbsEvent* anEvent ) { AppResult status = beginRun(anEvent); return status; } AppResult APPLevel3GenericOutputModule::beginRun( AbsEvent* anEvent ) { if(!_initdone) // protect against multiple calls { childBeginRun( anEvent ); // form a new Level3Accountant for bookkeeping if ( ! _noLevel3Accountant.value() ) _theLevel3Accountant = new Level3Accountant(_enableOldTL3.value(), _enableNewTL3.value(), !_noLevel3CpuMonitor.value(), _debug.value()); _initdone=true; // don't repeat this // process errorStreamName _reducedErrorStream = _errorStreamName.value(); // convert to upper case int i = _reducedErrorStream.size (); while (--i >= 0) _reducedErrorStream[i] = toupper (_reducedErrorStream[i]); // see if "STREAM" exists in the name and if so remove it string streamString("STREAM"); string::size_type streamLocation = _reducedErrorStream.find(streamString); if (streamLocation != string::npos) { _reducedErrorStream.erase(streamLocation,streamString.size()); } } return AppResult::OK; } AppResult APPLevel3GenericOutputModule::childBeginRun( AbsEvent* anEvent ) { return AppResult::OK; } AppResult APPLevel3GenericOutputModule::endRun( AbsEvent* anEvent ) { if ( _theLevel3Accountant != NULL ) delete _theLevel3Accountant; return AppResult::OK; } AppResult APPLevel3GenericOutputModule::childOutputEvent( AbsEvent* anEvent , const AppStopType& theDispatchStopType ) { // It's been agreed that any object created by level3 be marked as RAW data // Dave Waters, 22.3.2001. The objects appended in this method should be // marked with RAW, but subsequent objects should not necessarily. Hence, // save the current process name, to be re-set at the end of this method : std::string existing_process_name = anEvent->process_name(); // Set the process name for this method : anEvent->set_process_name( "RAW" ); // // for begin run, create the mapping of names to triggers // if ( ! _noLevel3Accountant.value()) { // Add APPLevel3GenericOutput (this) to pass trigger information // yschung 6/25/01 // if ( theDispatchStopType == AppStopType::begin_run ) _theLevel3Accountant->createLedger(framework(), streams(), anEvent, this); // // for physics events, update processing counts, yschung 5/8/01 // if ( theDispatchStopType == AppStopType::physics_event ) _theLevel3Accountant->countBeans( framework(), streams(), anEvent, this); } if ( theDispatchStopType == AppStopType::begin_run ) { formLevel3RunBeginResults( anEvent ); } if ( theDispatchStopType == AppStopType::physics_event ) { formLevel3RunEventResults( anEvent ); } // error summary object written into event // This happens before the loop over streams so add the error object // handling here. The error logger will fill this list if an error occured // on this event. fwk::writeErrorSummary(&_errorBuffer, anEvent); // Reset the process name to that at the entry to this method : anEvent->set_process_name(existing_process_name); if (_debug.value()){ std::cout << "at end of Level3GenericOutputModule::childOutputEvent\n"; //------------------------------------------------------------- // Print listing header //------------------------------------------------------------- std::cout << "ByteIn Class Name (ObjectId: Bank Info ) Proc Name, Description\n" ; std::cout << "--------------------------------------------------------------------------------\n" ; //------------------------------------------------------------- // List objects in this event //------------------------------------------------------------- for (EventRecord::ConstIterator iter = anEvent->begin(); iter.is_valid(); ++iter) { ConstHandle handle(iter); std::string class_name = handle->class_name() ; Id object_id = handle->object_id() ; size_t nbytes_input = handle->nbytes_last_streamed_in() ; std::string process_name = handle->process_name() ; std::string description = handle->description() ; std::cout << std::setw( 6) << nbytes_input << " " << std::setw(24) << class_name << "(" << std::setw( 8) << object_id << std::endl; } } // debug return AppResult::OK; } void APPLevel3GenericOutputModule::formLevel3RunEventResults( AbsEvent* anEvent ) { // // construct stream/trigger information from Level-3 // // EVCL bank contains L1 and L2 trigger summaries... note ugly hardcoding // for (int i = 0; i < L1_BITMASK_WORDS; i++ ) _cslMask.l1_bitmask[i] = 0; for (int i = 0; i < L2_BITMASK_WORDS; i++ ) _cslMask.l2_bitmask[i] = 0; if ( _useEvclBits.value() ) { EventRecord::ConstIterator p_EVCL_bank( anEvent, "EVCL_StorableBank" ); if ( p_EVCL_bank.is_valid() ) { ConstHandle evcl( p_EVCL_bank ); long int evcl_l1 = evcl->trigger_summary1() >> 16; long int evcl_l2_1 = evcl->trigger_summary2(); long int evcl_l2_2 = evcl->trigger_summary3() & 0x3ff; if (_debug.value()) { std::cout << "L1/L2:" << std::hex << evcl_l1 << " " << evcl_l2_1 << " " << evcl_l2_2 << std::dec << std::endl; } for (int i = 0; i < BITMASKS_PER_LONGWORD; i++) { _cslMask.l1_bitmask[i] = (byte) (evcl_l1 >> (BITMASK_BITS*i) ); _cslMask.l2_bitmask[i] = (byte) (evcl_l2_1 >> (BITMASK_BITS*i) ); if ( L2_BITMASK_WORDS > BITMASKS_PER_LONGWORD ) _cslMask.l2_bitmask[i+BITMASKS_PER_LONGWORD] = (byte) ( evcl_l2_2 >> (BITMASK_BITS*i) ); } } } else // not using EVCL bits { // // algorithm for L1 bits: try TL2D first, then TFRD // if preference is expressed // for TFRD, overwrite results of // TL2D L1 bits if TFRD present. // bool foundTL2D = false; EventRecord::ConstIterator TL2D_iter( anEvent, "TL2D_StorableBank" ); if ( TL2D_iter.is_valid() ) { foundTL2D = true; ConstHandle tl2d( TL2D_iter ); for (int iw=0; iwgetL1TriggerBit(ibit))>>bitWithinLongWord)&bitmaskMask; } // for (int iw=0; iwgetNL2Words()*BITMASKS_PER_LONGWORD ; iw++) { // note that getL2TriggerBit returns a whole long word!! int ibit = BITMASK_BITS*iw; int bitWithinLongWord = ibit%(8*sizeof(int4)); int4 bitmaskMask = (1<getL2TriggerBit(ibit))>>bitWithinLongWord)&bitmaskMask; } } // use TFRD if no TL2D or preference for TFRD if ( !foundTL2D || _preferTFRDLevel1Bits.value() ) { EventRecord::ConstIterator TFRD_iter( anEvent, "TFRD_StorableBank" ); if ( TFRD_iter.is_valid() ) { ConstHandle tfrd( TFRD_iter ); for (int iw=0; iwgetL1PrescaleTrigDecision(ibit)) >>bitWithinLongWord)&bitmaskMask; } /* if ( _debug.value() ) { std::cout << "BIT ANALYSIS of TFRD" << std::endl; tfrd->print(); std::cout << "getL1PrescaleTrigDecision returns:"<< hex << tfrd->getL1PrescaleTrigDecision(0) << ", " << tfrd->getL1PrescaleTrigDecision(32) << std::dec << std::endl; std::cout << "cslMask contains:" << hex << (int) _cslMask.l1_bitmask[0] << ", " << (int) _cslMask.l1_bitmask[1] << std::dec << std::endl; } */ } // found a TFRD } // using TFRD for L1 bits } // input method // // now fill L3 stream information from output module // for (int i = 0; i < STREAM_BITMASK_WORDS; i++ ) _cslMask.stream_bitmask[i] = 0; APPListIterator iter1( *streams( ) ); AppStream** theStream = NULL; int nstream = 0; #ifdef DEBUG_ERROR std::cout << "before error call in APPLevel3GenericOutputModule::formRunEventResults" << std::endl; #endif bool errorStreamEvent = errorEvent(false).first; if ( _debug.value() && errorStreamEvent ) std::cout << "Event is a candidate for the Error Stream" << std::endl; if ( _debug.value() ) std::cout<<"Streams Passed:"; while ( (theStream = iter1()) && (nstream < BITMASK_BITS*STREAM_BITMASK_WORDS) ) { if ( streamPassCriteria(theStream,false,errorStreamEvent)) { setStreamMask(nstream,(*theStream)->name()); if ( _debug.value() ) std::cout<<(*theStream)->name()<<", "; // streams printout } nstream++; } // loop over streams if ( _debug.value() ) std::cout< iter2(*(framework()->paths())); APPPath** thePath = NULL; int nl3trig = 0; while ( (thePath = iter2()) && (nl3trig < BITMASK_BITS*L3_BITMASK_WORDS) ) { if ( (*thePath)->isEnabled() ){ if ( (*thePath)->passed() ) { int nword=nl3trig/BITMASK_BITS; _cslMask.l3_bitmask[nword]+=(1<<(nl3trig%BITMASK_BITS)); } nl3trig++; } } // // dump results for debugging? // if ( _dumpResultMasks.value() ) { for (int i = 0; i < L1_BITMASK_WORDS; i++ ) std::cout << "L1 bitmask, word " << i << ": " << (int) _cslMask.l1_bitmask[i] << std::endl; for (int i = 0; i < L2_BITMASK_WORDS; i++ ) std::cout << "L2 bitmask, word " << i << ": " << (int) _cslMask.l2_bitmask[i] << std::endl; for (int i = 0; i < L3_BITMASK_WORDS; i++ ) std::cout << "L3 bitmask, word " << i << ": " << (int) _cslMask.l3_bitmask[i] << std::endl; for (int i = 0; i < STREAM_BITMASK_WORDS; i++ ) std::cout << "Stream bitmask, word " << i << ": " << (int) _cslMask.stream_bitmask[i] << std::endl; } } void APPLevel3GenericOutputModule::formLevel3RunBeginResults( AbsEvent* anEvent ) { // // clear trigger bitmasks // for (int i = 0; i < L1_BITMASK_WORDS; i++ ) _cslMask.l1_bitmask[i] = 0; for (int i = 0; i < L2_BITMASK_WORDS; i++ ) _cslMask.l2_bitmask[i] = 0; for (int i = 0; i < L3_BITMASK_WORDS; i++ ) _cslMask.l3_bitmask[i] = 0; // // now fill L3 stream information from output module // for (int i = 0; i < STREAM_BITMASK_WORDS; i++ ) _cslMask.stream_bitmask[i] = 0; APPListIterator iter1( *streams( ) ); AppStream** theStream = NULL; int nstream = 0; while ( (theStream = iter1()) && (nstream < BITMASK_BITS*STREAM_BITMASK_WORDS) ) { // note BORs should pass all streams, thus 2nd arg is "true" if ( streamPassCriteria(theStream,true,false) ) { setStreamMask(nstream, (*theStream)->name()); nstream++; } } // // dump results for debugging? // if ( _dumpResultMasks.value() ) { for (int i = 0; i < L1_BITMASK_WORDS; i++ ) std::cout << "L1 bitmask, word " << i << ": " << (int) _cslMask.l1_bitmask[i] << std::endl; for (int i = 0; i < L2_BITMASK_WORDS; i++ ) std::cout << "L2 bitmask, word " << i << ": " << (int) _cslMask.l2_bitmask[i] << std::endl; for (int i = 0; i < L3_BITMASK_WORDS; i++ ) std::cout << "L3 bitmask, word " << i << ": " << (int) _cslMask.l3_bitmask[i] << std::endl; for (int i = 0; i < STREAM_BITMASK_WORDS; i++ ) std::cout << "Stream bitmask, word " << i << ": " << (int) _cslMask.stream_bitmask[i] << std::endl; } } void APPLevel3GenericOutputModule::setStreamMask(const int nstream, const string theName) { errlog.setSubroutine("APPLevel3GenericOutputModule::setStreamMask"); int streamNumber = nstream; if ( !_streamByName.value() ) { int nword=streamNumber/BITMASK_BITS; _cslMask.stream_bitmask[nword]+=(1<<(streamNumber%BITMASK_BITS)); } else // stream names: "streamA","A", "Astream", case insens. { string streamName = theName; // convert to upper case int i = streamName.size (); while (--i >= 0) streamName[i] = toupper (streamName[i]); // see if "STREAM" exists in the name and if so remove it string streamString("STREAM"); string::size_type streamLocation = streamName.find(streamString); if (streamLocation != string::npos) { streamName.erase(streamLocation,streamString.size()); } // test the remaining string if ( streamName.size() == 1 && isalpha(streamName[0]) ) { int streamNumber = streamName[0]-'A'; int nword=streamNumber/BITMASK_BITS; _cslMask.stream_bitmask[nword] +=(1<<(streamNumber%BITMASK_BITS)); } else // illegal stream name { errlog(ELsevere,"Event Passed Stream with illegal name:") << theName; } } errlog(ELinfo,"Stream bit ") << streamNumber << " set: " << nstream << ", " << theName; } void APPLevel3GenericOutputModule::createLevel3LRIH(int thePartition, AbsEvent* anEvent) { // // create the new LRIH // Handle newLRIH(new LRIH_StorableBank ); // // set output stream bitmask according to result of filters // newLRIH->set_output_stream(_cslMask.stream_bitmask[0]); // // set creating process and timestamp // newLRIH->set_creating_process(0x4C336578); // "L3ex" time_t now; tm *tp; if((time(&now) == -1) || !(tp = localtime(&now))) { newLRIH->set_creation_timestamp(0); } else { newLRIH->set_creation_timestamp( mktime(tp) ) ; } // // first try to find an existing LRIH // EventRecord::ConstIterator LRIH_iter( anEvent, "LRIH_StorableBank" ); if ( LRIH_iter.is_valid() ) { // REAL RUN2 DATA, get all the info from LRIH bank ConstHandle LRIH( LRIH_iter ); if (_debug.value()) { //std::cout << "Filling new LRIH from old LRIH" << std::endl; //LRIH->print(); } newLRIH->set_run_number(LRIH->run_number()); newLRIH->set_run_type(LRIH->run_type()); newLRIH->set_experiment_type(LRIH->experiment_type()); newLRIH->set_trigger_number(LRIH->trigger_number()); newLRIH->set_record_type(LRIH->record_type()); newLRIH->set_section(LRIH->section()); newLRIH->set_partition_number(LRIH->partition_number()); } // // now look for LRID // else { EventRecord::ConstIterator LRID_iter( anEvent, "LRID_StorableBank" ); if ( LRID_iter.is_valid() ) { ConstHandle LRID( LRID_iter ); if (_debug.value()) { //std::cout << "Filling new LRIH from old LRID" << std::endl; //LRID->print(); } newLRIH->set_run_number(LRID->run_number()); newLRIH->set_run_type(LRID->run_type()); newLRIH->set_experiment_type(LRID->experiment_type()); newLRIH->set_trigger_number(LRID->record_number()); newLRIH->set_section(0); newLRIH->set_record_type(LRID->record_type()); newLRIH->set_partition_number((int4) thePartition); } else // no LRID or LRIH; something is wrong { if (_debug.value()) { //std::cout << "Filling new LRIH w/o existing LRIH/LRID" << std::endl; } newLRIH->set_run_number(0); newLRIH->set_run_type(LRID_run_type::invalid); newLRIH->set_experiment_type(LRID_experiment_type::invalid); newLRIH->set_trigger_number(0); newLRIH->set_section(0); newLRIH->set_record_type(LRID_record_type::invalid); newLRIH->set_partition_number((int4) thePartition); } } // // look for TFRD to get crossing trigger number from // (also handle case of faked crossing trigger) // EventRecord::ConstIterator TFRD_iter( anEvent, "TFRD_StorableBank" ); if ( TFRD_iter.is_valid() ) { ConstHandle TFRD( TFRD_iter ); if (_debug.value()) { //std::cout << "Found a TFRD bank for crossing trigger" << std::endl; //TFRD->print(); } // // NB ugly (and dangerous hardcoding here -- awaiting real accessor) // this is the location as of CDF4152 draft September 1st, 2000 // int n_crossing_offset = 7; int n_card = 0; int n_block = 0; //if ( n_crossing_offset < TFRD_StorableBank::n_words_per_card ) // { _nCrossingTrigger = TFRD->get_word(n_block, n_card, n_crossing_offset); // } if (_debug.value()) { std::cout << " Crossing trigger number is: " << _nCrossingTrigger << std::endl; } } // if found TFRD // if no TFRD is found, just use whatever the previous value is // note that this will be -1 if it is the default for the module, // e.g., no TFRD ever found if ( _fakeCrossingTrigger.value() ) { long maxEventsPerCrossing = _timeGranularity.value() *_crossingTriggerPeriod.value() *_maxNodeEventOffset.value(); long curtime = 0; do { curtime = whatTime(1,_realStartTime); _nCrossingTrigger = curtime/_crossingTriggerPeriod.value(); if ( _fakeEventNumber.value() ) { // use previous trigger to set _nTrigger if ( _lastEvent == 0 ) _lastEvent = _nodeEventOffset.value(); _nTrigger = _lastEvent + _maxNodeEventOffset.value(); // ensure that this is in the current run section range if ( _nTrigger < _nCrossingTrigger*maxEventsPerCrossing ) _nTrigger = _nCrossingTrigger*maxEventsPerCrossing + _nodeEventOffset.value(); // if ( _debug.value() ) std::cout << "maxEventsPerCrossing, lastEvent, crossTrig, _nTrigger: " << maxEventsPerCrossing << ", " << _lastEvent << ", " << _nCrossingTrigger << ", " << _nTrigger << std::endl; // check that nTrigger is within current crossing trigger period if (_nTrigger >= (_nCrossingTrigger + 1)*maxEventsPerCrossing) { // if not... sleep until next crossing begins // // timeInCrossing is the time since the current crossing began // (in units of sec/timeGranularity) long timeInCrossing = 0; timeInCrossing = whatTime(_timeGranularity.value(), _realStartTime + _nCrossingTrigger*_crossingTriggerPeriod.value()); if ( _debug.value() ) std::cout << "Sleep " << _crossingTriggerPeriod.value() - timeInCrossing/_timeGranularity.value() << " seconds until crossing " << _nCrossingTrigger + 1 << " begins." << std::endl; #ifndef OSF1 usleep( 1000000*(_crossingTriggerPeriod.value() - timeInCrossing/_timeGranularity.value()) ); #else sleep(1); // sleep for one second; OSF1V4 doesn't support usleep #endif // now the while loop serves as a safety valve for this sleep... } if ( _debug.value() ) { std::cout << "newLRIH trigger number faked, _nTrigger = " << _nTrigger << std::endl; } newLRIH->set_trigger_number((int4) _nTrigger); } }while (_nTrigger >= (_nCrossingTrigger + 1)*maxEventsPerCrossing && _fakeEventNumber.value() ); // set lastEvent ONLY when you are definitely using this event number... _lastEvent = _nTrigger; } // // create run section from crossing trigger? // if ( _createRunSection.value() ) { if ( _debug.value() ) { std::cout << "newLRIH run section created, crossingTrig = " << _nCrossingTrigger << std::endl; } int4 runSubSect = _initialRunSection.value(); if (_nCrossingTrigger >=0 ) // defined crossing trigger runSubSect = (_nCrossingTrigger/_crossingsPerRunSection.value() +_initialRunSection.value()); newLRIH->set_section(runSubSect); } // // fake run number? // if ( _fakeRunNumber.value() >= 0 ) { if ( _debug.value() ) { std::cout << "newLRIH run number faked, run_number = " << _fakeRunNumber.value() << std::endl; } newLRIH->set_run_number((int4) _fakeRunNumber.value()); } // // write the new bank to the event // if ( _debug.value() ) { //std::cout << "newLRIH bank (L3 filter)" << std::endl; //newLRIH->print(); } if ( !_disableNewLRIH.value() ) // write a description for this LRIH bank newLRIH->set_description("L3Filter"); Id LRIHoid = (anEvent->append( newLRIH ))->object_id(); } void APPLevel3GenericOutputModule::fillLevel3CsPointerSpace( int4* spaceStart, int spaceLength, long theSenderIdentification, int thePartition, bool normalEvent, bool errorOccurred, bool passedTrigger, AbsEvent* anEvent) { // // fill L3_POINTER_SPACE with the cslMask // size_t endPoint=CS_L3_SELECTION_OFFSET+ sizeof(cs_l3_selection_mask_t)/sizeof(int4); if (endPoint <= spaceLength) (void) memcpy(&spaceStart[CS_L3_SELECTION_OFFSET], &_cslMask,sizeof(cs_l3_selection_mask_t)); // Zero streammask if requested. if (_zeroStreamMask.value()) { (void) memset(&spaceStart[CS_L3_SELECTION_OFFSET], 0, sizeof(_cslMask.stream_bitmask)); } // // now want to add the word describing the data representation // int4 outputDataRep = ( CS_L3_FORMATX_DATAREP | TRY_Ybos_Physrec_Format::datarep_native_code ); // // add a marker to the data representation word based on the root version // (now simply testing for presence of version 2.26.00 or later) // //std::cout << "APPLevel3GenericOutputModule... root version test " // << gROOT->GetVersionInt() << std::endl; if ( gROOT->GetVersionInt() >= 22600 ) // version 2.26.00 or above outputDataRep |= CS_L3_ROOTV2_26_DATAREP; endPoint=CS_L3_DATAREP_OFFSET+1; if ( endPoint <= spaceLength ) (void) memcpy(&spaceStart[CS_L3_DATAREP_OFFSET], &outputDataRep,sizeof(int4)); // // fill information passed into this routine in the L3_CS_POINTER_SPACE // endPoint=CS_L3_NODEID_OFFSET+1; int4 tempC = theSenderIdentification; if ( endPoint <= spaceLength ) (void) memcpy(&spaceStart[CS_L3_NODEID_OFFSET], &tempC,sizeof(int4)); // endPoint=CS_L3_DIAG_OFFSET+1; tempC = 0; if ( normalEvent ) tempC = tempC | CS_L3_NORMAL_EVENT_MASK; if ( errorOccurred ) tempC = tempC | CS_L3_PROCESSING_ERROR_MASK; if ( passedTrigger ) tempC = tempC | CS_L3_PASSED_FILTER_MASK; if ( endPoint <= spaceLength ) (void) memcpy(&spaceStart[CS_L3_DIAG_OFFSET], &tempC,sizeof(int4)); // endPoint=CS_L3_PARTITION_OFFSET+1; tempC = thePartition; if ( endPoint <= spaceLength ) (void) memcpy(&spaceStart[CS_L3_PARTITION_OFFSET], &tempC,sizeof(int4)); if (_debug.value()) { std::cout << "outputDataRep, theSenderIdentification, thePartition" << outputDataRep << "," << theSenderIdentification << "," << thePartition << std::endl; } // // information from the record // // REAL RUN2 DATA, get all the info from the L3Filter LRIH bank // (or the FINAL LRIH bank if no description present) EventRecord::ConstIterator LRIH_iter; for (EventRecord::ConstIterator iter( anEvent, "LRIH_StorableBank" ); iter.is_valid(); iter++) { LRIH_iter=iter; ConstHandle LRIH( LRIH_iter); if ( LRIH->description() == "L3Filter") break; } if ( LRIH_iter.is_valid() ) { ConstHandle LRIH( LRIH_iter); int4 runType = LRIH->run_type(); int4 runNum = LRIH->run_number(); int4 eventNum = LRIH->trigger_number(); int4 runSubSect = LRIH->section(); // 16-bit sub-section number int4 crossTrig = _nCrossingTrigger; // was created when LRIH was if (_debug.value()) { std::cout << "Found an LRIH bank ->" << " runType, runNum, runSubSect, eventNum, crossTrig=" << runType << "," << runNum << "," << runSubSect << "," << eventNum << "," << crossTrig << std::endl; } endPoint=CS_L3_RUNTYP_OFFSET+1; if ( endPoint <= spaceLength ) (void) memcpy( &spaceStart[CS_L3_RUNTYP_OFFSET], &runType,sizeof(int4)); endPoint=CS_L3_NRUN_OFFSET+1; if ( endPoint <= spaceLength ) (void) memcpy( &spaceStart[CS_L3_NRUN_OFFSET], &runNum,sizeof(int4)); endPoint=CS_L3_NEV_OFFSET+1; if ( endPoint <= spaceLength ) (void) memcpy( &spaceStart[CS_L3_NEV_OFFSET], &eventNum,sizeof(int4)); endPoint=CS_L3_NSEC_OFFSET+1; if ( endPoint <= spaceLength ) (void) memcpy( &spaceStart[CS_L3_NSEC_OFFSET], &runSubSect,sizeof(int4)); endPoint=CS_L3_XTRG_OFFSET+1; if ( endPoint <= spaceLength ) (void) memcpy( &spaceStart[CS_L3_XTRG_OFFSET], &crossTrig,sizeof(int4)); } // debug output if ( _debug.value() ) { std::cout << "APPLevel3GenericOutputModule::fillLevel3CsPointerSpace :" << " contents of pointer space " << std::endl; printf("*********************************************************\n") ; /* print out the event "header" one word per line */ for (int i=0; i::const_iterator errorIndex; for ( errorIndex = _localErrorList.begin(); errorIndex != _localErrorList.end(); ++errorIndex ) { #ifdef DEBUG_ERROR std::cout << "error object dump" << std::endl; std::cout << errorIndex->xid().module << std::endl; std::cout << errorIndex->xid().subroutine << std::endl; std::cout << errorIndex->xid().id << errorIndex->idOverflow() << std::endl; #endif std::string subroutineString = errorIndex->xid().subroutine; summaryString += errorIndex->xid().severity.getName()+" ERROR in "; if ( subroutineString.length() != 0 ) summaryString += subroutineString; else summaryString += errorIndex->xid().module; summaryString += ": "+errorIndex->xid().id; summaryString += errorIndex->idOverflow(); summaryString += "\n"; newErrorCount++; } if ( resetError ) { errlog.setSubroutine("APPLevel3GenericOutputModule::errorEvent"); errlog(ELinfo,"error count = ") << newErrorCount << "\nerror summary = " << summaryString; _localErrorList.clear(); } _storedErrorCount = newErrorCount; return errorStatus(true,summaryString); } else return errorStatus(false,summaryString); } void APPLevel3GenericOutputModule::onlineDropKeep(AbsEvent* anEvent) { // Clear lists from previous events combination _combinedDropClasses.clear( ); _combinedKeepClasses.clear( ); _combinedProcKeepList.clear( ); _combinedProcKeepList.push_back( "RAW" ); APPListIterator iter1( *streams( ) ); AppStream** theStream = NULL; int nstream=0; // check the streams the event would pass, ignoring autopass // considerations, but including error stream #ifdef DEBUG_ERROR std::cout << "before error call in APPLevel3GenericOutputModule::onlineDropKeep" << std::endl; #endif bool errorStreamEvent = errorEvent(false).first; while ( (theStream = iter1()) && (nstream < BITMASK_BITS*STREAM_BITMASK_WORDS) ) { if ( streamPassCriteria(theStream, false, errorStreamEvent) ) { // this is the place we OR the keep, // AND the drop, // else we weep... mergeUnique( &_combinedProcKeepList, (*theStream)->processKeepList( ) ); mergeUnique( &_combinedKeepClasses, (*theStream)->keepList( ) ); if ( _combinedDropClasses.size( ) == 0 ) _combinedDropClasses = *((*theStream)->dropList( )); else intersectUnique( &_combinedDropClasses, (*theStream)->dropList( ) ); #if DEBUG_LISTS std::cout << (*theStream)->name() << " passed" << std::endl; #endif } else { #if DEBUG_LISTS std::cout << (*theStream)->name() << " failed" << std::endl; #endif } nstream++; } // loop over streams // Now attach these lists to the event if ( _combinedProcKeepList.size( ) != 0 ) anEvent->setOutputProcessKeepList( &_combinedProcKeepList ); #if DEBUG_LISTS std::cout << "_combinedProcKeepList=\n"; copy(_combinedProcKeepList.begin(),_combinedProcKeepList.end(), ostream_iterator(cout,"\n")); #endif if ( _combinedDropClasses.size( ) != 0 ) anEvent->setOutputClassDropList( &_combinedDropClasses ); #if DEBUG_LISTS std::cout << "_combinedDropClasses=\n"; for (edm::ClassDescList_t::const_iterator ipair(_combinedDropClasses.begin()) ; ipair != _combinedDropClasses.end() ; ++ipair ) std::cout << ipair->first << ":" << ipair->second << std::endl; #endif if ( _combinedKeepClasses.size( ) != 0 ) anEvent->setOutputClassKeepList( &_combinedKeepClasses ); #if DEBUG_LISTS std::cout << "_combinedKeepClasses=\n"; for (edm::ClassDescList_t::const_iterator ipair(_combinedKeepClasses.begin()) ; ipair != _combinedKeepClasses.end() ; ++ipair ) std::cout << ipair->first << ":" << ipair->second << std::endl; #endif } bool APPLevel3GenericOutputModule::streamPassCriteria(AppStream** theStream, bool passNoMatterWhat, bool errorStreamEvent) { if ( (*theStream)->isEnabled() ) { if ( (*theStream)->passed() || passNoMatterWhat ) return(true); else { //if (_debug.value()) // std::cout << "error stream name, reduced = " // << _errorStreamName.value() << "," << _reducedErrorStream // << std::endl; if ( errorStreamEvent && ( _reducedErrorStream.size() > 0 ) ) { // process the stream name string streamName = (*theStream)->name(); // convert to upper case int i = streamName.size (); while (--i >= 0) streamName[i] = toupper (streamName[i]); // see if "STREAM" exists in the name and if so remove it string streamString("STREAM"); string::size_type streamLocation = streamName.find(streamString); if (streamLocation != string::npos) { streamName.erase(streamLocation,streamString.size()); } // test the remaining string //if (_debug.value()) // std::cout << "reduced stream names: current, error = " // << streamName << "," << _reducedErrorStream // << std::endl; if ( streamName == _reducedErrorStream ) return(true); else return(false); } else return(false); } // didn't pass } else return(false); } const char * APPLevel3GenericOutputModule::rcsId( ) const { return rcsid; } long APPLevel3GenericOutputModule::whatTime(int musecMult, long tOffset) { struct timeval time; int maxMu = 1000000; gettimeofday(&time,NULL); long secDiff = time.tv_sec - tOffset; int muSec = time.tv_usec; long nowTime = musecMult*secDiff + std::min(maxMu,muSec)*musecMult/maxMu; return(nowTime); } void mergeUnique( edm::ClassDescList_t* dest, const edm::ClassDescList_t* input) { edm::ClassDescList_t::iterator idest((*dest).begin()), edest((*dest).end()); edm::ClassDescList_t::const_iterator iinput((*input).begin()), einput((*input).end()); while(idest!=edest && iinput!=einput) { if( *idest==*iinput ) { ++idest; ++iinput; } else if( *idest<*iinput ) ++idest; else { (*dest).insert(idest,*iinput); ++iinput; } } // Check to see if we ran off the end of dest; if so we have to // tack on the end of the input list to the end of the dest list if ( idest==edest ) (*dest).insert(idest,iinput,einput); } void mergeUnique( edm::ProcessList_t* dest, const edm::ProcessList_t* input) { edm::ProcessList_t::iterator idest((*dest).begin()), edest((*dest).end()); edm::ProcessList_t::const_iterator iinput((*input).begin()), einput((*input).end()); while(idest!=edest && iinput!=einput) { if( *idest==*iinput ) { ++idest; ++iinput; } else if( *idest<*iinput ) ++idest; else { (*dest).insert(idest,*iinput); ++iinput; } } // Check to see if we ran off the end of dest; if so we have to // tack on the end of the input list to the end of the dest list if ( idest==edest ) (*dest).insert(idest,iinput,einput); } void intersectUnique( edm::ClassDescList_t* dest, const edm::ClassDescList_t* input) { edm::ClassDescList_t::iterator idest((*dest).begin()), edest((*dest).end()); edm::ClassDescList_t::const_iterator iinput((*input).begin()), einput((*input).end()); while(idest!=edest && iinput!=einput) { if(*idest==*iinput) { ++idest; ++iinput; } else if(*idest<*iinput) { (*dest).erase(idest++); } else ++iinput; } if(iinput==einput) (*dest).erase(idest,edest); }