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 int nmsg;
00407
00408 m_msgCount[key] ++;
00409
00410 const Message *cmsg = &msg;
00411
00412
00413 if ( !m_loggedStreams.empty() ) {
00414 const LoggedStreamsMap_t::iterator iLog = m_loggedStreams.find( msg.getSource() );
00415 if ( m_loggedStreams.end() != iLog ) {
00416 (*iLog->second) << *cmsg << std::endl;
00417 }
00418 }
00419
00420 if ( m_suppress.value() || m_stats.value() ) {
00421
00422 std::map<std::string,msgAry>::iterator itr =
00423 m_sourceMap.find(msg.getSource());
00424 if (itr != m_sourceMap.end()) {
00425 itr->second.msg[key] += 1;
00426 nmsg = itr->second.msg[key];
00427 } else {
00428 msgAry A;
00429 for (int i=0; i<MSG::NUM_LEVELS; ++i) {
00430 A.msg[i] = 0;
00431 }
00432 A.msg[key] = 1;
00433 m_sourceMap[msg.getSource()] = A;
00434 nmsg = 1;
00435 }
00436
00437 if (m_suppress.value()) {
00438
00439 if ( m_msgLimit[key] != 0 ) {
00440 if (nmsg == m_msgLimit[key]) {
00441 char lim[16];
00442 std::string str = levelNames[key] + " message limit (";
00443 str += ::_itoa(m_msgLimit[key].value(),lim,10);
00444 str += ") reached for ";
00445 str += msg.getSource() + ". Suppressing further output.";
00446 cmsg = new Message(msg.getSource(),MSG::WARNING,str);
00447 cmsg->setFormat(msg.getFormat());
00448 } else if (nmsg > m_msgLimit[key]) {
00449 return;
00450 }
00451 }
00452 }
00453
00454 }
00455
00456 StreamMap::const_iterator first = m_streamMap.lower_bound( key );
00457 if ( first != m_streamMap.end() ) {
00458 StreamMap::const_iterator last = m_streamMap.upper_bound( key );
00459 while( first != last ) {
00460 std::ostream& stream = *( (*first).second.second );
00461 stream << *cmsg << std::endl;
00462 first++;
00463 }
00464 }
00465 else if ( key >= outputLevel ) {
00466 msg.setFormat(m_defaultFormat);
00467 msg.setTimeFormat(m_defaultTimeFormat);
00468 if (!m_color) {
00469 (*m_defaultStream) << *cmsg << std::endl << std::flush;
00470 } else {
00471 (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
00472 << std::endl << std::flush;
00473 }
00474 }
00475
00476 if (cmsg != &msg) { delete cmsg; }
00477
00478 }
00479
00480
00481
00482
00483
00484
00485
00486 void MessageSvc::reportMessage( const Message& msg ) {
00487 reportMessage(msg, outputLevel(msg.getSource()));
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 void MessageSvc::reportMessage (const char* source,
00497 int type,
00498 const char* message) {
00499 Message msg( source, type, message);
00500 reportMessage( msg );
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 void MessageSvc::reportMessage (const std::string& source,
00510 int type,
00511 const std::string& message) {
00512 Message msg( source, type, message);
00513 reportMessage( msg );
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523 void MessageSvc::reportMessage (const StatusCode& key,
00524 const std::string& source)
00525 {
00526 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00527
00528 MessageMap::const_iterator first = m_messageMap.lower_bound( key );
00529 if ( first != m_messageMap.end() ) {
00530 MessageMap::const_iterator last = m_messageMap.upper_bound( key );
00531 while( first != last ) {
00532 Message msg = (*first).second;
00533 msg.setSource( source );
00534 std::ostringstream os1;
00535 os1 << "Status Code " << key.getCode() << std::ends;
00536 Message stat_code1( source, msg.getType(), os1.str() );
00537 reportMessage( stat_code1 );
00538 reportMessage( msg );
00539 first++;
00540 }
00541 }
00542 else {
00543 Message mesg = m_defaultMessage;
00544 mesg.setSource( source );
00545 std::ostringstream os2;
00546 os2 << "Status Code " << key.getCode() << std::ends;
00547 Message stat_code2( source, mesg.getType(), os2.str() );
00548 reportMessage( stat_code2 );
00549 reportMessage( mesg );
00550 }
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560 void MessageSvc::insertStream (int key,
00561 const std::string& name,
00562 std::ostream *stream)
00563 {
00564 typedef StreamMap::value_type value_type;
00565 m_streamMap.insert( value_type( key, NamedStream(name,stream) ) );
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575 void MessageSvc::eraseStream()
00576 {
00577 m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() );
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587 void MessageSvc::eraseStream( int message_type )
00588 {
00589 m_streamMap.erase( message_type );
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599 void MessageSvc::eraseStream( int key, std::ostream* stream ) {
00600 if ( 0 != stream ) {
00601 bool changed = true;
00602 while( changed ) {
00603 changed = false;
00604 StreamMap::iterator first = m_streamMap.lower_bound( key );
00605 StreamMap::iterator last = m_streamMap.upper_bound( key );
00606 while( first != last ) {
00607 if ( (*first).second.second == stream ) {
00608 m_streamMap.erase( first );
00609 changed = true;
00610 break;
00611 }
00612 }
00613 }
00614 }
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624 void MessageSvc::eraseStream( std::ostream* stream ) {
00625 if ( 0 != stream ) {
00626 bool changed = true;
00627 while( changed ) {
00628 changed = false;
00629 StreamMap::iterator first = m_streamMap.begin();
00630 while( first != m_streamMap.end() ) {
00631 if ( (*first).second.second == stream ) {
00632 m_streamMap.erase( first );
00633 changed = true;
00634 break;
00635 }
00636 }
00637 }
00638 }
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 void MessageSvc::insertMessage( const StatusCode& key, const Message& msg )
00650 {
00651 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00652
00653 typedef MessageMap::value_type value_type;
00654 m_messageMap.insert( value_type( key, msg ) );
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664 void MessageSvc::eraseMessage()
00665 {
00666 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00667
00668 m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() );
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678 void MessageSvc::eraseMessage( const StatusCode& key )
00679 {
00680 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00681
00682 m_messageMap.erase( key );
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692 void MessageSvc::eraseMessage( const StatusCode& key, const Message& msg )
00693 {
00694 boost::recursive_mutex::scoped_lock lock(m_messageMapMutex);
00695
00696 bool changed = true;
00697 while( changed ) {
00698 changed = false;
00699 MessageMap::iterator first = m_messageMap.lower_bound( key );
00700 MessageMap::iterator last = m_messageMap.upper_bound( key );
00701 while( first != last ) {
00702 const Message& message = (*first).second;
00703 if ( message == msg ) {
00704 m_messageMap.erase( first );
00705 changed = true;
00706 break;
00707 }
00708 }
00709 }
00710 }
00711
00712
00713 int MessageSvc::outputLevel() const {
00714
00715 return m_outputLevel;
00716 }
00717
00718
00719 int MessageSvc::outputLevel( const std::string& source ) const {
00720
00721 boost::recursive_mutex::scoped_lock lock(m_thresholdMapMutex);
00722
00723 ThresholdMap::const_iterator it;
00724
00725 it = m_thresholdMap.find( source );
00726 if( it != m_thresholdMap.end() ) {
00727 return (*it).second;
00728 }
00729 else {
00730 return m_outputLevel;
00731 }
00732 }
00733
00734
00735 void MessageSvc::setOutputLevel(int new_level) {
00736
00737 m_outputLevel = new_level;
00738 }
00739
00740
00741 void MessageSvc::setOutputLevel(const std::string& source, int level) {
00742
00743 boost::recursive_mutex::scoped_lock lock(m_thresholdMapMutex);
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 m_thresholdMap[source] = level;
00755 }
00756
00757
00758 std::string MessageSvc::getLogColor(int logLevel) const {
00759
00760 if (logLevel < MSG::NUM_LEVELS) {
00761 return m_logColorCodes[logLevel];
00762 } else {
00763 return "";
00764 }
00765 }
00766
00767
00768 int MessageSvc::messageCount( MSG::Level level) const {
00769
00770 return m_msgCount[level];
00771
00772 }
00773
00774
00775 void MessageSvc::setupLogStreams()
00776 {
00777
00778 for ( LoggedStreamsMap_t::iterator iLog = m_loggedStreams.begin();
00779 iLog != m_loggedStreams.end();
00780 ++iLog ) {
00781 delete iLog->second;
00782 }
00783 m_loggedStreams.clear();
00784
00785 typedef std::map<std::string,std::string> StreamMap_t;
00786 const StreamMap_t& streamMap = m_loggedStreamsName;
00787 typedef StreamMap_t::const_iterator StreamMapIter;
00788
00789 for ( StreamMapIter iProp = streamMap.begin(), iEnd = streamMap.end();
00790 iProp != iEnd;
00791 ++iProp ) {
00792
00793 const std::string sourceName = iProp->first;
00794 const std::string outFileName = iProp->second;
00795
00796 std::set<std::string> outFileNames;
00797 for ( StreamMapIter jProp = streamMap.begin();
00798 jProp != iEnd;
00799 ++jProp ) {
00800 if ( jProp->first != iProp->first ) {
00801 outFileNames.insert( jProp->second );
00802 }
00803 }
00804
00805 tee( sourceName, outFileName, outFileNames );
00806
00807 }
00808
00809 return;
00810 }
00811
00812
00813 void MessageSvc::tee( const std::string& sourceName,
00814 const std::string& outFileName,
00815 const std::set<std::string>& outFileNames )
00816 {
00817 const std::ios_base::openmode openMode = std::ios_base::out |
00818 std::ios_base::trunc;
00819
00820 LoggedStreamsMap_t::iterator iEnd = m_loggedStreams.end();
00821 LoggedStreamsMap_t::iterator iStream = m_loggedStreams.find( sourceName );
00822 if ( iStream != iEnd ) {
00823 delete iStream->second;
00824 iStream->second = 0;
00825 m_loggedStreams.erase( iStream );
00826 }
00827
00828
00829
00830 iEnd = m_loggedStreams.end();
00831 for ( iStream = m_loggedStreams.begin(); iStream != iEnd; ++iStream ) {
00832 if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
00833 m_loggedStreams[sourceName] = m_loggedStreams[iStream->first];
00834 return;
00835 }
00836 }
00837
00838 std::ofstream * out = new std::ofstream( outFileName.c_str(), openMode );
00839
00840 if ( !out->good() ) {
00841 out->close();
00842 delete out;
00843 return;
00844 }
00845
00846 m_loggedStreams[sourceName] = out;
00847
00848 return;
00849 }
00850