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 if (prop.name() == "alwaysLimit") {
00249 IntegerProperty *p = dynamic_cast<IntegerProperty*>(&prop);
00250 if (p && p->value() != 0) {
00251 cout << "MessageSvc ERROR: cannot suppress ALWAYS messages" << endl;
00252 p->setValue(0);
00253 }
00254 } else if (prop.name() == "defaultLimit") {
00255 for (int i = MSG::VERBOSE; i< MSG::NUM_LEVELS; ++i) {
00256 if (i != MSG::ALWAYS) {
00257 m_msgLimit[i] = m_msgLimit[MSG::NIL].value();
00258 }
00259 }
00260 } else if (prop.name() != "fatalLimit" &&
00261 prop.name() != "errorLimit" &&
00262 prop.name() != "warningLimit" &&
00263 prop.name() == "infoLimit" &&
00264 prop.name() == "debugLimit" &&
00265 prop.name() == "verboseLimit") {
00266 cout << "MessageSvc ERROR: Unknown message limit parameter: "
00267 << prop.name() << endl;
00268 return;
00269 }
00270 }
00271
00272
00273 void MessageSvc::setupThreshold(Property& prop) {
00274
00275 int ic = 0;
00276 if (prop.name() == "setFatal") {
00277 ic = MSG::FATAL;
00278 } else if (prop.name() == "setError") {
00279 ic = MSG::ERROR;
00280 } else if (prop.name() == "setWarning") {
00281 ic = MSG::WARNING;
00282 } else if (prop.name() == "setInfo") {
00283 ic = MSG::INFO;
00284 } else if (prop.name() == "setDebug") {
00285 ic = MSG::DEBUG;
00286 } else if (prop.name() == "setVerbose") {
00287 ic = MSG::VERBOSE;
00288 } else if (prop.name() == "setAlways") {
00289 ic = MSG::ALWAYS;
00290 } else {
00291 cerr << "MessageSvc ERROR: Unknown message threshold parameter: "
00292 << prop.name() << endl;
00293 return;
00294 }
00295
00296 StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop);
00297 if (sap == 0) {
00298 std::cerr << "could not dcast " << prop.name()
00299 << " to a StringArrayProperty (which it should be!)" << endl;
00300 return;
00301 } else {
00302 std::vector<std::string>::const_iterator itr;
00303 for ( itr = sap->value().begin();
00304 itr != sap->value().end();
00305 ++itr) {
00306 setOutputLevel( *itr, ic );
00307 }
00308 }
00309
00310 }
00311
00313 StatusCode MessageSvc::finalize() {
00314
00315 m_suppress = false;
00316
00317 std::ostringstream os;
00318
00319 if (m_stats) {
00320 os << "Summarizing all message counts" << endl;
00321 } else {
00322 os << "Listing sources of suppressed message: " << endl;
00323 }
00324
00325 os << "=====================================================" << endl;
00326 os << " Message Source | Level | Count" << endl;
00327 os << "-----------------------------+---------+-------------" << endl;
00328
00329
00330 bool found(false);
00331
00332 std::map<std::string,MsgAry>::const_iterator itr;
00333 for (itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) {
00334 for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
00335 if ( (itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
00336 (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value()) ) {
00337 os << " ";
00338 os.width(28);
00339 os.setf(ios_base::left,ios_base::adjustfield);
00340 os << itr->first;
00341
00342 os << "|";
00343
00344 os.width(8);
00345 os.setf(ios_base::right,ios_base::adjustfield);
00346 os << levelNames[ic];
00347
00348 os << " |";
00349
00350 os.width(9);
00351 os << itr->second.msg[ic];
00352
00353 os << endl;
00354
00355 found = true;
00356 }
00357 }
00358 }
00359 os << "=====================================================" << endl;
00360
00361 if (found || m_stats) {
00362 cout << os.str();
00363 }
00364
00365 return StatusCode::SUCCESS;
00366 }
00367
00368
00369 std::string MessageSvc::colTrans(std::string col, int offset) {
00370 ColorMap::const_iterator itr = m_colMap.find(col);
00371 int icol;
00372 if (itr != m_colMap.end()) {
00373 icol = offset + itr->second;
00374 } else {
00375 icol = offset + 8;
00376 }
00377 std::ostringstream os1;
00378
00379 os1 << icol;
00380
00381 return os1.str();
00382
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 void MessageSvc::reportMessage( const Message& msg, int outputLevel ) {
00393 boost::recursive_mutex::scoped_lock lock(m_reportMutex);
00394
00395 int key = msg.getType();
00396
00397 m_msgCount[key] ++;
00398
00399 const Message *cmsg = &msg;
00400
00401
00402 if ( !m_loggedStreams.empty() ) {
00403 const LoggedStreamsMap_t::iterator iLog = m_loggedStreams.find( msg.getSource() );
00404 if ( m_loggedStreams.end() != iLog ) {
00405 (*iLog->second) << *cmsg << std::endl;
00406 }
00407 }
00408
00409 if ( m_suppress.value() || m_stats.value() ) {
00410
00411
00412
00413 const int nmsg = ++(m_sourceMap[msg.getSource()].msg[key]);
00414
00415 if (m_suppress.value()) {
00416
00417 if ( m_msgLimit[key] != 0 ) {
00418 if (nmsg == m_msgLimit[key]) {
00419 char lim[16];
00420 std::string str = levelNames[key] + " message limit (";
00421 str += ::_itoa(m_msgLimit[key].value(),lim,10);
00422 str += ") reached for ";
00423 str += msg.getSource() + ". Suppressing further output.";
00424 cmsg = new Message(msg.getSource(),MSG::WARNING,str);
00425 cmsg->setFormat(msg.getFormat());
00426 } else if (nmsg > m_msgLimit[key]) {
00427 return;
00428 }
00429 }
00430 }
00431
00432 }
00433
00434 StreamMap::const_iterator first = m_streamMap.lower_bound( key );
00435 if ( first != m_streamMap.end() ) {
00436 StreamMap::const_iterator last = m_streamMap.upper_bound( key );
00437 while( first != last ) {
00438 std::ostream& stream = *( (*first).second.second );
00439 stream << *cmsg << std::endl;
00440 first++;
00441 }
00442 }
00443 else if ( key >= outputLevel ) {
00444 msg.setFormat(m_defaultFormat);
00445 msg.setTimeFormat(m_defaultTimeFormat);
00446 if (!m_color) {
00447 (*m_defaultStream) << *cmsg << std::endl << std::flush;
00448 } else {
00449 (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
00450 << std::endl << std::flush;
00451 }
00452 }
00453
00454 if (cmsg != &msg) { delete cmsg; }
00455
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 void MessageSvc::reportMessage( const Message& msg ) {
00465 reportMessage(msg, outputLevel(msg.getSource()));
00466 }
00467
00468
00469
00470
00471
00472
00473
00474 void MessageSvc::reportMessage (const char* source,
00475 int type,
00476 const char* message) {
00477 Message msg( source, type, message);
00478 reportMessage( msg );
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 void MessageSvc::reportMessage (const std::string& source,
00488 int type,
00489 const std::string& message) {
00490 Message msg( source, type, message);
00491 reportMessage( msg );
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501 void MessageSvc::reportMessage (const StatusCode& key,
00502 const std::string& source)
00503 {
00504 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00505
00506 MessageMap::const_iterator first = m_messageMap.lower_bound( key );
00507 if ( first != m_messageMap.end() ) {
00508 MessageMap::const_iterator last = m_messageMap.upper_bound( key );
00509 while( first != last ) {
00510 Message msg = (*first).second;
00511 msg.setSource( source );
00512 std::ostringstream os1;
00513 os1 << "Status Code " << key.getCode() << std::ends;
00514 Message stat_code1( source, msg.getType(), os1.str() );
00515 reportMessage( stat_code1 );
00516 reportMessage( msg );
00517 first++;
00518 }
00519 }
00520 else {
00521 Message mesg = m_defaultMessage;
00522 mesg.setSource( source );
00523 std::ostringstream os2;
00524 os2 << "Status Code " << key.getCode() << std::ends;
00525 Message stat_code2( source, mesg.getType(), os2.str() );
00526 reportMessage( stat_code2 );
00527 reportMessage( mesg );
00528 }
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538 void MessageSvc::insertStream (int key,
00539 const std::string& name,
00540 std::ostream *stream)
00541 {
00542 typedef StreamMap::value_type value_type;
00543 m_streamMap.insert( value_type( key, NamedStream(name,stream) ) );
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553 void MessageSvc::eraseStream()
00554 {
00555 m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() );
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565 void MessageSvc::eraseStream( int message_type )
00566 {
00567 m_streamMap.erase( message_type );
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577 void MessageSvc::eraseStream( int key, std::ostream* stream ) {
00578 if ( 0 != stream ) {
00579 bool changed = true;
00580 while( changed ) {
00581 changed = false;
00582 StreamMap::iterator first = m_streamMap.lower_bound( key );
00583 StreamMap::iterator last = m_streamMap.upper_bound( key );
00584 while( first != last ) {
00585 if ( (*first).second.second == stream ) {
00586 m_streamMap.erase( first );
00587 changed = true;
00588 break;
00589 }
00590 }
00591 }
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602 void MessageSvc::eraseStream( std::ostream* stream ) {
00603 if ( 0 != stream ) {
00604 bool changed = true;
00605 while( changed ) {
00606 changed = false;
00607 StreamMap::iterator first = m_streamMap.begin();
00608 while( first != m_streamMap.end() ) {
00609 if ( (*first).second.second == stream ) {
00610 m_streamMap.erase( first );
00611 changed = true;
00612 break;
00613 }
00614 }
00615 }
00616 }
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 void MessageSvc::insertMessage( const StatusCode& key, const Message& msg )
00628 {
00629 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00630
00631 typedef MessageMap::value_type value_type;
00632 m_messageMap.insert( value_type( key, msg ) );
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642 void MessageSvc::eraseMessage()
00643 {
00644 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00645
00646 m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() );
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656 void MessageSvc::eraseMessage( const StatusCode& key )
00657 {
00658 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00659
00660 m_messageMap.erase( key );
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670 void MessageSvc::eraseMessage( const StatusCode& key, const Message& msg )
00671 {
00672 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00673
00674 bool changed = true;
00675 while( changed ) {
00676 changed = false;
00677 MessageMap::iterator first = m_messageMap.lower_bound( key );
00678 MessageMap::iterator last = m_messageMap.upper_bound( key );
00679 while( first != last ) {
00680 const Message& message = (*first).second;
00681 if ( message == msg ) {
00682 m_messageMap.erase( first );
00683 changed = true;
00684 break;
00685 }
00686 }
00687 }
00688 }
00689
00690
00691 int MessageSvc::outputLevel() const {
00692
00693 return m_outputLevel;
00694 }
00695
00696
00697 int MessageSvc::outputLevel( const std::string& source ) const {
00698
00699 boost::recursive_mutex::scoped_lock lock(m_thresholdMapMutex);
00700
00701 ThresholdMap::const_iterator it;
00702
00703 it = m_thresholdMap.find( source );
00704 if( it != m_thresholdMap.end() ) {
00705 return (*it).second;
00706 }
00707 else {
00708 return m_outputLevel;
00709 }
00710 }
00711
00712
00713 void MessageSvc::setOutputLevel(int new_level) {
00714
00715 m_outputLevel = new_level;
00716 }
00717
00718
00719 void MessageSvc::setOutputLevel(const std::string& source, int level) {
00720
00721 boost::recursive_mutex::scoped_lock lock(m_thresholdMapMutex);
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 m_thresholdMap[source] = level;
00733 }
00734
00735
00736 std::string MessageSvc::getLogColor(int logLevel) const {
00737
00738 if (logLevel < MSG::NUM_LEVELS) {
00739 return m_logColorCodes[logLevel];
00740 } else {
00741 return "";
00742 }
00743 }
00744
00745
00746 int MessageSvc::messageCount( MSG::Level level) const {
00747
00748 return m_msgCount[level];
00749
00750 }
00751
00752
00753 void MessageSvc::setupLogStreams()
00754 {
00755
00756 for ( LoggedStreamsMap_t::iterator iLog = m_loggedStreams.begin();
00757 iLog != m_loggedStreams.end();
00758 ++iLog ) {
00759 delete iLog->second;
00760 }
00761 m_loggedStreams.clear();
00762
00763 typedef std::map<std::string,std::string> StreamMap_t;
00764 const StreamMap_t& streamMap = m_loggedStreamsName;
00765 typedef StreamMap_t::const_iterator StreamMapIter;
00766
00767 for ( StreamMapIter iProp = streamMap.begin(), iEnd = streamMap.end();
00768 iProp != iEnd;
00769 ++iProp ) {
00770
00771 const std::string sourceName = iProp->first;
00772 const std::string outFileName = iProp->second;
00773
00774 std::set<std::string> outFileNames;
00775 for ( StreamMapIter jProp = streamMap.begin();
00776 jProp != iEnd;
00777 ++jProp ) {
00778 if ( jProp->first != iProp->first ) {
00779 outFileNames.insert( jProp->second );
00780 }
00781 }
00782
00783 tee( sourceName, outFileName, outFileNames );
00784
00785 }
00786
00787 return;
00788 }
00789
00790
00791 void MessageSvc::tee( const std::string& sourceName,
00792 const std::string& outFileName,
00793 const std::set<std::string>& outFileNames )
00794 {
00795 const std::ios_base::openmode openMode = std::ios_base::out |
00796 std::ios_base::trunc;
00797
00798 LoggedStreamsMap_t::iterator iEnd = m_loggedStreams.end();
00799 LoggedStreamsMap_t::iterator iStream = m_loggedStreams.find( sourceName );
00800 if ( iStream != iEnd ) {
00801 delete iStream->second;
00802 iStream->second = 0;
00803 m_loggedStreams.erase( iStream );
00804 }
00805
00806
00807
00808 iEnd = m_loggedStreams.end();
00809 for ( iStream = m_loggedStreams.begin(); iStream != iEnd; ++iStream ) {
00810 if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
00811 m_loggedStreams[sourceName] = m_loggedStreams[iStream->first];
00812 return;
00813 }
00814 }
00815
00816 std::ofstream * out = new std::ofstream( outFileName.c_str(), openMode );
00817
00818 if ( !out->good() ) {
00819 out->close();
00820 delete out;
00821 return;
00822 }
00823
00824 m_loggedStreams[sourceName] = out;
00825
00826 return;
00827 }
00828