Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ArLog.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArLog.h"
00030 #include "ArConfig.h"
00031 #include <time.h>
00032 #include <stdarg.h>
00033 #include <ctype.h>
00034 
00035 ArMutex ArLog::ourMutex;
00036 ArLog::LogType ArLog::ourType=StdOut;
00037 ArLog::LogLevel ArLog::ourLevel=ArLog::Normal;
00038 FILE * ArLog::ourFP=0;
00039 std::string ArLog::ourFileName;
00040 int ArLog::ourColbertStream = -1;
00041 bool ArLog::ourLoggingTime = false;
00042 bool ArLog::ourAlsoPrint = false;
00043 void (* ArLog::colbertPrint)(int i, const char *str);
00044 
00045 ArLog::LogType ArLog::ourConfigLogType = ArLog::StdOut;
00046 ArLog::LogLevel ArLog::ourConfigLogLevel = ArLog::Normal;
00047 char ArLog::ourConfigFileName[1024] = "log.txt";
00048 bool ArLog::ourConfigLogTime = false;
00049 bool ArLog::ourConfigAlsoPrint = false;
00050 ArGlobalRetFunctor<bool> ArLog::ourConfigProcessFileCB(&ArLog::processFile);
00051 
00052 void ArLog::logPlain(LogLevel level, const char *str)
00053 {
00054   log(level, str);
00055 }
00056 
00063 void ArLog::log(LogLevel level, const char *str, ...)
00064 {
00065   char buf[2048];
00066   char *bufPtr;
00067   char *timeStr;
00068   int timeLen = 20; // this is a value based on the standard length of
00069                        // ctime return
00070   time_t now;
00071 
00072 
00073   if (level <= ourLevel)
00074   {
00075     ourMutex.lock();
00076     // put our time in if we want it
00077     if (ourLoggingTime)
00078     {
00079       now = time(NULL);
00080       timeStr = ctime(&now);
00081       // get take just the portion of the time we want
00082       strncpy(buf, timeStr, timeLen);
00083       buf[timeLen] = '\0';
00084       bufPtr = &buf[timeLen];
00085     }
00086     else
00087       bufPtr = buf;
00088     va_list ptr;
00089     va_start(ptr, str);
00090     vsprintf(bufPtr, str, ptr);
00091     // can do whatever you want with the buf now
00092     if (ourType == Colbert)
00093     {
00094       if (colbertPrint)         // check if we have a print routine
00095         (*colbertPrint)(ourColbertStream, buf);
00096     }
00097     else if (ourFP)
00098     {
00099       fprintf(ourFP, "%s\n", buf);
00100       fflush(ourFP);
00101     }
00102     else if (ourType != None)
00103     {
00104       printf("%s\n", buf);
00105       fflush(stdout);
00106     }
00107     if (ourAlsoPrint)
00108       printf("%s\n", buf);
00109     va_end(ptr);
00110         ourMutex.unlock();
00111   }
00112 
00113 }
00114 
00125 bool ArLog::init(LogType type, LogLevel level, const char *fileName,
00126                           bool logTime, bool alsoPrint, bool printThisCall)
00127 {
00128   ourMutex.lock();
00129   
00130   // if we weren't or won't be doing a file then close any old file
00131   if (ourType != File || type != File)
00132   {
00133     close();
00134   }
00135   
00136   if (type == StdOut)
00137     ourFP=stdout;
00138   else if (type == StdErr)
00139     ourFP=stderr;
00140   else if (type == File)
00141   {
00142     if (fileName != NULL)
00143     {
00144       if (strcmp(ourFileName.c_str(), fileName) == 0)
00145       {
00146         ArLog::logNoLock(ArLog::Terse, "ArLog::init: Continuing to log to the same file.");
00147       }
00148       else
00149       {
00150         close();
00151         if ((ourFP = fopen(fileName, "w")) == NULL)
00152         {
00153           ArLog::logNoLock(ArLog::Terse, "ArLog::init: Could not open file %s for logging.", fileName);
00154           ourMutex.unlock();
00155           return(false);
00156         }
00157         ourFileName=fileName;
00158       }
00159     }
00160   }
00161   else if (type == Colbert)
00162   {
00163     colbertPrint = NULL;
00164     ourColbertStream = -1;      // use default stream
00165     if (fileName)
00166     {  // need to translate fileName to integer index
00167     }
00168   }
00169   else if (type == None)
00170   {
00171 
00172   }
00173   ourType=type;
00174   ourLevel=level;
00175 
00176   // environment variable overrides level
00177   {
00178     char* lev = getenv("ARLOG_LEVEL");
00179     if(lev)
00180     {
00181       switch(toupper(lev[0]))
00182       {
00183         case 'N':
00184           ourLevel = Normal;
00185           break;
00186         case 'T':
00187           ourLevel = Terse;
00188           break;
00189         case 'V':
00190           ourLevel = Verbose;
00191           break;
00192        }
00193     }
00194   }
00195 
00196   ourLoggingTime = logTime;
00197   ourAlsoPrint = alsoPrint;
00198 
00199   if (printThisCall)
00200   {
00201     printf("ArLog::init: ");
00202     
00203     if (ourType == StdOut)
00204       printf(" StdOut\t");
00205     else if (ourType == StdErr)
00206       printf(" StdErr\t");
00207     else if (ourType == File)
00208       printf(" File(%s)\t", ourFileName.c_str());
00209     else if (ourType == Colbert)
00210       printf(" Colbert\t");
00211     else if (ourType == None)
00212       printf(" None\t");
00213     else
00214       printf(" BadType\t");
00215     
00216     if (ourLevel == Terse)
00217       printf(" Terse\t");
00218     else if (ourLevel == Normal)
00219       printf(" Normal\t");
00220     else if (ourLevel == Verbose)
00221       printf(" Verbose\t");
00222     else
00223       printf(" BadLevel\t");
00224     
00225     if (ourLoggingTime)
00226       printf(" Logging Time\t");
00227     else
00228       printf(" Not logging time\t");
00229     
00230     if (ourAlsoPrint)
00231       printf(" Also printing\n");
00232     else
00233       printf(" Not also printing\n");
00234   }
00235   ourMutex.unlock();
00236   return(true);
00237 }
00238 
00239 void ArLog::close()
00240 {
00241   if (ourFP && (ourType == File))
00242   {
00243     fclose(ourFP);
00244     ourFP=0;
00245     ourFileName="";
00246   }
00247 }
00248 
00249 void ArLog::logNoLock(LogLevel level, const char *str, ...)
00250 {
00251   char buf[2048];
00252   char *bufPtr;
00253   char *timeStr;
00254   int timeLen = 20; // this is a value based on the standard length of
00255                        // ctime return
00256   time_t now;
00257 
00258   if (level <= ourLevel)
00259   {
00260     // put our time in if we want it
00261     if (ourLoggingTime)
00262     {
00263       now = time(NULL);
00264       timeStr = ctime(&now);
00265       // get take just the portion of the time we want
00266       strncpy(buf, timeStr, timeLen);
00267       buf[timeLen] = '\0';
00268       bufPtr = &buf[timeLen];
00269     }
00270     else
00271       bufPtr = buf;
00272     va_list ptr;
00273     va_start(ptr, str);
00274     vsprintf(bufPtr, str, ptr);
00275     // can do whatever you want with the buf now
00276     if (ourType == Colbert)
00277     {
00278       if (colbertPrint)         // check if we have a print routine
00279         (*colbertPrint)(ourColbertStream, buf);
00280     }
00281     else if (ourFP)
00282       fprintf(ourFP, "%s\n", buf);
00283     else if (ourType != None)
00284       printf("%s\n", buf);
00285     if (ourAlsoPrint)
00286       printf("%s\n", buf);
00287     va_end(ptr);
00288   }
00289 }
00290 
00291 void ArLog::addToConfig(ArConfig *config)
00292 {
00293   std::string section = "LogConfig";
00294   config->addParam(
00295           ArConfigArg("LogType", (int *)&ourConfigLogType,
00296                       "The type of log we'll be using, 0 for StdOut, 1 for StdErr, 2 for File (and give it a file name), 3 for colbert (don't use that), and 4 for None", 
00297                       ArLog::StdOut, ArLog::None), 
00298           section.c_str(), ArPriority::TRIVIAL);
00299   config->addParam(
00300           ArConfigArg("LogLevel", (int *)&ourConfigLogLevel,
00301                       "The level of logging to do, 0 for Terse, 1 for Normal, and 2 for Verbose", 
00302                       ArLog::Terse, ArLog::Verbose), 
00303           section.c_str(), ArPriority::TRIVIAL);
00304   config->addParam(
00305           ArConfigArg("LogFileName", ourConfigFileName,
00306                       "File to log to", sizeof(ourConfigFileName)),
00307           section.c_str(), ArPriority::TRIVIAL);
00308   config->addParam(
00309           ArConfigArg("LogTime", &ourConfigLogTime,
00310                       "True to prefix log messages with time and date, false not to"),
00311           section.c_str(), ArPriority::TRIVIAL);
00312   config->addParam(
00313           ArConfigArg("LogAlsoPrint", &ourConfigAlsoPrint,
00314                       "True to also printf the message, false not to"),   
00315           section.c_str(), ArPriority::TRIVIAL);
00316   ourConfigProcessFileCB.setName("ArLog");
00317   config->addProcessFileCB(&ourConfigProcessFileCB, 200);
00318 }
00319 
00320 bool ArLog::processFile(void)
00321 {
00322   if (ourConfigLogType != ourType || ourConfigLogLevel != ourLevel ||
00323       strcmp(ourConfigFileName, ourFileName.c_str()) != 0 || 
00324       ourConfigLogTime != ourLoggingTime || ourConfigAlsoPrint != ourAlsoPrint)
00325   {
00326     ArLog::log(ArLog::Normal, "Initializing log from config");
00327     return ArLog::init(ourConfigLogType, ourConfigLogLevel, ourConfigFileName, 
00328                        ourConfigLogTime, ourConfigAlsoPrint, true);
00329   }
00330   return true;
00331 }

Generated on Wed Oct 19 12:56:36 2005 for Aria by  doxygen 1.4.0