diff --git a/frameworks/libhilog/include/hilog_cmd.h b/frameworks/libhilog/include/hilog_cmd.h index 1043e1bf774907d3ae8abc186947a0280d365682..0529251b40d2101fb36b47e996427345db90a0dc 100644 --- a/frameworks/libhilog/include/hilog_cmd.h +++ b/frameworks/libhilog/include/hilog_cmd.h @@ -41,6 +41,10 @@ enum class IoctlCmd { PERSIST_STOP_RSP, PERSIST_QUERY_RQST, PERSIST_QUERY_RSP, + PERSIST_REFRESH_RQST, + PERSIST_REFRESH_RSP, + PERSIST_CLEAR_RQST, + PERSIST_CLEAR_RSP, BUFFERSIZE_GET_RQST, BUFFERSIZE_GET_RSP, BUFFERSIZE_SET_RQST, @@ -146,6 +150,23 @@ struct PersistQueryRsp { PersistTaskInfo taskInfo[MAX_JOBS]; } __attribute__((__packed__)); +struct PersistRefreshRqst { + uint32_t jobId; +} __attribute__((__packed__)); + +struct PersistRefreshRsp { + uint8_t jobNum; + uint32_t jobId[MAX_JOBS]; +} __attribute__((__packed__)); + +struct PersistClearRqst { + char placeholder; // Clear tasks needn't any parameter, this is just a placeholder +} __attribute__((__packed__)); + +struct PersistClearRsp { + char placeholder; +} __attribute__((__packed__)); + struct BufferSizeSetRqst { uint16_t types; int32_t size; diff --git a/services/hilogd/include/log_persister.h b/services/hilogd/include/log_persister.h index a370fbeb761a428416e2a880f762b9c1c2256d38..d3114deef31076264ed7ad9e3ce6bd0a7155d1c7 100644 --- a/services/hilogd/include/log_persister.h +++ b/services/hilogd/include/log_persister.h @@ -54,6 +54,8 @@ public: static int Kill(uint32_t id); static int Query(std::list &results); + static int Refresh(uint32_t id); + static void Clear(); int Init(const PersistRecoveryInfo& msg, bool restore); int Deinit(); diff --git a/services/hilogd/include/service_controller.h b/services/hilogd/include/service_controller.h index 5f258e40209805e74dc79ff2d6d129fca4d51e49..254005ec75784732321c9bc21bdf18e64c014324 100644 --- a/services/hilogd/include/service_controller.h +++ b/services/hilogd/include/service_controller.h @@ -77,6 +77,8 @@ private: void HandlePersistStartRqst(const PersistStartRqst &rqst); void HandlePersistStopRqst(const PersistStopRqst &rqst); void HandlePersistQueryRqst(const PersistQueryRqst& rqst); + void HandlePersistRefreshRqst(const PersistRefreshRqst& rqst); + void HandlePersistClearRqst(); void HandleBufferSizeGetRqst(const BufferSizeGetRqst& rqst); void HandleBufferSizeSetRqst(const BufferSizeSetRqst& rqst); void HandleStatsQueryRqst(const StatsQueryRqst& rqst); diff --git a/services/hilogd/log_persister.cpp b/services/hilogd/log_persister.cpp index 8fa5ee8bc35c0f6ffe1a44991a1934a22d59c495..98b34e6dcd4b3d738841809b9df9840f13fd0eec 100644 --- a/services/hilogd/log_persister.cpp +++ b/services/hilogd/log_persister.cpp @@ -29,8 +29,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -406,6 +408,51 @@ void LogPersister::Stop() } } +int LogPersister::Refresh(uint32_t id) +{ + auto logPersisterPtr = GetLogPersisterById(id); + if (logPersisterPtr) { + std::optional data = logPersisterPtr->m_hilogBuffer.Query(logPersisterPtr->m_startMsg.filter, + logPersisterPtr->m_bufReader); + if (data.has_value()) { + if (logPersisterPtr->WriteLogData(data.value())) { + std::cerr << " Can't write new log data!\n"; + } + } else { + std::unique_lockm_receiveLogCvMtx)> lk(logPersisterPtr->m_receiveLogCvMtx); + static const std::chrono::seconds waitTime(MAX_LOG_WRITE_INTERVAL); + if (cv_status::timeout == logPersisterPtr->m_receiveLogCv.wait_for(lk, waitTime)) { + std::cout << "no log timeout, write log forcely" << std::endl; + (void)logPersisterPtr->m_compressor->Compress(*(logPersisterPtr->m_mappedPlainLogFile), + *(logPersisterPtr->m_compressBuffer)); + logPersisterPtr->WriteCompressedLogs(); + } + } + return 0; + } + std::cerr << " Log persister with id: " << id << " does not exist.\n"; + return ERR_LOG_PERSIST_JOBID_FAIL; +} + +void LogPersister::Clear() +{ + std::regex hilogFilePattern("^hilog.*gz$"); + DIR *dir = nullptr; + struct dirent *ent = nullptr; + if ((dir = opendir(HILOG_FILE_DIR)) != nullptr) { + while ((ent = readdir(dir)) != nullptr) { + size_t length = strlen(ent->d_name); + std::string dName(ent->d_name, length); + if (std::regex_match(dName, hilogFilePattern)) { + remove((HILOG_FILE_DIR + dName).c_str()); + } + } + } + if (dir != nullptr) { + closedir(dir); + } +} + bool LogPersister::CheckRegistered(uint32_t id, const std::string& logPath) { std::lock_guard lock(s_logPersistersMtx); diff --git a/services/hilogd/main.cpp b/services/hilogd/main.cpp index e251f1aa6d7b241b8abb1c44325ddb6c8bd5743f..2f2836de0ad7efb12f511887a97b5671fdf9101a 100644 --- a/services/hilogd/main.cpp +++ b/services/hilogd/main.cpp @@ -201,6 +201,8 @@ int HilogdEntry() IoctlCmd::PERSIST_START_RQST, IoctlCmd::PERSIST_STOP_RQST, IoctlCmd::PERSIST_QUERY_RQST, + IoctlCmd::PERSIST_REFRESH_RQST, + IoctlCmd::PERSIST_CLEAR_RQST, IoctlCmd::BUFFERSIZE_GET_RQST, IoctlCmd::BUFFERSIZE_SET_RQST, IoctlCmd::STATS_QUERY_RQST, diff --git a/services/hilogd/service_controller.cpp b/services/hilogd/service_controller.cpp index a1ae223eddc90fd8b70593c742914a79ab538445..e79401f570d40d4c0aa4d82a2eb5da8eba3d6f8e 100644 --- a/services/hilogd/service_controller.cpp +++ b/services/hilogd/service_controller.cpp @@ -678,6 +678,39 @@ void ServiceController::HandlePersistQueryRqst(const PersistQueryRqst& rqst) (void)m_communicationSocket->Write(reinterpret_cast(&rsp), sizeof(rsp)); } +void ServiceController::HandlePersistRefreshRqst(const PersistRefreshRqst& rqst) +{ + PersistRefreshRsp rsp = { 0 }; + list resultList; + LogPersister::Query(resultList); + if (rqst.jobId == 0 && resultList.empty()) { + WriteErrorRsp(ERR_PERSIST_TASK_EMPTY); + return; + } + for (auto it = resultList.begin(); it != resultList.end() && rsp.jobNum < MAX_JOBS; ++it) { + uint32_t jobId = it->jobId; + if (rqst.jobId == 0 || rqst.jobId == jobId) { + (void)LogPersister::Refresh(jobId); + rsp.jobId[rsp.jobNum] = jobId; + rsp.jobNum++; + } + } + if (rsp.jobNum == 0) { + WriteErrorRsp(ERR_JOBID_NOT_EXSIST); + return; + } + WriteRspHeader(IoctlCmd::PERSIST_REFRESH_RSP, sizeof(rsp)); + (void)m_communicationSocket->Write(reinterpret_cast(&rsp), sizeof(rsp)); +} + +void ServiceController::HandlePersistClearRqst() +{ + LogPersister::Clear(); + PersistClearRsp rsp = { 0 }; + WriteRspHeader(IoctlCmd::PERSIST_CLEAR_RSP, sizeof(rsp)); + (void)m_communicationSocket->Write(reinterpret_cast(&rsp), sizeof(rsp)); +} + void ServiceController::HandleBufferSizeGetRqst(const BufferSizeGetRqst& rqst) { vector allTypes = GetAllLogTypes(); @@ -877,6 +910,18 @@ void ServiceController::CommunicationLoop(std::atomic& stopLoop, const Cmd }); break; } + case IoctlCmd::PERSIST_REFRESH_RQST: { + RequestHandler(hdr, [this](const PersistRefreshRqst& rqst) { + HandlePersistRefreshRqst(rqst); + }); + break; + } + case IoctlCmd::PERSIST_CLEAR_RQST: { + RequestHandler(hdr, [this](const PersistClearRqst& rqst) { + HandlePersistClearRqst(); + }); + break; + } case IoctlCmd::STATS_CLEAR_RQST: { RequestHandler(hdr, [this](const StatsClearRqst& rqst) { HandleStatsClearRqst(rqst); diff --git a/services/hilogtool/main.cpp b/services/hilogtool/main.cpp index 7f07aea4ebf076caca7fad6f855f041df0cbdbe8..b263f5936db4998d7c4118c7b8df163f3bc9732d 100644 --- a/services/hilogtool/main.cpp +++ b/services/hilogtool/main.cpp @@ -142,6 +142,8 @@ static void PersistTaskHelper() << " query query tasks informations" << endl << " stop stop all tasks" << endl << " start start one task" << endl + << " refresh refresh buffer content to file" << endl + << " clear clear /data/log/hilog/hilog*.gz" << endl << " Persistance task is used for saving logs in files." << endl << " The files are saved in directory: " << HILOG_FILE_DIR << endl << " Advanced options:" << endl @@ -878,6 +880,36 @@ static int PersistTaskQuery() return ret; } +static int PersistTaskRefresh() +{ + PersistRefreshRqst rqst = { 0 }; + LogIoctl ioctl(IoctlCmd::PERSIST_REFRESH_RQST, IoctlCmd::PERSIST_REFRESH_RSP); + int ret = ioctl.Request(rqst, [&rqst](const PersistRefreshRsp& rsp) { + for (int i = 0; i < rsp.jobNum; i++) { + PrintResult(RET_SUCCESS, (string("Persist task [jobid:") + to_string(rsp.jobId[i]) + "] refresh")); + } + return RET_SUCCESS; + }); + if (ret != RET_SUCCESS) { + PrintResult(RET_FAIL, (string("Persist task refresh"))); + } + return ret; +} + +static int ClearPersistLog() +{ + PersistClearRqst rqst = { 0 }; + LogIoctl ioctl(IoctlCmd::PERSIST_CLEAR_RQST, IoctlCmd::PERSIST_CLEAR_RSP); + int ret = ioctl.Request(rqst, [&rqst](const PersistClearRsp& rsp) { + PrintResult(RET_SUCCESS, (string("Persist log /data/log/hilog clear"))); + return RET_SUCCESS; + }); + if (ret != RET_SUCCESS) { + PrintResult(RET_FAIL, (string("Persist log /data/log/hilog clear"))); + } + return ret; +} + static int PersistTaskHandler(HilogArgs& context, const char *arg) { string strArg = arg; @@ -887,6 +919,10 @@ static int PersistTaskHandler(HilogArgs& context, const char *arg) return PersistTaskStop(context); } else if (strArg == "query") { return PersistTaskQuery(); + } else if (strArg == "refresh") { + return PersistTaskRefresh(); + } else if (strArg == "clear") { + return ClearPersistLog(); } else { return ERR_INVALID_ARGUMENT; } diff --git a/test/unittest/common/hilogtool_test.cpp b/test/unittest/common/hilogtool_test.cpp index 92b37b015a46bb99ed439623c04bde583f9a0b52..3e255bd72ff411293f6621e109884102487a09bb 100644 --- a/test/unittest/common/hilogtool_test.cpp +++ b/test/unittest/common/hilogtool_test.cpp @@ -14,6 +14,7 @@ */ #include "hilogtool_test.h" #include "hilog/log_c.h" +#include #include #include #include @@ -863,4 +864,31 @@ HWTEST_F(HilogToolTest, HandleTest_019, TestSize.Level1) // restore log level SetDomainLevel(domain, LOG_INFO); } + +/** + * @tc.name: Dfx_HilogToolTest_ClearTest_020 + * @tc.desc: hilog -w clear can delete /data/log/hilog/hilog*.gz. + * @tc.type: FUNC + */ +HWTEST_F(HilogToolTest, HandleTest_020, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleTest_020: start."; + (void)GetCmdResultFromPopen("hilog -w stop"); + std::string cmd = "hilog -w clear"; + std::string str = "Persist log /data/log/hilog clear successfully\n"; + EXPECT_EQ(GetCmdResultFromPopen(cmd), str); + + std::regex hilogFilePattern("^hilog.*gz$"); + DIR *dir = nullptr; + struct dirent *ent = nullptr; + if ((dir = opendir("/data/log/hilog")) != nullptr) { + while ((ent = readdir(dir)) != nullptr) { + EXPECT_FALSE(std::regex_match(ent->d_name, hilogFilePattern)); + } + } + if (dir != nullptr) { + closedir(dir); + } + (void)GetCmdResultFromPopen("hilog -w start"); +} } // namespace