//-------------------------------------------------------------------------- // File and Version Information: // $Id: APPLevel3InputModule.cc,v 1.70 2002/10/15 19:57:26 ksmcf Exp $ // // Description: // Class APPLevel3InputModule. This is an online input module // for the AC++ framework. It coordinates and interfaces farm // control with framework control. In addition it returns the // events/records and state information required by framework. // // Environment: // Software developed for CDF II. // // Author List: // Kevin McFarland // Liz Sexton-Kennedy // //------------------------------------------------------------------------ //----------------------- // This Class's Header -- //----------------------- #include "Level3Mods/APPLevel3InputModule.hh" //------------- // C Headers -- //------------- //#include //#include #include //#include //#include #include #include #ifndef DEFECT_NO_STDLIB_NAMESPACES using std::string; #endif extern "C" { #ifndef __GNUG__ #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE_EXTENDED==1) static pid_t vfork (void); #define __vfork vfork #endif #endif #include #if defined( AIX ) || defined( SunOS ) // // getopt.h is in stdlib on AIX: does not exist on its own. R. Harris 11/24/97 // same for Solaris 2. P.T. Keener 7 Apr 1999 // #else #include #endif #include } //------------------------------- // Collaborating Class Headers -- //------------------------------- #include "BaBar/Cdf.hh" #include "AbsEnv/AbsEnv.hh" #include "FrameMods/APPInputCommand.hh" #include "Framework/APPFramework.hh" #include "FrameUtil/AbsInterp.hh" #include "Trybos/TRY_Record_Iter_Any.hh" #include "Trybos/TRY_Generic_Bank.hh" #include "Edm/GenericConstHandle.hh" #include "Edm/ConstHandle.hh" #include "StorableBanks/StorableBank.hh" #include "BankTools/StorableBankUtilities.hh" // included for format information #include "HeaderObjects/LRIH_StorableBank.hh" #include "HeaderObjects/LRIH_StorableBank_format.hh" #include "StorableBanks/LRID_StorableBank.hh" #include "StorableBanks/LRID_StorableBank_utilities.hh" //------------------- // ConsumerServerLogger headers -- //------------------- extern "C" { #include "ConsumerInterface/l3_cs_pointer_space.h" } //----------------------------------------------------------------------- // Local Macros, Typedefs, Structures, Unions and Forward Declarations -- //----------------------------------------------------------------------- static const char rcsid[] = "$Id: APPLevel3InputModule.cc,v 1.70 2002/10/15 19:57:26 ksmcf Exp $"; // ---------------------------------------- // -- Public Function Member Definitions -- // ---------------------------------------- // //---------------- // Constructors -- //---------------- APPLevel3InputModule::APPLevel3InputModule( const char* const theName, const char* const theDescription, const int4 exeTag ) : APPReaderInputModule( theName, theDescription ), _isSilent( "isSilent", this, true ), _debugLevel( "debugLevel", this, 0, -5, 5 ), _inputfile( "inputfile", this, "test.ybs"), _outputfile( "outputfile", this, "results.root"), _num_events("num_events", this, 99), _filetype("filetype",this,0,0,2), _receivedEndRun (false), _onlineOperation ("onlineOperation", this, false), _sevbInterface ("sevbInterface", this, false), _sevbBufferKey ("sevbBufferKey", this, -10), _sevbRtrnKey ("sevbRtrnKey", this, -10), _sevbSemId ("sevbSemId", this, -10), _sevbBuffSize ("sevbBuffSize", this, 0), _useErrorEventStream("useErrorEventStream", this, true), _theTRYRecord(NULL), _edmEvent(NULL), _theInterface(NULL) { // setup talk-to parameters _isSilent.addDescription(" \tDon't report routine messages to log (default true)"); _debugLevel.addDescription(" \tLevel of debugging COUTs: 0 none, 1 one-time messages, 2 every event messages, 3 every event and hex dumps (default 1)"); _inputfile.addDescription(" \tInput file for the FileLEvel3Interface (default test.ybs)"); _outputfile.addDescription(" \tOutput file for the FileLevel3Interface (default result.root)"); _num_events.addDescription(" \tThe number of events to pass through FileLevel3Interface (default 99)"); _filetype.addDescription(" \tThe type of the input file sent to FileLevel3Interface (DEFAULT trybos=0, csl_badevent=1, l3_badevent=2)"); _onlineOperation.addDescription(" \t false for FileLevel3Interface, true for Level3Interface (default false)"); _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). NB, there is an identical parameter in the OnlineOutputModule; it is desirable to set them to the same value"); commands()->append(&_isSilent); commands()->append(&_debugLevel); commands()->append(&_inputfile); commands()->append(&_outputfile); commands()->append(&_num_events); commands()->append(&_filetype); commands()->append(&_onlineOperation); commands()->append(&_sevbInterface); commands()->append(&_sevbBufferKey); commands()->append(&_sevbRtrnKey); commands()->append(&_sevbSemId); commands()->append(&_sevbBuffSize); commands()->append(&_useErrorEventStream); // process level3 command line int opt; int error ( 0 ); // getopt swaps the order of the arguments (only on Linux?) // so only send it the last ones...the first arg must be the // command procedure to be executed. fprintf(stderr,"APPLevel3InputModule::__ct:Argc=%d,Argv=", framework( )->argc( )); for (int i = 0; i<(framework( )->argc( ));i++) { fprintf(stderr,"%s,",framework( )->argv( )[i] ); } fprintf(stderr,"\n"); fflush(stderr); fprintf(stderr,"APPLevel3InputModule::__ct:option parsing(!): "); while ( opt = getopt( (framework( )->argc( )), (framework( )->argv( )), "l:vk:r:s:b:") ) { if (opt == -1) break; switch( opt ) { case 'l': std::cout << "Deprecated option -l ignored" << std::endl; ::exit(0); case 'v': std::cout << "version " << exeTag << std::endl; ::exit(0); default: error = 1; } } fprintf(stderr,"\n");fflush(stderr); if ( error != 0 ) { std::cout << "WARNING: error while parsing command line arguments" << std::endl; } } //-------------- // Destructor -- //-------------- APPLevel3InputModule::~APPLevel3InputModule( ) { } //-------------- // Operations -- //-------------- AppResult APPLevel3InputModule::childBeginJob( AbsEvent* anEvent ) { // Initialize both Trybos and CdfEdm2 systems if (_theTRYRecord == 0) _theTRYRecord = new TRY_Ybos_Simple_Record(); if (_edmEvent == 0) _edmEvent = new EventRecord(); // command file processing //AbsInterp* interp = AbsInterp::theInterpreter( ); //assert( interp->isInitialized( ) ); //interp->runCommandFile(_commandInput.c_str()); return AppResult::OK; } AppResult APPLevel3InputModule::initIOSystem( ) { if ( onlineOperation() ) { if ( sevbInterface() ) { _theInterface = new SevbL3Interface (sevbBufferKey (), sevbRtrnKey (), sevbSemId (), sevbBuffSize ()); } else { #ifdef L3LINUX _theInterface = new Level3Interface( isSilent() ); #else errlog.setSubroutine("APPLevel3InputModule::initIOSystem"); errlog(ELfatal,"Cannot specify onlineOperation for OS other than Linux") << endmsg; #endif // __Linux__ } } else // default test (file) mode, using FileLevel3Interface { _theInterface = new FileLevel3Interface( isSilent(), inputfname(), outputfname(), eventnumber(), _filetype.value()); } if ( _theInterface->init( ) != SUCCESS) return AppResult::ERROR; return AppResult::OK; } AppResult APPLevel3InputModule::terminateIOSystem( ) { // // protect against case where initIOSystem is not called // if ( _theInterface != NULL ) { // // acknowledge disconnect and change state // if ( _theInterface->isGrandFinish() ) { if ( _theInterface->finish( ) != SUCCESS) return AppResult::ERROR; } else { // The input module should already have signaled an early exit } // // destroy the interface // delete _theInterface; } return AppResult::OK; } AppResult APPLevel3InputModule::beginRun( AbsEvent* aRun ) { // if aRun is NULL then this call is being made in the wrong state! if ( aRun != NULL ) { // Parse the trigger table _triggerTable! // If debug show the result // Mark the beginning of the run in the log file errlog.setSubroutine("APPLevel3InputModule::begin_run"); errlog(ELinfo,"called beginRun") << "========================== Beginning of Run " << gblEnv->runNumber( ) << "=========================" << endmsg; } return AppResult::OK; } AppResult APPLevel3InputModule::endRun( AbsEvent* aRun ) { return AppResult::OK; } //------------- // Selectors -- //------------- bool APPLevel3InputModule::isSilent( ) const { return _isSilent.value(); } int APPLevel3InputModule::debugLevel( ) const { return _debugLevel.value(); } // input file name for FileLevel3Interface string APPLevel3InputModule::inputfname( ) const { return _inputfile.value(); } // output file name for FileLevel3Interface string APPLevel3InputModule::outputfname( ) const { return _outputfile.value(); } // number of events for FileLevel3Interface int APPLevel3InputModule::eventnumber( ) const { return _num_events.value(); } // function that determines which type of Interface (FileLevel3Interface, // Level3Interface) is used bool APPLevel3InputModule::onlineOperation( ) const { return _onlineOperation.value(); } // function that determines whether the input comes from the software // event builder or not bool APPLevel3InputModule::sevbInterface( ) const { return _sevbInterface.value(); } int APPLevel3InputModule::sevbBufferKey() const { return _sevbBufferKey.value(); } int APPLevel3InputModule::sevbRtrnKey() const { return _sevbRtrnKey.value(); } int APPLevel3InputModule::sevbSemId() const { return _sevbSemId.value(); } int APPLevel3InputModule::sevbBuffSize() const { return _sevbBuffSize.value(); } // ----------------------------------------- // -- Private Function Member Definitions -- // ----------------------------------------- AppResult APPLevel3InputModule::mapEventToRecord() { // The event is now offset within the win buffer by a number of // long ints equal to L3_CS_POINTER_SPACE (in l3_cs_pointer_space.h) // Have to add this offset to pointers and subtract it from // lengths. int4* win = _theInterface->getWin(); // win_length is length in words; //note that getSize is returning the size in bytes int win_length = _theInterface->getSize()/sizeof(int4); if ( debugLevel() >= 3 ) { printf( "mapEventToRecord: WIN address = %p, logical len = %d, physical len = %d, event offset = %d\n", win, win[L3_CS_POINTER_SPACE], win_length, L3_CS_POINTER_SPACE ); hexBufferDump("mapEventToRecord: WIN buffer",(long *) win,512,0); } // Note that I originally cleared _theTRYRecord at this // point, but that caused the PRIVATE_set_iobuf to fail // Map the Trybos record's I/O buffer to win. Note that the second // arg. is the logical length of the buffer and the third is the // physical length if ( _theTRYRecord->PRIVATE_set_iobuf( (int *)&win[L3_CS_POINTER_SPACE], win[L3_CS_POINTER_SPACE], win_length-L3_CS_POINTER_SPACE, false )) { if ( debugLevel() >= 3 ) // TRYBOS bank scan { TRY_Record_Iter_Any p_bnk(_theTRYRecord); std::cout << "TRYBOS Bank List before translation" << std::endl; while (p_bnk.is_valid()) { TRY_Generic_Bank theBank(p_bnk); std::cout << (theBank.bank_name()).as_string() << " #" << (theBank.bank_number()).as_string() << " (" << theBank.body_size() << " size)" << std::endl; p_bnk++; } } _edmEvent->set_process_name( "RAW" ); bool translate_success = StorableBankUtilities:: translate_record_try2edm(_theTRYRecord, _edmEvent); if ( !translate_success ) { errlog.setSubroutine("APPLevel3InputModule::mapEventToRecord"); errlog(ELsevere, "Unable to translate record to EDM2") << endmsg; // // this will ultimately cause AppCDFInputModule::inputEvent to call // nextEvent of this class again; therefore need to report error // here and send event to error stream // if ( _useErrorEventStream.value() && _theInterface->isRunEvent() ) { _theInterface->send_error(_theInterface->getSize(),debugLevel(), Abs_Level3Interface::L3_INPUT_ERROR, "INPUT FAILURE: can't translate record"); } else { _theInterface->send_message(debugLevel(), Abs_Level3Interface::L3_INPUT_ERROR, "INPUT FAILURE: can't translate record"); } return AppResult::ERROR; } setTheRecord( _edmEvent ); setAbsEnvEventPointer( _edmEvent ); if ( debugLevel() >= 2 ) { bankList(theRecord()); } return AppResult::OK; } else { errlog.setSubroutine("APPLevel3InputModule::mapEventToRecord"); errlog(ELsevere, "Unable to make WIN buffer into event") << endmsg; // // this will ultimately cause AppCDFInputModule::inputEvent to call // nextEvent of this class again; therefore need to report error // here and send event to error stream // if ( _useErrorEventStream.value() && _theInterface->isRunEvent() ) { _theInterface->send_error(_theInterface->getSize(),debugLevel(), Abs_Level3Interface::L3_INPUT_ERROR, "INPUT FAILURE: WIN->TRYBOS fails"); } else { _theInterface->send_message(debugLevel(), Abs_Level3Interface::L3_INPUT_ERROR, "INPUT FAILURE: WIN->TRYBOS fails"); } return AppResult::ERROR; } } AppResult APPLevel3InputModule::nextEvent( AppStopType& theDispatchStopType ) { errlog.setSubroutine("APPLevel3InputModule::nextEvent"); if ( _debugLevel.value() == -3 && theRecordTotal()>=5) { errlog(ELwarning, "harmless fake error") << endmsg; return AppResult::ERROR; } if ( _receivedEndRun ) { // should be requesting a stop errlog(ELinfo, "EOR already sent; requesting stop") << endmsg; framework()->requestStop(); return AppResult::OK; } // // receive an event // if ( _theInterface->receive( ) != SUCCESS ) { // DSW, 12.06.2001 If this a file interface, this can happen // just because we reached the EOF, in which case don't die // quite so horribly : FileLevel3Interface* _fileInterface = dynamic_cast(_theInterface); if (_fileInterface) { if (_fileInterface->isEOF()) { errlog(ELinfo, "End of File. Stopping.") << endmsg; framework()->requestStop(); return AppResult::OK; } } // abnormal transition to finish (not done in output module) errlog(ELsevere, "receive of event fails; requesting stop") << endmsg; framework()->requestStop(); return AppResult::ERROR; } if ( mapEventToRecord() == AppResult::OK ) { // // for EOR, setting the dispatch type returns // "end of run, now proceed with next run" // AppResult recordResult = processRecordHeader( theDispatchStopType ); if ( recordResult != AppResult::OK) { errlog(ELerror,"LRIH/LRID processing returned an error") << endmsg; // // this will ultimately cause AppCDFInputModule::inputEvent to call // nextEvent of this class again; therefore need to report error // here and send event to error stream (if regular event) // if ( _useErrorEventStream.value() && _theInterface->isRunEvent() ) { _theInterface->send_error(_theInterface->getSize(),debugLevel(), Abs_Level3Interface::L3_INPUT_ERROR, "INPUT FAILURE: bad event header"); } else { _theInterface->send_message(debugLevel(), Abs_Level3Interface::L3_INPUT_ERROR, "INPUT FAILURE: bad event header"); } return AppResult::ERROR; } if ( _theInterface->isRunEvent() ) { errlog(ELinfo,"nextEvent found runEvent") << endmsg; if ( debugLevel() >= 3 ) { for (EventRecord::ConstIterator iter(theRecord(),"LRIH_StorableBank"); iter.is_valid(); ++iter) { ConstHandle handle(iter); handle->print(); } for (EventRecord::ConstIterator iter(theRecord(),"LRID_StorableBank"); iter.is_valid(); ++iter) { ConstHandle handle(iter); handle->print(); } } if ( theDispatchStopType != AppStopType::physics_event ) errlog(ELerror,"event type mismatch; control code runEvent"); return AppResult::OK; } else if ( _theInterface->isRunBegin() ) { errlog(ELinfo,"nextEvent found runBegin") << endmsg; if ( theDispatchStopType != AppStopType::begin_run ) errlog(ELerror,"event type mismatch; control code runBegin"); return AppResult::OK; } else if ( _theInterface->isRunEnd() ) { errlog(ELinfo,"nextEvent found runEnd") << endmsg; if ( theDispatchStopType != AppStopType::end_run ) errlog(ELerror,"event type mismatch; control code runEnd"); // // ensure that next time nextEvent is called, the job will end // _receivedEndRun = true; return AppResult::OK; } else // unknown message { errlog(ELerror,"unexpected message (event) type") << endmsg; theDispatchStopType = AppStopType::invalid; return AppResult::OK; } } else { // // forward mapRecordToEvent failure back to CDFInputModule // return AppResult::ERROR; } } void APPLevel3InputModule::bankList(AbsEvent* anEvent) { std::cout << "Bank List:" << std::endl; for (EventRecord::ConstIterator iter = anEvent->begin(); iter.is_valid(); ++iter) { GenericConstHandle handle(iter); std::string class_name = handle->class_name() ; std::cout << " " << class_name << " (oid " << handle->object_id() ; int index = class_name.find("StorableBank") ; if ( (index >= 0) && (index < class_name.size()) ) { ConstHandle bank_handle(handle) ; std::cout << ": " << bank_handle->bank_name() ; std::cout << ", " << bank_handle->bank_number() ; } std::cout << ")" ; if (!handle->description().empty()) { std::cout << ", " << handle->description(); } std::cout << std::endl; } // End object loop -------------------------- } string APPLevel3InputModule::theFilename( ) const { return "this ain't no file; this is Level3 you fool!!"; } void APPLevel3InputModule::hexBufferDump(const char *annotation, const long int *buffer, const long int buffer_size, const long int offset) { long int i ; long int io ; io = offset ; if (offset>buffer_size) { printf("APPLevel3InputModule::hexBufferDump: == WARNING ==\n") ; printf("buffer_size smaller than offset\n") ; printf("complete buffer_size: %ld offset: %ld\n\n",buffer_size, offset) ; io = buffer_size ; } /* print out annotation */ printf("*********************************************************\n") ; printf("%s\n", annotation) ; printf("---------------------------------------------------------\n") ; printf("nwords: %6ld, offset: %6ld\n", buffer_size, io) ; printf("---------------------------------------------------------\n") ; /* print out the event "header" one word per line */ if (io > 0) { for (i=0; i= 0) { for (i=io; i