// BasicColl.cc -- Rudimentary use of the ELcollected/ELrecv mechanism: // The ELcollected end // // This example program is in four logical pieces: // // We show the framework code that would support operations. // // Then we show the user code -- many physicist users could contribute // code of this nature, using errlog in the manner shown. // // Then we have MySender, derived from ELsender, a necessity which the // experiment would provide. The key (and only) method is send(). // In this simple case it merely writes nbytes and the character data // to an fstream. // // Portions of the code relevant to the ELcollected mechanism are // pointed out as follows: <<<---------------- // We base the example around BasicUsage, even though for illustration // purposes we will be skipping the physicist DoPhysics module. // // 12/5/02 mf - Modifications to also test debug level messages // --------------- // Framework Code // --------------- #include "BasicColl.h" // The framework would normally include some framework.h, plus Event.h, // Module.h, and the headers for any physicist classes like DoPhysics. // In our illustration these are all in BasicColl.h. // These are the ErrorLogger classes used by the typical framework: #include "ErrorLogger/ELadministrator.h" #include "ErrorLogger/ELdestControl.h" #include "ErrorLogger/ELoutput.h" #include "ErrorLogger/ELcollected.h" // <<<---------------- #include "ErrorLogger/ELsender.h" // <<<---------------- #include "ErrorLogger/ELstatistics.h" #include "ZMutility/iostream" USING( std::cout ) Module::Module( const std::string & name ) { errlog.setModule( name ); } // This is the MySender class - not very complicated: // <<<---------------- MySender::MySender ( ofstream & fs ) : file (fs) { } ZM_COVARIANT_TYPE(ELsender *, MySender *) MySender::clone() const { // <<<---- return new MySender ( *this ); // Just follow this form exactly; there is no // need to customize clone(). } void MySender::send (int nbytes, const char * data) { // <<<---------------- // // In real applications, this is where the meat is: // The sending side of the experiment's transport mechanism // cout << "\n******** send called: " << nbytes << " bytes\n"; file << "\n" << nbytes << "\n"; char d; for (int i=0; i < nbytes; i++) { d = *data++; file << d; } file << "%END-OF-DATA%\n"; } // This is the context supplier: int eventN; // I am making this global just to make it available to the // ClientContext methods. #include "ZMutility/sstream" USING( std::ostringstream ) string ClientContext::summaryContext() const { ostringstream ev; ev << eventN << "/1"; return ev.str(); } string ClientContext::context() const { ostringstream ev; ev << " Run = 1; Event = " << eventN; return ev.str(); } string ClientContext::fullContext() const { return context(); } ClientContext::ClientContext ( ) { } ZM_COVARIANT_TYPE(ELcontextSupplier *, ClientContext *) ClientContext::clone() const { return new ClientContext( *this ); } int main() { ELadministrator * logger = ELadministrator::instance(); // instantiate a logger object ClientContext cctxt; logger->setContextSupplier(cctxt); logger->setProcess("CPU 3"); ErrorLog errlog ("main Module"); // instantiate an ErrorLog for messages from main ELoutput logfileD( "BasicColl.errlog" ); // make an ELdestination ELdestControl logfile ( logger->attach(logfileD) ); // tell logger about it logfile.setThreshold ( ELsuccess ); // ignore messages below // ELsucess ELoutput outputD( cout ); // another ELdestination ELdestControl output ( logger->attach(outputD) ); // tell logger about it output.setThreshold ( ELerror ); // ignore messages below // ELerror // Now instantiate the ELcollected destination <<<------------------ ofstream tfile ("transmissionFile.dat"); MySender transmitter (tfile); ELcollected collectedD ( transmitter ); ELdestControl collected ( logger->attach(collectedD) ); collected.setThreshold ( ELwarning ); #ifdef NOT_HERE ELstatistics statsD( cout ); // a statistics dest ELdestControl stats ( logger->attach(statsD) ); // tell logger about it // Note that this would // be the LOCAL stats #endif // The following is a list of the modules in this program: DoPhysics doPhysics( "PHYSICS CODE" ); // There is only one module in this illustration. // The following tests debug level messages: int vlevel = 0; for ( eventN = 1; eventN < 17; ++eventN ) { Event event( eventN ); if (eventN%2) { vlevel++; errlog.setDebugVerbosity(vlevel); } if (eventN==9) { errlog.setDebugMessages(ELwarning, "newDebug"); } for (int i = 1; i <= 10; ++i) { errlog (i) << " verbosity level is" << vlevel << "debug level is" << i << endmsg; } #ifdef NOT_HERE doPhysics( event ); if (eventN%4 == 0) { stats.summary( output, "Error Statistics So Far" ); } #endif if (eventN%3 == 0) { errlog (ELwarning, "n%3==0") << eventN << "is divisible by 3." << endmsg; } if (eventN == 10) { errlog (ELerror, "event 10") << "@SUB=fake()" << "This event is deemed to have a real error" << endmsg; } } return 0; } // main() // ----------------- // Physicsists' Code // ----------------- #include "BasicColl.h" #include "ErrorLogger/ErrorLog.h" void DoPhysics::operator()( Event & event ) { // This is the same as per basicUsage, except the context is also set up. errlog( ELsuccess, "An Event" ) << "data = " << event.data << endmsg; if ( event.data == 9 ) { errlog( ELerror, "Ninth Event" ) << endmsg; } // I don't like event number 9. int sum = 0; for (int i = 1; i <= event.data; i++) { sum += i*(event.data+i); if (sum > 100) { errlog( ELwarning, "Big Sum" ); errlog << "event " << event.data; errlog << " i = " << i; errlog << " sum = " << sum << endmsg; break; } } errlog (ELsuccess, "Event Finished") << "event # " << event.data << endmsg; if ( event.data > 12 ) { errlog( ELabort, "> Twelve Events" ) << endmsg; } // I REALLY don't like event 13! } // DoPhysics::operator()(event)