MOOS 0.2375
|
00001 00002 // 00003 // MOOS - Mission Oriented Operating Suite 00004 // 00005 // A suit of Applications and Libraries for Mobile Robotics Research 00006 // Copyright (C) 2001-2005 Massachusetts Institute of Technology and 00007 // Oxford University. 00008 // 00009 // This software was written by Paul Newman at MIT 2001-2002 and Oxford 00010 // University 2003-2005. email: pnewman@robots.ox.ac.uk. 00011 // 00012 // This file is part of a MOOS Core Component. 00013 // 00014 // This program is free software; you can redistribute it and/or 00015 // modify it under the terms of the GNU General Public License as 00016 // published by the Free Software Foundation; either version 2 of the 00017 // License, or (at your option) any later version. 00018 // 00019 // This program is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00022 // General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with this program; if not, write to the Free Software 00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00027 // 02111-1307, USA. 00028 // 00030 // MOOSLogger.cpp: implementation of the CMOOSLogger class. 00031 // 00033 #ifdef _WIN32 00034 #pragma warning(disable : 4786) 00035 #endif 00036 00037 00038 #include <MOOSLIB/MOOSApp.h> 00039 #include <MOOSGenLib/MOOSGenLibGlobalHelper.h> 00040 #include <time.h> 00041 #include <iostream> 00042 #include <stdio.h> 00043 #include <iomanip> 00044 #include <algorithm> 00045 #include <MOOSGenLib/MOOSAssert.h> 00046 #include <cmath> 00047 #include <cstring> 00048 00049 00050 #ifndef _WIN32 00051 #include <errno.h> 00052 #include <sys/stat.h> 00053 #include <sys/types.h> 00054 #include <signal.h> 00055 #endif 00056 00057 00058 using namespace std; 00059 #include "MOOSLogger.h" 00060 00061 //maximum of logged columns... 00062 #define MAX_SYNC_COLUMNS 255 00063 #define MOOS_LOGGER_DEFAULT_PERIOD 2.0 00064 #define COLUMN_WIDTH 18 00065 #define DEFAULT_MONITOR_TIME 10.0 00066 #define MIN_SYNC_LOG_PERIOD 0.1 00067 #define DYNAMIC_NAME_SPACE 64 00068 #define DEFAULT_WILDCARD_TIME 1.0 //how often to call into the DB to get a list of all variables if wild card loggin is turned on 00069 #define DEFAULT_DOUBLE_PRECISION 5 //how many DP to use when logging double time stamps 00070 00071 00072 00074 // Construction/Destruction 00076 00077 CMOOSLogger::CMOOSLogger() 00078 { 00079 00080 00081 //be default we don't need to be too fast.. 00082 SetAppFreq(5); 00083 00084 //if no file name is given log files will begin with "MOOS" 00085 m_sStemFileName = "MOOS"; 00086 00087 //by default make an a-log 00088 m_bAsynchronousLog = true; 00089 00090 //by default make an s-log 00091 m_bSynchronousLog = true; 00092 00093 //and log every second 00094 m_dfSyncLogPeriod = 1.0; 00095 00096 //start immediately 00097 m_dfLastSyncLogTime = 0; 00098 00099 //we have no immediate need to check monitored variables 00100 m_dfLastMonitorTime = MOOSTime(); 00101 00102 //no s-log lines written yet 00103 m_nSyncLines = 0; 00104 00105 //by default (if no mission file is specified) log to a local directory 00106 m_sPath = "./"; 00107 00108 //in a directory with the following stem 00109 m_sStemFileName = "MOOSLog"; 00110 00111 //and append a time ot the stem 00112 m_bAppendFileTimeStamp = true; 00113 00114 //by default use local time for directory names 00115 m_bUseUTCLogNames = false; 00116 00117 //by default we do not log aux src field 00118 m_bLogAuxSrc = false; 00119 00120 00121 //lets always sort mail by time... 00122 SortMailByTime(true); 00123 00124 } 00125 00126 CMOOSLogger::~CMOOSLogger() 00127 { 00128 ShutDown(); 00129 } 00130 00131 bool CMOOSLogger::ShutDown() 00132 { 00133 return CloseFiles(); 00134 } 00135 00136 00137 bool CMOOSLogger::CloseFiles() 00138 { 00139 if(m_AsyncLogFile.is_open()) 00140 { 00141 m_AsyncLogFile.close(); 00142 } 00143 00144 if(m_SyncLogFile.is_open()) 00145 { 00146 m_SyncLogFile.close(); 00147 } 00148 00149 if(m_SystemLogFile.is_open()) 00150 { 00151 m_SystemLogFile.close(); 00152 } 00153 00154 //crucially make sure teh zipping thread has stopped 00155 00156 #ifdef ZLIB_FOUND 00157 00158 m_AlogZipper.Stop(); 00159 00160 if(m_bUseExcludedLog) 00161 { 00162 m_XlogZipper.Stop(); 00163 } 00164 00165 #endif 00166 return true; 00167 00168 } 00169 00170 00171 bool CMOOSLogger::OnConnectToServer() 00172 { 00173 //ok so now lets register our interest in all these MOOS vars! 00174 RegisterMOOSVariables(); 00175 00176 //additional variables that are intersting to us.. 00177 m_Comms.Register("LOGGER_RESTART",0.5); 00178 00179 return true; 00180 } 00181 00182 bool CMOOSLogger::OnNewMail(MOOSMSG_LIST &NewMail) 00183 { 00184 //these three calls look through the incoming mail 00185 //and handle all appropriate logging 00186 DoAsyncLog(NewMail); 00187 00188 UpdateMOOSVariables(NewMail); 00189 00190 LogSystemMessages(NewMail); 00191 00192 //here we look for more unusual things 00193 MOOSMSG_LIST::iterator q; 00194 00195 for(q=NewMail.begin();q!=NewMail.end();q++) 00196 { 00197 00198 if(q->IsSkewed(MOOSTime())) 00199 continue; 00200 00201 //are we being asked to restart? 00202 if(MOOSStrCmp(q->GetKey(),"LOGGER_RESTART")) 00203 { 00204 OnLoggerRestart(); 00205 } 00206 00207 } 00208 00209 return true; 00210 } 00211 00212 00213 bool CMOOSLogger::OnStartUp() 00214 { 00215 //alway subscribe to these variables 00216 //they make up the sync log 00217 AddMOOSVariable("MOOS_DEBUG","MOOS_DEBUG","",0); 00218 AddMOOSVariable("MOOS_SYSTEM","MOOS_SYSTEM","",0); 00219 00220 m_bSynchronousLog = false; 00221 //are we required to perform synchronous logs? 00222 string sTmp; 00223 if(m_MissionReader.GetConfigurationParam("SYNCLOG",sTmp)) 00224 { 00225 string sBool = MOOSChomp(sTmp,"@"); 00226 00227 m_bSynchronousLog = MOOSStrCmp(sBool,"TRUE"); 00228 00229 //look for an additional parameter saying how often to log... 00230 if(!sTmp.empty()) 00231 { 00232 //how often are we required to perform synchronous logs? 00233 m_dfSyncLogPeriod = atof(sTmp.c_str()); 00234 00235 //this limit is intentional - the thinking mans logs are alogs 00236 //slogs are more expensive to write. I choose about 10Hz 00237 if(m_dfSyncLogPeriod<MIN_SYNC_LOG_PERIOD) 00238 { 00239 m_dfSyncLogPeriod = MIN_SYNC_LOG_PERIOD; 00240 } 00241 } 00242 } 00243 00244 00245 //are we required to perform Asynchronous logs? 00246 m_MissionReader.GetConfigurationParam("ASYNCLOG",m_bAsynchronousLog); 00247 00248 //are we required to run an exclusion log (which is where wildcard rejections can be sent 00249 //for paranoid people 00250 m_MissionReader.GetConfigurationParam("WildcardExclusionLog",m_bUseExcludedLog); 00251 00252 //what sort of file name are we using 00253 m_MissionReader.GetConfigurationParam("FILETIMESTAMP",m_bAppendFileTimeStamp); 00254 00255 //do we want to use UTC times in directory names 00256 m_MissionReader.GetConfigurationParam("UTCLogDirectories",m_bUseUTCLogNames); 00257 00258 //where should we write a summary of where we are logging to? 00259 m_sSummaryFile = "./.LastOpenedMOOSLogDirectory"; 00260 m_MissionReader.GetConfigurationParam("LoggingDirectorySummaryFile",m_sSummaryFile); 00261 00262 m_nDoublePrecision = DEFAULT_DOUBLE_PRECISION; 00263 m_MissionReader.GetConfigurationParam("DoublePrecision",m_nDoublePrecision); 00264 00265 m_MissionReader.GetConfigurationParam("LogAuxSrc",m_bLogAuxSrc); 00266 00267 00268 00269 00270 //do we have a path global name? 00271 if(!m_MissionReader.GetValue("GLOBALLOGPATH",m_sPath)) 00272 { 00273 //read path name 00274 if(!m_MissionReader.GetConfigurationParam("PATH",m_sPath)) 00275 { 00276 MOOSTrace("Warning:\n\tneither \"::GlobalLogPath\" or \"Path\" are specified\n"); 00277 MOOSTrace("\tWill Log to %s\n",m_sPath.c_str()); 00278 } 00279 } 00280 00281 //remove trailing "/"; 00282 00283 if(*m_sPath.rbegin()=='/') 00284 { 00285 m_sPath.erase(m_sPath.size()-1,1); 00286 } 00287 00288 // read in and set up all the names we are required to log.. 00289 // note ConfigureLogging will return true even if registration 00290 // for variables doesn't complete (i.e DB not connected) 00291 if(!ConfigureLogging()) 00292 return false; 00293 00294 00295 //fetch file name to log to 00296 m_MissionReader.GetConfigurationParam("FILE",m_sStemFileName); 00297 00298 00299 //do we want to do zip logging 00300 m_bCompressAlog = false; 00301 m_MissionReader.GetConfigurationParam("CompressAlogs",m_bCompressAlog); 00302 00303 if(m_bCompressAlog) 00304 { 00305 #ifndef ZLIB_FOUND 00306 m_bCompressAlog = false; 00307 MOOSTrace("warning:\n\talogs will not be compressed because zlib was not found at build time"); 00308 #endif 00309 } 00310 00311 00312 00313 00315 // now open the log files // 00317 if(!OnNewSession()) 00318 return false; 00319 00320 return true; 00321 } 00322 00323 00324 bool CMOOSLogger::ConfigureLogging() 00325 { 00326 00327 //figure out what we are required to log.... 00328 //here we read in what we want to log from the mission file.. 00329 STRING_LIST Params; 00330 bool bHasMissionFile = true; 00331 if(m_MissionReader.GetConfiguration(m_sAppName,Params)) 00332 { 00333 //this will make columns in sync log in order they 00334 //were declared in *.moos file 00335 Params.reverse(); 00336 00337 STRING_LIST::iterator p; 00338 for(p=Params.begin();p!=Params.end();p++) 00339 { 00340 string sParam = *p; 00341 string sWhat = MOOSChomp(sParam,"="); 00342 00343 if(MOOSStrCmp(sWhat,"LOG")) 00344 { 00345 std::string sNewVar; 00346 HandleLogRequest(sParam,sNewVar); 00347 } 00348 00349 } 00350 } 00351 else 00352 { 00353 bHasMissionFile = false; 00354 MOOSTrace("Warning:\n\tNo Configuration block was read - unusual but not terminal\n"); 00355 } 00356 00357 00358 //are we allowing dynamic logging of variables is via PLOGGER_CMD message? 00359 int nNumDynamicVariables = m_MissionReader.IsOpen() ? 0 : 10; 00360 00361 //this won't touch nNumDynamicVariables if mission file isn't open. 00362 m_MissionReader.GetConfigurationParam("DynamicSyncLogColumns",nNumDynamicVariables); 00363 00364 if(nNumDynamicVariables>0) 00365 { 00366 MOOSTrace("Comment:\n\tReserving space for %d dynamic variables in slog\n",nNumDynamicVariables); 00367 for(int i = 0; i<nNumDynamicVariables;i++) 00368 { 00369 m_UnusedDynamicVariables.push_back(MOOSFormat("DYNAMIC_%d",i)); 00370 } 00371 } 00372 00373 //and generally turn on command message filtering at the CMOOSApp level 00374 EnableCommandMessageFiltering(true); 00375 00376 //do we want wildcard logging - ie have the logger log every change... 00377 m_bWildCardLogging = false; 00378 if(bHasMissionFile) 00379 { 00380 m_MissionReader.GetConfigurationParam("WildcardLogging",m_bWildCardLogging); 00381 } 00382 else 00383 { 00384 m_bWildCardLogging = true; 00385 } 00386 00387 00388 //what sort of things do we want to wild card log 00389 if(m_bWildCardLogging ) 00390 { 00391 00392 //we never want to log mission files sent between communities - this is done elsewhere 00393 m_sWildCardOmitted.push_back("MISSION_FILE"); 00394 00395 //there was a request to allow multiple statements of the these patterns...hence the 00396 //more complicated parsing here 00397 STRING_LIST sList; 00398 if(m_MissionReader.GetConfiguration(GetAppName(), sList)) 00399 { 00400 STRING_LIST::iterator q; 00401 for(q = sList.begin();q!=sList.end();q++) 00402 { 00403 //are we being told exactly what accept and what not to accept 00404 std::string sTok,sVal; 00405 if(!CMOOSFileReader::GetTokenValPair(*q, sTok,sVal)) 00406 continue; 00407 00408 if(MOOSStrCmp("WildCardPattern",sTok)) 00409 { 00410 while(!sVal.empty()) 00411 { 00412 m_sWildCardAccepted.push_back(MOOSChomp(sVal,",")); 00413 } 00414 } 00415 else if(MOOSStrCmp("WildCardOmitPattern",sTok)) 00416 { 00417 while(!sVal.empty()) 00418 { 00419 m_sWildCardOmitted.push_back(MOOSChomp(sVal)); 00420 } 00421 } 00422 } 00423 } 00424 00425 00426 m_bAsynchronousLog = true; 00427 } 00428 00429 //ok so now lets register our interest in all these MOOS vars! 00430 if(!RegisterMOOSVariables()) 00431 MOOSDebugWrite("Variable subscription is still pending - not terminal, but unusual"); 00432 00433 return true; 00434 00435 } 00436 00437 bool CMOOSLogger::HandleLogRequest(std::string sParam,std::string & sVar, bool bDynamic) 00438 { 00439 sVar = MOOSChomp(sParam,"@"); 00440 00441 if(GetMOOSVar(sVar)!=NULL) 00442 return MOOSFail("Ignoring request to log %s - already requested\n",sVar.c_str()); 00443 00444 //do we want to monitor it? 00445 size_t iMonitor = sParam.find("MONITOR"); 00446 if(iMonitor!=string::npos) 00447 { 00448 m_MonitorMap[sVar] = DEFAULT_MONITOR_TIME; 00449 } 00450 00451 //now figure out where/if it should go in the synchronous log 00452 if(sParam.find("NOSYNC")==string::npos) 00453 { 00454 if(!bDynamic || m_UnusedDynamicVariables.size()>0) 00455 { 00456 //give it a default location... 00457 //and add to our list of syncronous vars 00458 m_SynchronousLogVars.push_back(sVar); 00459 } 00460 } 00461 00462 00463 string sFreq = MOOSChomp(sParam,","); 00464 00465 double dfPeriod = MOOS_LOGGER_DEFAULT_PERIOD; 00466 if(!sFreq.empty()) 00467 { 00468 dfPeriod = atof(sFreq.c_str()); 00469 } 00470 00471 //OK lets make a (internal) MOOS variable to hold this data 00472 AddMOOSVariable(sVar,sVar,"",dfPeriod); 00473 00474 return true; 00475 } 00476 00477 bool CMOOSLogger::Iterate() 00478 { 00479 double dfTimeNow = MOOSTime(); 00480 00481 //look to do a synchronous log.... 00482 if(m_bSynchronousLog) 00483 { 00484 if(dfTimeNow-m_dfLastSyncLogTime>m_dfSyncLogPeriod) 00485 { 00486 m_dfLastSyncLogTime = dfTimeNow; 00487 00488 DoSyncLog(dfTimeNow); 00489 00490 //finally everything is now stale.. 00491 MOOSVARMAP::iterator q; 00492 00493 for(q = m_MOOSVars.begin();q!=m_MOOSVars.end();q++) 00494 { 00495 q->second.SetFresh(false); 00496 } 00497 } 00498 } 00499 00500 00501 //check monitored variables 00502 if(dfTimeNow-m_dfLastMonitorTime>DEFAULT_MONITOR_TIME) 00503 { 00504 m_dfLastMonitorTime = dfTimeNow; 00505 VARIABLE_TIMER_MAP::iterator p; 00506 00507 int nMissing = 0; 00508 for(p = m_MonitorMap.begin();p!=m_MonitorMap.end();p++) 00509 { 00510 CMOOSVariable* pV = GetMOOSVar(p->first); 00511 if(pV) 00512 { 00513 double dfTolerance = p->second; 00514 if(pV->GetAge(dfTimeNow)>dfTolerance) 00515 { 00516 MOOSTrace("Monitored Variable \"%s\" is not appearing\n",pV->GetName().c_str()); 00517 nMissing++; 00518 } 00519 } 00520 } 00521 if(nMissing>0) 00522 { 00523 MOOSDebugWrite(MOOSFormat("%d monitored variable%s not being logged\n",nMissing,nMissing==1?" is":"s are")); 00524 } 00525 00526 //piggy back on this timer to publish current log directory 00527 m_Comms.Notify("LOGGER_DIRECTORY",m_sLogDirectoryName.c_str()); 00528 } 00529 00530 //are we requested to do wild card logging? 00531 if(m_bWildCardLogging) 00532 HandleWildCardLogging(); 00533 00534 00535 //finally flush all files to be safe 00536 m_SyncLogFile.flush(); 00537 m_AsyncLogFile.flush(); 00538 m_SystemLogFile.flush(); 00539 00540 00541 00542 return true; 00543 } 00544 00545 bool CMOOSLogger::HandleWildCardLogging() 00546 { 00547 static double dfLastWildCardTime = -1.0; 00548 00549 if(MOOSTime()-dfLastWildCardTime>DEFAULT_WILDCARD_TIME) 00550 { 00551 MOOSMSG_LIST InMail; 00552 if(m_Comms.ServerRequest("VAR_SUMMARY", InMail, 2.0, false)) 00553 { 00554 MOOSAssert(InMail.size()==1); 00555 std::string ss(InMail.begin()->GetString()); 00556 bool bHit = false; 00557 while(!ss.empty()) 00558 { 00559 std::string sVar = MOOSChomp(ss); 00560 if(GetMOOSVar(sVar)==NULL) 00561 { 00562 bool bWouldNormallyReject = IsWildCardRejected(sVar); 00563 bool bWouldNormallyAccept = IsWildCardAccepted(sVar); 00564 bool bWanted = false; 00565 00566 if(m_bUseExcludedLog) 00567 { 00568 bWanted = true; 00569 if( bWouldNormallyAccept && !bWouldNormallyReject) 00570 { 00571 MOOSTrace(" Added wildcard logging of %-20s\n",sVar.c_str()); 00572 m_LogDestinations[sVar] = ALOG; 00573 } 00574 else 00575 { 00576 MOOSTrace(" Added wildcard logging of %-20s (xlog) \n",sVar.c_str()); 00577 m_LogDestinations[sVar] = XLOG; 00578 00579 } 00580 } 00581 00582 else 00583 { 00584 if( bWouldNormallyAccept && !bWouldNormallyReject ) 00585 { 00586 MOOSTrace(" Added wildcard logging of %-20s\n",sVar.c_str()); 00587 m_LogDestinations[sVar] = ALOG; 00588 bWanted = true; 00589 } 00590 else if(bWouldNormallyAccept && bWouldNormallyReject) 00591 { 00592 //MOOSTrace(" denied added wildcard logging of %-20s (fits Omit pattern as well as Accept pattern)\n",sVar.c_str()); 00593 bWanted = false; 00594 } 00595 } 00596 00597 if(bWanted) 00598 { 00599 //yep we want to know.... 00600 if(AddMOOSVariable(sVar,sVar,"",0.0)) 00601 { 00602 bHit = true; 00603 } 00604 } 00605 00606 } 00607 } 00608 00609 if(bHit) 00610 RegisterMOOSVariables(); 00611 } 00612 00613 dfLastWildCardTime = MOOSTime(); 00614 } 00615 00616 return true; 00617 } 00618 00619 00620 struct StringMatcher 00621 { 00622 std::string m_sString; 00623 StringMatcher(const std::string & sStr) 00624 { 00625 m_sString = sStr; 00626 } 00627 bool operator () (const std::string & sPattern) const 00628 { 00629 return MOOSWildCmp(sPattern,m_sString); 00630 } 00631 }; 00632 00633 bool CMOOSLogger::IsWildCardRejected(const std::string & sVariableName) const 00634 { 00635 return std::find_if(m_sWildCardOmitted.begin(), 00636 m_sWildCardOmitted.end(), 00637 StringMatcher(sVariableName)) !=m_sWildCardOmitted.end(); 00638 00639 } 00640 00641 bool CMOOSLogger::IsWildCardAccepted(const std::string & sVariableName) const 00642 { 00643 00644 //we assume by default we want everything 00645 if(m_sWildCardAccepted.empty()) 00646 return true; 00647 00648 //looks like some masks have been set 00649 return std::find_if(m_sWildCardAccepted.begin(), 00650 m_sWildCardAccepted.end(), 00651 StringMatcher(sVariableName)) !=m_sWildCardAccepted.end(); 00652 00653 } 00654 00655 00656 std::string CMOOSLogger::MakeLogName(string sStem) 00657 { 00658 struct tm *Now; 00659 time_t aclock; 00660 time( &aclock ); 00661 00662 if(m_bUseUTCLogNames) 00663 { 00664 Now = gmtime(&aclock); 00665 } 00666 else 00667 { 00668 Now = localtime( &aclock ); 00669 } 00670 00671 std::string sTmp; 00672 00673 if(m_bAppendFileTimeStamp) 00674 { 00675 // Print local time as a string 00676 00677 //ODYSSEYLOG_14_5_1993_____9_30.log 00678 sTmp = MOOSFormat( "%s_%d_%d_%d_____%.2d_%.2d_%.2d", 00679 sStem.c_str(), 00680 Now->tm_mday, 00681 Now->tm_mon+1, 00682 Now->tm_year+1900, 00683 Now->tm_hour, 00684 Now->tm_min, 00685 Now->tm_sec); 00686 } 00687 else 00688 { 00689 sTmp = MOOSFormat("%s",sStem.c_str()); 00690 } 00691 00692 return sTmp; 00693 00694 } 00695 00696 00697 bool CMOOSLogger::DoSyncLog(double dfTimeNow) 00698 { 00699 00700 //begin with time... 00701 m_SyncLogFile<<setw(COLUMN_WIDTH)<<setprecision(7)<<dfTimeNow-GetAppStartTime()<<' '; 00702 00703 //now for all our variables... 00704 int nLogVarsSize = m_SynchronousLogVars.size(); 00705 for(int nVar = 0; nVar<nLogVarsSize;nVar++) 00706 { 00707 string sVar = m_SynchronousLogVars[nVar]; 00708 00709 //oops empty string! 00710 if(sVar.empty()) 00711 continue; 00712 00713 //we want left justification 00714 m_SyncLogFile.setf(ios::left); 00715 00716 //ok we have a name at column nVar...(numerical order retained in vector) 00717 MOOSVARMAP::iterator q = m_MOOSVars.find(sVar); 00718 00719 if(q!=m_MOOSVars.end()) 00720 { 00721 //OK so now we have the variable ..log it simply 00722 CMOOSVariable & rVar = q->second; 00723 00724 m_SyncLogFile<<setw(COLUMN_WIDTH); 00725 00726 //has this variable changed since last time? 00727 if(rVar.IsFresh()) 00728 { 00729 //we can only write doubles 00730 if(rVar.IsDouble()) 00731 { 00732 m_SyncLogFile<<rVar.GetAsString(COLUMN_WIDTH).c_str()<<' '; 00733 } 00734 else 00735 { 00736 //signify string variables or other types by NaN 00737 //sync log is only for numbers 00738 m_SyncLogFile<<"NaN"<<' '; 00739 } 00740 00741 //we have used this variable so it is no longer fresh 00742 rVar.SetFresh(false); 00743 } 00744 else 00745 { 00746 //NO! 00747 m_SyncLogFile<<"NaN"<<' '; 00748 } 00749 00750 00751 } 00752 00753 } 00754 00755 00756 //here we want to add columns for unclaimed dynamic variables; 00757 for(unsigned int i = 0; i<m_UnusedDynamicVariables.size();i++) 00758 { 00759 m_SyncLogFile<<setw(COLUMN_WIDTH); 00760 m_SyncLogFile<<"NaN"<<' '; 00761 } 00762 00763 //put a new line in... 00764 m_SyncLogFile<<endl; 00765 00766 //every few lines put a comment in 00767 if((m_nSyncLines++)%30==0) 00768 LabelSyncColumns(); 00769 00770 return true; 00771 } 00772 00773 00774 bool CMOOSLogger::OpenFile(std::ofstream & of,const std::string & sName,bool bBinary) 00775 { 00776 if(!bBinary) 00777 of.open(sName.c_str()); 00778 else 00779 { 00780 of.open(sName.c_str(),std::ios::binary); 00781 } 00782 00783 00784 if(!of.is_open()) 00785 { 00786 string sErr = MOOSFormat("ERROR: Failed to open File: %s",sName.c_str()); 00787 MOOSDebugWrite(sErr); 00788 return false; 00789 } 00790 00791 return true; 00792 } 00793 00794 bool CMOOSLogger::OpenSyncFile() 00795 { 00796 if(!OpenFile(m_SyncLogFile,m_sSyncFileName)) 00797 return MOOSFail("Failed to Open slog file"); 00798 00799 00800 //be pretty 00801 DoBanner(m_SyncLogFile,m_sSyncFileName); 00802 00803 00804 //put a column of names and where they can be found 00805 m_SyncLogFile<<"%% (1) TIME "<<endl; 00806 00807 //now for all our variables say what the columns mean.. 00808 int nCount = 2; 00809 int nLogVarsSize = m_SynchronousLogVars.size(); 00810 for(int nVar = 0; nVar<nLogVarsSize;nVar++) 00811 { 00812 string sVar = m_SynchronousLogVars[nVar]; 00813 00814 //oops empty string! 00815 if(sVar.empty()) 00816 continue; 00817 00818 m_SyncLogFile<<"%% ("<<nCount++<<") "<<sVar.c_str()<<endl; 00819 00820 } 00821 00822 00823 //here we want to describe columns for unclaimed dynamic variables; 00824 STRING_LIST::iterator q; 00825 for( q = m_UnusedDynamicVariables.begin();q!=m_UnusedDynamicVariables.end();q++) 00826 { 00827 m_SyncLogFile<<"%% ("<<nCount++<<") "; 00828 00829 //remember where the next string will be.. 00830 m_DynamicNameIndex[*q] = m_SyncLogFile.tellp(); 00831 00832 //write the as yet unclaimed name - note we are also writing a tonne of spare space so we can 00833 //later acccess the file here and write a new MOOS variabl name.. 00834 m_SyncLogFile<<setw(DYNAMIC_NAME_SPACE)<<left<<q->c_str()<<endl; 00835 } 00836 00837 m_SyncLogFile<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"<<endl; 00838 00839 LabelSyncColumns(); 00840 00841 00842 return true; 00843 } 00844 00845 00846 bool CMOOSLogger::OpenSystemFile() 00847 { 00848 00849 if(!OpenFile(m_SystemLogFile,m_sSystemFileName)) 00850 return MOOSFail("Failed to Open system log file"); 00851 00852 00853 DoBanner(m_SystemLogFile,m_sSystemFileName); 00854 00855 return true; 00856 } 00857 00858 00859 00860 bool CMOOSLogger::OpenAsyncFiles() 00861 { 00862 00863 00864 00865 if(m_bCompressAlog) 00866 { 00867 //we need to write a banner to a compressed stream 00868 std::stringstream ss; 00869 DoBanner(ss,m_sAsyncFileName); 00870 m_AlogZipper.Push(ss.str()); 00871 00872 if(m_bUseExcludedLog) 00873 { 00874 m_XlogZipper.Push(ss.str()); 00875 } 00876 } 00877 else 00878 { 00879 //usual banner write to a regular alog file 00880 if(!OpenFile(m_AsyncLogFile,m_sAsyncFileName)) 00881 return MOOSFail("Failed to Open alog file"); 00882 00883 DoBanner(m_AsyncLogFile,m_sAsyncFileName); 00884 00885 if(m_bUseExcludedLog) 00886 { 00887 if(!OpenFile(m_ExcludeLogFile, m_sExcludeFileName)) 00888 return MOOSFail("failed to open xlog log"); 00889 } 00890 } 00891 00892 //also open a binary log file - this is always created 00893 00894 //*note* that the binary file is _not_ compressed 00895 //no matter what flags you set - this is so that 00896 //we can jump around in it using memory offsets 00897 00898 if(!OpenFile(m_BinaryLogFile,m_sBinaryFileName)) 00899 return MOOSFail("Failed to Open blog file"); 00900 00901 m_BinaryCursor = m_BinaryLogFile.tellp(); 00902 00903 return true; 00904 } 00905 00906 bool CMOOSLogger::LogSystemMessages(MOOSMSG_LIST &NewMail) 00907 { 00908 MOOSMSG_LIST::iterator p; 00909 00910 m_SystemLogFile.setf(ios::left); 00911 00912 double dfTimeNow = MOOSTime(); 00913 00914 for(p = NewMail.begin();p!=NewMail.end();p++) 00915 { 00916 CMOOSMsg & rMsg = *p; 00917 if(IsSystemMessage(rMsg.m_sKey) && !rMsg.IsSkewed(dfTimeNow)) 00918 { 00919 00920 m_SystemLogFile<<setw(10)<<setprecision(7)<<rMsg.m_dfTime-GetAppStartTime()<<' '; 00921 00922 m_SystemLogFile<<setw(20)<<rMsg.m_sKey.c_str()<<' '; 00923 00924 m_SystemLogFile<<setw(20)<<rMsg.m_sSrc.c_str()<<' '; 00925 00926 if(rMsg.m_cDataType==MOOS_DOUBLE) 00927 { 00928 m_SystemLogFile<<setw(20)<<rMsg.m_dfVal<<' '; 00929 } 00930 else 00931 { 00932 MOOSRemoveChars(rMsg.m_sVal,"\n"); 00933 m_SystemLogFile<<setw(20)<<rMsg.m_sVal.c_str()<<' '; 00934 } 00935 m_SystemLogFile<<endl; 00936 } 00937 } 00938 00939 return true; 00940 } 00941 00942 bool CMOOSLogger::IsSystemMessage(string &sKey) 00943 { 00944 if (MOOSStrCmp(sKey,"MOOS_DEBUG")) return true; 00945 if (MOOSStrCmp(sKey,"MOOS_SYSTEM")) return true; 00946 00947 return false; 00948 } 00949 00950 bool CMOOSLogger::DoBanner(ostream &os, string &sFileName) 00951 { 00952 os<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 00953 os<<"%% LOG FILE: "<<sFileName.c_str()<<endl; 00954 os<<"%% FILE OPENED ON "<<MOOSGetDate().c_str(); 00955 os<<"%% LOGSTART "<<setw(20)<<setprecision(12)<<GetAppStartTime()<<endl; 00956 os<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 00957 00958 return true; 00959 } 00960 00961 bool CMOOSLogger::LabelSyncColumns() 00962 { 00963 //now put a header on each column... 00964 m_SyncLogFile.setf(ios::left); 00965 00966 m_SyncLogFile<<setw(COLUMN_WIDTH)<<"%% TIME"<<' '; 00967 00968 int nLogVarsSize = m_SynchronousLogVars.size(); 00969 for(int nVar = 0; nVar<nLogVarsSize;nVar++) 00970 { 00971 string sVar = m_SynchronousLogVars[nVar]; 00972 00973 //oops empty string! 00974 if(sVar.empty()) 00975 continue; 00976 00977 m_SyncLogFile.setf(ios::left); 00978 00979 m_SyncLogFile<<setw(COLUMN_WIDTH)<<sVar.c_str()<<' '; 00980 } 00981 00982 //here we want to add columns for unclaimed dynamic variables; 00983 STRING_LIST::iterator q; 00984 for( q = m_UnusedDynamicVariables.begin();q!=m_UnusedDynamicVariables.end();q++) 00985 { 00986 m_SyncLogFile.setf(ios::left); 00987 m_SyncLogFile<<setw(COLUMN_WIDTH)<<q->c_str()<<' '; 00988 } 00989 00990 00991 m_SyncLogFile<<endl; 00992 00993 //and add a line of times for good measure.. 00994 AddSyncLineOfTimes(MOOSTime()-GetAppStartTime()); 00995 00996 return true; 00997 } 00998 00999 bool CMOOSLogger::AddSyncLineOfTimes(double dfTimeNow) 01000 { 01001 //now put a header on each column... 01002 m_SyncLogFile.setf(ios::left); 01003 01004 m_SyncLogFile<<setw(COLUMN_WIDTH)<<"%% TIME"<<' '; 01005 01006 string sNow = MOOSFormat("[%7.2f]",dfTimeNow); 01007 01008 int nLogVarsSize = m_SynchronousLogVars.size()+ m_UnusedDynamicVariables.size(); 01009 for(int nVar = 0; nVar<nLogVarsSize;nVar++) 01010 { 01011 m_SyncLogFile<<setw(COLUMN_WIDTH)<<sNow.c_str()<<' '; 01012 } 01013 01014 01015 m_SyncLogFile<<endl; 01016 01017 return true; 01018 01019 } 01020 01021 bool CMOOSLogger::CreateDirectory(const std::string & sDirectory) 01022 { 01023 01024 #if _WIN32 01025 int bOK = ::CreateDirectory(sDirectory.c_str(),NULL); 01026 01027 if(!bOK) 01028 { 01029 DWORD TheError = GetLastError(); 01030 01031 if(TheError!=ERROR_ALREADY_EXISTS) 01032 { 01033 01034 LPVOID lpMsgBuf; 01035 FormatMessage( 01036 FORMAT_MESSAGE_ALLOCATE_BUFFER | 01037 FORMAT_MESSAGE_FROM_SYSTEM | 01038 FORMAT_MESSAGE_IGNORE_INSERTS, 01039 NULL, 01040 TheError, 01041 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 01042 (LPTSTR) &lpMsgBuf, 01043 0, 01044 NULL 01045 ); 01046 // Process any inserts in lpMsgBuf. 01047 // ... 01048 // Display the string. 01049 MOOSTrace("Error %ld making directory : \"%s\"\n",TheError,(LPCTSTR)lpMsgBuf); 01050 01051 // Free the buffer. 01052 LocalFree( lpMsgBuf ); 01053 01054 return false; 01055 } 01056 01057 } 01058 #else 01059 if(mkdir(sDirectory.c_str(),0755)==-1) 01060 { 01061 switch(errno) 01062 { 01063 case EEXIST: 01064 break; 01065 default: 01066 MOOSTrace("Error %ld making directory : \"%s\"\n",errno,strerror(errno)); 01067 return false; 01068 } 01069 } 01070 01071 #endif 01072 01073 01074 return true; 01075 } 01076 01077 bool CMOOSLogger::OnNewSession() 01078 { 01079 01080 //what is the root name of all log files? 01081 m_sLogRootName = MakeLogName(m_sStemFileName); 01082 01083 //Make a directory to hold the new files 01084 std::string sLogDirectory = m_sPath+"/"+m_sLogRootName; 01085 01086 if(!CMOOSLogger::CreateDirectory(sLogDirectory)) 01087 { 01088 MOOSTrace("Warning:\n\tFailed to create directory %s\n",sLogDirectory.c_str()); 01089 01090 sLogDirectory = "./"+m_sLogRootName; 01091 MOOSTrace("\tfalling back to creating %s...",sLogDirectory.c_str()); 01092 if(!CMOOSLogger::CreateDirectory(sLogDirectory)) 01093 { 01094 return MOOSFail("Failed to create a logging directory either in specified path or locally\n"); 01095 } 01096 else 01097 { 01098 MOOSTrace("OK\n"); 01099 } 01100 } 01101 01102 //looks safe remember it... 01103 m_sLogDirectoryName = sLogDirectory; 01104 01105 //and publish it 01106 m_Comms.Notify("LOGGER_DIRECTORY",m_sLogDirectoryName.c_str()); 01107 01108 //and write this to file 01109 ofstream LF(m_sSummaryFile.c_str()); 01110 if(LF.is_open()) 01111 { 01112 LF<<"LastOpenedLoggingDirectory="<<m_sLogDirectoryName<<std::endl; 01113 01114 } 01115 01116 01117 m_sAsyncFileName = m_sLogDirectoryName+"/"+m_sLogRootName+".alog"; 01118 m_sExcludeFileName = m_sLogDirectoryName+"/"+m_sLogRootName+".xlog"; 01119 m_sSyncFileName = m_sLogDirectoryName+"/"+m_sLogRootName+".slog"; 01120 m_sSystemFileName = m_sLogDirectoryName+"/"+m_sLogRootName+".ylog"; 01121 m_sMissionCopyName = m_sLogDirectoryName+"/"+m_sLogRootName+"._moos"; 01122 m_sHoofCopyName = m_sLogDirectoryName+"/"+m_sLogRootName+"._hoof"; 01123 m_sBinaryFileName = m_sLogDirectoryName+"/"+m_sLogRootName+".blog"; 01124 01125 if(!OpenAsyncFiles()) 01126 return MOOSFail("Error:\n\tUnable to open Asynchronous log file\n"); 01127 01128 if(m_bSynchronousLog && ! OpenSyncFile()) 01129 return MOOSFail("Error:\n\tUnable to open Synchronous log file\n"); 01130 01131 if(!OpenSystemFile()) 01132 return MOOSFail("Error:\n\tUnable to open System log file\n"); 01133 01134 if(!CopyMissionFile()) 01135 MOOSTrace("Warning:\n\tunable to create a back up of the mission file\n"); 01136 01137 01138 if(m_bCompressAlog) 01139 { 01140 #ifdef ZLIB_FOUND 01141 //restart the a log zipper 01142 MOOSTrace("pLogger: Alog compression is enabled\n"); 01143 if(m_AlogZipper.IsRunning()) 01144 { 01145 m_AlogZipper.Stop(); 01146 } 01147 m_AlogZipper.Start(m_sAsyncFileName); 01148 01149 //restart the Xlog zipper 01150 if(m_XlogZipper.IsRunning()) 01151 { 01152 m_XlogZipper.Stop(); 01153 } 01154 m_XlogZipper.Start(m_sExcludeFileName); 01155 01156 01157 #else 01158 m_bCompressAlog = false; 01159 MOOSTrace("WARNING: alogs will not be compressed because zlib was not found at build time"); 01160 #endif 01161 } 01162 01163 01164 return true; 01165 } 01166 01167 01168 std::string GetDirectoryName(const std::string & sStr) 01169 { 01170 std::string sT = sStr; 01171 std::string sD; 01172 01173 while(!sT.empty()) 01174 sD = MOOSChomp(sT,"/"); 01175 01176 return sD; 01177 } 01178 01179 bool CMOOSLogger::OnLoggerRestart() 01180 { 01181 string sTxt = MOOSFormat("Closing : %s",GetDirectoryName(m_sLogDirectoryName).c_str()); 01182 MOOSDebugWrite(sTxt); 01183 01184 CloseFiles(); 01185 01186 //start up fresh 01187 if(!OnNewSession()) 01188 return MOOSFail("Failed to start a new logging session"); 01189 01190 MOOSDebugWrite(MOOSFormat("Now Logging to : %s",GetDirectoryName(m_sLogDirectoryName).c_str())); 01191 01192 return true; 01193 } 01194 01195 01196 CMOOSLogger::LogType CMOOSLogger::GetDestinationLog(const std::string & sMsg) 01197 { 01198 std::map<std::string,LogType>::iterator q = m_LogDestinations.find(sMsg); 01199 if( q==m_LogDestinations.end()) 01200 return UNKNOWN; 01201 else 01202 return q->second; 01203 01204 } 01205 01206 bool CMOOSLogger::DoAsyncLog(MOOSMSG_LIST &NewMail) 01207 { 01208 //log asynchronously... 01209 if(m_bAsynchronousLog) 01210 { 01211 MOOSMSG_LIST::iterator q; 01212 01213 std::stringstream sStream[2]; 01214 01215 for(q = NewMail.begin();q!=NewMail.end();q++) 01216 { 01217 CMOOSMsg & rMsg = *q; 01218 01219 //now see if we are logging this kind of message.. 01220 //if so we will have a variable named after it... 01221 //which is used for the synchronous case.. 01222 if(m_MOOSVars.find(rMsg.m_sKey)!=m_MOOSVars.end()) 01223 { 01224 01225 01226 std::stringstream sEntry; 01227 01228 sEntry.setf(ios::left); 01229 01230 sEntry.setf(ios::fixed); 01231 01232 sEntry<<setw(15)<<setprecision(3)<<rMsg.GetTime()-GetAppStartTime()<<' '; 01233 01234 sEntry<<setw(20)<<rMsg.GetKey().c_str()<<' '; 01235 01236 if(!m_bLogAuxSrc) 01237 { 01238 sEntry<<setw(15)<<rMsg.GetSource().c_str()<<' '; 01239 } 01240 else 01241 { 01242 std::string sT = rMsg.GetSource()+":"+(rMsg.GetSourceAux().empty() ? "NO_AUX_SRC" : rMsg.GetSourceAux()); 01243 sEntry<<setw(15)<<sT<<' '; 01244 } 01245 01246 if(rMsg.IsDataType(MOOS_STRING) || rMsg.IsDataType(MOOS_DOUBLE)) 01247 { 01248 sEntry<<rMsg.GetAsString(12,m_nDoublePrecision).c_str()<<' '; 01249 } 01250 else if(rMsg.IsDataType(MOOS_BINARY_STRING)) 01251 { 01252 //here we append to the binary log and begin each line with a summary.... 01253 m_BinaryLogFile<<sEntry.str(); 01254 01255 //write in coordinates in the alog 01256 sEntry<<"<MOOS_BINARY>File="<<(m_sLogRootName+".blog")<<",Offset="<<m_BinaryLogFile.tellp()<<",Bytes="<<rMsg.m_sVal.size()<<"</MOOS_BINARY>"; 01257 01258 //write the binary data to file 01259 m_BinaryLogFile.write(rMsg.m_sVal.data(), rMsg.m_sVal.size()); 01260 01261 //add a new line so even the binary log file is broadly human readable 01262 m_BinaryLogFile<<std::endl; 01263 01264 } 01265 01266 01267 01268 int i=0; 01269 if(m_bUseExcludedLog) 01270 { 01271 switch(GetDestinationLog(rMsg.m_sKey)) 01272 { 01273 case XLOG: i = 1; break; 01274 case ALOG: i = 0; break; 01275 default: 01276 i = 0; 01277 } 01278 } 01279 sStream[i]<<sEntry.str()<<endl; 01280 01281 01282 } 01283 } 01284 01285 if(m_bCompressAlog) 01286 { 01287 //send to the worker thread... 01288 m_AlogZipper.Push(sStream[0].str()); 01289 m_XlogZipper.Push(sStream[1].str()); 01290 } 01291 else 01292 { 01293 //a regular write 01294 if(m_AsyncLogFile.is_open()) 01295 m_AsyncLogFile<<sStream[0].str(); 01296 01297 if(m_ExcludeLogFile.is_open()) 01298 m_ExcludeLogFile<<sStream[1].str(); 01299 } 01300 } 01301 return true; 01302 } 01303 01304 bool CMOOSLogger::CopyMissionFile() 01305 { 01306 //open the original 01307 ifstream MissionFile; 01308 MissionFile.open(m_sMissionFile.c_str()); 01309 if(!MissionFile.is_open()) 01310 return MOOSFail("\nWarning:\n\tfailed to open copy of mission file - it can't be backed up\n");; 01311 01312 01313 //open a copy file 01314 ofstream MissionCopy; 01315 01316 if(!OpenFile(MissionCopy,m_sMissionCopyName)) 01317 return MOOSFail("Failed to open a destination copy of mission file"); 01318 01319 //write a banner 01320 DoBanner(MissionCopy,m_sMissionCopyName); 01321 01322 //do the copy.. 01323 while(!MissionFile.eof()) 01324 { 01325 char Tmp[10000]; 01326 MissionFile.getline(Tmp,sizeof(Tmp)); 01327 string sLine = string(Tmp); 01328 01329 MissionCopy<<sLine.c_str()<<endl; 01330 } 01331 MissionCopy.close(); 01332 MissionFile.close(); 01333 01334 01335 01336 //now look for hoof files! 01337 CProcessConfigReader HelmReader; 01338 HelmReader.SetFile(m_sMissionFile); 01339 HelmReader.SetAppName("pHelm"); 01340 01341 string sHoof; 01342 if(HelmReader.GetConfigurationParam("TaskFile",sHoof)) 01343 { 01344 01345 //open a copy file 01346 ofstream HoofCopy; 01347 01348 if(!OpenFile(HoofCopy,m_sHoofCopyName)) 01349 return MOOSFail("Failed to copy of mission file"); 01350 01351 //open the original 01352 ifstream HoofFile; 01353 HoofFile.open(sHoof.c_str()); 01354 01355 if(HoofFile.is_open() && HoofCopy.is_open()) 01356 { 01357 01358 //do the copy.. 01359 while(!HoofFile.eof()) 01360 { 01361 char Tmp[10000]; 01362 HoofFile.getline(Tmp,sizeof(Tmp)); 01363 string sLine = string(Tmp); 01364 01365 HoofCopy<<sLine.c_str()<<endl; 01366 } 01367 01368 HoofCopy.close(); 01369 HoofFile.close(); 01370 } 01371 } 01372 01373 01374 01375 return true; 01376 01377 } 01378 01379 bool CMOOSLogger::OnCommandMsg(CMOOSMsg Msg) 01380 { 01381 if(Msg.IsSkewed(MOOSTime())) 01382 return true; 01383 01384 if(!Msg.IsString()) 01385 return MOOSFail("pLogger only accepts string command messages\n"); 01386 01387 std::string sCmd = Msg.GetString(); 01388 01389 //OK lets look for dynamic log messages: 01390 std::string sTask,sParam; 01391 m_MissionReader.GetTokenValPair(sCmd,sTask,sParam); 01392 01393 if(MOOSStrCmp(sTask,"LOG_REQUEST")) 01394 { 01395 HandleDynamicLogRequest(sParam); 01396 } 01397 else if(MOOSStrCmp(sTask,"COPY_FILE_REQUEST")) 01398 { 01399 HandleCopyFileRequest(sParam); 01400 } 01401 else 01402 { 01403 return MOOSFail("Dynamic command %s is not supported\n",sTask.c_str()); 01404 } 01405 01406 return true; 01407 } 01408 01409 01410 01411 bool CMOOSLogger::HandleCopyFileRequest(std::string sFileToCopy) 01412 { 01413 std::string sPath,sFile,sExtension; 01414 01415 MOOSFileParts(sFileToCopy,sPath,sFile,sExtension); 01416 01417 //alter extension to show its been harvested by the logger 01418 //similar to the way *.moos ->*._moos 01419 if(sExtension.empty()) 01420 { 01421 sExtension = "_bak"; 01422 } 01423 else 01424 { 01425 sExtension = "_"+sExtension; 01426 } 01427 01428 std::string sBackUpName = m_sLogDirectoryName+"/"+sFile+"."+sExtension; 01429 01430 std::ifstream In(sFileToCopy.c_str()); 01431 01432 if(!In.is_open()) 01433 { 01434 MOOSDebugWrite("failed to open file for reading"); 01435 return false; 01436 } 01437 01438 std::ofstream Out(sBackUpName.c_str()); 01439 if(!Out.is_open()) 01440 { 01441 MOOSDebugWrite("failed to open file for writing"); 01442 return false; 01443 } 01444 01445 //you've gotta lurve C++ ... 01446 Out<<In.rdbuf(); 01447 01448 Out.close(); 01449 In.close(); 01450 01451 MOOSTrace("copied file to %s\n",sBackUpName.c_str()); 01452 01453 01454 return true; 01455 } 01456 01457 bool CMOOSLogger::HandleDynamicLogRequest(std::string sRequest) 01458 { 01459 std::string sNewVar; 01460 if(HandleLogRequest(sRequest,sNewVar,true)) 01461 { 01462 //now the above will have added the variable to async logs but maybe not to 01463 //sync logs - there maynot be space - but that the price you pay for not talking to each other 01464 //users can set DynamicSyncLogColumns = N to reserve space 01465 if(!m_UnusedDynamicVariables.empty()) 01466 { 01467 //looks like we have space...so reserved slog columns is still filling up 01468 //but we now have one less column as yet unclaimed 01469 std::string sDynamic = m_UnusedDynamicVariables.front(); 01470 01471 //remember where the next string will be.. 01472 if(m_DynamicNameIndex.find(sDynamic)==m_DynamicNameIndex.end()) 01473 { 01474 MOOSAssert("this is a logical error - call PMN"); 01475 } 01476 01477 01478 //better remember where we are... 01479 std::streampos pNow = m_SyncLogFile.tellp(); 01480 01481 //where do we write the new name to? 01482 std::streampos p = m_DynamicNameIndex[sDynamic]; 01483 01484 //go there... 01485 m_SyncLogFile.seekp(p); 01486 01487 //write the as yet unclaimed name - note we are also writing a tonne of spare space so we can 01488 //later acccess the file here and write a new MOOS variable name.. 01489 if(sNewVar.size()>DYNAMIC_NAME_SPACE-1) 01490 { 01491 //we only reserved a limited amount of space... 01492 MOOSTrace("warning:\n\t name \"%s\" will be truncated to %d characters in the slog\n", 01493 sNewVar.c_str(), 01494 DYNAMIC_NAME_SPACE-1); 01495 } 01496 01497 m_SyncLogFile<<setw(DYNAMIC_NAME_SPACE-1)<<left<<sNewVar;; 01498 01499 //and return from whence you came.... 01500 m_SyncLogFile.seekp(pNow); 01501 01502 //pop the name of a now used, dynamic variable 01503 m_UnusedDynamicVariables.pop_front(); 01504 } 01505 01506 //indicate column semantics have changed 01507 LabelSyncColumns(); 01508 01509 //register to receive notifications on this 01510 RegisterMOOSVariables(); 01511 01512 MOOSTrace("Processed dynamic log request on \"%s\". \nSpace for %d more such requests before slog becomes full\n",sNewVar.c_str(),m_UnusedDynamicVariables.size()); 01513 } 01514 else 01515 { 01516 MOOSDebugWrite("failed to process dynamic log request - see pLogger output\n"); 01517 return false; 01518 } 01519 01520 return true; 01521 01522 01523 } 01524 01525 std::string CMOOSLogger::MakeStatusString() 01526 { 01527 std::stringstream ss; 01528 ss<<CMOOSApp::MakeStatusString()<<","; 01529 ss<<"LogAuxSrc="<<std::boolalpha<<m_bLogAuxSrc; 01530 return ss.str(); 01531 } 01532 01533 01534 01535 01536