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 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArLog.h"
00029 #include "ArConfig.h"
00030 #include <time.h>
00031 #include <stdarg.h>
00032 #include <ctype.h>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 ArMutex ArLog::ourMutex;
00043 ArLog::LogType ArLog::ourType=StdOut;
00044 ArLog::LogLevel ArLog::ourLevel=ArLog::Normal;
00045 FILE * ArLog::ourFP=0;
00046 std::string ArLog::ourFileName;
00047 int ArLog::ourColbertStream = -1;
00048 bool ArLog::ourLoggingTime = false;
00049 bool ArLog::ourAlsoPrint = false;
00050 AREXPORT void (* ArLog::colbertPrint)(int i, const char *str);
00051
00052 ArLog::LogType ArLog::ourConfigLogType = ArLog::StdOut;
00053 ArLog::LogLevel ArLog::ourConfigLogLevel = ArLog::Normal;
00054 char ArLog::ourConfigFileName[1024] = "log.txt";
00055 bool ArLog::ourConfigLogTime = false;
00056 bool ArLog::ourConfigAlsoPrint = false;
00057 ArGlobalRetFunctor<bool> ArLog::ourConfigProcessFileCB(&ArLog::processFile);
00058
00059 AREXPORT void ArLog::logPlain(LogLevel level, const char *str)
00060 {
00061 log(level, str);
00062 }
00063
00070 AREXPORT void ArLog::log(LogLevel level, const char *str, ...)
00071 {
00072 char buf[2048];
00073 char *bufPtr;
00074 char *timeStr;
00075 int timeLen = 20;
00076
00077 time_t now;
00078
00079
00080 if (level <= ourLevel)
00081 {
00082 ourMutex.lock();
00083
00084 if (ourLoggingTime)
00085 {
00086 now = time(NULL);
00087 timeStr = ctime(&now);
00088
00089 strncpy(buf, timeStr, timeLen);
00090 buf[timeLen] = '\0';
00091 bufPtr = &buf[timeLen];
00092 }
00093 else
00094 bufPtr = buf;
00095 va_list ptr;
00096 va_start(ptr, str);
00097 vsprintf(bufPtr, str, ptr);
00098
00099 if (ourType == Colbert)
00100 {
00101 if (colbertPrint)
00102 (*colbertPrint)(ourColbertStream, buf);
00103 }
00104 else if (ourFP)
00105 {
00106 fprintf(ourFP, "%s\n", buf);
00107 fflush(ourFP);
00108 }
00109 else if (ourType != None)
00110 {
00111 printf("%s\n", buf);
00112 fflush(stdout);
00113 }
00114 if (ourAlsoPrint)
00115 printf("%s\n", buf);
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 va_end(ptr);
00127 ourMutex.unlock();
00128 }
00129
00130 }
00131
00142 AREXPORT bool ArLog::init(LogType type, LogLevel level, const char *fileName,
00143 bool logTime, bool alsoPrint, bool printThisCall)
00144 {
00145 ourMutex.lock();
00146
00147
00148 if (ourType != File || type != File)
00149 {
00150 close();
00151 }
00152
00153 if (type == StdOut)
00154 ourFP=stdout;
00155 else if (type == StdErr)
00156 ourFP=stderr;
00157 else if (type == File)
00158 {
00159 if (fileName != NULL)
00160 {
00161 if (strcmp(ourFileName.c_str(), fileName) == 0)
00162 {
00163 ArLog::logNoLock(ArLog::Terse, "ArLog::init: Continuing to log to the same file.");
00164 }
00165 else
00166 {
00167 close();
00168 if ((ourFP = fopen(fileName, "w")) == NULL)
00169 {
00170 ArLog::logNoLock(ArLog::Terse, "ArLog::init: Could not open file %s for logging.", fileName);
00171 ourMutex.unlock();
00172 return(false);
00173 }
00174 ourFileName=fileName;
00175 }
00176 }
00177 }
00178 else if (type == Colbert)
00179 {
00180 colbertPrint = NULL;
00181 ourColbertStream = -1;
00182 if (fileName)
00183 {
00184 }
00185 }
00186 else if (type == None)
00187 {
00188
00189 }
00190 ourType=type;
00191 ourLevel=level;
00192
00193
00194 {
00195 char* lev = getenv("ARLOG_LEVEL");
00196 if(lev)
00197 {
00198 switch(toupper(lev[0]))
00199 {
00200 case 'N':
00201 ourLevel = Normal;
00202 break;
00203 case 'T':
00204 ourLevel = Terse;
00205 break;
00206 case 'V':
00207 ourLevel = Verbose;
00208 break;
00209 }
00210 }
00211 }
00212
00213 ourLoggingTime = logTime;
00214 ourAlsoPrint = alsoPrint;
00215
00216 if (printThisCall)
00217 {
00218 printf("ArLog::init: ");
00219
00220 if (ourType == StdOut)
00221 printf(" StdOut\t");
00222 else if (ourType == StdErr)
00223 printf(" StdErr\t");
00224 else if (ourType == File)
00225 printf(" File(%s)\t", ourFileName.c_str());
00226 else if (ourType == Colbert)
00227 printf(" Colbert\t");
00228 else if (ourType == None)
00229 printf(" None\t");
00230 else
00231 printf(" BadType\t");
00232
00233 if (ourLevel == Terse)
00234 printf(" Terse\t");
00235 else if (ourLevel == Normal)
00236 printf(" Normal\t");
00237 else if (ourLevel == Verbose)
00238 printf(" Verbose\t");
00239 else
00240 printf(" BadLevel\t");
00241
00242 if (ourLoggingTime)
00243 printf(" Logging Time\t");
00244 else
00245 printf(" Not logging time\t");
00246
00247 if (ourAlsoPrint)
00248 printf(" Also printing\n");
00249 else
00250 printf(" Not also printing\n");
00251 }
00252 ourMutex.unlock();
00253 return(true);
00254 }
00255
00256 AREXPORT void ArLog::close()
00257 {
00258 if (ourFP && (ourType == File))
00259 {
00260 fclose(ourFP);
00261 ourFP=0;
00262 ourFileName="";
00263 }
00264 }
00265
00266 AREXPORT void ArLog::logNoLock(LogLevel level, const char *str, ...)
00267 {
00268 char buf[2048];
00269 char *bufPtr;
00270 char *timeStr;
00271 int timeLen = 20;
00272
00273 time_t now;
00274
00275 if (level <= ourLevel)
00276 {
00277
00278 if (ourLoggingTime)
00279 {
00280 now = time(NULL);
00281 timeStr = ctime(&now);
00282
00283 strncpy(buf, timeStr, timeLen);
00284 buf[timeLen] = '\0';
00285 bufPtr = &buf[timeLen];
00286 }
00287 else
00288 bufPtr = buf;
00289 va_list ptr;
00290 va_start(ptr, str);
00291 vsprintf(bufPtr, str, ptr);
00292
00293 if (ourType == Colbert)
00294 {
00295 if (colbertPrint)
00296 (*colbertPrint)(ourColbertStream, buf);
00297 }
00298 else if (ourFP)
00299 fprintf(ourFP, "%s\n", buf);
00300 else if (ourType != None)
00301 printf("%s\n", buf);
00302 if (ourAlsoPrint)
00303 printf("%s\n", buf);
00304 va_end(ptr);
00305 }
00306 }
00307
00308 AREXPORT void ArLog::addToConfig(ArConfig *config)
00309 {
00310 std::string section = "LogConfig";
00311 config->addParam(
00312 ArConfigArg("LogType", (int *)&ourConfigLogType,
00313 "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",
00314 ArLog::StdOut, ArLog::None),
00315 section.c_str(), ArPriority::TRIVIAL);
00316 config->addParam(
00317 ArConfigArg("LogLevel", (int *)&ourConfigLogLevel,
00318 "The level of logging to do, 0 for Terse, 1 for Normal, and 2 for Verbose",
00319 ArLog::Terse, ArLog::Verbose),
00320 section.c_str(), ArPriority::TRIVIAL);
00321 config->addParam(
00322 ArConfigArg("LogFileName", ourConfigFileName,
00323 "File to log to", sizeof(ourConfigFileName)),
00324 section.c_str(), ArPriority::TRIVIAL);
00325 config->addParam(
00326 ArConfigArg("LogTime", &ourConfigLogTime,
00327 "True to prefix log messages with time and date, false not to"),
00328 section.c_str(), ArPriority::TRIVIAL);
00329 config->addParam(
00330 ArConfigArg("LogAlsoPrint", &ourConfigAlsoPrint,
00331 "True to also printf the message, false not to"),
00332 section.c_str(), ArPriority::TRIVIAL);
00333 ourConfigProcessFileCB.setName("ArLog");
00334 config->addProcessFileCB(&ourConfigProcessFileCB, 200);
00335 }
00336
00337 AREXPORT bool ArLog::processFile(void)
00338 {
00339 if (ourConfigLogType != ourType || ourConfigLogLevel != ourLevel ||
00340 strcmp(ourConfigFileName, ourFileName.c_str()) != 0 ||
00341 ourConfigLogTime != ourLoggingTime || ourConfigAlsoPrint != ourAlsoPrint)
00342 {
00343 ArLog::log(ArLog::Normal, "Initializing log from config");
00344 return ArLog::init(ourConfigLogType, ourConfigLogLevel, ourConfigFileName,
00345 ourConfigLogTime, ourConfigAlsoPrint, true);
00346 }
00347 return true;
00348 }