00001
00002 #ifdef _WIN32
00003
00004 #define NOMSG
00005 #define NOGDI
00006 #endif
00007
00008 #include "GaudiKernel/Kernel.h"
00009 #include "GaudiKernel/StatusCode.h"
00010 #include "GaudiKernel/SvcFactory.h"
00011 #include "GaudiKernel/Message.h"
00012 #include "GaudiKernel/xtoa.h"
00013 #include "MessageSvc.h"
00014
00015 #include <sstream>
00016 #include <iostream>
00017 #include <fstream>
00018
00019 using namespace std;
00020
00021
00022
00023 DECLARE_SERVICE_FACTORY(MessageSvc)
00024
00025 static std::string levelNames[MSG::NUM_LEVELS];
00026
00027
00028 MessageSvc::MessageSvc( const std::string& name, ISvcLocator* svcloc )
00029 : base_class( name, svcloc ) {
00030 m_defaultStream = &std::cout;
00031 m_outputLevel = MSG::NIL;
00032 declareProperty( "Format", m_defaultFormat = Message::getDefaultFormat() );
00033 declareProperty( "timeFormat", m_defaultTimeFormat = Message::getDefaultTimeFormat() );
00034 declareProperty( "showStats", m_stats = false );
00035 declareProperty( "statLevel", m_statLevel = 0 );
00036
00037
00038 declareProperty( "setVerbose", m_thresholdProp[MSG::VERBOSE] );
00039 declareProperty( "setDebug", m_thresholdProp[MSG::DEBUG] );
00040 declareProperty( "setInfo", m_thresholdProp[MSG::INFO] );
00041 declareProperty( "setWarning", m_thresholdProp[MSG::WARNING] );
00042 declareProperty( "setError", m_thresholdProp[MSG::ERROR] );
00043 declareProperty( "setFatal", m_thresholdProp[MSG::FATAL] );
00044 declareProperty( "setAlways", m_thresholdProp[MSG::ALWAYS] );
00045
00046 declareProperty( "useColors", m_color=false);
00047 m_color.declareUpdateHandler(&MessageSvc::initColors, this);
00048
00049 declareProperty( "fatalColorCode", m_logColors[MSG::FATAL] );
00050 declareProperty( "errorColorCode", m_logColors[MSG::ERROR] );
00051 declareProperty( "warningColorCode", m_logColors[MSG::WARNING] );
00052 declareProperty( "infoColorCode", m_logColors[MSG::INFO] );
00053 declareProperty( "debugColorCode", m_logColors[MSG::DEBUG] );
00054 declareProperty( "verboseColorCode", m_logColors[MSG::VERBOSE] );
00055 declareProperty( "alwaysColorCode", m_logColors[MSG::ALWAYS] );
00056
00057 const int defaultLimit = 500;
00058 declareProperty( "fatalLimit", m_msgLimit[MSG::FATAL] = defaultLimit );
00059 declareProperty( "errorLimit", m_msgLimit[MSG::ERROR] = defaultLimit );
00060 declareProperty( "warningLimit", m_msgLimit[MSG::WARNING] = defaultLimit );
00061 declareProperty( "infoLimit", m_msgLimit[MSG::INFO] = defaultLimit );
00062 declareProperty( "debugLimit", m_msgLimit[MSG::DEBUG] = defaultLimit );
00063 declareProperty( "verboseLimit", m_msgLimit[MSG::VERBOSE] = defaultLimit );
00064 declareProperty( "alwaysLimit", m_msgLimit[MSG::ALWAYS] = 0 );
00065
00066 declareProperty( "defaultLimit", m_msgLimit[MSG::NIL] = defaultLimit );
00067
00068 declareProperty( "enableSuppression", m_suppress = false );
00069
00070 declareProperty( "loggedStreams",
00071 m_loggedStreamsName,
00072 "MessageStream sources we want to dump into a logfile" );
00073
00074 for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
00075 m_logColors[ic].declareUpdateHandler(&MessageSvc::setupColors, this);
00076 m_msgLimit[ic].declareUpdateHandler(&MessageSvc::setupLimits, this);
00077 m_thresholdProp[ic].declareUpdateHandler(&MessageSvc::setupThreshold, this);
00078 }
00079
00080 levelNames[0] = "NIL";
00081 levelNames[1] = "VERBOSE";
00082 levelNames[2] = "DEBUG";
00083 levelNames[3] = "INFO";
00084 levelNames[4] = "WARNING";
00085 levelNames[5] = "ERROR";
00086 levelNames[6] = "FATAL";
00087 levelNames[7] = "ALWAYS";
00088
00089 for (int i=0; i<MSG::NUM_LEVELS; ++i) {
00090 m_msgCount[i] = 0;
00091 }
00092
00093 }
00094
00095
00096
00097 MessageSvc::~MessageSvc()
00098 {
00099
00100 LoggedStreamsMap_t::iterator iStream = m_loggedStreams.begin();
00101 LoggedStreamsMap_t::iterator endStream = m_loggedStreams.end();
00102 for ( ; iStream != endStream; ++iStream ) {
00103 delete iStream->second;
00104 iStream->second = 0;
00105 }
00106 }
00107
00108
00109
00111 StatusCode MessageSvc::initialize() {
00112 StatusCode sc;
00113 sc = Service::initialize();
00114 if( sc.isFailure() ) return sc;
00115
00116
00117
00118
00119
00120 sc = setProperties();
00121 if (sc.isFailure()) return sc;
00122
00123 #ifdef _WIN32
00124 m_color = false;
00125 #endif
00126
00127 m_colMap["black"] = MSG::BLACK;
00128 m_colMap["red"] = MSG::RED;
00129 m_colMap["green"] = MSG::GREEN;
00130 m_colMap["yellow"] = MSG::YELLOW;
00131 m_colMap["blue"] = MSG::BLUE;
00132 m_colMap["purple"] = MSG::PURPLE;
00133 m_colMap["cyan"] = MSG::CYAN;
00134 m_colMap["white"] = MSG::WHITE;
00135
00136
00137 setupLogStreams();
00138
00139 return StatusCode::SUCCESS;
00140 }
00141
00142
00143
00145 StatusCode MessageSvc::reinitialize() {
00146 m_state = Gaudi::StateMachine::OFFLINE;
00147 return initialize();
00148 }
00149
00150
00151
00152 void MessageSvc::initColors(Property& ) {
00153
00154 if (m_color == true) {
00155
00156 if (m_logColors[MSG::FATAL].value().size() == 0) {
00157 vector<string> fatDef;
00158 fatDef.push_back( "[94;101;1m" );
00159 m_logColors[MSG::FATAL].set( fatDef );
00160 } else {
00161 MessageSvc::setupColors( m_logColors[MSG::FATAL] );
00162 }
00163
00164 if (m_logColors[MSG::ERROR].value().size() == 0) {
00165 vector<string> errDef;
00166 errDef.push_back( "[97;101;1m" );
00167 m_logColors[MSG::ERROR].set( errDef );
00168 } else {
00169 MessageSvc::setupColors( m_logColors[MSG::ERROR] );
00170 }
00171
00172 if (m_logColors[MSG::WARNING].value().size() == 0) {
00173 vector<string> warDef;
00174 warDef.push_back( "[93;1m" );
00175 m_logColors[MSG::WARNING].set( warDef );
00176 } else {
00177 MessageSvc::setupColors( m_logColors[MSG::WARNING] );
00178 }
00179
00180 } else {
00181
00182
00183 for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
00184 vector<string> def;
00185 m_logColors[ic].set( def );
00186 }
00187
00188 }
00189
00190 }
00191
00192
00193
00194 void MessageSvc::setupColors(Property& prop) {
00195
00196 if (! m_color) return;
00197
00198 int ic;
00199 if (prop.name() == "fatalColorCode") {
00200 ic = MSG::FATAL;
00201 } else if (prop.name() == "errorColorCode") {
00202 ic = MSG::ERROR;
00203 } else if (prop.name() == "warningColorCode") {
00204 ic = MSG::WARNING;
00205 } else if (prop.name() == "infoColorCode") {
00206 ic = MSG::INFO;
00207 } else if (prop.name() == "debugColorCode") {
00208 ic = MSG::DEBUG;
00209 } else if (prop.name() == "verboseColorCode") {
00210 ic = MSG::VERBOSE;
00211 } else if (prop.name() == "alwaysColorCode") {
00212 ic = MSG::ALWAYS;
00213 } else {
00214 cout << "ERROR: Unknown message color parameter: " << prop.name()
00215 << endl;
00216 return;
00217 }
00218
00219 string code;
00220 vector<string>::const_iterator itr;
00221 itr = m_logColors[ic].value().begin();
00222
00223 if ( m_logColors[ic].value().size() == 1 ) {
00224
00225 if (*itr == "") {
00226 code = "";
00227 } else if (itr->substr(0,1) == "[") {
00228 code = "\033" + *itr;
00229 } else {
00230 code = "\033[" + colTrans(*itr, 90) + ";1m";
00231 }
00232
00233 } else if (m_logColors[ic].value().size() == 2) {
00234 vector<string>::const_iterator itr2 = itr + 1;
00235
00236 code = "\033[" + colTrans(*itr, 90) + ";"
00237 + colTrans(*itr2, 100) + ";1m";
00238
00239 }
00240
00241 m_logColorCodes[ic] = code;
00242
00243 }
00244
00245
00246 void MessageSvc::setupLimits(Property& prop) {
00247
00248 int ic = 0;
00249 if (prop.name() == "fatalLimit") {
00250 ic = MSG::FATAL;
00251 } else if (prop.name() == "errorLimit") {
00252 ic = MSG::ERROR;
00253 } else if (prop.name() == "warningLimit") {
00254 ic = MSG::WARNING;
00255 } else if (prop.name() == "infoLimit") {
00256 ic = MSG::INFO;
00257 } else if (prop.name() == "debugLimit") {
00258 ic = MSG::DEBUG;
00259 } else if (prop.name() == "verboseLimit") {
00260 ic = MSG::VERBOSE;
00261 } else if (prop.name() == "alwaysLimit") {
00262 IntegerProperty *p = dynamic_cast<IntegerProperty*>(&prop);
00263 if (p && p->value() != 0) {
00264 cout << "MessageSvc ERROR: cannot suppress ALWAYS messages" << endl;
00265 p->setValue(0);
00266 }
00267 ic = MSG::ALWAYS;
00268 } else if (prop.name() == "defaultLimit") {
00269 for (int i = MSG::VERBOSE; i< MSG::NUM_LEVELS; ++i) {
00270 if (i != MSG::ALWAYS) {
00271 m_msgLimit[i] = m_msgLimit[MSG::NIL].value();
00272 }
00273 }
00274 } else {
00275 cout << "MessageSvc ERROR: Unknown message limit parameter: "
00276 << prop.name() << endl;
00277 return;
00278 }
00279
00280 }
00281
00282
00283 void MessageSvc::setupThreshold(Property& prop) {
00284
00285 int ic = 0;
00286 if (prop.name() == "setFatal") {
00287 ic = MSG::FATAL;
00288 } else if (prop.name() == "setError") {
00289 ic = MSG::ERROR;
00290 } else if (prop.name() == "setWarning") {
00291 ic = MSG::WARNING;
00292 } else if (prop.name() == "setInfo") {
00293 ic = MSG::INFO;
00294 } else if (prop.name() == "setDebug") {
00295 ic = MSG::DEBUG;
00296 } else if (prop.name() == "setVerbose") {
00297 ic = MSG::VERBOSE;
00298 } else if (prop.name() == "setAlways") {
00299 ic = MSG::ALWAYS;
00300 } else {
00301 cerr << "MessageSvc ERROR: Unknown message threshold parameter: "
00302 << prop.name() << endl;
00303 return;
00304 }
00305
00306 StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop);
00307 if (sap == 0) {
00308 std::cerr << "could not dcast " << prop.name()
00309 << " to a StringArrayProperty (which it should be!)" << endl;
00310 return;
00311 } else {
00312 std::vector<std::string>::const_iterator itr;
00313 for ( itr = sap->value().begin();
00314 itr != sap->value().end();
00315 ++itr) {
00316 setOutputLevel( *itr, ic );
00317 }
00318 }
00319
00320 }
00321
00323 StatusCode MessageSvc::finalize() {
00324
00325 m_suppress = false;
00326
00327 std::ostringstream os;
00328
00329 if (m_stats) {
00330 os << "Summarizing all message counts" << endl;
00331 } else {
00332 os << "Listing sources of suppressed message: " << endl;
00333 }
00334
00335 os << "=====================================================" << endl;
00336 os << " Message Source | Level | Count" << endl;
00337 os << "-----------------------------+---------+-------------" << endl;
00338
00339
00340 bool found(false);
00341
00342 std::map<std::string,MsgAry>::const_iterator itr;
00343 for (itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) {
00344 for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
00345 if ( (itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
00346 (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value()) ) {
00347 os << " ";
00348 os.width(28);
00349 os.setf(ios_base::left,ios_base::adjustfield);
00350 os << itr->first;
00351
00352 os << "|";
00353
00354 os.width(8);
00355 os.setf(ios_base::right,ios_base::adjustfield);
00356 os << levelNames[ic];
00357
00358 os << " |";
00359
00360 os.width(9);
00361 os << itr->second.msg[ic];
00362
00363 os << endl;
00364
00365 found = true;
00366 }
00367 }
00368 }
00369 os << "=====================================================" << endl;
00370
00371 if (found || m_stats) {
00372 cout << os.str();
00373 }
00374
00375 return StatusCode::SUCCESS;
00376 }
00377
00378
00379 std::string MessageSvc::colTrans(std::string col, int offset) {
00380 ColorMap::const_iterator itr = m_colMap.find(col);
00381 int icol;
00382 if (itr != m_colMap.end()) {
00383 icol = offset + itr->second;
00384 } else {
00385 icol = offset + 8;
00386 }
00387 std::ostringstream os1;
00388
00389 os1 << icol;
00390
00391 return os1.str();
00392
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402 void MessageSvc::reportMessage( const Message& msg, int outputLevel ) {
00403 boost::recursive_mutex::scoped_lock lock(m_reportMutex);
00404
00405 int key = msg.getType();
00406
00407 m_msgCount[key] ++;
00408
00409 const Message *cmsg = &msg;
00410
00411
00412 if ( !m_loggedStreams.empty() ) {
00413 const LoggedStreamsMap_t::iterator iLog = m_loggedStreams.find( msg.getSource() );
00414 if ( m_loggedStreams.end() != iLog ) {
00415 (*iLog->second) << *cmsg << std::endl;
00416 }
00417 }
00418
00419 if ( m_suppress.value() || m_stats.value() ) {
00420
00421
00422
00423 const int nmsg = ++(m_sourceMap[msg.getSource()].msg[key]);
00424
00425 if (m_suppress.value()) {
00426
00427 if ( m_msgLimit[key] != 0 ) {
00428 if (nmsg == m_msgLimit[key]) {
00429 char lim[16];
00430 std::string str = levelNames[key] + " message limit (";
00431 str += ::_itoa(m_msgLimit[key].value(),lim,10);
00432 str += ") reached for ";
00433 str += msg.getSource() + ". Suppressing further output.";
00434 cmsg = new Message(msg.getSource(),MSG::WARNING,str);
00435 cmsg->setFormat(msg.getFormat());
00436 } else if (nmsg > m_msgLimit[key]) {
00437 return;
00438 }
00439 }
00440 }
00441
00442 }
00443
00444 StreamMap::const_iterator first = m_streamMap.lower_bound( key );
00445 if ( first != m_streamMap.end() ) {
00446 StreamMap::const_iterator last = m_streamMap.upper_bound( key );
00447 while( first != last ) {
00448 std::ostream& stream = *( (*first).second.second );
00449 stream << *cmsg << std::endl;
00450 first++;
00451 }
00452 }
00453 else if ( key >= outputLevel ) {
00454 msg.setFormat(m_defaultFormat);
00455 msg.setTimeFormat(m_defaultTimeFormat);
00456 if (!m_color) {
00457 (*m_defaultStream) << *cmsg << std::endl << std::flush;
00458 } else {
00459 (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
00460 << std::endl << std::flush;
00461 }
00462 }
00463
00464 if (cmsg != &msg) { delete cmsg; }
00465
00466 }
00467
00468
00469
00470
00471
00472
00473
00474 void MessageSvc::reportMessage( const Message& msg ) {
00475 reportMessage(msg, outputLevel(msg.getSource()));
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 void MessageSvc::reportMessage (const char* source,
00485 int type,
00486 const char* message) {
00487 Message msg( source, type, message);
00488 reportMessage( msg );
00489 }
00490
00491
00492
00493
00494
00495
00496
00497 void MessageSvc::reportMessage (const std::string& source,
00498 int type,
00499 const std::string& message) {
00500 Message msg( source, type, message);
00501 reportMessage( msg );
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511 void MessageSvc::reportMessage (const StatusCode& key,
00512 const std::string& source)
00513 {
00514 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00515
00516 MessageMap::const_iterator first = m_messageMap.lower_bound( key );
00517 if ( first != m_messageMap.end() ) {
00518 MessageMap::const_iterator last = m_messageMap.upper_bound( key );
00519 while( first != last ) {
00520 Message msg = (*first).second;
00521 msg.setSource( source );
00522 std::ostringstream os1;
00523 os1 << "Status Code " << key.getCode() << std::ends;
00524 Message stat_code1( source, msg.getType(), os1.str() );
00525 reportMessage( stat_code1 );
00526 reportMessage( msg );
00527 first++;
00528 }
00529 }
00530 else {
00531 Message mesg = m_defaultMessage;
00532 mesg.setSource( source );
00533 std::ostringstream os2;
00534 os2 << "Status Code " << key.getCode() << std::ends;
00535 Message stat_code2( source, mesg.getType(), os2.str() );
00536 reportMessage( stat_code2 );
00537 reportMessage( mesg );
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548 void MessageSvc::insertStream (int key,
00549 const std::string& name,
00550 std::ostream *stream)
00551 {
00552 typedef StreamMap::value_type value_type;
00553 m_streamMap.insert( value_type( key, NamedStream(name,stream) ) );
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563 void MessageSvc::eraseStream()
00564 {
00565 m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() );
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575 void MessageSvc::eraseStream( int message_type )
00576 {
00577 m_streamMap.erase( message_type );
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587 void MessageSvc::eraseStream( int key, std::ostream* stream ) {
00588 if ( 0 != stream ) {
00589 bool changed = true;
00590 while( changed ) {
00591 changed = false;
00592 StreamMap::iterator first = m_streamMap.lower_bound( key );
00593 StreamMap::iterator last = m_streamMap.upper_bound( key );
00594 while( first != last ) {
00595 if ( (*first).second.second == stream ) {
00596 m_streamMap.erase( first );
00597 changed = true;
00598 break;
00599 }
00600 }
00601 }
00602 }
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612 void MessageSvc::eraseStream( std::ostream* stream ) {
00613 if ( 0 != stream ) {
00614 bool changed = true;
00615 while( changed ) {
00616 changed = false;
00617 StreamMap::iterator first = m_streamMap.begin();
00618 while( first != m_streamMap.end() ) {
00619 if ( (*first).second.second == stream ) {
00620 m_streamMap.erase( first );
00621 changed = true;
00622 break;
00623 }
00624 }
00625 }
00626 }
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 void MessageSvc::insertMessage( const StatusCode& key, const Message& msg )
00638 {
00639 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00640
00641 typedef MessageMap::value_type value_type;
00642 m_messageMap.insert( value_type( key, msg ) );
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652 void MessageSvc::eraseMessage()
00653 {
00654 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00655
00656 m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() );
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666 void MessageSvc::eraseMessage( const StatusCode& key )
00667 {
00668 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00669
00670 m_messageMap.erase( key );
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680 void MessageSvc::eraseMessage( const StatusCode& key, const Message& msg )
00681 {
00682 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00683
00684 bool changed = true;
00685 while( changed ) {
00686 changed = false;
00687 MessageMap::iterator first = m_messageMap.lower_bound( key );
00688 MessageMap::iterator last = m_messageMap.upper_bound( key );
00689 while( first != last ) {
00690 const Message& message = (*first).second;
00691 if ( message == msg ) {
00692 m_messageMap.erase( first );
00693 changed = true;
00694 break;
00695 }
00696 }
00697 }
00698 }
00699
00700
00701 int MessageSvc::outputLevel() const {
00702
00703 return m_outputLevel;
00704 }
00705
00706
00707 int MessageSvc::outputLevel( const std::string& source ) const {
00708
00709 boost::recursive_mutex::scoped_lock lock(m_thresholdMapMutex);
00710
00711 ThresholdMap::const_iterator it;
00712
00713 it = m_thresholdMap.find( source );
00714 if( it != m_thresholdMap.end() ) {
00715 return (*it).second;
00716 }
00717 else {
00718 return m_outputLevel;
00719 }
00720 }
00721
00722
00723 void MessageSvc::setOutputLevel(int new_level) {
00724
00725 m_outputLevel = new_level;
00726 }
00727
00728
00729 void MessageSvc::setOutputLevel(const std::string& source, int level) {
00730
00731 boost::recursive_mutex::scoped_lock lock(m_thresholdMapMutex);
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 m_thresholdMap[source] = level;
00743 }
00744
00745
00746 std::string MessageSvc::getLogColor(int logLevel) const {
00747
00748 if (logLevel < MSG::NUM_LEVELS) {
00749 return m_logColorCodes[logLevel];
00750 } else {
00751 return "";
00752 }
00753 }
00754
00755
00756 int MessageSvc::messageCount( MSG::Level level) const {
00757
00758 return m_msgCount[level];
00759
00760 }
00761
00762
00763 void MessageSvc::setupLogStreams()
00764 {
00765
00766 for ( LoggedStreamsMap_t::iterator iLog = m_loggedStreams.begin();
00767 iLog != m_loggedStreams.end();
00768 ++iLog ) {
00769 delete iLog->second;
00770 }
00771 m_loggedStreams.clear();
00772
00773 typedef std::map<std::string,std::string> StreamMap_t;
00774 const StreamMap_t& streamMap = m_loggedStreamsName;
00775 typedef StreamMap_t::const_iterator StreamMapIter;
00776
00777 for ( StreamMapIter iProp = streamMap.begin(), iEnd = streamMap.end();
00778 iProp != iEnd;
00779 ++iProp ) {
00780
00781 const std::string sourceName = iProp->first;
00782 const std::string outFileName = iProp->second;
00783
00784 std::set<std::string> outFileNames;
00785 for ( StreamMapIter jProp = streamMap.begin();
00786 jProp != iEnd;
00787 ++jProp ) {
00788 if ( jProp->first != iProp->first ) {
00789 outFileNames.insert( jProp->second );
00790 }
00791 }
00792
00793 tee( sourceName, outFileName, outFileNames );
00794
00795 }
00796
00797 return;
00798 }
00799
00800
00801 void MessageSvc::tee( const std::string& sourceName,
00802 const std::string& outFileName,
00803 const std::set<std::string>& outFileNames )
00804 {
00805 const std::ios_base::openmode openMode = std::ios_base::out |
00806 std::ios_base::trunc;
00807
00808 LoggedStreamsMap_t::iterator iEnd = m_loggedStreams.end();
00809 LoggedStreamsMap_t::iterator iStream = m_loggedStreams.find( sourceName );
00810 if ( iStream != iEnd ) {
00811 delete iStream->second;
00812 iStream->second = 0;
00813 m_loggedStreams.erase( iStream );
00814 }
00815
00816
00817
00818 iEnd = m_loggedStreams.end();
00819 for ( iStream = m_loggedStreams.begin(); iStream != iEnd; ++iStream ) {
00820 if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
00821 m_loggedStreams[sourceName] = m_loggedStreams[iStream->first];
00822 return;
00823 }
00824 }
00825
00826 std::ofstream * out = new std::ofstream( outFileName.c_str(), openMode );
00827
00828 if ( !out->good() ) {
00829 out->close();
00830 delete out;
00831 return;
00832 }
00833
00834 m_loggedStreams[sourceName] = out;
00835
00836 return;
00837 }
00838