12498b56bSopenharmony_ci/*
22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42498b56bSopenharmony_ci * you may not use this file except in compliance with the License.
52498b56bSopenharmony_ci * You may obtain a copy of the License at
62498b56bSopenharmony_ci *
72498b56bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82498b56bSopenharmony_ci *
92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122498b56bSopenharmony_ci * See the License for the specific language governing permissions and
132498b56bSopenharmony_ci * limitations under the License.
142498b56bSopenharmony_ci */
152498b56bSopenharmony_ci
162498b56bSopenharmony_ci#include <cstring>
172498b56bSopenharmony_ci#include <thread>
182498b56bSopenharmony_ci#include <vector>
192498b56bSopenharmony_ci#include <sys/time.h>
202498b56bSopenharmony_ci#include <regex>
212498b56bSopenharmony_ci#include <string>
222498b56bSopenharmony_ci
232498b56bSopenharmony_ci#include <hilog_common.h>
242498b56bSopenharmony_ci#include <flow_control.h>
252498b56bSopenharmony_ci#include <log_timestamp.h>
262498b56bSopenharmony_ci#include <properties.h>
272498b56bSopenharmony_ci#include <log_utils.h>
282498b56bSopenharmony_ci
292498b56bSopenharmony_ci#include "log_buffer.h"
302498b56bSopenharmony_ci
312498b56bSopenharmony_cinamespace OHOS {
322498b56bSopenharmony_cinamespace HiviewDFX {
332498b56bSopenharmony_ciusing namespace std;
342498b56bSopenharmony_ci
352498b56bSopenharmony_cistatic size_t g_maxBufferSizeByType[LOG_TYPE_MAX] = {262144, 262144, 262144, 262144, 262144, 0};
362498b56bSopenharmony_cistatic int GenerateHilogMsgInside(HilogMsg& hilogMsg, const string& msg, uint16_t logType);
372498b56bSopenharmony_ci
382498b56bSopenharmony_ci// LOG_ONLY_PRERELEASE and LOG_CORE use the same buffer.
392498b56bSopenharmony_cistatic inline int ConvertBufType(int type)
402498b56bSopenharmony_ci{
412498b56bSopenharmony_ci    return type == LOG_ONLY_PRERELEASE ? LOG_CORE : type;
422498b56bSopenharmony_ci}
432498b56bSopenharmony_ci
442498b56bSopenharmony_ciHilogBuffer::HilogBuffer(bool isSupportSkipLog) : m_isSupportSkipLog(isSupportSkipLog)
452498b56bSopenharmony_ci{
462498b56bSopenharmony_ci    for (int i = 0; i < LOG_TYPE_MAX; i++) {
472498b56bSopenharmony_ci        sizeByType[i] = 0;
482498b56bSopenharmony_ci    }
492498b56bSopenharmony_ci    InitBuffLen();
502498b56bSopenharmony_ci    InitBuffHead();
512498b56bSopenharmony_ci}
522498b56bSopenharmony_ci
532498b56bSopenharmony_civoid HilogBuffer::InitBuffLen()
542498b56bSopenharmony_ci{
552498b56bSopenharmony_ci    size_t global_size = GetBufferSize(LOG_TYPE_MAX, false);
562498b56bSopenharmony_ci    size_t persist_global_size = GetBufferSize(LOG_TYPE_MAX, true);
572498b56bSopenharmony_ci    for (int i = 0; i < LOG_TYPE_MAX; i++) {
582498b56bSopenharmony_ci        size_t size = GetBufferSize(i, false);
592498b56bSopenharmony_ci        size_t persist_size = GetBufferSize(i, true);
602498b56bSopenharmony_ci        SetBuffLen(i, global_size);
612498b56bSopenharmony_ci        SetBuffLen(i, persist_global_size);
622498b56bSopenharmony_ci        SetBuffLen(i, size);
632498b56bSopenharmony_ci        SetBuffLen(i, persist_size);
642498b56bSopenharmony_ci    }
652498b56bSopenharmony_ci}
662498b56bSopenharmony_ci
672498b56bSopenharmony_civoid HilogBuffer::InitBuffHead()
682498b56bSopenharmony_ci{
692498b56bSopenharmony_ci    const string msg = "========Zeroth log of type: ";
702498b56bSopenharmony_ci    std::vector<char> buf(MAX_LOG_LEN, 0);
712498b56bSopenharmony_ci    HilogMsg *headMsg = reinterpret_cast<HilogMsg *>(buf.data());
722498b56bSopenharmony_ci
732498b56bSopenharmony_ci    for (uint16_t i = 0; i < LOG_TYPE_MAX; i++) {
742498b56bSopenharmony_ci        string typeStr = LogType2Str(i);
752498b56bSopenharmony_ci        if (typeStr == "invalid") {
762498b56bSopenharmony_ci            continue;
772498b56bSopenharmony_ci        }
782498b56bSopenharmony_ci        string tmpStr = msg + typeStr;
792498b56bSopenharmony_ci        if (GenerateHilogMsgInside(*headMsg, tmpStr, i) == RET_SUCCESS) {
802498b56bSopenharmony_ci            bool isFull = false;
812498b56bSopenharmony_ci            Insert(*headMsg, isFull);
822498b56bSopenharmony_ci        }
832498b56bSopenharmony_ci    }
842498b56bSopenharmony_ci}
852498b56bSopenharmony_ci
862498b56bSopenharmony_ciHilogBuffer::~HilogBuffer() {}
872498b56bSopenharmony_ci
882498b56bSopenharmony_cisize_t HilogBuffer::Insert(const HilogMsg& msg, bool& isFull)
892498b56bSopenharmony_ci{
902498b56bSopenharmony_ci    size_t elemSize = CONTENT_LEN((&msg)); /* include '\0' */
912498b56bSopenharmony_ci    if (unlikely(msg.tagLen > MAX_TAG_LEN || msg.tagLen == 0 || elemSize > MAX_LOG_LEN ||
922498b56bSopenharmony_ci        elemSize == 0 || msg.type >= LOG_TYPE_MAX)) {
932498b56bSopenharmony_ci        return 0;
942498b56bSopenharmony_ci    }
952498b56bSopenharmony_ci    isFull = false;
962498b56bSopenharmony_ci    {
972498b56bSopenharmony_ci        std::lock_guard<decltype(hilogBufferMutex)> lock(hilogBufferMutex);
982498b56bSopenharmony_ci        int bufferType = ConvertBufType(msg.type);
992498b56bSopenharmony_ci
1002498b56bSopenharmony_ci        // Delete old entries when full
1012498b56bSopenharmony_ci        if (elemSize + sizeByType[bufferType] >= g_maxBufferSizeByType[bufferType]) {
1022498b56bSopenharmony_ci            // Drop 5% of maximum log when full
1032498b56bSopenharmony_ci            std::list<HilogData>::iterator it = hilogDataList.begin();
1042498b56bSopenharmony_ci            static const float DROP_RATIO = 0.05;
1052498b56bSopenharmony_ci            while (sizeByType[bufferType] > g_maxBufferSizeByType[bufferType] * (1 - DROP_RATIO) &&
1062498b56bSopenharmony_ci                it != hilogDataList.end()) {
1072498b56bSopenharmony_ci                if (ConvertBufType((*it).type) != bufferType) {    // Only remove old logs of the same type
1082498b56bSopenharmony_ci                    ++it;
1092498b56bSopenharmony_ci                    continue;
1102498b56bSopenharmony_ci                }
1112498b56bSopenharmony_ci
1122498b56bSopenharmony_ci                if (IsItemUsed(it)) {
1132498b56bSopenharmony_ci                    isFull = true;
1142498b56bSopenharmony_ci                    return 0;
1152498b56bSopenharmony_ci                }
1162498b56bSopenharmony_ci
1172498b56bSopenharmony_ci                OnDeleteItem(it, DeleteReason::BUFF_OVERFLOW);
1182498b56bSopenharmony_ci                size_t cLen = it->len - it->tagLen;
1192498b56bSopenharmony_ci                sizeByType[ConvertBufType((*it).type)] -= cLen;
1202498b56bSopenharmony_ci                it = hilogDataList.erase(it);
1212498b56bSopenharmony_ci            }
1222498b56bSopenharmony_ci
1232498b56bSopenharmony_ci            // Re-confirm if enough elements has been removed
1242498b56bSopenharmony_ci            if (sizeByType[bufferType] >= g_maxBufferSizeByType[bufferType]) {
1252498b56bSopenharmony_ci                std::cout << "Failed to clean old logs." << std::endl;
1262498b56bSopenharmony_ci            }
1272498b56bSopenharmony_ci        }
1282498b56bSopenharmony_ci
1292498b56bSopenharmony_ci        // Append new log into HilogBuffer
1302498b56bSopenharmony_ci        hilogDataList.emplace_back(msg);
1312498b56bSopenharmony_ci        // Update current size of HilogBuffer
1322498b56bSopenharmony_ci        sizeByType[bufferType] += elemSize;
1332498b56bSopenharmony_ci        OnPushBackedItem(hilogDataList);
1342498b56bSopenharmony_ci    }
1352498b56bSopenharmony_ci
1362498b56bSopenharmony_ci    // Notify readers about new element added
1372498b56bSopenharmony_ci    OnNewItem(hilogDataList);
1382498b56bSopenharmony_ci    return elemSize;
1392498b56bSopenharmony_ci}
1402498b56bSopenharmony_ci
1412498b56bSopenharmony_ci// Replace wildcard with regex
1422498b56bSopenharmony_cistatic std::string WildcardToRegex(const std::string& wildcard)
1432498b56bSopenharmony_ci{
1442498b56bSopenharmony_ci    // Original and Replacement char array
1452498b56bSopenharmony_ci    const static char* WILDCARDS = "*?[]+.^&";
1462498b56bSopenharmony_ci    const static std::string REPLACEMENT_S[] = {".*", ".", "\\[", "\\]", "\\+", "\\.", "\\^", "\\&"};
1472498b56bSopenharmony_ci    // Modify every wildcard to regex
1482498b56bSopenharmony_ci    std::string result = "";
1492498b56bSopenharmony_ci    for (char c : wildcard) {
1502498b56bSopenharmony_ci        // strchr matches wildcard and char
1512498b56bSopenharmony_ci        if (std::strchr(WILDCARDS, c) != nullptr) {
1522498b56bSopenharmony_ci            size_t index = std::strchr(WILDCARDS, c) - WILDCARDS;
1532498b56bSopenharmony_ci            result += REPLACEMENT_S[index];
1542498b56bSopenharmony_ci        } else {
1552498b56bSopenharmony_ci            result += c;
1562498b56bSopenharmony_ci        }
1572498b56bSopenharmony_ci    }
1582498b56bSopenharmony_ci    return result;
1592498b56bSopenharmony_ci}
1602498b56bSopenharmony_ci
1612498b56bSopenharmony_cistatic bool LogMatchFilter(const LogFilter& filter, const HilogData& logData)
1622498b56bSopenharmony_ci{
1632498b56bSopenharmony_ci    // types & levels match
1642498b56bSopenharmony_ci    if (((static_cast<uint16_t>(0b01 << logData.type)) & filter.types) == 0) {
1652498b56bSopenharmony_ci        return false;
1662498b56bSopenharmony_ci    }
1672498b56bSopenharmony_ci    if (((static_cast<uint16_t>(0b01 << logData.level)) & filter.levels) == 0) {
1682498b56bSopenharmony_ci        return false;
1692498b56bSopenharmony_ci    }
1702498b56bSopenharmony_ci
1712498b56bSopenharmony_ci    int i = 0;
1722498b56bSopenharmony_ci    // domain match
1732498b56bSopenharmony_ci    static constexpr uint32_t LOW_BYTE = 0xFF;
1742498b56bSopenharmony_ci    static constexpr uint32_t LOW_BYTE_REVERSE = ~LOW_BYTE;
1752498b56bSopenharmony_ci    /* 1) domain id equals exactly: (0xd012345 == 0xd012345)
1762498b56bSopenharmony_ci       2) last 8 bits is sub domain id, if it's 0xFF, compare high 24 bits:
1772498b56bSopenharmony_ci       (0xd0123ff & 0xffffff00 == 0xd012345 & 0xffffff00) */
1782498b56bSopenharmony_ci    bool match = false;
1792498b56bSopenharmony_ci    for (i = 0; i < filter.domainCount; i++) {
1802498b56bSopenharmony_ci        if ((logData.domain == filter.domains[i]) || ((static_cast<uint8_t>(filter.domains[i]) == LOW_BYTE)
1812498b56bSopenharmony_ci             && ((logData.domain & LOW_BYTE_REVERSE) == (filter.domains[i] & LOW_BYTE_REVERSE)))) {
1822498b56bSopenharmony_ci            match = true;
1832498b56bSopenharmony_ci            break;
1842498b56bSopenharmony_ci        }
1852498b56bSopenharmony_ci    }
1862498b56bSopenharmony_ci    if (filter.domainCount && match == filter.blackDomain) {
1872498b56bSopenharmony_ci        return false;
1882498b56bSopenharmony_ci    }
1892498b56bSopenharmony_ci    match = false;
1902498b56bSopenharmony_ci    // tag match
1912498b56bSopenharmony_ci    for (i = 0; i < filter.tagCount; i++) {
1922498b56bSopenharmony_ci        if (strcmp(logData.tag, filter.tags[i]) == 0) {
1932498b56bSopenharmony_ci            match = true;
1942498b56bSopenharmony_ci            break;
1952498b56bSopenharmony_ci        }
1962498b56bSopenharmony_ci    }
1972498b56bSopenharmony_ci    if (filter.tagCount && match == filter.blackTag) {
1982498b56bSopenharmony_ci        return false;
1992498b56bSopenharmony_ci    }
2002498b56bSopenharmony_ci    match = false;
2012498b56bSopenharmony_ci    // pid match
2022498b56bSopenharmony_ci    for (i = 0; i < filter.pidCount; i++) {
2032498b56bSopenharmony_ci        if (logData.pid == filter.pids[i]) {
2042498b56bSopenharmony_ci            match = true;
2052498b56bSopenharmony_ci            break;
2062498b56bSopenharmony_ci        }
2072498b56bSopenharmony_ci    }
2082498b56bSopenharmony_ci    if (filter.pidCount && match == filter.blackPid) {
2092498b56bSopenharmony_ci        return false;
2102498b56bSopenharmony_ci    }
2112498b56bSopenharmony_ci    // regular expression match
2122498b56bSopenharmony_ci    if (filter.regex[0] != 0) {
2132498b56bSopenharmony_ci        // Added a WildcardToRegex function for invalid regex.
2142498b56bSopenharmony_ci        std::string wildcardRegex = WildcardToRegex(filter.regex);
2152498b56bSopenharmony_ci        std::regex regExpress(wildcardRegex);
2162498b56bSopenharmony_ci        if (std::regex_search(logData.content, regExpress) == false) {
2172498b56bSopenharmony_ci            return false;
2182498b56bSopenharmony_ci        }
2192498b56bSopenharmony_ci    }
2202498b56bSopenharmony_ci    return true;
2212498b56bSopenharmony_ci}
2222498b56bSopenharmony_ci
2232498b56bSopenharmony_cistd::optional<HilogData> HilogBuffer::Query(const LogFilter& filter, const ReaderId& id, int tailCount)
2242498b56bSopenharmony_ci{
2252498b56bSopenharmony_ci    auto reader = GetReader(id);
2262498b56bSopenharmony_ci    if (!reader) {
2272498b56bSopenharmony_ci        std::cerr << "Reader not registered!\n";
2282498b56bSopenharmony_ci        return std::nullopt;
2292498b56bSopenharmony_ci    }
2302498b56bSopenharmony_ci
2312498b56bSopenharmony_ci    std::shared_lock<decltype(hilogBufferMutex)> lock(hilogBufferMutex);
2322498b56bSopenharmony_ci
2332498b56bSopenharmony_ci    if (reader->m_msgList != &hilogDataList) {
2342498b56bSopenharmony_ci        reader->m_msgList = &hilogDataList;
2352498b56bSopenharmony_ci        if (tailCount == 0) {
2362498b56bSopenharmony_ci            reader->m_pos = hilogDataList.begin();
2372498b56bSopenharmony_ci        } else {
2382498b56bSopenharmony_ci            reader->m_pos = hilogDataList.end();
2392498b56bSopenharmony_ci            reader->m_pos--;
2402498b56bSopenharmony_ci        }
2412498b56bSopenharmony_ci        for (int i = 0; (i < tailCount) && (reader->m_pos != hilogDataList.begin());) {
2422498b56bSopenharmony_ci            if (LogMatchFilter(filter, (*reader->m_pos))) {
2432498b56bSopenharmony_ci                i++;
2442498b56bSopenharmony_ci            }
2452498b56bSopenharmony_ci            reader->m_pos--;
2462498b56bSopenharmony_ci        }
2472498b56bSopenharmony_ci    }
2482498b56bSopenharmony_ci
2492498b56bSopenharmony_ci    if (reader->skipped) {
2502498b56bSopenharmony_ci        const string msg = "========Slow reader missed log lines: ";
2512498b56bSopenharmony_ci        const string tmpStr = msg + to_string(reader->skipped);
2522498b56bSopenharmony_ci        std::vector<char> buf(MAX_LOG_LEN, 0);
2532498b56bSopenharmony_ci        HilogMsg *headMsg = reinterpret_cast<HilogMsg *>(buf.data());
2542498b56bSopenharmony_ci        if (GenerateHilogMsgInside(*headMsg, tmpStr, LOG_CORE) == RET_SUCCESS) {
2552498b56bSopenharmony_ci            const HilogData logData(*headMsg);
2562498b56bSopenharmony_ci            reader->skipped = 0;
2572498b56bSopenharmony_ci            return logData;
2582498b56bSopenharmony_ci        }
2592498b56bSopenharmony_ci    }
2602498b56bSopenharmony_ci
2612498b56bSopenharmony_ci    while (reader->m_pos != hilogDataList.end()) {
2622498b56bSopenharmony_ci        const HilogData& logData = *reader->m_pos;
2632498b56bSopenharmony_ci        reader->m_pos++;
2642498b56bSopenharmony_ci        if (LogMatchFilter(filter, logData)) {
2652498b56bSopenharmony_ci            return logData;
2662498b56bSopenharmony_ci        }
2672498b56bSopenharmony_ci    }
2682498b56bSopenharmony_ci    return std::nullopt;
2692498b56bSopenharmony_ci}
2702498b56bSopenharmony_ci
2712498b56bSopenharmony_ciint32_t HilogBuffer::Delete(uint16_t logType)
2722498b56bSopenharmony_ci{
2732498b56bSopenharmony_ci    if (logType >= LOG_TYPE_MAX) {
2742498b56bSopenharmony_ci        return ERR_LOG_TYPE_INVALID;
2752498b56bSopenharmony_ci    }
2762498b56bSopenharmony_ci    size_t sum = 0;
2772498b56bSopenharmony_ci    std::unique_lock<decltype(hilogBufferMutex)> lock(hilogBufferMutex);
2782498b56bSopenharmony_ci    std::list<HilogData>::iterator it = hilogDataList.begin();
2792498b56bSopenharmony_ci
2802498b56bSopenharmony_ci    // Delete logs corresponding to queryCondition
2812498b56bSopenharmony_ci    while (it != hilogDataList.end()) {
2822498b56bSopenharmony_ci        // Only remove old logs of the same type
2832498b56bSopenharmony_ci        if ((*it).type != logType) {
2842498b56bSopenharmony_ci            ++it;
2852498b56bSopenharmony_ci            continue;
2862498b56bSopenharmony_ci        }
2872498b56bSopenharmony_ci        // Delete corresponding logs
2882498b56bSopenharmony_ci        OnDeleteItem(it, DeleteReason::CMD_CLEAR);
2892498b56bSopenharmony_ci
2902498b56bSopenharmony_ci        size_t cLen = it->len - it->tagLen;
2912498b56bSopenharmony_ci        sum += cLen;
2922498b56bSopenharmony_ci        sizeByType[(*it).type] -= cLen;
2932498b56bSopenharmony_ci        it = hilogDataList.erase(it);
2942498b56bSopenharmony_ci    }
2952498b56bSopenharmony_ci    return sum;
2962498b56bSopenharmony_ci}
2972498b56bSopenharmony_ci
2982498b56bSopenharmony_ciHilogBuffer::ReaderId HilogBuffer::CreateBufReader(std::function<void()> onNewDataCallback)
2992498b56bSopenharmony_ci{
3002498b56bSopenharmony_ci    std::unique_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3012498b56bSopenharmony_ci    auto reader = std::make_shared<BufferReader>();
3022498b56bSopenharmony_ci    if (reader != nullptr) {
3032498b56bSopenharmony_ci        reader->skipped = 0;
3042498b56bSopenharmony_ci        reader->m_onNewDataCallback = onNewDataCallback;
3052498b56bSopenharmony_ci    }
3062498b56bSopenharmony_ci    ReaderId id = reinterpret_cast<ReaderId>(reader.get());
3072498b56bSopenharmony_ci    m_logReaders.insert(std::make_pair(id, reader));
3082498b56bSopenharmony_ci    return id;
3092498b56bSopenharmony_ci}
3102498b56bSopenharmony_ci
3112498b56bSopenharmony_civoid HilogBuffer::RemoveBufReader(const ReaderId& id)
3122498b56bSopenharmony_ci{
3132498b56bSopenharmony_ci    std::unique_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3142498b56bSopenharmony_ci    auto it = m_logReaders.find(id);
3152498b56bSopenharmony_ci    if (it != m_logReaders.end()) {
3162498b56bSopenharmony_ci        m_logReaders.erase(it);
3172498b56bSopenharmony_ci    }
3182498b56bSopenharmony_ci}
3192498b56bSopenharmony_ci
3202498b56bSopenharmony_cibool HilogBuffer::IsItemUsed(LogMsgContainer::iterator itemPos)
3212498b56bSopenharmony_ci{
3222498b56bSopenharmony_ci    if (m_isSupportSkipLog) {
3232498b56bSopenharmony_ci        return false;
3242498b56bSopenharmony_ci    }
3252498b56bSopenharmony_ci    std::shared_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3262498b56bSopenharmony_ci    for (auto& [id, readerPtr] : m_logReaders) {
3272498b56bSopenharmony_ci        if (readerPtr->m_pos == itemPos) {
3282498b56bSopenharmony_ci            return true;
3292498b56bSopenharmony_ci        }
3302498b56bSopenharmony_ci    }
3312498b56bSopenharmony_ci    return false;
3322498b56bSopenharmony_ci}
3332498b56bSopenharmony_ci
3342498b56bSopenharmony_civoid HilogBuffer::OnDeleteItem(LogMsgContainer::iterator itemPos, DeleteReason reason)
3352498b56bSopenharmony_ci{
3362498b56bSopenharmony_ci    std::shared_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3372498b56bSopenharmony_ci    for (auto& [id, readerPtr] : m_logReaders) {
3382498b56bSopenharmony_ci        if (readerPtr->m_pos == itemPos) {
3392498b56bSopenharmony_ci            readerPtr->m_pos = std::next(itemPos);
3402498b56bSopenharmony_ci            if (reason == DeleteReason::BUFF_OVERFLOW) {
3412498b56bSopenharmony_ci                readerPtr->skipped++;
3422498b56bSopenharmony_ci            }
3432498b56bSopenharmony_ci        }
3442498b56bSopenharmony_ci    }
3452498b56bSopenharmony_ci}
3462498b56bSopenharmony_ci
3472498b56bSopenharmony_civoid HilogBuffer::OnPushBackedItem(LogMsgContainer& msgList)
3482498b56bSopenharmony_ci{
3492498b56bSopenharmony_ci    std::shared_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3502498b56bSopenharmony_ci    for (auto& [id, readerPtr] : m_logReaders) {
3512498b56bSopenharmony_ci        if (readerPtr->m_pos == msgList.end()) {
3522498b56bSopenharmony_ci            readerPtr->m_pos = std::prev(msgList.end());
3532498b56bSopenharmony_ci        }
3542498b56bSopenharmony_ci    }
3552498b56bSopenharmony_ci}
3562498b56bSopenharmony_ci
3572498b56bSopenharmony_civoid HilogBuffer::OnNewItem(LogMsgContainer& msgList)
3582498b56bSopenharmony_ci{
3592498b56bSopenharmony_ci    std::shared_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3602498b56bSopenharmony_ci    for (auto& [id, readerPtr] : m_logReaders) {
3612498b56bSopenharmony_ci        if (readerPtr->m_msgList == &msgList && readerPtr->m_onNewDataCallback) {
3622498b56bSopenharmony_ci            readerPtr->m_onNewDataCallback();
3632498b56bSopenharmony_ci        }
3642498b56bSopenharmony_ci    }
3652498b56bSopenharmony_ci}
3662498b56bSopenharmony_ci
3672498b56bSopenharmony_cistd::shared_ptr<HilogBuffer::BufferReader> HilogBuffer::GetReader(const ReaderId& id)
3682498b56bSopenharmony_ci{
3692498b56bSopenharmony_ci    std::shared_lock<decltype(m_logReaderMtx)> lock(m_logReaderMtx);
3702498b56bSopenharmony_ci    auto it = m_logReaders.find(id);
3712498b56bSopenharmony_ci    if (it != m_logReaders.end()) {
3722498b56bSopenharmony_ci        return it->second;
3732498b56bSopenharmony_ci    }
3742498b56bSopenharmony_ci    return std::shared_ptr<HilogBuffer::BufferReader>();
3752498b56bSopenharmony_ci}
3762498b56bSopenharmony_ci
3772498b56bSopenharmony_ciint64_t HilogBuffer::GetBuffLen(uint16_t logType)
3782498b56bSopenharmony_ci{
3792498b56bSopenharmony_ci    if (logType >= LOG_TYPE_MAX) {
3802498b56bSopenharmony_ci        return ERR_LOG_TYPE_INVALID;
3812498b56bSopenharmony_ci    }
3822498b56bSopenharmony_ci    uint64_t buffSize = g_maxBufferSizeByType[logType];
3832498b56bSopenharmony_ci    return buffSize;
3842498b56bSopenharmony_ci}
3852498b56bSopenharmony_ci
3862498b56bSopenharmony_ciint32_t HilogBuffer::SetBuffLen(uint16_t logType, uint64_t buffSize)
3872498b56bSopenharmony_ci{
3882498b56bSopenharmony_ci    if (logType >= LOG_TYPE_MAX) {
3892498b56bSopenharmony_ci        return ERR_LOG_TYPE_INVALID;
3902498b56bSopenharmony_ci    }
3912498b56bSopenharmony_ci    if (buffSize < MIN_BUFFER_SIZE || buffSize > MAX_BUFFER_SIZE) {
3922498b56bSopenharmony_ci        return ERR_BUFF_SIZE_INVALID;
3932498b56bSopenharmony_ci    }
3942498b56bSopenharmony_ci    std::unique_lock<decltype(hilogBufferMutex)> lock(hilogBufferMutex);
3952498b56bSopenharmony_ci    g_maxBufferSizeByType[logType] = buffSize;
3962498b56bSopenharmony_ci    return RET_SUCCESS;
3972498b56bSopenharmony_ci}
3982498b56bSopenharmony_ci
3992498b56bSopenharmony_civoid HilogBuffer::CountLog(const StatsInfo &info)
4002498b56bSopenharmony_ci{
4012498b56bSopenharmony_ci    stats.Count(info);
4022498b56bSopenharmony_ci}
4032498b56bSopenharmony_ci
4042498b56bSopenharmony_civoid HilogBuffer::ResetStats()
4052498b56bSopenharmony_ci{
4062498b56bSopenharmony_ci    stats.Reset();
4072498b56bSopenharmony_ci}
4082498b56bSopenharmony_ci
4092498b56bSopenharmony_ciLogStats& HilogBuffer::GetStatsInfo()
4102498b56bSopenharmony_ci{
4112498b56bSopenharmony_ci    return stats;
4122498b56bSopenharmony_ci}
4132498b56bSopenharmony_ci
4142498b56bSopenharmony_cistatic int GenerateHilogMsgInside(HilogMsg& hilogMsg, const string& msg, uint16_t logType)
4152498b56bSopenharmony_ci{
4162498b56bSopenharmony_ci    const string tag = "HiLog";
4172498b56bSopenharmony_ci    size_t contentLen =  tag.length() + 1 + msg.length() + 1;
4182498b56bSopenharmony_ci    hilogMsg.len = static_cast<uint16_t>(sizeof(HilogMsg) + contentLen);
4192498b56bSopenharmony_ci    hilogMsg.len = hilogMsg.len > MAX_LOG_LEN ? MAX_LOG_LEN : hilogMsg.len;
4202498b56bSopenharmony_ci    contentLen = hilogMsg.len - static_cast<uint16_t>(sizeof(HilogMsg));
4212498b56bSopenharmony_ci
4222498b56bSopenharmony_ci    struct timespec ts = {0};
4232498b56bSopenharmony_ci    (void)clock_gettime(CLOCK_REALTIME, &ts);
4242498b56bSopenharmony_ci    struct timespec ts_mono = {0};
4252498b56bSopenharmony_ci    (void)clock_gettime(CLOCK_MONOTONIC, &ts_mono);
4262498b56bSopenharmony_ci    hilogMsg.tv_sec = static_cast<uint32_t>(ts.tv_sec);
4272498b56bSopenharmony_ci    hilogMsg.tv_nsec = static_cast<uint32_t>(ts.tv_nsec);
4282498b56bSopenharmony_ci    hilogMsg.mono_sec = static_cast<uint32_t>(ts_mono.tv_nsec);
4292498b56bSopenharmony_ci    hilogMsg.type = logType;
4302498b56bSopenharmony_ci    hilogMsg.level = LOG_INFO;
4312498b56bSopenharmony_ci    hilogMsg.pid = 0;
4322498b56bSopenharmony_ci    hilogMsg.tid = 0;
4332498b56bSopenharmony_ci    hilogMsg.domain = 0;
4342498b56bSopenharmony_ci    hilogMsg.tagLen = tag.length() + 1;
4352498b56bSopenharmony_ci    if (memcpy_s(hilogMsg.tag, contentLen, tag.c_str(), hilogMsg.tagLen) != 0) {
4362498b56bSopenharmony_ci        return RET_FAIL;
4372498b56bSopenharmony_ci    }
4382498b56bSopenharmony_ci    if (memcpy_s(hilogMsg.tag + hilogMsg.tagLen, contentLen - hilogMsg.tagLen, msg.c_str(), msg.length() + 1) != 0) {
4392498b56bSopenharmony_ci        return RET_FAIL;
4402498b56bSopenharmony_ci    }
4412498b56bSopenharmony_ci
4422498b56bSopenharmony_ci    return RET_SUCCESS;
4432498b56bSopenharmony_ci}
4442498b56bSopenharmony_ci} // namespace HiviewDFX
4452498b56bSopenharmony_ci} // namespace OHOS
446