//-------------------------------------------------------------------------- // File and Version Information: // $Id: APPLevel3OnlineOutputModule.cc,v 1.17 2002/10/19 01:11:23 kennedy Exp $ // // Description: // Class APPLevel3OnlineOutputModule. This is an online output module // for the AC++ framework. It coordinates and interfaces farm // control with framework control. In addition it outputs the // events/records and state information required by the farm. // // Environment: // Software developed for CDF II. // // Author List: // Liz Sexton-Kennedy Original Author // Kevin McFarland // //------------------------------------------------------------------------ #include "Experiment/Experiment.hh" //------------------------------- // Collaborating Class Headers -- //------------------------------- // this (which refers to the interface) // has to come before declaration of OnlineOutputModule which // inherits from the Sender class that has all the csl definition... // it's a mess. #include "Level3Mods/APPLevel3InputModule.hh" //----------------------- // This Class's Header -- //----------------------- #include "Level3Mods/APPLevel3OnlineOutputModule.hh" //------------------------------- // Collaborating Class Headers -- //------------------------------- #include "Framework/APPFramework.hh" // for access to the input module #include "Framework/APPJob.hh" #include "Framework/AppStream.hh" class AbsEvent; #include "Framework/APPList.hh" #include "Framework/APPListIterator.hh" #include "Trybos/TRY_Fixed_Size_Types.hh" #include "Trybos/TRY_Ybos_Simple_Record.hh" #include "Trybos/TRY_Record_Iter_Any.hh" #include "Trybos/TRY_Record_Iter_Same.hh" #include "Trybos/TRY_Generic_Bank.hh" #include "Trybos/private/TRY_Ybos_Physrec_Format.hh" #include "Banks/LRID_Bank_Utils.hh" #include "Banks/LRIH_Bank.hh" #include "Banks/EVCL_Bank.hh" //------------------- // ConsumerServerLogger headers -- //------------------- extern "C" { #include "ConsumerInterface/l3_cs_pointer_space.h" } //------------- // C Headers -- //------------- #include #include //----------------------------------------------------------------------- // Local Macros, Typedefs, Structures, Unions and Forward Declarations -- //----------------------------------------------------------------------- static const char rcsid[] = "$Id: APPLevel3OnlineOutputModule.cc,v 1.17 2002/10/19 01:11:23 kennedy Exp $"; //---------------- // Constructors -- //---------------- APPLevel3OnlineOutputModule::APPLevel3OnlineOutputModule( const char* const theName, const char* const theDescription, const int4 exeTag ) : APPLevel3SenderOutputModule ( headerWords(), theName, theDescription, exeTag ), _theInputModule ( NULL ), _theInterface ( NULL ) { } //-------------- // Destructor -- //-------------- APPLevel3OnlineOutputModule::~APPLevel3OnlineOutputModule( ) { } //-------------- // Operations -- //-------------- AppResult APPLevel3OnlineOutputModule::initIOSystem( ) { // communication with the Level-3 system is through the input module // Find the pointer to the input module, downcast it to the correct type here... // of course this means that one can't use this module with anything // other then the Level3InputModule _theInputModule = ( APPLevel3InputModule* )framework( )->theInputModule( ); // the primary purpose of knowing about the input module is to get the // interface _theInterface = _theInputModule->_theInterface; errlog.setSubroutine("APPLevel3OnlineOutputModule::initIOSystem"); errlog(ELinfo, "found Level3InputModule:") << _theInputModule->name( ) << " is YOUR input module" << endmsg; _partitionId = (_theInterface)->getPartitionId(); // // Check tags from theInterface against tags from talk-tos and build file // errlog.setSubroutine("APPLevel3OnlineOutputModule::initIOSystem"); if ( _exeTag != _theInterface->getExecutableTag() && _theInterface->getExecutableTag() != Abs_Level3Interface::ignoreTag ) { string errString = "internal and external EXE tags disagree:"; std::stringstream tagList; tagList << _exeTag << "," << _theInterface->getExecutableTag(); errString += tagList.str(); errlog(ELsevere,errString) << endmsg; _theInterface ->send_message(debugLevel(), Abs_Level3Interface::L3_INIT_ERROR, errString); } if ( _calibTag.value() != _theInterface->getCalibTag() && _theInterface->getCalibTag() != Abs_Level3Interface::ignoreTag ) { string errString = "internal and external CALIB tags disagree:"; std::stringstream tagList; tagList << _calibTag.value() << "," << _theInterface->getCalibTag(); errString += tagList.str(); errlog(ELsevere,errString) << endmsg; _theInterface ->send_message(debugLevel(), Abs_Level3Interface::L3_INIT_ERROR, errString); } if ( _tclTag.value() != _theInterface->getTclTag() && _theInterface->getTclTag() != Abs_Level3Interface::ignoreTag ) { string errString = "internal and external TCL tags disagree:"; std::stringstream tagList; tagList << _tclTag.value() << "," << _theInterface->getTclTag(); errString += tagList.str(); errlog(ELsevere,errString) << endmsg; _theInterface ->send_message(debugLevel(), Abs_Level3Interface::L3_INIT_ERROR, errString); } return AppResult::OK; } AppResult APPLevel3OnlineOutputModule::sendFlatEvent( bool sendIt, size_t flatEventLength, errorStatus status) { errlog.setSubroutine("APPLevel3OnlineOutputModule::sendFlatEvent"); // // message now exists in the onlineBuffer structure; must copy to // _win data area (obtained from the Interface) // // // check to see if the allocated online buffer is smaller than the // flat event; if so, scream! // // (flatEventLength is in bytes; BufferSize is in long words) // if ( flatEventLength > (_theInterface->getMaxBufferSize()*sizeof(int4) )) { // report the error to error logger std::stringstream truncError; truncError << "TRUNCATING LEVEL-3 OUTPUT EVENT:" << "event size is " << flatEventLength << " bytes; buffer is only " << (_theInterface->getMaxBufferSize()*sizeof(int4)) << " bytes"; errlog(ELsevere,truncError.str()) << endmsg; // manually report the error to DAQ if (status.first != true) { status.first = true; status.second = truncError.str(); } else (_theInterface) ->send_message(debugLevel(), Abs_Level3Interface::L3_ERRORLOGGER_ERROR, truncError.str()); // truncate the event flatEventLength = _theInterface->getMaxBufferSize()*sizeof(int4); } memcpy(_theInterface->getAddress(), _onlineBuffer, flatEventLength); // // handle errors reported by the framework // if ( status.first ) // error reported by framework { errlog(ELinfo,"got an error message: ") << status.second << endmsg; // // if using error stream and if event is a RunEvent, send as // an error event // if ( _useErrorEventStream.value() && (_theInterface)->isRunEvent() ) { if ( (_theInterface) ->send_error( flatEventLength, debugLevel(), Abs_Level3Interface::L3_ERRORLOGGER_ERROR, status.second ) != SUCCESS ) return(AppResult::ERROR); } else { (_theInterface) ->send_message(debugLevel(), Abs_Level3Interface::L3_ERRORLOGGER_ERROR, status.second); if ( (_theInterface)->send( sendIt, flatEventLength, debugLevel() ) != SUCCESS ) return(AppResult::ERROR); } } else // no error reported by the framework { if ( (_theInterface)->send( sendIt, flatEventLength, debugLevel() ) != SUCCESS ) return(AppResult::ERROR); } return(AppResult::OK); } AppResult APPLevel3OnlineOutputModule::terminateIOSystem( ) { return AppResult::OK; } AppResult APPLevel3OnlineOutputModule::disconnectOnAbort() { // // here the input module contains the outside connection // _theInputModule->terminateIOSystem(); return AppResult::OK; } // Accessors const char * APPLevel3OnlineOutputModule::rcsId( ) const { return rcsid; } int APPLevel3OnlineOutputModule::debugLevel( ) const { return _theInputModule->_debugLevel.value(); } int APPLevel3OnlineOutputModule:: headerWords() const { return(sizeof(msghdr_t)/sizeof(int4)); } long APPLevel3OnlineOutputModule:: externalMaximumBufferSize() const { errlog.setSubroutine("APPLevel3OnlineOutputModule::externalMaximumBufferSize"); // this was an attempt to get the buffer size on the fly if it // didn't exist... not a great idea. Let's just forget this... // KSM, 7/26/02 // //APPLevel3InputModule* myInputModule; //if ( _theInputModule == NULL ) // myInputModule = ( APPLevel3InputModule* )framework( )->theInputModule( ); //else // myInputModule = _theInputModule; // //if (myInputModule->_theInterface) // return(myInputModule->_theInterface->getMaxBufferSize()); if ( _theInterface != NULL ) return (_theInterface->getMaxBufferSize()); else errlog(ELsevere, "unable to access the Level3 Interface to get buffer size") <getCopyId(); } int4 APPLevel3OnlineOutputModule:: getHost() const { return _theInterface->getBoxId(); } void APPLevel3OnlineOutputModule:: fillHeaderWords(int4* pHeader, const AppStopType& theDispatchStopType, size_t length, long processId) { msghdr_t* header = (msghdr_t*) pHeader; int4 eventMessage = L3_RUN_EVENT; if ( theDispatchStopType == AppStopType::begin_run ) eventMessage = L3_RUN_BEGIN; else if ( theDispatchStopType == AppStopType::end_run ) eventMessage = L3_RUN_END; header->msg_type = eventMessage; // message type header->msg_length = length; // message length header->msg_origination = processId ; // sender ID header->msg_destination = L3_DISPATCHER; // destination ID }