📄 sblog.cpp
字号:
if (*info != *(*i)) continue; status = *i; contentCallbacks.erase(i); break; } if (! Unlock( )) return NULL; } return status; } VXIlogResult SBlog::ParseKeyValue(const VXIchar *format, va_list args, VXIVector *keys, VXIVector *values) const { const VXIchar SEP[] = L"{*}"; const int SEP_LEN = 3; if (( format == NULL ) || ( keys == NULL ) || ( values == NULL )) { Error(208, L"SBlog: Internal error in ParseKeyValue(), invalid argument", NULL); return VXIlog_RESULT_INVALID_ARGUMENT; } // Insert delimiters into a revised format string, this does // validation as well as letting us split it into key/values later VXIlogResult rc = VXIlog_RESULT_SUCCESS; bool hadFreeformText = false; int replacementStart = -1, fieldCount = 0; size_t resultFormatLen = 0; VXIchar resultFormat[MAX_LOG_BUFFER]; resultFormat[0] = L'\0'; for (int i = 0; (format[i] != L'\0') && (rc == VXIlog_RESULT_SUCCESS); i++) { if (format[i] == '%') { if (replacementStart > -1) replacementStart = -1; // double %% else replacementStart = i; } else if ((replacementStart > -1) && (SBlogIsAlpha(format[i])) && (format[i] != L'l') && (format[i] != L'L') && (format[i] != L'h')) { if ((fieldCount % 2 == 0) && (format[i] != L's') && (format[i] != L'S')) { // Keys must be a %s or %S, truncate from here Error(301, L"SBlog: Invalid format string for VXIlog API call, " L"replacements for key names must be %s", L"%s%s", L"format", format); rc = VXIlog_RESULT_NON_FATAL_ERROR; } else { // Insert the replacement expression and the seperator size_t index = resultFormatLen; resultFormatLen += (i - replacementStart) + 1 + SEP_LEN; if (resultFormatLen < MAX_LOG_BUFFER) { wcsncpy(&resultFormat[index], &format[replacementStart], (i - replacementStart) + 1); index += (i - replacementStart) + 1; wcscpy(&resultFormat[index], SEP); } else { // Overflow, truncate the format string from here rc = VXIlog_RESULT_NON_FATAL_ERROR; } replacementStart = -1; fieldCount++; } } else if (replacementStart == -1) { // Shouldn't have free-form text, skip it. Proceeding allows us // to gracefully handle things like "%s0x%p". hadFreeformText = true; } } // if key/value is not even truncate the field and return an error, // but proceed with the other fields. If there was free form text, // we skipped it and return an error, but proceed with logging. if (fieldCount % 2 != 0) { Error(302, L"SBlog: Invalid format string for VXIlog API call, " L"missing value for a key", L"%s%s", L"format", format); rc = VXIlog_RESULT_NON_FATAL_ERROR; fieldCount--; } else if (hadFreeformText) { Error(303, L"SBlog: Invalid format string for VXIlog API call, " L"must be a list of format strings for key/value pairs", L"%s%s", L"format", format); rc = VXIlog_RESULT_NON_FATAL_ERROR; } // get the values VXIchar result[MAX_LOG_BUFFER]; result[0] = L'\0'; SBlogVswprintf(result, MAX_LOG_BUFFER-1, resultFormat, args); // parse the key/value based on the inserted separators long fieldNum = 0; const VXIchar *start = result, *end; while ((fieldNum < fieldCount) && ((end = wcsstr(start, SEP)) != NULL)) { // Insert into key/value vector fieldNum++; if (fieldNum % 2) // odd is key VXIVectorAddElement(keys,(VXIValue*)VXIStringCreateN(start,end-start)); else VXIVectorAddElement(values,(VXIValue*)VXIStringCreateN(start,end-start)); // Advance start = &end[SEP_LEN]; } if (fieldNum != fieldCount) { // parse error Error(304, L"SBlog: Internal error, parse failure after key/value " L"insertions", L"%s%s%s%s", L"format", format, L"result", result); rc = VXIlog_RESULT_NON_FATAL_ERROR; } return rc; } VXIlogResult SBlog::Error(VXIunsigned errorID, const VXIchar *errorIDText, const VXIchar *format, ...) const { VXIlogResult rc = VXIlog_RESULT_SUCCESS; // Avoid recursively reporting logging errors if (_internalErrorLoggingThread == GetThreadID()) return VXIlog_RESULT_FAILURE; if (VXItrdMutexLock(_internalErrorLoggingLock) != VXItrd_RESULT_SUCCESS) { return VXIlog_RESULT_SYSTEM_ERROR; } else { VXIthreadID *loggingThread = const_cast<VXIthreadID *>(&_internalErrorLoggingThread); *loggingThread = GetThreadID(); va_list args; va_start(args, format); rc = ErrorLog(MODULE_NAME, errorID, format, args); if ( rc != VXIlog_RESULT_SUCCESS ) SBlogVLogErrorToConsole(MODULE_NAME, errorID, errorIDText, format, args); va_end(args); *loggingThread = (VXIthreadID) -1; if (VXItrdMutexUnlock(_internalErrorLoggingLock) != VXItrd_RESULT_SUCCESS) return VXIlog_RESULT_SYSTEM_ERROR; } return rc; } VXIlogResult SBlog::GlobalError(VXIunsigned errorID, const VXIchar *errorIDText, const VXIchar *format, ...) { va_list args; va_start(args, format); VXIlogResult rc = SBlogVLogErrorToConsole(MODULE_NAME, errorID, errorIDText, format, args); va_end(args); return rc; } bool SBlog::DiagnosticIsEnabled(VXIunsigned tagID) { VXIunsigned bindex, bpos; if (!Convert2Index(tagID, &bindex, &bpos)) return false; // if this tag is not turned on, just return if (!testbit(_tagIDs[bindex],bpos)) return false; return true; } VXIlogResult SBlog::DiagnosticLog(VXIunsigned tagID, const VXIchar* subtag, const VXIchar* format, va_list arguments) const { VXIunsigned bindex, bpos; if (!Convert2Index(tagID, &bindex, &bpos)) return VXIlog_RESULT_INVALID_ARGUMENT; // if this tag is not turned on, just return if (!testbit(_tagIDs[bindex],bpos)) return VXIlog_RESULT_SUCCESS; time_t timestamp; VXIunsigned timestampMsec; SBlogGetTime (×tamp, ×tampMsec); wchar_t printmsg[MAX_LOG_BUFFER]; printmsg[0] = L'\0'; if (format != NULL) SBlogVswprintf(printmsg, MAX_LOG_BUFFER-1, format, arguments); if (subtag == NULL) subtag = L""; // Get a temporary callback vector copy to traverse, allows // listeners to unregister from within the listener, also increases // parallelism by allowing multiple threads to be calling the // callbacks at once VXIlogResult rc = VXIlog_RESULT_FAILURE; if (! Lock( )) { return VXIlog_RESULT_SYSTEM_ERROR; } else { DIAGCALLBACKS tempDiag = diagCallbacks; if (! Unlock( )) return VXIlog_RESULT_SYSTEM_ERROR; for (DIAGCALLBACKS::iterator i = tempDiag.begin(); i != tempDiag.end();++i) { (*i)->callback(_pThis, tagID, subtag, timestamp, timestampMsec, printmsg, (*i)->userdata); rc = VXIlog_RESULT_SUCCESS; } } return rc; } VXIlogResult SBlog::EventLog(VXIunsigned eventID, const VXIchar* format, va_list args) const { time_t timestamp; VXIunsigned timestampMsec; SBlogGetTime (×tamp, ×tampMsec); // Create key/value pairs VXIVector *keys = VXIVectorCreate(); VXIVector *values = VXIVectorCreate(); if ((! keys) || (! values)) { Error(SBLOG_ERR_OUT_OF_MEMORY); return VXIlog_RESULT_OUT_OF_MEMORY; } VXIlogResult rc = VXIlog_RESULT_SUCCESS; if (format) { rc = ParseKeyValue(format, args, keys, values); if (rc < VXIlog_RESULT_SUCCESS) { VXIVectorDestroy(&keys); VXIVectorDestroy(&values); return rc; } } // Get a temporary callback vector copy to traverse, allows // listeners to unregister from within the listener, also increases // parallelism by allowing multiple threads to be calling the // callbacks at once if (rc == VXIlog_RESULT_SUCCESS) rc = VXIlog_RESULT_FAILURE; if (! Lock( )) { return VXIlog_RESULT_SYSTEM_ERROR; } else { EVENTCALLBACKS tempEvent = eventCallbacks; if (! Unlock( )) return VXIlog_RESULT_SYSTEM_ERROR; for (EVENTCALLBACKS::iterator i = tempEvent.begin(); i != tempEvent.end(); ++i) { (*i)->callback(_pThis, eventID, timestamp, timestampMsec, keys, values, (*i)->userdata); if (rc == VXIlog_RESULT_FAILURE) rc = VXIlog_RESULT_SUCCESS; } } VXIVectorDestroy(&keys); VXIVectorDestroy(&values); return rc; } VXIlogResult SBlog::EventLog(VXIunsigned eventID, const VXIVector* keys, const VXIVector* values) const { time_t timestamp; VXIunsigned timestampMsec; SBlogGetTime (×tamp, ×tampMsec); // Get a temporary callback vector copy to traverse, allows // listeners to unregister from within the listener, also increases // parallelism by allowing multiple threads to be calling the // callbacks at once VXIlogResult rc = VXIlog_RESULT_FAILURE; if (! Lock( )) { return VXIlog_RESULT_SYSTEM_ERROR; } else { EVENTCALLBACKS tempEvent = eventCallbacks; if (! Unlock( )) return VXIlog_RESULT_SYSTEM_ERROR; for (EVENTCALLBACKS::iterator i = tempEvent.begin(); i != tempEvent.end(); ++i) { (*i)->callback(_pThis, eventID, timestamp, timestampMsec, keys, values, (*i)->userdata); rc = VXIlog_RESULT_SUCCESS; } } return rc; } VXIlogResult SBlog::ErrorLog(const VXIchar* moduleName, VXIunsigned errorID, const VXIchar* format, va_list args) const { time_t timestamp; VXIunsigned timestampMsec; SBlogGetTime (×tamp, ×tampMsec); // Create key/value pairs VXIVector *keys = VXIVectorCreate(); VXIVector *values = VXIVectorCreate(); if ((! keys) || (! values)) { Error(SBLOG_ERR_OUT_OF_MEMORY); return VXIlog_RESULT_OUT_OF_MEMORY; } VXIlogResult rc = VXIlog_RESULT_SUCCESS; if (format) { rc = ParseKeyValue(format, args, keys, values); if (rc < VXIlog_RESULT_SUCCESS) { VXIVectorDestroy(&keys); VXIVectorDestroy(&values); return rc; } } // Get a temporary callback vector copy to traverse, allows // listeners to unregister from within the listener, also increases // parallelism by allowing multiple threads to be calling the // callbacks at once if (rc == VXIlog_RESULT_SUCCESS) rc = VXIlog_RESULT_FAILURE; if (! Lock( )) { return VXIlog_RESULT_SYSTEM_ERROR; } else { ERRORCALLBACKS tempError = errorCallbacks; if (! Unlock( )) return VXIlog_RESULT_SYSTEM_ERROR; for (ERRORCALLBACKS::iterator i = tempError.begin(); i != tempError.end(); ++i) { (*i)->callback(_pThis, (moduleName && moduleName[0] ? moduleName : L"UNKNOWN"), errorID, timestamp, timestampMsec, keys, values, (*i)->userdata); if (rc == VXIlog_RESULT_FAILURE) rc = VXIlog_RESULT_SUCCESS; } } VXIVectorDestroy(&keys); VXIVectorDestroy(&values); // Want to warn the caller that NULL moduleName really isn't OK, but // logged it anyway if ((! moduleName) || (! moduleName[0])) { Error(305, L"SBlog: Empty module name passed to VXIlog API call", NULL); rc = VXIlog_RESULT_INVALID_ARGUMENT; } return rc; } VXIlogResult SBlog::ContentOpen(const VXIchar* moduleName, const VXIchar* contentType, VXIString** logKey, VXIString** logValue, VXIlogStream** stream) const { if ((! contentType) || (! contentType[0]) || (! logKey) || (! logValue) || (! stream)) { Error(306, L"SBlog: Invalid argument to VXIlog::ContentOpen()", NULL); return VXIlog_RESULT_INVALID_ARGUMENT; } *logKey = *logValue = NULL; *stream = NULL; const VXIchar *finalModuleName = L"UNKNOWN"; if ((! moduleName) || (! moduleName[0])) { Error(305, L"SBlog: Empty module name passed to VXIlog API call", NULL); } else { finalModuleName = moduleName; } VXIlogResult rc = VXIlog_RESULT_FAILURE; // Get a temporary callback vector copy to traverse, allows // listeners to unregister from within the listener, also increases // parallelism by allowing multiple threads to be calling the // callbacks at once if (! Lock( )) { return VXIlog_RESULT_SYSTEM_ERROR; } else { CONTENTCALLBACKS tempContent = contentCallbacks; if (! Unlock( )) return VXIlog_RESULT_SYSTEM_ERROR; VXIlogStream *finalStream = NULL; for (CONTENTCALLBACKS::iterator i = tempContent.begin(); i != tempContent.end(); ++i) { VXIString *logKey_ = NULL; VXIString *logValue_ = NULL; SBlogStream *stream_ = NULL; VXIlogResult rc2 = (*i)->callback(_pThis, finalModuleName, contentType, (*i)->userdata, &logKey_, &logValue_, &stream_); if ((rc2 == VXIlog_RESULT_SUCCESS) && (stream_)) { // Return the key and value of only the first listener if ( rc != VXIlog_RESULT_SUCCESS ) { finalStream = new VXIlogStream; if (! finalStream) { VXIStringDestroy(&logKey_); VXIStringDestroy(&logValue_); stream_->Close(&stream_); Error(SBLOG_ERR_OUT_OF_MEMORY); return VXIlog_RESULT_OUT_OF_MEMORY; } rc = VXIlog_RESULT_SUCCESS; *logKey = logKey_; *logValue = logValue_; *stream = (VXIlogStream *) finalStream; } else { VXIStringDestroy(&logKey_); VXIStringDestroy(&logValue_); } // Store the stream finalStream->streams.push_back(stream_); } else if ((rc != VXIlog_RESULT_SUCCESS) && (((rc < 0) && (rc2 < rc)) || ((rc > 0) && (rc2 > rc)))) { // Return success if any listener returns success but keep the // worst error otherwise rc = rc2; } } } return rc; } VXIlogResult SBlog::ContentClose(VXIlogStream** stream) const { if ((! stream) || (! *stream)) { Error(307, L"SBlog: Invalid argument to VXIlog::ContentClose()", NULL); return VXIlog_RESULT_INVALID_ARGUMENT; } VXIlogResult rc = VXIlog_RESULT_SUCCESS; // Close each of the underlying listener streams for (VXIlogStream::STREAMS::iterator vi = (*stream)->streams.begin( ); vi != (*stream)->streams.end( ); vi++) { SBlogStream *s = *vi; VXIlogResult rc2 = s->Close (&s); if ((rc == VXIlog_RESULT_SUCCESS) || ((rc < 0) && (rc2 < rc)) || ((rc > 0) && (rc2 > rc))) rc = rc2; } delete *stream; *stream = NULL; return rc; } VXIlogResult SBlog::ContentWrite(const VXIbyte* buffer, VXIulong buflen, VXIulong* nwritten, VXIlogStream* stream) const { if ((! buffer) || (buflen < 1) || (! nwritten) || (! stream)) { Error(308, L"SBlog: Invalid argument to VXIlog::ContentWrite()", NULL); return VXIlog_RESULT_INVALID_ARGUMENT; } VXIlogResult rc = VXIlog_RESULT_SUCCESS; *nwritten = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -