MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Essentials/pLogger/MOOSLogger.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines