00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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;
00069
00070 time_t now;
00071
00072
00073 if (level <= ourLevel)
00074 {
00075 ourMutex.lock();
00076
00077 if (ourLoggingTime)
00078 {
00079 now = time(NULL);
00080 timeStr = ctime(&now);
00081
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
00092 if (ourType == Colbert)
00093 {
00094 if (colbertPrint)
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
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;
00165 if (fileName)
00166 {
00167 }
00168 }
00169 else if (type == None)
00170 {
00171
00172 }
00173 ourType=type;
00174 ourLevel=level;
00175
00176
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;
00255
00256 time_t now;
00257
00258 if (level <= ourLevel)
00259 {
00260
00261 if (ourLoggingTime)
00262 {
00263 now = time(NULL);
00264 timeStr = ctime(&now);
00265
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
00276 if (ourType == Colbert)
00277 {
00278 if (colbertPrint)
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 }