* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "dlog_async_process.h"
#include "log_ring_buffer.h"
#include "dlog_time.h"
#include "dlog_level_mgr.h"
#include "log_time.h"
#include "dlog_unified_timer_api.h"
#include "unified_timer_error_code.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LOG_TIMER_PERIOD 1000U
#define LOG_TIMER_TRIGER_COST_MAX_TIME 2U * LOG_TIMER_PERIOD * US_TO_MS
#define LOG_SEND_COST_MAX_TIME 150000U
#define LOG_LOCK_COST_MAX_TIME 50000U
#define LOG_LOST_PRINT_PERIOD_TIME 900000000UL
#define LOG_MAX_COVERED_LOSS_NUM 10000UL
#define LOG_SYNC_PERIOD 1
#define LOG_BUF_NUM 4U
#define LOG_MONITOR_TIME_OUT_PRINT(cost, threshold, format, ...) \
NO_ACT_WARN_LOG((cost) / LogGetCpuFrequency() * TICK_TO_US >= (threshold), \
format " timeout, cost time = %llu us", ##__VA_ARGS__, (cost) / LogGetCpuFrequency() * TICK_TO_US)
#define LOG_MONITOR_TIME_OUT(action, threshold, format, ...) \
do { \
uint64_t start = LogGetCpuCycleCounter(); \
action; \
uint64_t end = LogGetCpuCycleCounter(); \
uint64_t cost = end - start; \
LOG_MONITOR_TIME_OUT_PRINT(cost, threshold, format, ##__VA_ARGS__); \
} while (0)
#if defined LOG_CPP || defined APP_LOG
#define DLOG_TIMER_NAME "alog_send_task_timer"
#define DLOG_SYNC_TIMER_NAME "alog_sync_task_timer"
#else
#define DLOG_TIMER_NAME "slog_send_task_timer"
#define DLOG_SYNC_TIMER_NAME "slog_sync_task_timer"
#endif
typedef struct DlogBufferMgr {
RingBufferStat *dlogBuf[LOG_BUF_NUM];
uint64_t lossCount;
uint64_t lastPrintTime;
uint32_t writeBufIndex;
uint32_t sendBufIndex;
} DlogBufferMgr;
typedef struct DlogLevelCtrlMgr {
bool ctrlSwitch;
int32_t ctrlLevel;
uint64_t lossCount;
struct timespec ctrlLastTv;
} DlogLevelCtrlMgr;
typedef struct DlogNsycMgr {
bool initFlag;
bool syncFlag;
DlogBufferMgr bufMgr;
ToolMutex mutex;
DlogLevelCtrlMgr levelCtrl;
int32_t himemFd;
} DlogNsycMgr;
STATIC DlogNsycMgr g_dlogAsyncMgr = {false, false, {{NULL, NULL, NULL, NULL}, 0, 0, 0, 0}, PTHREAD_MUTEX_INITIALIZER,
{false, DLOG_DEBUG, 0, {0, 0}}, -1};
* @brief : init mutex, set robust
*/
STATIC void DlogInitMutex(void)
{
pthread_mutexattr_t mAttr;
(void)pthread_mutexattr_init(&mAttr);
(void)pthread_mutexattr_setrobust(&mAttr, PTHREAD_MUTEX_ROBUST);
(void)pthread_mutex_init(&g_dlogAsyncMgr.mutex, &mAttr);
(void)pthread_mutexattr_destroy(&mAttr);
}
STATIC void DlogLock(void)
{
int32_t ret = pthread_mutex_lock(&g_dlogAsyncMgr.mutex);
if (ret == EOWNERDEAD) {
(void)pthread_mutex_consistent(&g_dlogAsyncMgr.mutex);
} else if (ret != SYS_OK) {
SELF_LOG_WARN("can not lock, strerr=%s", strerror(ToolGetErrorCode()));
} else {
;
}
}
STATIC void DlogUnLock(void)
{
UNLOCK_WARN_LOG(&g_dlogAsyncMgr.mutex);
}
* @brief : exec this function in child process after fork
* @return : SYS_OK unlock success; others unlock failed and reinit
*/
STATIC void DlogChildUnLock(void)
{
int32_t ret = pthread_mutex_unlock(&g_dlogAsyncMgr.mutex);
if (ret != SYS_OK) {
(void)pthread_mutex_destroy(&g_dlogAsyncMgr.mutex);
DlogInitMutex();
}
return;
}
* @brief : get log num in buffer
* @return : log count
*/
STATIC uint64_t DlogGetBufNodeCount(RingBufferStat *ringBuffer)
{
if ((ringBuffer == NULL) || (ringBuffer->ringBufferCtrl == NULL)) {
return 0;
}
uint64_t nodeCount;
RingBufferCtrl *ringBufferCtrl = ringBuffer->ringBufferCtrl;
if (ringBufferCtrl->logNextSeq < ringBufferCtrl->lastSeq) {
ringBufferCtrl->lastSeq = ringBufferCtrl->logNextSeq;
nodeCount = 0;
} else {
nodeCount = ringBufferCtrl->logNextSeq - ringBufferCtrl->lastSeq - LogBufLost(ringBuffer->ringBufferCtrl);
}
return nodeCount;
}
STATIC void LogCtrlDecLogic(void)
{
const int64_t timeValue = DlogTimeDiff(&g_dlogAsyncMgr.levelCtrl.ctrlLastTv);
if (timeValue >= LOG_WARN_INTERVAL) {
if (timeValue < LOG_INFO_INTERVAL) {
if (g_dlogAsyncMgr.levelCtrl.ctrlLevel != DLOG_WARN) {
g_dlogAsyncMgr.levelCtrl.ctrlLevel = DLOG_WARN;
SELF_LOG_WARN("log control down to level=WARNING, pid=%d, pid_name=%s,"
"log level control loss num is %lu",
DlogGetCurrPid(), DlogGetPidName(), g_dlogAsyncMgr.levelCtrl.lossCount);
}
} else if (timeValue < LOG_CTRL_TOTAL_INTERVAL) {
if (g_dlogAsyncMgr.levelCtrl.ctrlLevel != DLOG_INFO) {
g_dlogAsyncMgr.levelCtrl.ctrlLevel = DLOG_INFO;
SELF_LOG_WARN("log control down to level=INFO, pid=%d, pid_name=%s, log level control loss num is %lu",
DlogGetCurrPid(), DlogGetPidName(), g_dlogAsyncMgr.levelCtrl.lossCount);
}
} else {
g_dlogAsyncMgr.levelCtrl.ctrlSwitch = false;
g_dlogAsyncMgr.levelCtrl.ctrlLevel = DLOG_DEBUG;
g_dlogAsyncMgr.levelCtrl.ctrlLastTv.tv_sec = 0;
g_dlogAsyncMgr.levelCtrl.ctrlLastTv.tv_nsec = 0;
SELF_LOG_WARN("clear log control switch, pid=%d, pid_name=%s, log level control loss num is %lu",
DlogGetCurrPid(), DlogGetPidName(), g_dlogAsyncMgr.levelCtrl.lossCount);
g_dlogAsyncMgr.levelCtrl.lossCount = 0;
}
}
}
STATIC void LogCtrlIncLogic(void)
{
if (!g_dlogAsyncMgr.levelCtrl.ctrlSwitch) {
g_dlogAsyncMgr.levelCtrl.ctrlSwitch = true;
g_dlogAsyncMgr.levelCtrl.ctrlLevel = DLOG_ERROR;
SELF_LOG_WARN("set log control switch to level=ERROR, pid=%d, pid_name=%s, log loss num=%lu.",
DlogGetCurrPid(), DlogGetPidName(), g_dlogAsyncMgr.levelCtrl.lossCount);
} else {
if (g_dlogAsyncMgr.levelCtrl.ctrlLevel < DLOG_ERROR) {
g_dlogAsyncMgr.levelCtrl.ctrlLevel++;
if (g_dlogAsyncMgr.levelCtrl.ctrlLevel == DLOG_ERROR) {
SELF_LOG_WARN("log control up to level=ERROR, pid=%d, pid_name=%s, log loss num=%lu.",
DlogGetCurrPid(), DlogGetPidName(), g_dlogAsyncMgr.levelCtrl.lossCount);
} else {
SELF_LOG_WARN("log control up to level=WARNING, pid=%d, pid_name=%s, log loss num=%lu.",
DlogGetCurrPid(), DlogGetPidName(), g_dlogAsyncMgr.levelCtrl.lossCount);
}
}
}
(void)LogGetMonotonicTime(&g_dlogAsyncMgr.levelCtrl.ctrlLastTv);
}
* @brief : write log from buffer to iam
* @return : >= 0 success; < 0 failure
*/
STATIC int32_t DlogWriteBufToIam(RingBufferStat *ringBuffer)
{
return DlogIamWrite((void *)(ringBuffer->ringBufferCtrl), ringBuffer->logBufSize);
}
* @brief : write log from buffer to himem
* @return : >= 0 success; < 0 failure
*/
STATIC int32_t DlogWriteBufToHiMem(RingBufferStat *ringBuffer)
{
return HiMemWriteIamLog(g_dlogAsyncMgr.himemFd, ringBuffer);
}
STATIC void CountLogLoss(void)
{
for (uint32_t i = 0; i < LOG_BUF_NUM; i++) {
g_dlogAsyncMgr.bufMgr.lossCount += DlogGetBufNodeCount(g_dlogAsyncMgr.bufMgr.dlogBuf[i]);
}
}
* @brief : reinit log buffer to 0
*/
STATIC void DlogBufReInit(RingBufferStat *ringBuffer)
{
LogBufReInit(ringBuffer);
}
* @brief : if level is already sync, refresh level filter status once
*/
STATIC void DlogFilterStatus(RingBufferStat *ringBuffer)
{
LogBufSetLevelFilter(ringBuffer->ringBufferCtrl, LEVEL_FILTER_CLOSE);
}
STATIC void SafeWritesByIam(RingBufferStat *ringBuffer)
{
int32_t n = -1;
int32_t err = 0;
int32_t retryTimes = 0;
static int32_t printNum = 0U;
do {
LOG_MONITOR_TIME_OUT(n = DlogWriteBufToIam(ringBuffer), LOG_SEND_COST_MAX_TIME, "iam send msg");
if (n > 0) {
break;
}
err = ToolGetErrorCode();
if (err == EINTR) {
continue;
} else if (IS_BADFD(err)) {
if (DlogIamOpenService() == SYS_OK) {
SELF_LOG_INFO("reopen iam service fd done.");
} else {
(void)ToolSleep(10);
}
continue;
} else {
break;
}
} while (++retryTimes < WRITE_MAX_RETRY_TIMES);
if (n > 0) {
DlogFilterStatus(ringBuffer);
DlogBufReInit(ringBuffer);
} else {
SELF_LOG_WARN_N_AO(&printNum, WRITE_E_PRINT_NUM,
"can not write to server, print every %d times, result=%d, strerr=%s, pid=%d, pid_name=%s.",
WRITE_E_PRINT_NUM, n, strerror(err), DlogGetCurrPid(), DlogGetPidName());
if (DlogIsAosCore()) {
(void)DlogWriteBufToHiMem(ringBuffer);
}
}
return;
}
static inline void DlogModifySendBuf(uint32_t sendIdx)
{
if (!LogBufCheckEmpty(g_dlogAsyncMgr.bufMgr.dlogBuf[sendIdx])) {
SafeWritesByIam(g_dlogAsyncMgr.bufMgr.dlogBuf[sendIdx]);
}
}
STATIC void DlogSyncAllSendBuf(uint32_t *sendIdx, uint32_t writeIdx)
{
while (*sendIdx != writeIdx) {
DlogModifySendBuf(*sendIdx);
*sendIdx = (*sendIdx + 1U) % LOG_BUF_NUM;
}
}
static void DlogMonitorTimerDelay(void)
{
static uint64_t lastRoundTime = 0;
if (lastRoundTime == 0) {
lastRoundTime = LogGetCpuCycleCounter();
}
uint64_t now = LogGetCpuCycleCounter();
LOG_MONITOR_TIME_OUT_PRINT((now - lastRoundTime), LOG_TIMER_TRIGER_COST_MAX_TIME, "trigger %s", DLOG_TIMER_NAME);
lastRoundTime = now;
}
static bool DlogCheckWriteBufModify(uint32_t writeBufIndex)
{
bool ret = false;
DlogLock();
if ((g_dlogAsyncMgr.bufMgr.writeBufIndex == writeBufIndex) &&
!LogBufCheckEmpty(g_dlogAsyncMgr.bufMgr.dlogBuf[writeBufIndex])) {
g_dlogAsyncMgr.bufMgr.writeBufIndex = (writeBufIndex + 1U) % LOG_BUF_NUM;
ret = true;
}
DlogUnLock();
return ret;
}
static void DlogUnifiedTimerCb(void)
{
DlogMonitorTimerDelay();
if (!DlogIamServiceIsValid()) {
return;
}
uint32_t writeBufIndex = g_dlogAsyncMgr.bufMgr.writeBufIndex;
LOG_MONITOR_TIME_OUT(DlogSyncAllSendBuf(&g_dlogAsyncMgr.bufMgr.sendBufIndex, writeBufIndex), LOG_SEND_COST_MAX_TIME,
"%s send all buffer", DLOG_TIMER_NAME);
bool ret = false;
LOG_MONITOR_TIME_OUT(ret = DlogCheckWriteBufModify(writeBufIndex), LOG_LOCK_COST_MAX_TIME,
"%s buffer switch get lock", DLOG_TIMER_NAME);
if (ret) {
LOG_MONITOR_TIME_OUT(DlogModifySendBuf(writeBufIndex), LOG_SEND_COST_MAX_TIME,
"%s send newest buffer", DLOG_TIMER_NAME);
g_dlogAsyncMgr.bufMgr.sendBufIndex = (writeBufIndex + 1U) % LOG_BUF_NUM;
}
return;
}
static void DlogSyncUnifiedTimerCb(void)
{
DlogUnifiedTimerCb();
(void)__sync_lock_test_and_set(&g_dlogAsyncMgr.syncFlag, false);
return;
}
static void DlogAddSyncTask(void)
{
if (!__sync_bool_compare_and_swap(&g_dlogAsyncMgr.syncFlag, false, true)) {
return;
}
if (DlogLoadTimerDll() != LOG_SUCCESS) {
SELF_LOG_ERROR("dlog load unified_timer library failed, pid = %d, strerr = %s.",
ToolGetPid(), strerror(ToolGetErrorCode()));
(void)__sync_lock_test_and_set(&g_dlogAsyncMgr.syncFlag, false);
return;
}
uint32_t ret = DlogAddUnifiedTimer(DLOG_SYNC_TIMER_NAME, DlogSyncUnifiedTimerCb, LOG_SYNC_PERIOD, ONESHOT_TIMER);
if ((ret != 0) && (ret != UNIFILED_TIMER_NAME_DUPLICATE)) {
SELF_LOG_ERROR("add unified timer failed, ret = %u, errno = %d, pid = %d, timerName = %s.",
ret, ToolGetErrorCode(), ToolGetPid(), DLOG_SYNC_TIMER_NAME);
(void)__sync_lock_test_and_set(&g_dlogAsyncMgr.syncFlag, false);
}
return;
}
static LogStatus DlogStartSendTask(void)
{
if (DlogLoadTimerDll() != LOG_SUCCESS) {
SELF_LOG_ERROR("dlog load unified_timer library failed, pid = %d, strerr = %s.",
ToolGetPid(), strerror(ToolGetErrorCode()));
return LOG_FAILURE;
}
uint32_t ret = DlogAddUnifiedTimer(DLOG_TIMER_NAME, DlogUnifiedTimerCb, LOG_TIMER_PERIOD, PERIODIC_TIMER);
if (ret != 0) {
SELF_LOG_ERROR("add unified timer failed, ret = %u, errno = %d, pid = %d, timerName = %s.",
ret, ToolGetErrorCode(), ToolGetPid(), DLOG_TIMER_NAME);
return LOG_FAILURE;
}
SELF_LOG_INFO("add unified timer success, pid = %d, timerName = %s.", ToolGetPid(), DLOG_TIMER_NAME);
return LOG_SUCCESS;
}
* @brief: check sub process, restart thread
* @return: void
*/
void CheckPid(void)
{
if (DlogCheckCurrPid()) {
return;
}
DlogLock();
if (DlogCheckCurrPid() == false) {
DlogSetCurrPid();
(void)DlogStartSendTask();
}
DlogUnLock();
}
* @brief : notify thread synchronize, when buffer is empty or time out, return
* @return : void
*/
STATIC void DlogSyncNotify(void)
{
int32_t retry = 0;
const uint32_t retryWaitTime = 50U;
bool isExit = false;
if (g_dlogAsyncMgr.bufMgr.sendBufIndex != g_dlogAsyncMgr.bufMgr.writeBufIndex) {
DlogAddSyncTask();
}
do {
if (g_dlogAsyncMgr.bufMgr.sendBufIndex == g_dlogAsyncMgr.bufMgr.writeBufIndex) {
ONE_ACT_NO_LOG(isExit, return);
DlogLock();
if (g_dlogAsyncMgr.bufMgr.sendBufIndex == g_dlogAsyncMgr.bufMgr.writeBufIndex) {
g_dlogAsyncMgr.bufMgr.writeBufIndex = (g_dlogAsyncMgr.bufMgr.writeBufIndex + 1U) % LOG_BUF_NUM;
}
DlogUnLock();
DlogAddSyncTask();
isExit = true;
}
(void)ToolSleep(retryWaitTime);
retry++;
} while (retry <= WRITE_MAX_RETRY_TIMES);
}
void DlogFlushBuf(void)
{
if (!g_dlogAsyncMgr.initFlag) {
return;
}
if (!DlogIamServiceIsValid()) {
SELF_LOG_WARN("slogd is not ready, please flush later.");
return;
}
FlushInfo info;
struct IAMIoctlArg arg;
DlogSyncNotify();
#if defined LOG_CPP || defined APP_LOG
info.appPid = DlogGetCurrPid();
#else
info.appPid = INVALID;
#endif
arg.size = sizeof(FlushInfo);
arg.argData = (void *)&info;
const int32_t ret = DlogIamIoctlFlushLog(&arg);
if (ret != SYS_OK) {
SELF_LOG_ERROR("log flush failed, ret=%d, strerr=%s, pid=%d.",
ret, strerror(ToolGetErrorCode()), DlogGetCurrPid());
return;
}
}
void DlogUpdateFlierLevelStatus(void)
{
if (!g_dlogAsyncMgr.initFlag) {
return;
}
DlogLock();
uint32_t curIdx = g_dlogAsyncMgr.bufMgr.writeBufIndex;
if (LogBufCheckEmpty(g_dlogAsyncMgr.bufMgr.dlogBuf[curIdx])) {
DlogFilterStatus(g_dlogAsyncMgr.bufMgr.dlogBuf[curIdx]);
} else {
uint32_t nextIdx = (curIdx + 1U) % LOG_BUF_NUM;
if (LogBufCheckEmpty(g_dlogAsyncMgr.bufMgr.dlogBuf[nextIdx])) {
g_dlogAsyncMgr.bufMgr.writeBufIndex = nextIdx;
DlogFilterStatus(g_dlogAsyncMgr.bufMgr.dlogBuf[nextIdx]);
} else {
LogBufReInit(g_dlogAsyncMgr.bufMgr.dlogBuf[curIdx]);
DlogFilterStatus(g_dlogAsyncMgr.bufMgr.dlogBuf[curIdx]);
}
}
for (uint32_t i = 0; i < LOG_BUF_NUM; i++) {
if (LogBufCheckEmpty(g_dlogAsyncMgr.bufMgr.dlogBuf[i])) {
DlogFilterStatus(g_dlogAsyncMgr.bufMgr.dlogBuf[i]);
}
}
DlogUnLock();
}
STATIC void DlogInitHead(LogHead *head, const LogMsg *logMsg)
{
(void)memset_s(head, sizeof(LogHead), 0, sizeof(LogHead));
head->magic = HEAD_MAGIC;
head->version = HEAD_VERSION;
head->aosType = (uint8_t)DlogGetAosType();
head->processType = (uint8_t)DlogGetProcessType();
head->logType = (uint8_t)logMsg->type;
head->logLevel = (uint8_t)logMsg->level;
head->hostPid = DlogGetHostPid();
head->devicePid = (uint32_t)DlogGetCurrPid();
head->deviceId = (uint16_t)DlogGetAttrDeviceId();
head->moduleId = (uint16_t)logMsg->moduleId;
head->allLength = 0;
head->msgLength = (uint16_t)logMsg->msgLength;
head->tagSwitch = 0;
head->saveMode = 0;
}
STATIC void DlogPrintLogLoss(void)
{
if (g_dlogAsyncMgr.bufMgr.lossCount > LOG_MAX_COVERED_LOSS_NUM) {
g_dlogAsyncMgr.bufMgr.lossCount = LOG_MAX_COVERED_LOSS_NUM;
}
uint64_t costTime = 0;
uint64_t currTime = LogGetCpuCycleCounter();
const uint64_t periodTime = LOG_LOST_PRINT_PERIOD_TIME / TICK_TO_US * LogGetCpuFrequency();
if (g_dlogAsyncMgr.bufMgr.lastPrintTime == 0) {
costTime = periodTime;
} else {
costTime = currTime - g_dlogAsyncMgr.bufMgr.lastPrintTime;
}
if (costTime >= periodTime) {
SELF_LOG_WARN("dlog buffer covered log loss num = %lu, print every %lu seconds.",
g_dlogAsyncMgr.bufMgr.lossCount, LOG_LOST_PRINT_PERIOD_TIME / (uint64_t)S_TO_MS);
g_dlogAsyncMgr.bufMgr.lastPrintTime = currTime;
g_dlogAsyncMgr.bufMgr.lossCount = 0;
}
}
STATIC RingBufferStat *DlogGetWriteBuf(bool *isBufSwitch, uint32_t msgLen)
{
uint32_t curIdx = g_dlogAsyncMgr.bufMgr.writeBufIndex;
uint32_t nextIdx = (curIdx + 1U) % LOG_BUF_NUM;
RingBufferStat *bufMgr = g_dlogAsyncMgr.bufMgr.dlogBuf[curIdx];
if (!LogBufCheckEnough(bufMgr, msgLen)) {
if (LogBufCheckEmpty(g_dlogAsyncMgr.bufMgr.dlogBuf[nextIdx])) {
g_dlogAsyncMgr.bufMgr.writeBufIndex = nextIdx;
*isBufSwitch = true;
ONE_ACT_NO_LOG(g_dlogAsyncMgr.levelCtrl.ctrlSwitch, LogCtrlDecLogic());
} else {
LogCtrlIncLogic();
}
} else {
ONE_ACT_NO_LOG(g_dlogAsyncMgr.levelCtrl.ctrlSwitch, LogCtrlDecLogic());
}
return g_dlogAsyncMgr.bufMgr.dlogBuf[g_dlogAsyncMgr.bufMgr.writeBufIndex];
}
* @brief : write log to buffer
* @param [in] : logMsg log messages
*/
void DlogWriteToBuf(const LogMsg *logMsg)
{
if (!g_dlogAsyncMgr.initFlag) {
return;
}
if ((logMsg == NULL) || (logMsg->msgLength == 0)) {
SELF_LOG_ERROR("log messaegs is null, pid = %d", ToolGetPid());
return;
}
DlogLock();
bool isBufSwitch = false;
RingBufferStat *bufMgr = DlogGetWriteBuf(&isBufSwitch, logMsg->msgLength);
TWO_ACT_NO_LOG(bufMgr == NULL, DlogUnLock(), return);
if (g_dlogAsyncMgr.levelCtrl.ctrlSwitch && (logMsg->type == DEBUG_LOG)
&& (logMsg->level < g_dlogAsyncMgr.levelCtrl.ctrlLevel)) {
g_dlogAsyncMgr.levelCtrl.lossCount++;
DlogUnLock();
return;
}
LogHead head = { 0 };
DlogInitHead(&head, logMsg);
uint64_t coverCount = 0;
int32_t res = LogBufWrite(bufMgr->ringBufferCtrl, logMsg->msg, &head, &coverCount);
if (res < 0) {
SELF_LOG_ERROR("DlogWriteToBuf fail res %d", res);
} else {
if (coverCount > 0) {
g_dlogAsyncMgr.bufMgr.lossCount += coverCount;
DlogPrintLogLoss();
}
}
DlogUnLock();
if (isBufSwitch) {
DlogAddSyncTask();
}
return;
}
STATIC void DlogStopSendTask(void)
{
if (g_dlogAsyncMgr.initFlag && (DlogCheckCurrPid())) {
uint32_t ret = DlogRemoveUnifiedTimer(DLOG_TIMER_NAME);
(void)DlogRemoveUnifiedTimer(DLOG_SYNC_TIMER_NAME);
NO_ACT_ERR_LOG(DlogCloseTimerDll() != LOG_SUCCESS,
"close unified_timer library failed, pid = %d, timer name = %s.", ToolGetPid(), DLOG_TIMER_NAME);
if (ret != 0) {
SELF_LOG_ERROR("remove unified timer failed, ret = %u, errno = %d, pid = %d, timer name = %s.",
ret, ToolGetErrorCode(), ToolGetPid(), DLOG_TIMER_NAME);
return;
}
SELF_LOG_INFO("remove unified timer success, pid = %d, timer name = %s.", ToolGetPid(), DLOG_TIMER_NAME);
}
}
STATIC void DlogRingBufExit(RingBufferStat **ringBuffer)
{
if (*ringBuffer != NULL) {
XFREE((*ringBuffer)->ringBufferCtrl);
XFREE(*ringBuffer);
}
}
* @brief : free log buffer
*/
STATIC void DlogBufExit(void)
{
for (uint32_t i = 0; i < LOG_BUF_NUM; i++) {
DlogRingBufExit(&g_dlogAsyncMgr.bufMgr.dlogBuf[i]);
}
}
STATIC int32_t DlogRingBufInit(RingBufferStat **ringBuffer, uint32_t size)
{
*ringBuffer = (RingBufferStat *)LogMalloc(sizeof(RingBufferStat));
if (*ringBuffer == NULL) {
SELF_LOG_ERROR("malloc for log buffer failed, strerr = %s.", strerror(ToolGetErrorCode()));
return LOG_FAILURE;
}
(*ringBuffer)->logBufSize = size;
(*ringBuffer)->ringBufferCtrl = (RingBufferCtrl *)malloc((*ringBuffer)->logBufSize);
if ((*ringBuffer)->ringBufferCtrl == NULL) {
SELF_LOG_ERROR("malloc for log buffer ctrl failed, strerr = %s.", strerror(ToolGetErrorCode()));
XFREE(*ringBuffer);
return LOG_FAILURE;
}
int32_t err = LogBufInitHead((*ringBuffer)->ringBufferCtrl, (*ringBuffer)->logBufSize, 0);
if (err != LOG_SUCCESS) {
SELF_LOG_ERROR("init log buffer head failed, err = %d, strerr = %s, pid = %d.",
err, strerror(ToolGetErrorCode()), ToolGetPid());
DlogRingBufExit(ringBuffer);
return LOG_FAILURE;
}
LogBufSetLevelFilter((*ringBuffer)->ringBufferCtrl, LEVEL_FILTER);
return LOG_SUCCESS;
}
* @brief : init log buffer, malloc for buffer
* @return : LOG_SUCCESS success; LOG_FAILURE failure
*/
STATIC int32_t DlogBufInit(void)
{
int32_t ret = 0;
uint32_t size = DEF_SIZE / LOG_BUF_NUM;
for (uint32_t i = 0; i < LOG_BUF_NUM; i++) {
ret = DlogRingBufInit(&g_dlogAsyncMgr.bufMgr.dlogBuf[i], size);
if (ret != LOG_SUCCESS) {
SELF_LOG_ERROR("init buffer[%u] failed.", i);
return LOG_FAILURE;
}
}
return LOG_SUCCESS;
}
* @brief : init nsyc process, apply for resource
* @return : SYS_OK success; SYS_ERROR failure
*/
int32_t DlogAsyncInit(void)
{
if (DlogIsAosCore()) {
(void)HiMemInit(&g_dlogAsyncMgr.himemFd);
}
DlogInitMutex();
int32_t ret = pthread_atfork((ThreadAtFork)DlogLock, (ThreadAtFork)DlogUnLock, (ThreadAtFork)DlogChildUnLock);
NO_ACT_WARN_LOG(ret != 0, "can not register fork, ret=%d, strerr=%s.", ret, strerror(ToolGetErrorCode()));
ret = DlogIamInit();
if (ret != SYS_OK) {
return SYS_ERROR;
}
ret = DlogBufInit();
if (ret != SYS_OK) {
DlogBufExit();
DlogIamExit();
return SYS_ERROR;
}
if (!g_dlogAsyncMgr.initFlag) {
if (DlogStartSendTask() == LOG_SUCCESS) {
g_dlogAsyncMgr.initFlag = true;
}
}
return SYS_OK;
}
* @brief : exit nsyc process, release resource
*/
void DlogAsyncExit(void)
{
DlogStopSendTask();
DlogLock();
CountLogLoss();
SELF_LOG_INFO("pid=%d, pid_name=%s quit, log covered loss num is %lu, log level control loss num is %lu.",
DlogGetCurrPid(), DlogGetPidName(),
g_dlogAsyncMgr.bufMgr.lossCount, g_dlogAsyncMgr.levelCtrl.lossCount);
DlogBufExit();
DlogUnLock();
if (DlogIsAosCore()) {
(void)HiMemFree(&g_dlogAsyncMgr.himemFd);
}
DlogIamExit();
g_dlogAsyncMgr.initFlag = false;
}
#ifdef __cplusplus
}
#endif