ESR_ReturnCode SR_EventLogCreate(SR_EventLog** self) { SR_EventLogImpl *impl, *any_existing_eventlog; ESR_ReturnCode rc; LCHAR* dataCaptureDir; #define TIMESTAMP_LENGTH 18 LCHAR timeStr[TIMESTAMP_LENGTH]; struct tm *ct, ct_r; PTimeStamp timestamp; #ifdef ANDROID struct timeval dir_stamp; #endif if (self == NULL) { PLogError(L("ESR_INVALID_ARGUMENT")); return ESR_INVALID_ARGUMENT; } any_existing_eventlog = NULL; rc = ESR_SessionGetProperty(L("eventlog"), (void **)&any_existing_eventlog, TYPES_SR_EVENTLOG); if (rc == ESR_SUCCESS && any_existing_eventlog) { *self = (SR_EventLog*)any_existing_eventlog; PLogError("eventlog was already created"); return ESR_SUCCESS; } impl = NEW(SR_EventLogImpl, MTAG); if (impl == NULL) { PLogError(L("ESR_OUT_OF_MEMORY")); return ESR_OUT_OF_MEMORY; } impl->Interface.destroy = &SR_EventLog_Destroy; impl->Interface.event = &SR_EventLog_Event; impl->Interface.token = &SR_EventLog_Token; impl->Interface.tokenInt = &SR_EventLog_TokenInt; impl->Interface.tokenPointer = &SR_EventLog_TokenPointer; impl->Interface.tokenUint16_t = &SR_EventLog_TokenUint16_t; impl->Interface.tokenSize_t = &SR_EventLog_TokenSize_t; impl->Interface.tokenBool = &SR_EventLog_TokenBool; impl->Interface.tokenFloat = &SR_EventLog_TokenFloat; impl->Interface.eventSession = &SR_EventLogEventSessionImpl; impl->Interface.audioOpen = &SR_EventLog_AudioOpen; impl->Interface.audioClose = &SR_EventLog_AudioClose; impl->Interface.audioWrite = &SR_EventLog_AudioWrite; impl->Interface.audioGetFilename = &SR_EventLog_AudioGetFilename; impl->sessionListenerPair.data = NULL; impl->sessionListenerPair.listener = &impl->sessionListener; impl->sessionListener.propertyChanged = &propertyChanged; impl->waveformCounter = 0; impl->logFile = NULL; impl->tokenBuf[0] = 0; impl->logFile_state = NO_FILE; impl->logLevel = 0; impl->waveformFile = NULL; LSTRCPY(impl->logFilename, L("")); CHKLOG(rc, ESR_SessionSetProperty(L("eventlog"), impl, TYPES_SR_EVENTLOG)); rc = ESR_SessionGetSize_t(L("SREC.Recognizer.osi_log_level"), &impl->logLevel); if (rc == ESR_NO_MATCH_ERROR) { impl->logLevel = 7; CHKLOG(rc, ESR_SessionSetSize_t(L("SREC.Recognizer.osi_log_level"), impl->logLevel)); } else if (rc != ESR_SUCCESS) { PLogError(ESR_rc2str(rc)); goto CLEANUP; } if (impl->logLevel > 0) { CHKLOG(rc, ESR_SessionGetProperty(L("cmdline.DataCaptureDirectory"), (void**) &dataCaptureDir, TYPES_PLCHAR)); LSTRCPY(impl->logFilename, dataCaptureDir); #ifdef ANDROID /* * The existing functions did not work on the desired platform, hence this code for the device. */ gettimeofday ( &dir_stamp, NULL ); sprintf(timeStr, "%lu", (unsigned long) dir_stamp.tv_sec ); #else PTimeStampSet(×tamp); ct = localtime_r(×tamp.secs, &ct_r); sprintf(timeStr, "%04d%02d%02d%02d%02d%02d", ct->tm_year + 1900, ct->tm_mon + 1, ct->tm_mday, ct->tm_hour, ct->tm_min, ct->tm_sec); #endif /* create capture directory if it doesn't already exist */ rc = pf_make_dir (impl->logFilename); if (rc != ESR_SUCCESS && rc != ESR_IDENTIFIER_COLLISION) { PLogError(ESR_rc2str(rc)); goto CLEANUP; } /* create the directory for today's log if it doesn't already exist */ LSTRCAT(impl->logFilename, L("/")); LSTRCAT(impl->logFilename, timeStr); /* * There used to be a while forever loop here with a break, but that caused an infinite loop * for the customer. With 1 second resolution, a pre-existing directory probably means a bug. * It's not worth trying to handle this. */ rc = pf_make_dir (impl->logFilename); if (rc != ESR_SUCCESS) { PLogError(ESR_rc2str(rc)); goto CLEANUP; } /* create the log file */ LSTRCAT(impl->logFilename, L("/SWIevent-")); LSTRCAT(impl->logFilename, timeStr); LSTRCAT(impl->logFilename, L(".log")); impl->logFile = pfopen ( impl->logFilename, L("w") ); /* CHKLOG(rc, PFileSystemCreatePFile(impl->logFilename, ESR_TRUE, &impl->logFile)); CHKLOG(rc, PFileOpen(impl->logFile, L("w")));*/ if ( impl->logFile != NULL ) impl->logFile_state = FILE_OK; else goto CLEANUP; } *self = (SR_EventLog*) impl; return ESR_SUCCESS; CLEANUP: if (impl->logFile) pfclose (impl->logFile); return rc; }
ESR_ReturnCode logIt(SR_EventLogImpl *impl, LCHAR* evtt, LCHAR* log_record, size_t* writtenSize) { struct tm *ct, ct_r; LCHAR header[128], header2[64]; PTimeStamp timestamp; const size_t sizeof_LCHAR = sizeof(LCHAR); const LCHAR* bar = "|"; const LCHAR* nl = "\n"; size_t i, len; const LCHAR* toWrite[5]; toWrite[0] = header; toWrite[1] = bar; toWrite[2] = evtt; toWrite[3] = log_record; toWrite[4] = nl; ct = &ct_r; memset(ct, 0, sizeof(struct tm)); switch (impl->logFile_state) { case FILE_OK: case SPACE_SETTING: PTimeStampSet(×tamp); ct = localtime_r(×tamp.secs, &ct_r); sprintf(header, "TIME=%04d%02d%02d%02d%02d%02d%03d", ct->tm_year + 1900, ct->tm_mon + 1, ct->tm_mday, ct->tm_hour, ct->tm_min, ct->tm_sec, timestamp.msecs); quote_delimiter(header, 128); sprintf(header2, "CHAN=%s", L("0")); /* default is channel 0 in ESR */ quote_delimiter(header2, 128); LSTRCAT(header, bar); LSTRCAT(header, header2); /* write the header,bar,evtt, and record */ for (*writtenSize = 0, i = 0; i < 5; i++) { len = LSTRLEN(toWrite[i]); if (pfwrite(toWrite[i], sizeof_LCHAR, len, impl->logFile)) *writtenSize += len; } if (*writtenSize <= 0) { PLogError(L("Could not write to log file; logging halted")); impl->logFile_state = FILE_ERROR; break; } else { pfflush(impl->logFile); } break; /* If couldn't open file or error previously, just return */ case UNINITIALIZED: case NO_FILE: case FILE_ERROR: case SEEK_ERROR: default: return ESR_INVALID_STATE; } return ESR_SUCCESS; }
static ESR_ReturnCode logIt(const LCHAR *format, va_list args, ESR_BOOL showStackTrace) { ESR_ReturnCode rc = ESR_SUCCESS; ESR_ReturnCode flushRC = ESR_SUCCESS; #ifdef USE_STACKTRACE #define BUFFER_SIZE P_MAX_STACKTRACE + 2000 #else #define BUFFER_SIZE 2000 #endif LCHAR buffer[BUFFER_SIZE] = L(""); // TODO: Remove once logging subsystem supports "warn" level if (strstr(format, "ESR_BUFFER_OVERFLOW")==format) return ESR_SUCCESS; #ifdef USE_STACKTRACE if (Glogger == NULL) { /* * There are three possible scenerios for why logging would occur although the PLog module * is uninitialized: * * 1) The code fails before PLog is initialized (perhaps in other portable components) * 2) The user forgets to initialize the PLog module * 3) The code fails after PLog is uninitialized (on shutdown) * * We do our best by logging any errors but this might result in the memory leak of * the PStackTrace module in case 3. */ rc = PStackTraceCreate(); if (rc != ESR_SUCCESS) { PLOG_PANIC(L("PStackTraceCreate"), rc); goto CLEANUP; } } else { #ifdef USE_THREAD rc = PtrdMutexLock(Gmutex); if (rc != ESR_SUCCESS) return rc; #endif } if (locked) return ESR_INVALID_STATE; locked = ESR_TRUE; if (GlogFormat & LOG_OUTPUT_FORMAT_DATE_TIME) { PTimeStamp now; struct tm* loctime; LCHAR timeStr[TIME_BUF_SIZE]; size_t timeStrSize; PTimeStampSet(&now); loctime = localtime(&now.secs); timeStrSize = LSTRFTIME(timeStr, TIME_BUF_SIZE, TIME_FORMAT, loctime); passert(timeStrSize == (TIME_BUF_SIZE - 5)); psprintf(timeStr + (TIME_BUF_SIZE - 5), ".%03hu", now.msecs); psprintf(buffer + LSTRLEN(buffer), L("%s|"), timeStr); passert(LSTRLEN(buffer) < BUFFER_SIZE); } if (GlogFormat & LOG_OUTPUT_FORMAT_THREAD_ID) { rc = psprintf(buffer + LSTRLEN(buffer), L("trd=%u|"), PtrdGetCurrentThreadId()); passert(LSTRLEN(buffer) < BUFFER_SIZE); } if (GlogFormat & LOG_OUTPUT_FORMAT_MODULE_NAME && showStackTrace) { size_t len = P_MAX_STACKTRACE; LCHAR text[P_MAX_STACKTRACE]; LCHAR* index; size_t i; rc = PStackTraceGetValue((LCHAR*) & text, &len); if (rc == ESR_SUCCESS) { for (i = 0; i < 2; ++i) { rc = PStackTracePopLevel((LCHAR*) & text); if (rc != ESR_SUCCESS) { PLOG_PANIC(L("PStackTracePopLevel"), rc); goto CLEANUP; } } index = text; while (index) { index = LSTRSTR(index, L(" at\n")); if (index != NULL) { *(index + 1) = L('<'); *(index + 2) = L('-'); *(index + 3) = L(' '); } } } else if (rc == ESR_NOT_SUPPORTED) LSTRCPY(text, L("")); else if (rc != ESR_SUCCESS) { PLOG_PANIC(L("PStackTraceGetValue"), rc); goto CLEANUP; } rc = psprintf(buffer + LSTRLEN(buffer), L("Module=%s|"), text); passert(LSTRLEN(buffer) < BUFFER_SIZE); } pvsprintf(buffer + LSTRLEN(buffer), format, args); #else pvsprintf(buffer + LSTRLEN(buffer), format, args); #endif passert(LSTRLEN(buffer) < BUFFER_SIZE); psprintf(buffer + LSTRLEN(buffer), L("\n")); passert(LSTRLEN(buffer) < BUFFER_SIZE); if (Glogger != NULL) { rc = Glogger->printf(Glogger, L("%s"), buffer); if (rc != ESR_SUCCESS) goto CLEANUP; flushRC = Glogger->flush(Glogger); } else { /* We need to log but the logging module is disabled or is locked so we output to stderr instead */ { pfprintf(PSTDERR, L("%s"), buffer); pfflush(PSTDERR); } } locked = ESR_FALSE; #ifdef USE_THREAD PtrdMutexUnlock(Gmutex); #endif return flushRC; CLEANUP: if (Glogger != NULL && Glogger->flush != NULL) flushRC = Glogger->flush(Glogger); locked = ESR_FALSE; #ifdef USE_THREAD PtrdMutexUnlock(Gmutex); #endif return rc != ESR_SUCCESS ? rc : flushRC; }