diff --git a/frameworks/native/hilog_input_socket_server.cpp b/frameworks/native/hilog_input_socket_server.cpp index cf84d45d8c755b079f985bdebc2f1c037f0572b1..ed35b73f3702445ec6df4ca8c1fe7c0a927bddc0 100644 --- a/frameworks/native/hilog_input_socket_server.cpp +++ b/frameworks/native/hilog_input_socket_server.cpp @@ -29,8 +29,8 @@ HilogInputSocketServer::ServerThreadState HilogInputSocketServer::RunServingThre if (m_serverThread.get_id() != std::thread().get_id()) { return ServerThreadState::ALREADY_STARTED; } - m_serverThread = std::thread(&HilogInputSocketServer::ServingThread, this); m_stopServer.store(false); + m_serverThread = std::thread(&HilogInputSocketServer::ServingThread, this); if (m_serverThread.get_id() != std::thread().get_id()) { return ServerThreadState::JUST_STARTED; } diff --git a/frameworks/native/include/hilog_common.h b/frameworks/native/include/hilog_common.h index 1486b1466669dc0199b8689483c2a27c09b23265..9fff0225fda1448260f7fef00e92fa45fec65349 100644 --- a/frameworks/native/include/hilog_common.h +++ b/frameworks/native/include/hilog_common.h @@ -84,6 +84,9 @@ using HilogShowFormatBuffer = struct { template using OptRef = std::optional>; +template +using OptCRef = std::optional>; + #define CONTENT_LEN(pMsg) (pMsg->len - sizeof(HilogMsg) - pMsg->tag_len) /* include '\0' */ #define CONTENT_PTR(pMsg) (pMsg->tag + pMsg->tag_len) diff --git a/frameworks/native/include/socket.h b/frameworks/native/include/socket.h index afd66904993cca7a8f153cd113474a987658447f..18e5a900e788c4dfdbf5fdcc045f511e7224e3c7 100644 --- a/frameworks/native/include/socket.h +++ b/frameworks/native/include/socket.h @@ -34,7 +34,7 @@ public: int Poll(); int Write(const char *data, unsigned int len); int WriteAll(const char *data, unsigned int len); - int WriteV(iovec *vec, unsigned int len); + int WriteV(const iovec *vec, unsigned int len); int Read(char *buffer, unsigned int len); int Recv(void *buffer, unsigned int bufferLen, int flags = MSG_PEEK); protected: diff --git a/frameworks/native/socket.cpp b/frameworks/native/socket.cpp index 1140258a66be2c50849d81c05cbe87fb9c9fcb67..1332e0f5e956ef23c49f05b1e4f92b41ac0ce3fb 100644 --- a/frameworks/native/socket.cpp +++ b/frameworks/native/socket.cpp @@ -96,7 +96,7 @@ int Socket::WriteAll(const char *data, unsigned int len) } -int Socket::WriteV(iovec *vec, unsigned int len) +int Socket::WriteV(const iovec *vec, unsigned int len) { return TEMP_FAILURE_RETRY(::writev(socketHandler, vec, len)); } diff --git a/services/hilogd/BUILD.gn b/services/hilogd/BUILD.gn index 46d3cf4d049a279a361608b6471f513337749152..cba4fdc91ba5afffe08e54ce5689a60597a00f00 100644 --- a/services/hilogd/BUILD.gn +++ b/services/hilogd/BUILD.gn @@ -30,9 +30,8 @@ ohos_executable("hilogd") { "log_kmsg.cpp", "log_persister.cpp", "log_persister_rotator.cpp", - "log_querier.cpp", - "log_reader.cpp", "main.cpp", + "service_controller.cpp", ] configs = [ ":hilogd_config" ] defines = [ "__RECV_MSG_WITH_UCRED_" ] diff --git a/services/hilogd/cmd_executor.cpp b/services/hilogd/cmd_executor.cpp index 6c3fd6f9fa36aeca5eeeceff3c037e0d0495b16d..78bfeb90c8e7ec9717cf7b5fd822666c457cf7c4 100644 --- a/services/hilogd/cmd_executor.cpp +++ b/services/hilogd/cmd_executor.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #include "cmd_executor.h" -#include "log_querier.h" +#include "service_controller.h" #include @@ -120,8 +120,8 @@ void CmdExecutor::ClientEventLoop(std::unique_ptr handler) assert(clientInfoIt != m_clients.end()); prctl(PR_SET_NAME, "hilogd.query"); - auto logQuerier = std::make_shared(std::move(handler), m_hilogBuffer); - logQuerier->LogQuerierThreadFunc(logQuerier); + ServiceController serviceCtrl(std::move(handler), m_hilogBuffer); + serviceCtrl.CommunicationLoop((*clientInfoIt)->m_stopThread); std::lock_guard ul(m_finishedClientAccess); m_finishedClients.push_back(std::this_thread::get_id()); @@ -151,6 +151,5 @@ void CmdExecutor::CleanFinishedClients() } } } - } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/kmsg_parser.h b/services/hilogd/include/kmsg_parser.h index c647b3298f88bbe74a9df5fd76a759c5355449b5..4aa1d3f1966d16f5ad0e05aee60f7cc469f62f48 100644 --- a/services/hilogd/include/kmsg_parser.h +++ b/services/hilogd/include/kmsg_parser.h @@ -16,14 +16,15 @@ #define KMSG_PARSER_H #include "log_collector.h" +#include "log_msg_wrapper.h" namespace OHOS { namespace HiviewDFX { class KmsgParser { public: - using BootTp = std::chrono::time_point; - std::optional ParseKmsg(std::vector& kmsgBuffer); - BootTp BootTime(); + using BootTp = std::chrono::time_point; + static std::optional ParseKmsg(const std::vector& kmsgBuffer); + static BootTp BootTime(); }; } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/log_buffer.h b/services/hilogd/include/log_buffer.h index 5dd12f96637bc32283ba9d7b7145b16e5ccb618f..4e676ea44ae719c98813e7d16070c00a3a2bba5b 100644 --- a/services/hilogd/include/log_buffer.h +++ b/services/hilogd/include/log_buffer.h @@ -17,29 +17,32 @@ #define LOG_BUFFER_H #include +#include #include #include #include -#include #include -#include -#include "log_reader.h" +#include "log_data.h" +#include "log_filter.h" namespace OHOS { namespace HiviewDFX { class HilogBuffer { public: + using LogMsgContainer = std::list; + using ReaderId = uintptr_t; + using OnFound = std::function; + HilogBuffer(); ~HilogBuffer(); - std::vector> logReaderList; - std::shared_mutex logReaderListMutex; size_t Insert(const HilogMsg& msg); - bool Query(LogReader* reader); - bool Query(std::shared_ptr reader); - void AddLogReader(std::weak_ptr); - void RemoveLogReader(std::shared_ptr reader); + bool Query(const LogFilterExt& filter, const ReaderId& id, OnFound onFound); + + ReaderId CreateBufReader(std::function onNewDataCallback); + void RemoveBufReader(const ReaderId& id); + size_t Delete(uint16_t logType); size_t GetBuffLen(uint16_t logType); size_t SetBuffLen(uint16_t logType, uint64_t buffSize); @@ -47,13 +50,25 @@ public: int32_t GetStatisticInfoByDomain(uint32_t domain, uint64_t& printLen, uint64_t& cacheLen, int32_t& dropped); int32_t ClearStatisticInfoByLog(uint16_t logType); int32_t ClearStatisticInfoByDomain(uint32_t domain); - void GetBufferLock(); - void ReleaseBufferLock(); + + static bool LogMatchFilter(const LogFilterExt& filter, const HilogData& logData); private: + struct BufferReader { + LogMsgContainer::iterator m_pos; + LogMsgContainer* m_msgList = nullptr; + std::function m_onNewDataCallback; + }; + + void UpdateStatistics(const HilogData& logData); + void OnDeleteItem(LogMsgContainer::iterator itemPos); + void OnPushBackedItem(LogMsgContainer& msgList); + void OnNewItem(LogMsgContainer& msgList); + std::shared_ptr GetReader(const ReaderId& id); + size_t size; size_t sizeByType[LOG_TYPE_MAX]; - std::list hilogDataList; - std::list hilogKlogList; + LogMsgContainer hilogDataList; + LogMsgContainer hilogKlogList; std::shared_mutex hilogBufferMutex; std::map cacheLenByDomain; std::map printLenByDomain; @@ -61,8 +76,9 @@ private: uint64_t cacheLenByType[LOG_TYPE_MAX]; uint64_t droppedByType[LOG_TYPE_MAX]; uint64_t printLenByType[LOG_TYPE_MAX]; - bool ConditionMatch(std::shared_ptr reader); - void ReturnNoLog(std::shared_ptr reader); + + std::map> m_logReaders; + std::shared_mutex m_logReaderMtx; }; } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/log_compress.h b/services/hilogd/include/log_compress.h index 7897845a1a66d9b6066d5f06be0212a6654a3bc4..95f87ede02d49ea215d5199d258fbff78ed849e2 100644 --- a/services/hilogd/include/log_compress.h +++ b/services/hilogd/include/log_compress.h @@ -31,36 +31,38 @@ typedef struct { uint32_t offset; } LogPersisterBuffer; -const uint16_t CHUNK = 16384; class LogCompress { public: - LogCompress(); + LogCompress() = default; virtual ~LogCompress() = default; - virtual int Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer) = 0; - void DeleteZData(); - unsigned char *zdata = nullptr; - char buffIn[CHUNK] = {0}; - char buffOut[CHUNK] = {0}; + virtual int Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressBuffer) = 0; }; class NoneCompress : public LogCompress { public: - int Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer); + int Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressBuffer) override; }; class ZlibCompress : public LogCompress { public: - int Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer); + int Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressBuffer) override; private: + static const uint16_t CHUNK = 16384; + char buffIn[CHUNK] = {0}; + char buffOut[CHUNK] = {0}; + z_stream cStream; }; class ZstdCompress : public LogCompress { public: - int Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer); + int Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressBuffer) override; private: #ifdef USING_ZSTD_COMPRESS + static const uint16_t CHUNK = 16384; + char buffIn[CHUNK] = {0}; + char buffOut[CHUNK] = {0}; ZSTD_CCtx* cctx; #endif }; diff --git a/services/hilogd/include/log_data.h b/services/hilogd/include/log_data.h index dac520b6688b24b5a9dfaf5ee79da86036a8858e..15446464213c56a5abfad634b59c51b704ee7d21 100644 --- a/services/hilogd/include/log_data.h +++ b/services/hilogd/include/log_data.h @@ -71,11 +71,21 @@ struct HilogData { tag(nullptr), content(nullptr) { init(msg.tag, msg.tag_len, CONTENT_PTR((&msg)), CONTENT_LEN((&msg))); - }; + } + HilogData(const HilogData&) = delete; + HilogData& operator=(const HilogData&) = delete; + + HilogData(HilogData&& cpy) + { + std::memcpy(this, &cpy, sizeof(HilogData)); + cpy.tag = nullptr; + cpy.content = nullptr; + } + ~HilogData() { deinit(); - }; + } }; } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/log_querier.h b/services/hilogd/include/log_filter.h similarity index 50% rename from services/hilogd/include/log_querier.h rename to services/hilogd/include/log_filter.h index d14360daa2c029482fe6476a7c14dc48b7f7c1e9..c6a519bf81e50006fc8f5fc0bbfae6a026c454c9 100644 --- a/services/hilogd/include/log_querier.h +++ b/services/hilogd/include/log_filter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -12,26 +12,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef LOG_QUERIER_H -#define LOG_QUERIER_H -#include -#include -#include "log_buffer.h" -#include "log_reader.h" + +#ifndef LOG_FILTER_H +#define LOG_FILTER_H + +#include +#include +#include namespace OHOS { namespace HiviewDFX { -class LogQuerier : public LogReader { -public: - LogQuerier(std::unique_ptr handler, HilogBuffer& buffer); - static void LogQuerierThreadFunc(std::shared_ptr logReader); - int WriteData(LogQueryResponse& rsp, OptRef pData); - int WriteData(OptRef pData); - void NotifyForNewData(); - uint8_t GetType() const; - int RestorePersistJobs(HilogBuffer& _buffer); - ~LogQuerier() = default; +struct LogFilter { + uint16_t levels = 0; + uint16_t types = 0; + std::vector pids; + std::vector domains; + std::vector tags; +}; +struct LogFilterExt { + LogFilter inclusions; + LogFilter exclusions; }; } // namespace HiviewDFX } // namespace OHOS -#endif +#endif // LOG_FILTER_H diff --git a/services/hilogd/include/log_kmsg.h b/services/hilogd/include/log_kmsg.h index a911e8f1c3b9a1384a7772d21423e0750e4d69f0..ce4fc096ba608ebef99a66acf188a6233811aafc 100644 --- a/services/hilogd/include/log_kmsg.h +++ b/services/hilogd/include/log_kmsg.h @@ -23,7 +23,6 @@ namespace HiviewDFX { class LogKmsg { public: LogKmsg(HilogBuffer& hilogBuffer) : hilogBuffer(hilogBuffer) {}; - LogKmsg(HilogBuffer&&) = delete; ~LogKmsg(); ssize_t LinuxReadOneKmsg(KmsgParser& parser); int LinuxReadAllKmsg(); diff --git a/services/hilogd/include/log_msg_wrapper.h b/services/hilogd/include/log_msg_wrapper.h index b0748a7d356c720eb7a2e15c4147ee33d216a973..e2b01e29de58c6009bd1e440c9291c52d25af5bd 100644 --- a/services/hilogd/include/log_msg_wrapper.h +++ b/services/hilogd/include/log_msg_wrapper.h @@ -29,26 +29,23 @@ namespace HiviewDFX { class HilogMsgWrapper { public: explicit HilogMsgWrapper(const std::vector & _msgBuffer) : msgBuffer(_msgBuffer) - {}; + {} explicit HilogMsgWrapper(std::vector && _msgBuffer) { std::swap(msgBuffer, _msgBuffer); } - HilogMsg& getHilogMsg() + HilogMsg& GetHilogMsg() { return *reinterpret_cast(msgBuffer.data()); } - bool IsValid() - { - return validity; - } - void SetInvalid() + + const std::vector & GetRawData() const { - validity = false; + return msgBuffer; } + private: std::vector msgBuffer; - bool validity = true; }; } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/log_persister.h b/services/hilogd/include/log_persister.h index fd69bf875f2861a3025ec888d2df3e851f5062ba..1f1eab1f985e3afd9a04412dbf6899b981d04afb 100644 --- a/services/hilogd/include/log_persister.h +++ b/services/hilogd/include/log_persister.h @@ -19,63 +19,96 @@ #include #include +#include #include #include +#include #include +#include +#include +#include +#include "log_buffer.h" +#include "log_filter.h" #include "log_persister_rotator.h" -#include "log_reader.h" #include "log_compress.h" namespace OHOS { namespace HiviewDFX { -using namespace std; - -class LogPersister : public LogReader { +class LogPersister : public std::enable_shared_from_this { public: - LogPersister(uint32_t id, std::string path, uint32_t fileSize, uint16_t compressAlg, int sleepTime, - shared_ptr rotator, HilogBuffer &buffer); + using InitData = std::variant; + + [[nodiscard]] static std::shared_ptr CreateLogPersister(HilogBuffer &buffer); + ~LogPersister(); - void SetBufferOffset(int off); - void NotifyForNewData(); - int WriteData(OptRef pData); - int ThreadFunc(); + static int Kill(uint32_t id); - void Exit(); static int Query(uint16_t logType, std::list &results); - int Init(); - int InitCompress(); + + int Init(const InitData& initData); + int Deinit(); + void Start(); - bool Identify(uint32_t id); + void Stop(); + void FillInfo(LogPersistQueryResult &response); - bool writeUnCompressedBuffer(HilogData &data); - uint8_t GetType() const; - std::string getPath(); - LogPersisterBuffer *buffer; - LogPersisterBuffer *compressBuffer; private: - uint32_t id; - std::string path; - uint32_t fileSize; - std::string mmapPath; - uint16_t compressAlg; - int sleepTime; - std::mutex cvMutex; - std::condition_variable condVariable; - std::mutex mutexForhasExited; - std::condition_variable cvhasExited; - shared_ptr rotator; - bool toExit; - bool hasExited; - inline void WriteFile(); - bool isExited(); - FILE* fd = nullptr; - LogCompress *compressor; - list persistList; - uint32_t plainLogSize; + struct BaseData { + uint32_t id; + std::string logPath; + uint32_t logFileSizeLimit; + uint16_t compressAlg; + uint32_t maxLogFileNum; + std::chrono::seconds newLogTimeout; + }; + + LogPersister(HilogBuffer &buffer); + + static bool CheckRegistered(uint32_t id, const std::string& logPath); + static std::shared_ptr GetLogPersisterById(uint32_t id); + static void RegisterLogPersister(const std::shared_ptr& obj); + static void DeregisterLogPersister(const std::shared_ptr& obj); + + void NotifyNewLogAvailable(); + + int ReceiveLogLoop(); + + int InitCompression(); + int InitFileRotator(const InitData& initData); + int WriteLogData(const HilogData& logData); + bool WriteUncompressedLogs(std::list& formatedTextLogs); + void WriteCompressedLogs(); + + int PrepareUncompressedFile(const std::string& parentPath, bool restore); + + BaseData m_baseData = {0}; + + std::string m_plainLogFilePath; + LogPersisterBuffer *m_mappedPlainLogFile; + uint32_t m_plainLogSize = 0; + std::unique_ptr m_compressor; + std::unique_ptr m_compressBuffer; + std::unique_ptr m_fileRotator; + + std::mutex m_receiveLogCvMtx; + std::condition_variable m_receiveLogCv; + + volatile bool m_stopThread = false; + std::thread m_persisterThread; + + HilogBuffer &m_hilogBuffer; + HilogBuffer::ReaderId m_bufReader; + LogFilterExt m_filters; + + std::mutex m_initMtx; + volatile bool m_inited = false; + + static std::recursive_mutex s_logPersistersMtx; + static std::list> s_logPersisters; }; -int GenPersistLogHeader(HilogData *data, list& persistList); +std::list LogDataToFormatedStrings(HilogData *data); } // namespace HiviewDFX } // namespace OHOS #endif diff --git a/services/hilogd/include/log_persister_rotator.h b/services/hilogd/include/log_persister_rotator.h index 119f8cac4f07ffdc43466e61400b0390b5ac584a..1e85f9c3a9a323cf18779821017ecfad8c49c7d1 100644 --- a/services/hilogd/include/log_persister_rotator.h +++ b/services/hilogd/include/log_persister_rotator.h @@ -16,10 +16,11 @@ #define _HILOG_PERSISTER_ROTATOR_H #include #include + #include #include "hilog_common.h" #include "hilogtool_msg.h" -#include "log_buffer.h" +#include "log_filter.h" namespace OHOS { namespace HiviewDFX { typedef struct { @@ -29,41 +30,42 @@ typedef struct { LogPersistStartMsg msg; } PersistRecoveryInfo; -const std::string ANXILLARY_FILE_NAME = "persisterInfo_"; -uint64_t GetInfoHash(const PersistRecoveryInfo &info); +static constexpr const char* AUXILLARY_PERSISTER_PREFIX = "persisterInfo_"; + +uint64_t GenerateHash(const PersistRecoveryInfo &info); + class LogPersisterRotator { public: - LogPersisterRotator(std::string path, uint32_t fileSize, uint32_t fileNum, std::string suffix = ""); + LogPersisterRotator(const std::string& path, uint32_t id, uint32_t maxFiles, const std::string& suffix = ""); ~LogPersisterRotator(); - int Init(); + int Init(const PersistRecoveryInfo& info, bool restore = false); int Input(const char *buf, uint32_t length); - void FillInfo(uint32_t &size, uint32_t &num); void FinishInput(); - void SetIndex(int pIndex); - void SetId(uint32_t pId); - void OpenInfoFile(); + + void SetFileIndex(uint32_t index, bool forceRotate); +private: + int OpenInfoFile(); void UpdateRotateNumber(); - int SaveInfo(const LogPersistStartMsg& pMsg, const QueryCondition queryCondition); void WriteRecoveryInfo(); - void SetRestore(bool flag); - bool GetRestore(); - void RemoveInfo(); -protected: - void InternalRotate(); - uint32_t fileNum; - uint32_t fileSize; - std::string fileName; - std::string fileSuffix; - int index; - std::fstream output; -private: + int SetInfo(const LogPersistStartMsg& pMsg, uint16_t logType, uint8_t logLevel); + + std::string CreateLogFileName(uint32_t logIndex); + void CreateLogFile(); void Rotate(); - bool needRotate = false; - FILE* fdinfo = nullptr; - uint32_t id = 0; - std::string infoPath; - PersistRecoveryInfo info; - bool restore = false; + void PhysicalShiftFile(); + + uint32_t m_maxLogFileNum = 0; + std::string m_logsPath; + std::string m_fileNameSuffix; + uint32_t m_currentLogFileIdx = 0; + std::fstream m_currentLogOutput; + + uint32_t m_id = 0; + std::fstream m_infoFile; + std::string m_infoFilePath; + PersistRecoveryInfo m_info = {0}; + + bool m_needRotate = false; }; } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/include/log_reader.h b/services/hilogd/include/log_reader.h deleted file mode 100644 index 6235656f6e5804fc3517bd0ac3e3e1f1986a6ebe..0000000000000000000000000000000000000000 --- a/services/hilogd/include/log_reader.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LOG_READER_H -#define LOG_READER_H - -#include -#include -#include -#include -#include -#include "log_data.h" -#include "log_msg_wrapper.h" -#include "hilogtool_msg.h" -#include "socket.h" - -namespace OHOS { -namespace HiviewDFX { -class HilogBuffer; - -#define TYPE_QUERIER 1 -#define TYPE_PERSISTER 2 -#define TYPE_CONTROL 3 - -using QueryCondition = struct QueryCondition { - uint8_t nPid = 0; - uint8_t nNoPid = 0; - uint8_t nDomain = 0; - uint8_t nNoDomain = 0; - uint8_t nTag = 0; - uint8_t nNoTag = 0; - uint16_t levels = 0; - uint16_t types = 0; - uint32_t pids[MAX_PIDS]; - uint32_t domains[MAX_DOMAINS]; - std::string tags[MAX_TAGS]; - uint8_t noLevels = 0; - uint16_t noTypes = 0; - uint32_t noPids[MAX_PIDS]; - uint32_t noDomains[MAX_DOMAINS]; - std::string noTags[MAX_TAGS]; -}; - -class LogReader : public std::enable_shared_from_this { -public: - std::list::iterator readPos; - std::list::iterator lastPos; - QueryCondition queryCondition; - std::unique_ptr hilogtoolConnectSocket; - bool isNotified; - - LogReader(); - virtual ~LogReader(); - bool GetReload() const; - void SetReload(bool); - virtual void NotifyForNewData() = 0; - void NotifyReload(); - - virtual int WriteData(OptRef pData) =0; - void SetSendId(unsigned int value); - void SetCmd(uint8_t value); - virtual uint8_t GetType() const = 0; -protected: - unsigned int sendId = 1; - uint8_t cmd = 0; - static HilogBuffer* hilogBuffer; - -private: - bool isReload = true; -}; -} // namespace HiviewDFX -} // namespace OHOS -#endif diff --git a/services/hilogd/include/service_controller.h b/services/hilogd/include/service_controller.h new file mode 100644 index 0000000000000000000000000000000000000000..158e1220e4ff08a5c3f88c6ea9e86e18b6726927 --- /dev/null +++ b/services/hilogd/include/service_controller.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_QUERIER_H +#define LOG_QUERIER_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "log_buffer.h" + +namespace OHOS { +namespace HiviewDFX { +class ServiceController { +public: + static constexpr int MAX_DATA_LEN = 2048; + using PacketBuf = std::array; + + ServiceController(std::unique_ptr communicationSocket, HilogBuffer& buffer); + ~ServiceController(); + + void CommunicationLoop(const std::atomic& stopLoop); +private: + void SetFilters(const PacketBuf& rawData); + + void HandleLogQueryRequest(); + void HandleNextRequest(const PacketBuf& rawData, const std::atomic& stopLoop); + + // persist storage + void HandlePersistStartRequest(const PacketBuf& rawData); + void HandlePersistStopRequest(const PacketBuf& rawData); + void HandlePersistQueryRequest(const PacketBuf& rawData); + + // buffer size + void HandleBufferResizeRequest(const PacketBuf& rawData); + void HandleBufferSizeRequest(const PacketBuf& rawData); + + // statistics + void HandleInfoQueryRequest(const PacketBuf& rawData); + void HandleInfoClearRequest(const PacketBuf& rawData); + void HandleBufferClearRequest(const PacketBuf& rawData); + + int WriteData(LogQueryResponse& rsp, OptCRef pData); + int WriteV(const iovec* vec, size_t len); + int WriteLogQueryRespond(unsigned int sendId, uint32_t respondCmd, OptCRef pData); + void NotifyForNewData(); + + std::unique_ptr m_communicationSocket; + HilogBuffer& m_hilogBuffer; + HilogBuffer::ReaderId m_bufReader; + + std::condition_variable m_notifyNewDataCv; + std::mutex m_notifyNewDataMtx; + + LogFilterExt m_filters; +}; + +int RestorePersistJobs(HilogBuffer& _buffer); +} // namespace HiviewDFX +} // namespace OHOS +#endif diff --git a/services/hilogd/kmsg_parser.cpp b/services/hilogd/kmsg_parser.cpp index 95f7362bf567d2d8dfafc78f094b7124bdd7d9ad..c7f763e648dbd731607fc3542a37748192d54422 100644 --- a/services/hilogd/kmsg_parser.cpp +++ b/services/hilogd/kmsg_parser.cpp @@ -32,8 +32,8 @@ namespace OHOS { namespace HiviewDFX { -using namespace std; using namespace std::chrono; +using namespace std::literals; constexpr int DEC = 10; @@ -44,7 +44,7 @@ constexpr int DEC = 10; #undef LOG_INFO #undef LOG_DEBUG -void ParseHeader(std::string& str, uint16_t* level, uint64_t* timestamp) +static void ParseHeader(std::string& str, uint16_t* level, uint64_t* timestamp) { static const std::string pattern = "(\\d+),(\\d+),(\\d+),(\\S);"; static const std::regex express(pattern); @@ -57,7 +57,7 @@ void ParseHeader(std::string& str, uint16_t* level, uint64_t* timestamp) } // Parse pid if exists -uint32_t ParsePid(std::string& str) +static uint32_t ParsePid(std::string& str) { static const std::string pattern = "\\[pid=(\\d+)\\]"; static const std::regex express(pattern); @@ -70,7 +70,7 @@ uint32_t ParsePid(std::string& str) return 0; } -std::string ParseTag(std::string& str) +static std::string ParseTag(std::string& str) { static const std::string pattern = "\\[.*?\\]"; static const std::regex express(pattern); @@ -84,7 +84,7 @@ std::string ParseTag(std::string& str) } // Log levels are different in syslog.h and hilog log_c.h -uint16_t KmsgLevelMap(uint16_t prio) +static uint16_t KmsgLevelMap(uint16_t prio) { uint16_t level; switch (prio) { @@ -110,7 +110,7 @@ uint16_t KmsgLevelMap(uint16_t prio) return level; } -constexpr timespec TimepointToTimespec(time_point tp) +static constexpr timespec TimepointToTimespec(time_point tp) { auto secs = time_point_cast(tp); auto nsecs = time_point_cast(tp) - time_point_cast(secs); @@ -127,7 +127,7 @@ KmsgParser::BootTp KmsgParser::BootTime() auto boottime = current - uptime; return boottime; } -std::optional KmsgParser::ParseKmsg(std::vector& kmsgBuffer) +std::optional KmsgParser::ParseKmsg(const std::vector& kmsgBuffer) { std::string kmsgStr(kmsgBuffer.data()); std::vector mtag(MAX_TAG_LEN, '\0'); @@ -135,33 +135,28 @@ std::optional KmsgParser::ParseKmsg(std::vector& kmsgBuf uint64_t timestamp = 0; ParseHeader(kmsgStr, &mLevel, ×tamp); // Parses pid if exists. Pid in kmsg content is like: [pid=xxx,...] - uint32_t mpid = 0; - mpid = ParsePid(kmsgStr); + uint32_t mpid = ParsePid(kmsgStr); // If there are some other content wrapped in square brackets "[]", parse it as tag // Otherwise, use default tag "kmsg" int tagLen = 0; std::string tagStr = ParseTag(kmsgStr); if (!tagStr.empty()) { tagLen = tagStr.size(); - if (strncpy_s(mtag.data(), MAX_TAG_LEN - 1, tagStr.c_str(), tagLen) != 0) { - HilogMsgWrapper nullMsg((std::vector())); - nullMsg.SetInvalid(); - return nullMsg; + if (strncpy_s(mtag.data(), MAX_TAG_LEN - 1, tagStr.c_str(), tagStr.size()) != 0) { + return {}; } } else { constexpr auto defaultTag = "kmsg"sv; tagLen = defaultTag.size(); - if (strncpy_s(mtag.data(), MAX_TAG_LEN - 1, "kmsg", defaultTag.size()) != 0) { - HilogMsgWrapper nullMsg((std::vector())); - nullMsg.SetInvalid(); - return nullMsg; + if (strncpy_s(mtag.data(), MAX_TAG_LEN - 1, defaultTag.data(), defaultTag.size()) != 0) { + return {}; } } // Now build HilogMsg and insert it into buffer int len = kmsgStr.size() + 1; int msgLen = sizeof(HilogMsg) + tagLen + len + 1; HilogMsgWrapper msgWrap((std::vector(msgLen, '\0'))); - HilogMsg& msg = msgWrap.getHilogMsg(); + HilogMsg& msg = msgWrap.GetHilogMsg(); msg.len = msgLen; msg.tag_len = tagLen + 1; msg.type = LOG_KMSG; @@ -174,12 +169,10 @@ std::optional KmsgParser::ParseKmsg(std::vector& kmsgBuf msg.pid = mpid; msg.tid = mpid; if (strncpy_s(msg.tag, tagLen + 1, mtag.data(), tagLen) != 0) { - msgWrap.SetInvalid(); - return msgWrap; + return {}; } if (strncpy_s(CONTENT_PTR((&msg)), MAX_LOG_LEN, kmsgStr.c_str(), len) != 0) { - msgWrap.SetInvalid(); - return msgWrap; + return {}; } return msgWrap; } diff --git a/services/hilogd/log_buffer.cpp b/services/hilogd/log_buffer.cpp index 6f5384f7180c848f6d918ad1001d187483295491..79d36ae1a7831116e1d3552d31ce1fe6a3d2f750 100644 --- a/services/hilogd/log_buffer.cpp +++ b/services/hilogd/log_buffer.cpp @@ -16,6 +16,7 @@ #include "log_buffer.h" #include +#include #include "hilog_common.h" #include "flow_control_init.h" #include "log_time_stamp.h" @@ -43,110 +44,104 @@ HilogBuffer::HilogBuffer() HilogBuffer::~HilogBuffer() {} - size_t HilogBuffer::Insert(const HilogMsg& msg) { - size_t eleSize = CONTENT_LEN((&msg)); /* include '\0' */ + size_t elemSize = CONTENT_LEN((&msg)); /* include '\0' */ - if (unlikely(msg.tag_len > MAX_TAG_LEN || msg.tag_len == 0 || eleSize > MAX_LOG_LEN || eleSize <= 0)) { + if (unlikely(msg.tag_len > MAX_TAG_LEN || msg.tag_len == 0 || elemSize > MAX_LOG_LEN || elemSize <= 0)) { return 0; } - std::list &msgList = (msg.type == LOG_KMSG) ? hilogKlogList : hilogDataList; - // Delete old entries when full - if (eleSize + sizeByType[msg.type] >= (size_t)g_maxBufferSizeByType[msg.type]) { - hilogBufferMutex.lock(); - // Drop 5% of maximum log when full - std::list::iterator it = msgList.begin(); - while (sizeByType[msg.type] > g_maxBufferSizeByType[msg.type] * (1 - DROP_RATIO) && - it != msgList.end()) { - if ((*it).type != msg.type) { // Only remove old logs of the same type - ++it; - continue; - } - logReaderListMutex.lock_shared(); - for (auto &itr :logReaderList) { - auto reader = itr.lock(); - if (reader == nullptr) { + LogMsgContainer &msgList = (msg.type == LOG_KMSG) ? hilogKlogList : hilogDataList; + HilogData msgAsData(msg); + { + std::unique_lock lock(hilogBufferMutex); + + // Delete old entries when full + if (elemSize + sizeByType[msg.type] >= (size_t)g_maxBufferSizeByType[msg.type]) { + // Drop 5% of maximum log when full + std::list::iterator it = msgList.begin(); + while (sizeByType[msg.type] > g_maxBufferSizeByType[msg.type] * (1 - DROP_RATIO) && + it != msgList.end()) { + if ((*it).type != msg.type) { // Only remove old logs of the same type + ++it; continue; } - if (reader->readPos == it) { - reader->readPos = std::next(it); - } - if (reader->lastPos == it) { - reader->lastPos = std::next(it); - } + OnDeleteItem(it); + size_t cLen = it->len - it->tag_len; + size -= cLen; + sizeByType[(*it).type] -= cLen; + it = msgList.erase(it); } - logReaderListMutex.unlock_shared(); - size_t cLen = it->len - it->tag_len; - size -= cLen; - sizeByType[(*it).type] -= cLen; - it = msgList.erase(it); - } - // Re-confirm if enough elements has been removed - if (sizeByType[msg.type] >= (size_t)g_maxBufferSizeByType[msg.type]) { - std::cout << "Failed to clean old logs." << std::endl; + // Re-confirm if enough elements has been removed + if (sizeByType[msg.type] >= (size_t)g_maxBufferSizeByType[msg.type]) { + std::cout << "Failed to clean old logs." << std::endl; + } } - hilogBufferMutex.unlock(); - } - // Insert new log into HilogBuffer - msgList.emplace_back(msg); + // Append new log into HilogBuffer + msgList.push_back(std::move(msgAsData)); + OnPushBackedItem(msgList); + } // Update current size of HilogBuffer - size += eleSize; - sizeByType[msg.type] += eleSize; - cacheLenByType[msg.type] += eleSize; + size += elemSize; + sizeByType[msg.type] += elemSize; + cacheLenByType[msg.type] += elemSize; if (cacheLenByDomain.count(msg.domain) == 0) { - cacheLenByDomain.insert(pair(msg.domain, eleSize)); + cacheLenByDomain.insert(pair(msg.domain, elemSize)); } else { - cacheLenByDomain[msg.domain] += eleSize; + cacheLenByDomain[msg.domain] += elemSize; } - return eleSize; -} + // Notify readers about new element added + OnNewItem(msgList); + return elemSize; +} -bool HilogBuffer::Query(std::shared_ptr reader) +bool HilogBuffer::Query(const LogFilterExt& filter, const ReaderId& id, OnFound onFound) { - uint16_t qTypes = reader->queryCondition.types; - std::list &msgList = (qTypes == (0b01 << LOG_KMSG)) ? hilogKlogList : hilogDataList; - hilogBufferMutex.lock_shared(); - if (reader->GetReload()) { - reader->readPos = msgList.begin(); - reader->lastPos = msgList.begin(); - reader->SetReload(false); + auto reader = GetReader(id); + if (!reader) { + std::cerr << "Reader not registered!\n"; + return false; } + uint16_t qTypes = filter.inclusions.types; + LogMsgContainer &msgList = (qTypes == (0b01 << LOG_KMSG)) ? hilogKlogList : hilogDataList; - if (reader->isNotified) { - if (reader->readPos == msgList.end()) { - reader->readPos = std::next(reader->lastPos); - } + std::shared_lock lock(hilogBufferMutex); + + if (reader->m_msgList != &msgList) { + reader->m_msgList = &msgList; + reader->m_pos = msgList.begin(); } - while (reader->readPos != msgList.end()) { - reader->lastPos = reader->readPos; - if (ConditionMatch(reader)) { - reader->SetSendId(SENDIDA); - reader->WriteData(*(reader->readPos)); - printLenByType[reader->readPos->type] += strlen(reader->readPos->content); - if (printLenByDomain.count(reader->readPos->domain) == 0) { - printLenByDomain.insert(pair(reader->readPos->domain, - strlen(reader->readPos->content))); - } else { - printLenByDomain[reader->readPos->domain] += strlen(reader->readPos->content); + + while (reader->m_pos != msgList.end()) { + const HilogData& logData = *reader->m_pos; + reader->m_pos++; + if (LogMatchFilter(filter, logData)) { + UpdateStatistics(logData); + if (onFound) { + onFound(logData); } - reader->readPos++; - hilogBufferMutex.unlock_shared(); return true; } - reader->readPos++; } - reader->isNotified = false; - ReturnNoLog(reader); - hilogBufferMutex.unlock_shared(); return false; } +void HilogBuffer::UpdateStatistics(const HilogData& logData) +{ + printLenByType[logData.type] += strlen(logData.content); + auto it = printLenByDomain.find(logData.domain); + if (it == printLenByDomain.end()) { + printLenByDomain.insert(pair(logData.domain, strlen(logData.content))); + } else { + printLenByDomain[logData.domain] += strlen(logData.content); + } +} + size_t HilogBuffer::Delete(uint16_t logType) { std::list &msgList = (logType == (0b01 << LOG_KMSG)) ? hilogKlogList : hilogDataList; @@ -154,7 +149,7 @@ size_t HilogBuffer::Delete(uint16_t logType) return ERR_LOG_TYPE_INVALID; } size_t sum = 0; - hilogBufferMutex.lock(); + std::unique_lock lock(hilogBufferMutex); std::list::iterator it = msgList.begin(); // Delete logs corresponding to queryCondition @@ -165,20 +160,7 @@ size_t HilogBuffer::Delete(uint16_t logType) continue; } // Delete corresponding logs - logReaderListMutex.lock_shared(); - for (auto &itr :logReaderList) { - auto reader = itr.lock(); - if (reader == nullptr) { - continue; - } - if (reader->readPos == it) { - reader->readPos = std::next(it); - } - if (reader->lastPos == it) { - reader->lastPos = std::next(it); - } - } - logReaderListMutex.unlock_shared(); + OnDeleteItem(it); size_t cLen = it->len - it->tag_len; sum += cLen; @@ -186,38 +168,66 @@ size_t HilogBuffer::Delete(uint16_t logType) size -= cLen; it = msgList.erase(it); } - - hilogBufferMutex.unlock(); return sum; } -void HilogBuffer::AddLogReader(std::weak_ptr reader) +HilogBuffer::ReaderId HilogBuffer::CreateBufReader(std::function onNewDataCallback) { - std::list &msgList = (reader.lock()->queryCondition.types == - (0b01 << LOG_KMSG)) ? hilogKlogList : hilogDataList; - logReaderListMutex.lock(); - // If reader not in logReaderList - logReaderList.push_back(reader); - reader.lock()->lastPos = msgList.end(); - logReaderListMutex.unlock(); + std::unique_lock lock(m_logReaderMtx); + auto reader = std::make_shared(); + reader->m_onNewDataCallback = onNewDataCallback; + ReaderId id = reinterpret_cast(reader.get()); + m_logReaders.insert(std::make_pair(id, reader)); + return id; } -void HilogBuffer::RemoveLogReader(std::shared_ptr reader) +void HilogBuffer::RemoveBufReader(const ReaderId& id) { - logReaderListMutex.lock(); - const auto findIter = std::find_if(logReaderList.begin(), logReaderList.end(), - [&reader](const std::weak_ptr& ptr0) { - return ptr0.lock() == reader; - }); - if (findIter != logReaderList.end()) { - logReaderList.erase(findIter); + std::unique_lock lock(m_logReaderMtx); + auto it = m_logReaders.find(id); + if (it != m_logReaders.end()) { + m_logReaders.erase(it); } - logReaderListMutex.unlock(); } -bool HilogBuffer::Query(LogReader* reader) +void HilogBuffer::OnDeleteItem(LogMsgContainer::iterator itemPos) { - return Query(std::shared_ptr(reader)); + std::shared_lock lock(m_logReaderMtx); + for (auto& [id, readerPtr] : m_logReaders) { + if (readerPtr->m_pos == itemPos) { + readerPtr->m_pos = std::next(itemPos); + } + } +} + +void HilogBuffer::OnPushBackedItem(LogMsgContainer& msgList) +{ + std::shared_lock lock(m_logReaderMtx); + for (auto& [id, readerPtr] : m_logReaders) { + if (readerPtr->m_pos == msgList.end()) { + readerPtr->m_pos = std::prev(msgList.end()); + } + } +} + +void HilogBuffer::OnNewItem(LogMsgContainer& msgList) +{ + std::shared_lock lock(m_logReaderMtx); + for (auto& [id, readerPtr] : m_logReaders) { + if (readerPtr->m_msgList == &msgList && readerPtr->m_onNewDataCallback) { + readerPtr->m_onNewDataCallback(); + } + } +} + +std::shared_ptr HilogBuffer::GetReader(const ReaderId& id) +{ + std::shared_lock lock(m_logReaderMtx); + auto it = m_logReaders.find(id); + if (it != m_logReaders.end()) { + return it->second; + } + return std::shared_ptr(); } size_t HilogBuffer::GetBuffLen(uint16_t logType) @@ -283,90 +293,63 @@ int32_t HilogBuffer::ClearStatisticInfoByDomain(uint32_t domain) return 0; } -bool HilogBuffer::ConditionMatch(std::shared_ptr reader) +bool HilogBuffer::LogMatchFilter(const LogFilterExt& filter, const HilogData& logData) { /* domain patterns: * strict mode: 0xdxxxxxx (full) * fuzzy mode: 0xdxxxx (using last 2 digits of full domain as mask) */ - if (((static_cast((0b01 << (reader->readPos->type)) & (reader->queryCondition.types)) == 0) || - (static_cast((0b01 << (reader->readPos->level)) & (reader->queryCondition.levels)) == 0))) + // inclusions + if (((static_cast((0b01 << (logData.type)) & (filter.inclusions.types)) == 0) || + (static_cast((0b01 << (logData.level)) & (filter.inclusions.levels)) == 0))) return false; - int ret = 0; - if (reader->queryCondition.nPid > 0) { - for (int i = 0; i < reader->queryCondition.nPid; i++) { - if (reader->readPos->pid == reader->queryCondition.pids[i]) { - ret = 1; - break; - } - } - if (ret == 0) return false; - ret = 0; + if (!filter.inclusions.pids.empty()) { + auto it = std::find(filter.inclusions.pids.begin(), filter.inclusions.pids.end(), logData.pid); + if (it == filter.inclusions.pids.end()) + return false; } - if (reader->queryCondition.nDomain > 0) { - for (int i = 0; i < reader->queryCondition.nDomain; i++) { - uint32_t domains = reader->queryCondition.domains[i]; - if (!((domains >= DOMAIN_STRICT_MASK && domains != reader->readPos->domain) || - (domains <= DOMAIN_FUZZY_MASK && domains != (reader->readPos->domain >> DOMAIN_MODULE_BITS)))) { - ret = 1; - break; - } - } - if (ret == 0) return false; - ret = 0; + if (!filter.inclusions.domains.empty()) { + auto it = std::find_if(filter.inclusions.domains.begin(), filter.inclusions.domains.end(), + [&] (uint32_t domain) { + return !((domain >= DOMAIN_STRICT_MASK && domain != logData.domain) || + (domain <= DOMAIN_FUZZY_MASK && domain != (logData.domain >> DOMAIN_MODULE_BITS))); + }); + if (it == filter.inclusions.domains.end()) + return false; } - if (reader->queryCondition.nTag > 0) { - for (int i = 0; i < reader->queryCondition.nTag; i++) { - if (reader->readPos->tag == reader->queryCondition.tags[i]) { - ret = 1; - break; - } - } - if (ret == 0) return false; - ret = 0; + if (!filter.inclusions.tags.empty()) { + auto it = std::find(filter.inclusions.tags.begin(), filter.inclusions.tags.end(), logData.tag); + if (it == filter.inclusions.tags.end()) + return false; } // exclusion - if (reader->queryCondition.nNoPid > 0) { - for (int i = 0; i < reader->queryCondition.nNoPid; i++) { - if (reader->readPos->pid == reader->queryCondition.noPids[i]) return false; - } + if (!filter.exclusions.pids.empty()) { + auto it = std::find(filter.exclusions.pids.begin(), filter.exclusions.pids.end(), logData.pid); + if (it != filter.exclusions.pids.end()) + return false; } - if (reader->queryCondition.nNoDomain != 0) { - for (int i = 0; i < reader->queryCondition.nNoDomain; i++) { - uint32_t noDomains = reader->queryCondition.noDomains[i]; - if (((noDomains >= DOMAIN_STRICT_MASK && noDomains == reader->readPos->domain) || - (noDomains <= DOMAIN_FUZZY_MASK && noDomains == (reader->readPos->domain >> DOMAIN_MODULE_BITS)))) - return false; - } + + if (!filter.exclusions.domains.empty()) { + auto it = std::find_if(filter.exclusions.domains.begin(), filter.exclusions.domains.end(), + [&] (uint32_t domain) { + return ((domain >= DOMAIN_STRICT_MASK && domain == logData.domain) || + (domain <= DOMAIN_FUZZY_MASK && domain == (logData.domain >> DOMAIN_MODULE_BITS))); + }); + if (it != filter.exclusions.domains.end()) + return false; } - if (reader->queryCondition.nNoTag > 0) { - for (int i = 0; i < reader->queryCondition.nNoTag; i++) { - if (reader->readPos->tag == reader->queryCondition.noTags[i]) return false; - } + if (!filter.exclusions.tags.empty()) { + auto it = std::find(filter.exclusions.tags.begin(), filter.exclusions.tags.end(), logData.tag); + if (it != filter.exclusions.tags.end()) + return false; } - if ((static_cast((0b01 << (reader->readPos->type)) & (reader->queryCondition.noTypes)) != 0) || - (static_cast((0b01 << (reader->readPos->level)) & (reader->queryCondition.noLevels)) != 0)) { + if ((static_cast((0b01 << (logData.type)) & (filter.exclusions.types)) != 0) || + (static_cast((0b01 << (logData.level)) & (filter.exclusions.levels)) != 0)) { return false; } return true; } - -void HilogBuffer::ReturnNoLog(std::shared_ptr reader) -{ - reader->SetSendId(SENDIDN); - reader->WriteData(std::nullopt); -} - -void HilogBuffer::GetBufferLock() -{ - hilogBufferMutex.lock(); -} - -void HilogBuffer::ReleaseBufferLock() -{ - hilogBufferMutex.unlock(); -} } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/log_collector.cpp b/services/hilogd/log_collector.cpp index cf22f79231ed61354e50425ed51c93f6ba80e8dc..8cca61ce72344c894f13fbc49e54221e06985f4c 100644 --- a/services/hilogd/log_collector.cpp +++ b/services/hilogd/log_collector.cpp @@ -93,19 +93,7 @@ size_t LogCollector::InsertLogToBuffer(const HilogMsg& msg) if (msg.type >= LOG_TYPE_MAX) { return ERR_LOG_TYPE_INVALID; } - size_t result = m_hilogBuffer.Insert(msg); - if (result <= 0) { - return result; - } - m_hilogBuffer.logReaderListMutex.lock_shared(); - for (auto &itr :m_hilogBuffer.logReaderList) { - auto reader = itr.lock(); - if ((reader != nullptr) && (reader->GetType() != TYPE_CONTROL)) { - reader->NotifyForNewData(); - } - } - m_hilogBuffer.logReaderListMutex.unlock_shared(); - return result; + return m_hilogBuffer.Insert(msg); } } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/log_compress.cpp b/services/hilogd/log_compress.cpp index d3eb74eac0b45d6e359fa7ca442af8e8e68bcf2a..78ac60621e2a691236bdf459d7a9033c2adf9743 100644 --- a/services/hilogd/log_compress.cpp +++ b/services/hilogd/log_compress.cpp @@ -13,69 +13,59 @@ * limitations under the License. */ #include "log_compress.h" -#include "malloc.h" + #include #include #include +#include + #include -using namespace std; namespace OHOS { namespace HiviewDFX { -LogCompress::LogCompress() -{ -} - -void LogCompress::DeleteZData() +int NoneCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer) { - delete zdata; - zdata = nullptr; -} - -int NoneCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer) -{ - if (memcpy_s(compressBuffer->content + compressBuffer->offset, MAX_PERSISTER_BUFFER_SIZE - compressBuffer->offset, - buffer->content, buffer->offset) != 0) { + void *dest = compressedBuffer.content + compressedBuffer.offset; + size_t destSize = MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset; + if (memcpy_s(dest, destSize, inBuffer.content, inBuffer.offset) != 0) { return -1; } - compressBuffer->offset += buffer->offset; + compressedBuffer.offset += inBuffer.offset; return 0; } -int ZlibCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer) +int ZlibCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer) { - uint32_t zdlen = compressBound(buffer->offset); - zdata = new unsigned char [zdlen]; + uint32_t zdlen = compressBound(inBuffer.offset); + std::vector zdataBuf(zdlen, 0); + char* zdata = zdataBuf.data(); if (zdata == nullptr) { - cout << "no enough memory!" << endl; + std::cerr << "no enough memory!\n"; return -1; } size_t const toRead = CHUNK; auto src_pos = 0; auto dst_pos = 0; - size_t read = buffer->offset; + size_t read = inBuffer.offset; int flush = 0; cStream.zalloc = Z_NULL; cStream.zfree = Z_NULL; cStream.opaque = Z_NULL; if (deflateInit2(&cStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) { - DeleteZData(); return -1; } do { bool flag = read - src_pos < toRead; if (flag) { memset_s(buffIn, CHUNK, 0, CHUNK); - if (memmove_s(buffIn, CHUNK, buffer->content + src_pos, read - src_pos) != 0) { - DeleteZData(); + if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, read - src_pos) != 0) { return -1; } cStream.avail_in = read - src_pos; src_pos += read - src_pos; } else { memset_s(buffIn, CHUNK, 0, CHUNK); - if (memmove_s(buffIn, CHUNK, buffer->content + src_pos, toRead) != 0) { - DeleteZData(); + if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, toRead) != 0) { return -1; }; src_pos += toRead; @@ -89,12 +79,10 @@ int ZlibCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &com cStream.avail_out = CHUNK; cStream.next_out = (Bytef *)buffOut; if (deflate(&cStream, flush) == Z_STREAM_ERROR) { - DeleteZData(); return -1; } unsigned have = CHUNK - cStream.avail_out; if (memmove_s(zdata + dst_pos, CHUNK, buffOut, have) != 0) { - DeleteZData(); return -1; } dst_pos += have; @@ -102,53 +90,49 @@ int ZlibCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &com } while (flush != Z_FINISH); /* clean up and return */ (void)deflateEnd(&cStream); - if (memcpy_s(compressBuffer->content + compressBuffer->offset, - MAX_PERSISTER_BUFFER_SIZE - compressBuffer->offset, zdata, dst_pos) != 0) { - DeleteZData(); + if (memcpy_s(compressedBuffer.content + compressedBuffer.offset, + MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset, zdata, dst_pos) != 0) { return -1; } - compressBuffer->offset += dst_pos; - DeleteZData(); + compressedBuffer.offset += dst_pos; return 0; } -int ZstdCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &compressBuffer) +int ZstdCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer) { #ifdef USING_ZSTD_COMPRESS uint32_t zdlen = ZSTD_CStreamOutSize(); - zdata = new unsigned char [zdlen]; + std::vector zdataBuf(zdlen, 0); + char* zdata = zdataBuf.data(); if (zdata == nullptr) { - cout << "no enough memory!" << endl; + std::cerr << "no enough memory!\n"; return -1; } ZSTD_EndDirective mode; int compressionlevel = 1; cctx = ZSTD_createCCtx(); if (cctx == nullptr) { - cout << "ZSTD_createCCtx() failed!" << endl; - DeleteZData(); + std::cerr << "ZSTD_createCCtx() failed!\n"; return -1; } ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionlevel); size_t const toRead = CHUNK; auto src_pos = 0; auto dst_pos = 0; - size_t read = buffer->offset; + size_t read = inBuffer.offset; ZSTD_inBuffer input; do { bool flag = read - src_pos < toRead; if (flag) { memset_s(buffIn, CHUNK, 0, CHUNK); - if (memmove_s(buffIn, CHUNK, buffer->content + src_pos, read - src_pos) != 0) { - DeleteZData(); + if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, read - src_pos) != 0) { return -1; } input = {buffIn, read - src_pos, 0}; src_pos += read - src_pos; } else { memset_s(buffIn, CHUNK, 0, CHUNK); - if (memmove_s(buffIn, CHUNK, buffer->content + src_pos, toRead) != 0) { - DeleteZData(); + if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, toRead) != 0) { return -1; } input = {buffIn, toRead, 0}; @@ -160,7 +144,6 @@ int ZstdCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &com ZSTD_outBuffer output = {buffOut, CHUNK, 0}; size_t const remaining = ZSTD_compressStream2(cctx, &output, &input, mode); if (memmove_s(zdata + dst_pos, zdlen, (Bytef *)buffOut, output.pos) != 0) { - DeleteZData(); return -1; } dst_pos += output.pos; @@ -168,15 +151,13 @@ int ZstdCompress::Compress(LogPersisterBuffer* &buffer, LogPersisterBuffer* &com } while (!finished); } while (mode != ZSTD_e_end); ZSTD_freeCCtx(cctx); - if (memcpy_s(compressBuffer->content + compressBuffer->offset, - MAX_PERSISTER_BUFFER_SIZE - compressBuffer->offset, zdata, dst_pos) != 0) { - DeleteZData(); + if (memcpy_s(compressedBuffer.content + compressedBuffer.offset, + MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset, zdata, dst_pos) != 0) { return -1; } - compressBuffer->offset += dst_pos; - DeleteZData(); + compressedBuffer.offset += dst_pos; #endif // #ifdef USING_ZSTD_COMPRESS return 0; } -} -} +} // namespace HiviewDFX +} // namespace OHOS diff --git a/services/hilogd/log_kmsg.cpp b/services/hilogd/log_kmsg.cpp index a0eeb8b1182848afb33d00dc92cc33c2743faa2a..fa0c30a13c32631943a8f62b2ebb7d6826975c57 100644 --- a/services/hilogd/log_kmsg.cpp +++ b/services/hilogd/log_kmsg.cpp @@ -40,20 +40,12 @@ ssize_t LogKmsg::LinuxReadOneKmsg(KmsgParser& parser) size = read(kmsgCtl, kmsgBuffer.data(), BUFSIZ - 1); } while (size < 0 && errno == EPIPE); if (size > 0) { - std::optional msgWrap = parser.ParseKmsg(kmsgBuffer); - if (msgWrap->IsValid()) { - size_t result = hilogBuffer.Insert(msgWrap->getHilogMsg()); + std::optional msgWrap = parser.ParseKmsg(kmsgBuffer); + if (msgWrap.has_value()) { + size_t result = hilogBuffer.Insert(msgWrap->GetHilogMsg()); if (result <= 0) { return result; } - hilogBuffer.logReaderListMutex.lock_shared(); - for (auto &itr :hilogBuffer.logReaderList) { - auto reader = itr.lock(); - if ((reader != nullptr) && (reader->GetType() != TYPE_CONTROL)) { - reader->NotifyForNewData(); - } - } - hilogBuffer.logReaderListMutex.unlock_shared(); } } return size; diff --git a/services/hilogd/log_persister.cpp b/services/hilogd/log_persister.cpp index 014374be455a38b55ccdcdda6a624d988efc2c6b..bcd27daf4c5bab8bef81ccbbbca0ac1a34114d15 100644 --- a/services/hilogd/log_persister.cpp +++ b/services/hilogd/log_persister.cpp @@ -15,22 +15,27 @@ #include "log_persister.h" -#include #include #include #include -#include + +#include +#include + +#include +#include #include +#include #include +#include #include #include #include #include #include #include -#include -#include -#include +#include + #include "hilog_common.h" #include "log_buffer.h" #include "log_compress.h" @@ -38,294 +43,403 @@ namespace OHOS { namespace HiviewDFX { -using namespace std::literals::chrono_literals; -using namespace std; - -static std::list> logPersisters; -static std::mutex g_listMutex; - -#define SAFE_DELETE(x) \ - do { \ - delete (x); \ - (x) = nullptr; \ - } while (0) - -LogPersister::LogPersister(uint32_t id, string path, uint32_t fileSize, uint16_t compressAlg, int sleepTime, - shared_ptr rotator, HilogBuffer &_buffer) - : id(id), path(path), fileSize(fileSize), compressAlg(compressAlg), - sleepTime(sleepTime), rotator(rotator) + +static constexpr int DEFAULT_LOG_LEVEL = 1<> LogPersister::s_logPersisters; + +std::shared_ptr LogPersister::CreateLogPersister(HilogBuffer &buffer) +{ + // Because of: + // - static_assert(is_constructible<_Tp, _Args...>::value, "Can't construct object in make_shared"); + // make shared can't be used! + return std::shared_ptr(new LogPersister(buffer)); +} + +LogPersister::LogPersister(HilogBuffer &buffer) : m_hilogBuffer(buffer) +{ + m_bufReader = m_hilogBuffer.CreateBufReader([this]() { NotifyNewLogAvailable(); }); } LogPersister::~LogPersister() { - SAFE_DELETE(compressor); - SAFE_DELETE(compressBuffer); + m_hilogBuffer.RemoveBufReader(m_bufReader); + Deinit(); } -int LogPersister::InitCompress() +int LogPersister::InitCompression() { - compressBuffer = new LogPersisterBuffer; - if (compressBuffer == NULL) { + m_compressBuffer = std::make_unique(); + if (!m_compressBuffer) { return RET_FAIL; } - switch (compressAlg) { + switch (m_baseData.compressAlg) { case COMPRESS_TYPE_NONE: - compressor = new NoneCompress(); + m_compressor = std::make_unique(); break; case COMPRESS_TYPE_ZLIB: - compressor = new ZlibCompress(); + m_compressor = std::make_unique(); break; case COMPRESS_TYPE_ZSTD: - compressor = new ZstdCompress(); + m_compressor = std::make_unique(); break; default: break; - } + } + if (!m_compressor) { + return RET_FAIL; + } return RET_SUCCESS; } -int LogPersister::Init() +int LogPersister::InitFileRotator(const InitData& initData) { - bool restore = rotator->GetRestore(); - int nPos = path.find_last_of('/'); - if (nPos == RET_FAIL) { + std::string fileSuffix = ""; + switch (m_baseData.compressAlg) { + case CompressAlg::COMPRESS_TYPE_ZSTD: + fileSuffix = ".zst"; + break; + case CompressAlg::COMPRESS_TYPE_ZLIB: + fileSuffix = ".gz"; + break; + default: + break; + }; + m_fileRotator = std::make_unique(m_baseData.logPath, m_baseData.id, + m_baseData.maxLogFileNum, fileSuffix); + if (!m_fileRotator) { + std::cerr << "Not enough memory!\n"; + return RET_FAIL; + } + + PersistRecoveryInfo info = {0}; + bool restore = false; + if (std::holds_alternative(initData)) { + info.msg = std::get(initData); + info.types = m_filters.inclusions.types; + info.levels = m_filters.inclusions.levels; + } else if (std::holds_alternative(initData)) { + info = std::get(initData); + restore = true; + } + return m_fileRotator->Init(info, restore); +} + +int LogPersister::Init(const InitData& initData) +{ + std::cout << __PRETTY_FUNCTION__ << " Begin\n"; + std::lock_guard lock(m_initMtx); + if (m_inited) { + return 0; + } + + auto initByMsg = [this](const LogPersistStartMsg& msg) { + m_baseData.id = msg.jobId; + m_baseData.logPath = msg.filePath; + m_baseData.logFileSizeLimit = msg.fileSize; + m_baseData.maxLogFileNum = msg.fileNum; + m_baseData.compressAlg = msg.compressAlg; + m_baseData.newLogTimeout = std::chrono::seconds(SLEEP_TIME); + + m_filters.inclusions.types = msg.logType; + m_filters.inclusions.levels = DEFAULT_LOG_LEVEL; + }; + + bool restore = false; + if (std::holds_alternative(initData)) { + const LogPersistStartMsg& msg = std::get(initData); + initByMsg(msg); + } else if (std::holds_alternative(initData)) { + const LogPersistStartMsg& msg = std::get(initData).msg; + initByMsg(msg); + restore = true; + } else { + std::cerr << __PRETTY_FUNCTION__ << "Init data not provided\n"; + return RET_FAIL; + } + + size_t separatorPos = m_baseData.logPath.find_last_of('/'); + if (separatorPos == std::string::npos) { return ERR_LOG_PERSIST_FILE_PATH_INVALID; } - mmapPath = path.substr(0, nPos) + "/." + ANXILLARY_FILE_NAME + to_string(id); - if (access(path.substr(0, nPos).c_str(), F_OK) != 0) { + + std::string parentPath = m_baseData.logPath.substr(0, separatorPos); + if (access(parentPath.c_str(), F_OK) != 0) { perror("persister directory does not exist."); return ERR_LOG_PERSIST_FILE_PATH_INVALID; } - bool hit = false; - const lock_guard lock(g_listMutex); - for (auto it = logPersisters.begin(); it != logPersisters.end(); ++it) { - if ((*it)->getPath() == path || (*it)->Identify(id)) { - std::cout << path << std::endl; - hit = true; - break; - } - } - if (hit) { + + // below guard is needed to have sure only one Path and Id is reqistered till end of init! + std::lock_guard guard(s_logPersistersMtx); + if (CheckRegistered(m_baseData.id, m_baseData.logPath)) { + std::cerr << __PRETTY_FUNCTION__ << "Log persister already registered. Path:" << m_baseData.logPath + << " id:" << m_baseData.id << "\n"; return ERR_LOG_PERSIST_TASK_FAIL; } - if (InitCompress() == RET_FAIL) { + if (InitCompression() != RET_SUCCESS) { return ERR_LOG_PERSIST_COMPRESS_INIT_FAIL; } - if (restore) { - fd = fopen(mmapPath.c_str(), "r+"); - } else { - fd = fopen(mmapPath.c_str(), "w+"); + if (int result = InitFileRotator(initData); result != RET_SUCCESS) { + return result; } - if (fd == nullptr) { -#ifdef DEBUG - cout << "open log file(" << mmapPath << ") failed: " << strerror(errno) << endl; -#endif + if (int result = PrepareUncompressedFile(parentPath, restore)) { + return result; + } + + RegisterLogPersister(shared_from_this()); + m_inited = true; + std::cout << __PRETTY_FUNCTION__ << " Done\n"; + return 0; +} + +int LogPersister::Deinit() +{ + std::cout << __PRETTY_FUNCTION__ << " Begin\n"; + std::lock_guard lock(m_initMtx); + if (!m_inited) { + return 0; + } + + Stop(); + + munmap(m_mappedPlainLogFile, MAX_PERSISTER_BUFFER_SIZE); + std::cout << "Removing unmapped plain log file: " << m_plainLogFilePath << "\n"; + if (remove(m_plainLogFilePath.c_str())) { + std::cerr << "File: " << m_plainLogFilePath << " can't be removed. " + << "Errno: " << errno << " " << strerror(errno) << "\n"; + } + + DeregisterLogPersister(shared_from_this()); + m_inited = false; + std::cout << __PRETTY_FUNCTION__ << " Done\n"; + return 0; +} + +int LogPersister::PrepareUncompressedFile(const std::string& parentPath, bool restore) +{ + std::string fileName = std::string(".") + AUXILLARY_PERSISTER_PREFIX + std::to_string(m_baseData.id); + m_plainLogFilePath = parentPath + "/" + fileName; + FILE* plainTextFile = fopen(m_plainLogFilePath.c_str(), restore ? "r+" : "w+"); + + if (!plainTextFile) { + std::cerr << __PRETTY_FUNCTION__ << " Open uncompressed log file(" << m_plainLogFilePath << ") failed: " + << strerror(errno) << "\n"; return ERR_LOG_PERSIST_FILE_OPEN_FAIL; } if (!restore) { - ftruncate(fileno(fd), sizeof(LogPersisterBuffer)); - fflush(fd); - fsync(fileno(fd)); - } - buffer = (LogPersisterBuffer *)mmap(nullptr, sizeof(LogPersisterBuffer), PROT_READ | PROT_WRITE, - MAP_SHARED, fileno(fd), 0); - fclose(fd); - if (buffer == MAP_FAILED) { -#ifdef DEBUG - cout << "mmap file failed: " << strerror(errno) << endl; -#endif + ftruncate(fileno(plainTextFile), sizeof(LogPersisterBuffer)); + fflush(plainTextFile); + fsync(fileno(plainTextFile)); + } + m_mappedPlainLogFile = (LogPersisterBuffer *)mmap(nullptr, sizeof(LogPersisterBuffer), PROT_READ | PROT_WRITE, + MAP_SHARED, fileno(plainTextFile), 0); + if (fclose(plainTextFile)) { + std::cerr << "File: " << plainTextFile << " can't be closed. " + << "Errno: " << errno << " " << strerror(errno) << "\n"; + } + if (m_mappedPlainLogFile == MAP_FAILED) { + std::cerr << __PRETTY_FUNCTION__ << " mmap file failed: " << strerror(errno) << "\n"; return RET_FAIL; } if (restore == true) { #ifdef DEBUG - cout << "Recovered persister, Offset=" << buffer->offset << endl; + std::cout << __PRETTY_FUNCTION__ << " Recovered persister, Offset=" << m_mappedPlainLogFile->offset << "\n"; #endif - WriteFile(); + // try to store previous uncompressed logs + auto compressionResult = m_compressor->Compress(*m_mappedPlainLogFile, *m_compressBuffer); + if (compressionResult != 0) { + std::cerr << __PRETTY_FUNCTION__ << " Compression error. Result:" << compressionResult << "\n"; + return RET_FAIL; + }; + WriteCompressedLogs(); } else { - SetBufferOffset(0); + m_mappedPlainLogFile->offset = 0; } - logPersisters.push_back(std::static_pointer_cast(shared_from_this())); return 0; } -void LogPersister::NotifyForNewData() -{ - condVariable.notify_one(); - isNotified = true; -} - -void LogPersister::SetBufferOffset(int off) +void LogPersister::NotifyNewLogAvailable() { - buffer->offset = off; + m_receiveLogCv.notify_one(); } -int GenPersistLogHeader(HilogData& data, list& persistList) +std::list LogDataToFormatedStrings(const HilogData& logData) { - char buffer[MAX_LOG_LEN + MAX_LOG_LEN]; + std::list resultLogLines; + std::array tempBuffer = {0}; HilogShowFormatBuffer showBuffer; - showBuffer.level = data.level; - showBuffer.pid = data.pid; - showBuffer.tid = data.tid; - showBuffer.domain = data.domain; - showBuffer.tv_sec = data.tv_sec; - showBuffer.tv_nsec = data.tv_nsec; - - int offset = data.tag_len; - char *dataCopy = (char*)calloc(data.len, sizeof(char)); - if (dataCopy == nullptr) { - return 0; + showBuffer.level = logData.level; + showBuffer.pid = logData.pid; + showBuffer.tid = logData.tid; + showBuffer.domain = logData.domain; + showBuffer.tv_sec = logData.tv_sec; + showBuffer.tv_nsec = logData.tv_nsec; + + std::vector dataCopy(logData.len, 0); + if (dataCopy.data() == nullptr) { + return resultLogLines; } - if (memcpy_s(dataCopy, data.len, data.tag, data.len)) { - free(dataCopy); - return 0; + if (memcpy_s(dataCopy.data(), logData.len, logData.tag, logData.len)) { + return resultLogLines; } - showBuffer.data = dataCopy; - char *dataBegin = dataCopy + offset; - char *dataPos = dataCopy + offset; - while (*dataPos != 0) { - if (*dataPos == '\n') { - if (dataPos != dataBegin) { - *dataPos = 0; - showBuffer.tag_len = offset; - showBuffer.data = dataCopy; - HilogShowBuffer(buffer, MAX_LOG_LEN + MAX_LOG_LEN, showBuffer, 0); - persistList.push_back(buffer); - offset += dataPos - dataBegin + 1; + showBuffer.data = dataCopy.data(); + // Below code replace 'new line' character with 'zero' to simulate + // continuation of very long log message with tag prefix at the begining of every line. + // e.g. "This is very \n long line \n for sure!!!" + // This will be changed into: + // This is very + // long line + // for sure!!! + size_t newLineOffset = logData.tag_len; + char *msgBegin = dataCopy.data() + newLineOffset; + char *currenMsgPos = msgBegin; + while (*currenMsgPos != 0) { + if (*currenMsgPos == '\n') { + if (currenMsgPos != msgBegin) { + *currenMsgPos = 0; + showBuffer.tag_len = newLineOffset; + HilogShowBuffer(tempBuffer.data(), tempBuffer.size(), showBuffer, OFF_SHOWFORMAT); + resultLogLines.push_back(tempBuffer.data()); + newLineOffset += currenMsgPos - msgBegin + 1; } else { - offset++; + newLineOffset++; } - dataBegin = dataPos + 1; + msgBegin = currenMsgPos + 1; } - dataPos++; + currenMsgPos++; } - if (dataPos != dataBegin) { - showBuffer.tag_len = offset; - showBuffer.data = dataCopy; - HilogShowBuffer(buffer, MAX_LOG_LEN + MAX_LOG_LEN, showBuffer, 0); - persistList.push_back(buffer); + if (currenMsgPos != msgBegin) { + showBuffer.tag_len = newLineOffset; + HilogShowBuffer(tempBuffer.data(), tempBuffer.size(), showBuffer, OFF_SHOWFORMAT); + resultLogLines.push_back(tempBuffer.data()); } - free(dataCopy); - return persistList.size(); + return resultLogLines; } -bool LogPersister::writeUnCompressedBuffer(HilogData &data) +bool LogPersister::WriteUncompressedLogs(std::list& formatedTextLogs) { - int listSize = persistList.size(); - - if (persistList.empty()) { - listSize = GenPersistLogHeader(data, persistList); - } - while (listSize--) { - string header = persistList.front(); - uint16_t headerLen = header.length(); - uint16_t size = headerLen + 1; - uint32_t orig_offset = buffer->offset; - int r = 0; - if (buffer->offset + size > MAX_PERSISTER_BUFFER_SIZE) + while (!formatedTextLogs.empty()) { + std::string logLine = formatedTextLogs.front(); + uint16_t size = logLine.length() + 1; // we want to add new line character + uint32_t origOffset = m_mappedPlainLogFile->offset; + if (m_mappedPlainLogFile->offset + size > MAX_PERSISTER_BUFFER_SIZE) return false; - r = memcpy_s(buffer->content + buffer->offset, MAX_PERSISTER_BUFFER_SIZE - buffer->offset, - header.c_str(), headerLen); + + char* currentContentPos = m_mappedPlainLogFile->content + m_mappedPlainLogFile->offset; + uint32_t remainingSpace = MAX_PERSISTER_BUFFER_SIZE - m_mappedPlainLogFile->offset; + int r = memcpy_s(currentContentPos, remainingSpace, logLine.c_str(), logLine.length()); if (r != 0) { - SetBufferOffset(orig_offset); + std::cerr << __PRETTY_FUNCTION__ << " Can't copy part of memory!\n"; + m_mappedPlainLogFile->offset = origOffset; return true; } - persistList.pop_front(); - SetBufferOffset(buffer->offset + headerLen); - buffer->content[buffer->offset] = '\n'; - SetBufferOffset(buffer->offset + 1); + formatedTextLogs.pop_front(); + m_mappedPlainLogFile->offset += logLine.length(); + m_mappedPlainLogFile->content[m_mappedPlainLogFile->offset] = '\n'; + m_mappedPlainLogFile->offset += 1; } return true; } -int LogPersister::WriteData(OptRef pData) +int LogPersister::WriteLogData(const HilogData& logData) { - if (pData == std::nullopt) - return -1; - if (writeUnCompressedBuffer(pData->get())) + std::list formatedTextLogs = LogDataToFormatedStrings(logData); + + // Firstly gather uncompressed logs in auxiliary file + if (WriteUncompressedLogs(formatedTextLogs)) return 0; - if (compressor->Compress(buffer, compressBuffer) != 0) { - cout << "COMPRESS Error" << endl; + // Try to compress auxiliary file + auto compressionResult = m_compressor->Compress(*m_mappedPlainLogFile, *m_compressBuffer); + if (compressionResult != 0) { + std::cerr << __PRETTY_FUNCTION__ << " Compression error. Result:" << compressionResult << "\n"; return RET_FAIL; }; - WriteFile(); - return writeUnCompressedBuffer(pData->get()) ? 0 : -1; + // Write compressed buffor and clear counters + WriteCompressedLogs(); + // Try again write data that wasn't written at the beginning + // If again fail then these logs are skipped + return WriteUncompressedLogs(formatedTextLogs) ? 0 : RET_FAIL; } -void LogPersister::Start() +inline void LogPersister::WriteCompressedLogs() { - hilogBuffer->AddLogReader(weak_from_this()); - auto newThread = - thread(&LogPersister::ThreadFunc, static_pointer_cast(shared_from_this())); - newThread.detach(); - return; + if (m_mappedPlainLogFile->offset == 0) + return; + m_fileRotator->Input(m_compressBuffer->content, m_compressBuffer->offset); + m_plainLogSize += m_mappedPlainLogFile->offset; + std::cout << __PRETTY_FUNCTION__ << " Stored plain log bytes: " << m_plainLogSize + << " from: " << m_baseData.logFileSizeLimit << "\n"; + if (m_plainLogSize >= m_baseData.logFileSizeLimit) { + m_plainLogSize = 0; + m_fileRotator->FinishInput(); + } + m_compressBuffer->offset = 0; + m_mappedPlainLogFile->offset = 0; } -inline void LogPersister::WriteFile() +void LogPersister::Start() { - if (buffer->offset == 0) - return; - rotator->Input((char *)compressBuffer->content, compressBuffer->offset); - plainLogSize += buffer->offset; - if (plainLogSize >= fileSize) { - plainLogSize = 0; - rotator->FinishInput(); - } - compressBuffer->offset = 0; - SetBufferOffset(0); + { + std::lock_guard lock(m_initMtx); + if (!m_inited) { + std::cerr << __PRETTY_FUNCTION__ << " Log persister wasn't inited!\n"; + return; + } + } + + if (isEmptyThread(m_persisterThread)) { + m_persisterThread = std::thread(&LogPersister::ReceiveLogLoop, shared_from_this()); + } else { + std::cout << __PRETTY_FUNCTION__ << " Persister thread already started!\n"; + } } -int LogPersister::ThreadFunc() +int LogPersister::ReceiveLogLoop() { prctl(PR_SET_NAME, "hilogd.pst"); - std::thread::id tid = std::this_thread::get_id(); - cout << __func__ << " " << tid << endl; - while (true) { - if (toExit) { + std::cout << __PRETTY_FUNCTION__ << " " << std::this_thread::get_id() << "\n"; + for (;;) { + if (m_stopThread) { break; } - if (!hilogBuffer->Query(shared_from_this())) { - unique_lock lk(cvMutex); - - if (condVariable.wait_for(lk, std::chrono::seconds(sleepTime)) == - cv_status::timeout) { - if (toExit) { - break; - } - WriteFile(); + + auto result = m_hilogBuffer.Query(m_filters, m_bufReader, [this](const HilogData& logData) { + if (WriteLogData(logData)) { + std::cerr << __PRETTY_FUNCTION__ << " Can't write new log data!\n"; } + }); + + if (!result) { + std::unique_lock lk(m_receiveLogCvMtx); + m_receiveLogCv.wait_for(lk, m_baseData.newLogTimeout); } } - WriteFile(); - { - std::lock_guard guard(mutexForhasExited); - hasExited = true; - } - cvhasExited.notify_all(); - hilogBuffer->RemoveLogReader(shared_from_this()); + WriteCompressedLogs(); + m_fileRotator->FinishInput(); return 0; } -int LogPersister::Query(uint16_t logType, list &results) +int LogPersister::Query(uint16_t logType, std::list &results) { - std::lock_guard guard(g_listMutex); - cout << "Persister.Query: logType " << logType << endl; - for (auto it = logPersisters.begin(); it != logPersisters.end(); ++it) { - cout << "Persister.Query: (*it)->queryCondition.types " - << unsigned((*it)->queryCondition.types) << endl; - if (((*it)->queryCondition.types & logType) != 0) { + std::lock_guard guard(s_logPersistersMtx); + std::cout << __PRETTY_FUNCTION__ << " Persister.Query: logType " << logType << "\n"; + for (auto& logPersister : s_logPersisters) { + uint16_t currentType = logPersister->m_filters.inclusions.types; + std::cout << __PRETTY_FUNCTION__ << " Persister.Query: (*it)->queryCondition.types " << currentType << "\n"; + if (currentType & logType) { LogPersistQueryResult response; - response.logType = (*it)->queryCondition.types; - (*it)->FillInfo(response); + response.logType = currentType; + logPersister->FillInfo(response); results.push_back(response); } } @@ -334,68 +448,96 @@ int LogPersister::Query(uint16_t logType, list &results) void LogPersister::FillInfo(LogPersistQueryResult &response) { - response.jobId = id; - if (strcpy_s(response.filePath, FILE_PATH_MAX_LEN, path.c_str())) { + response.jobId = m_baseData.id; + if (strcpy_s(response.filePath, FILE_PATH_MAX_LEN, m_baseData.logPath.c_str())) { return; } - response.compressAlg = compressAlg; - rotator->FillInfo(response.fileSize, response.fileNum); - return; + response.compressAlg = m_baseData.compressAlg; + response.fileSize = m_baseData.logFileSizeLimit; + response.fileNum = m_baseData.maxLogFileNum; } -int LogPersister::Kill(const uint32_t id) +int LogPersister::Kill(uint32_t id) { - bool found = false; - std::lock_guard guard(g_listMutex); - for (auto it = logPersisters.begin(); it != logPersisters.end(); ) { - if ((*it)->Identify(id)) { -#ifdef DEBUG - cout << "find a persister" << endl; -#endif - (*it)->Exit(); - it = logPersisters.erase(it); - found = true; - } else { - ++it; - } + auto logPersisterPtr = GetLogPersisterById(id); + if (logPersisterPtr) { + return logPersisterPtr->Deinit(); } - return found ? 0 : ERR_LOG_PERSIST_JOBID_FAIL; + std::cerr << __PRETTY_FUNCTION__ << " Log persister with id: " << id << " does not exist.\n"; + return ERR_LOG_PERSIST_JOBID_FAIL; } -bool LogPersister::isExited() +void LogPersister::Stop() { - return hasExited; + std::cout << __PRETTY_FUNCTION__ << " Exiting LogPersister!\n"; + if (isEmptyThread(m_persisterThread)) { + std::cout << __PRETTY_FUNCTION__ << " Thread was exited or not started!\n"; + return; + } + + m_stopThread = true; + m_receiveLogCv.notify_all(); + + if (m_persisterThread.joinable()) { + m_persisterThread.join(); + } } -void LogPersister::Exit() +bool LogPersister::CheckRegistered(uint32_t id, const std::string& logPath) { - std::cout << "LogPersister Exit!" << std::endl; - toExit = true; - condVariable.notify_all(); - unique_lock lk(mutexForhasExited); - if (!isExited()) { - cvhasExited.wait(lk); - } - rotator->RemoveInfo(); - rotator.reset(); - munmap(buffer, MAX_PERSISTER_BUFFER_SIZE); - cout << "removed mmap file" << endl; - remove(mmapPath.c_str()); - return; + std::lock_guard lock(s_logPersistersMtx); + auto it = std::find_if(s_logPersisters.begin(), s_logPersisters.end(), + [&](const std::shared_ptr& logPersister) { + if (logPersister->m_baseData.logPath == logPath || logPersister->m_baseData.id == id) { + return true; + } + return false; + }); + return it != s_logPersisters.end(); } -bool LogPersister::Identify(uint32_t id) + +std::shared_ptr LogPersister::GetLogPersisterById(uint32_t id) { - return this->id == id; + std::lock_guard guard(s_logPersistersMtx); + + auto it = std::find_if(s_logPersisters.begin(), s_logPersisters.end(), + [&](const std::shared_ptr& logPersister) { + if (logPersister->m_baseData.id == id) { + return true; + } + return false; + }); + if (it == s_logPersisters.end()) { + return std::shared_ptr(); + } + return *it; } -string LogPersister::getPath() +void LogPersister::RegisterLogPersister(const std::shared_ptr& obj) { - return path; + std::lock_guard lock(s_logPersistersMtx); + s_logPersisters.push_back(obj); } -uint8_t LogPersister::GetType() const +void LogPersister::DeregisterLogPersister(const std::shared_ptr& obj) { - return TYPE_PERSISTER; + if (!obj) { + std::cerr << __PRETTY_FUNCTION__ << " Invalid invoke - this should never happened!\n"; + return; + } + std::lock_guard lock(s_logPersistersMtx); + auto it = std::find_if(s_logPersisters.begin(), s_logPersisters.end(), + [&](const std::shared_ptr& logPersister) { + if (logPersister->m_baseData.id == obj->m_baseData.id) { + return true; + } + return false; + }); + if (it == s_logPersisters.end()) { + std::cerr << __PRETTY_FUNCTION__ << " Inconsistent data - this should never happended!\n"; + return; + } + s_logPersisters.erase(it); } } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/log_persister_rotator.cpp b/services/hilogd/log_persister_rotator.cpp index ab4ad21d6821a5c57e70c0c34d2850cfd69c98dc..4f4d517e485753ecb78a76e24b9db7bfd62c1458 100644 --- a/services/hilogd/log_persister_rotator.cpp +++ b/services/hilogd/log_persister_rotator.cpp @@ -23,9 +23,7 @@ namespace OHOS { namespace HiviewDFX { -using namespace std; - -uint64_t GetInfoHash(const PersistRecoveryInfo &info) +uint64_t GenerateHash(const PersistRecoveryInfo &info) { uint64_t ret {BASIS}; const char *p = (char *)&info; @@ -38,160 +36,173 @@ uint64_t GetInfoHash(const PersistRecoveryInfo &info) return ret; } -LogPersisterRotator::LogPersisterRotator(string path, uint32_t fileSize, uint32_t fileNum, string suffix) - : fileNum(fileNum), fileSize(fileSize), fileName(path), fileSuffix(suffix) +LogPersisterRotator::LogPersisterRotator(const std::string& logsPath, uint32_t id, uint32_t maxFiles, + const std::string& fileNameSuffix) + : m_maxLogFileNum(maxFiles) + , m_logsPath(logsPath) + , m_fileNameSuffix(fileNameSuffix) + , m_id(id) { - index = -1; - needRotate = true; - memset_s(&info, sizeof(info), 0, sizeof(info)); } -void LogPersisterRotator::RemoveInfo() +LogPersisterRotator::~LogPersisterRotator() { - remove(infoPath.c_str()); + m_infoFile.close(); + remove(m_infoFilePath.c_str()); } -LogPersisterRotator::~LogPersisterRotator() +int LogPersisterRotator::Init(const PersistRecoveryInfo& info, bool restore) { - if (fdinfo != nullptr) { - fclose(fdinfo); + if (!m_infoFile.is_open()) { + if (int result = OpenInfoFile(); result != RET_SUCCESS) { + return result; + } } -} -int LogPersisterRotator::Init() -{ - OpenInfoFile(); - if (fdinfo == nullptr) return RET_FAIL; + m_info = info; + SetFileIndex(m_info.index, restore); + UpdateRotateNumber(); return RET_SUCCESS; } -int LogPersisterRotator::Input(const char *buf, uint32_t length) +int LogPersisterRotator::OpenInfoFile() { - cout << __func__ << " " << fileName << " " << index - << " " << length << " need: " << needRotate << endl; - if (length <= 0 || buf == nullptr) return ERR_LOG_PERSIST_COMPRESS_BUFFER_EXP; - if (needRotate) { - output.close(); - Rotate(); - needRotate = false; + auto lastSeparatorIdx = m_logsPath.find_last_of('/'); + std::string parentDirPath = m_logsPath.substr(0, lastSeparatorIdx); + if (access(parentDirPath.c_str(), F_OK) != 0) { + if (errno == ENOENT) { + mkdir(parentDirPath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO); + } } - output.write(buf, length); - output.flush(); - return 0; + std::string infoFileName = std::string(".") + AUXILLARY_PERSISTER_PREFIX + std::to_string(m_id) + ".info"; + m_infoFilePath = parentDirPath + "/" + infoFileName; + m_infoFile.open(m_infoFilePath, std::ios::binary | std::ios::out | std::ios::trunc); + return m_infoFile.is_open() ? RET_SUCCESS : RET_FAIL; } -void LogPersisterRotator::InternalRotate() +int LogPersisterRotator::Input(const char *buf, uint32_t length) { - stringstream ss; - ss << fileName << "."; - int pos = ss.tellp(); - ss << 0 << fileSuffix; - remove(ss.str().c_str()); - - for (uint32_t i = 1; i < fileNum; ++i) { - ss.seekp(pos); - ss << (i - 1) << fileSuffix; - string newName = ss.str(); - ss.seekp(pos); - ss << i << fileSuffix; - string oldName = ss.str(); - cout << "OLD NAME " << oldName << " NEW NAME " << newName << endl; - rename(oldName.c_str(), newName.c_str()); + std::cout << __PRETTY_FUNCTION__ + << " Log location: " << m_logsPath + << " idx: " << m_currentLogFileIdx << "/" << m_maxLogFileNum + << " buf: " << (void*) buf << " len: " << length + << " needRotate: " << (m_needRotate ? 'T' : 'F') << "\n"; + if (length <= 0 || buf == nullptr) { + return ERR_LOG_PERSIST_COMPRESS_BUFFER_EXP; + } + if (m_needRotate) { + Rotate(); + m_needRotate = false; + } else if (!m_currentLogOutput.is_open()) { + CreateLogFile(); } - output.open(ss.str(), ios::out | ios::trunc); + m_currentLogOutput.write(buf, length); + m_currentLogOutput.flush(); + return 0; } void LogPersisterRotator::Rotate() { - cout << __func__ << endl; - if (index >= (int)(fileNum - 1)) { - InternalRotate(); + std::cout << __PRETTY_FUNCTION__ << "\n"; + if (m_currentLogFileIdx + 1 >= m_maxLogFileNum) { + PhysicalShiftFile(); } else { - index += 1; - stringstream ss; - ss << fileName << "." << index << fileSuffix; - cout << "THE FILE NAME !!!!!!! " << ss.str() << endl; - output.open(ss.str(), ios::out | ios::trunc); + m_currentLogFileIdx++; + CreateLogFile(); } UpdateRotateNumber(); } -void LogPersisterRotator::FillInfo(uint32_t &size, uint32_t &num) +std::string LogPersisterRotator::CreateLogFileName(uint32_t logIndex) { - size = fileSize; - num = fileNum; + std::stringstream ss; + ss << m_logsPath << "." << logIndex << m_fileNameSuffix; + return ss.str(); } -void LogPersisterRotator::FinishInput() +void LogPersisterRotator::CreateLogFile() { - needRotate = true; + std::cout << __PRETTY_FUNCTION__ << "\n"; + std::string newFile = CreateLogFileName(m_currentLogFileIdx); + std::cout << "Creating file: " << newFile << "\n"; + m_currentLogOutput.open(newFile, std::ios::out | std::ios::trunc); } -void LogPersisterRotator::SetIndex(int pIndex) +void LogPersisterRotator::PhysicalShiftFile() { - index = pIndex; + std::cout << __PRETTY_FUNCTION__ << "\n"; + std::string oldestFile = CreateLogFileName(0); + if (remove(oldestFile.c_str())) { + std::cerr << "File: " << oldestFile << " can't be removed. Errno: " << errno << " " << strerror(errno) << "\n"; + } + + for (uint32_t i = 1; i < m_maxLogFileNum; ++i) { + std::string olderFile = CreateLogFileName(i-1); + std::string newerFile = CreateLogFileName(i); + std::cout << "Rename from: " << newerFile << " to: " << olderFile << "\n"; + if (rename(newerFile.c_str(), olderFile.c_str())) { + std::cerr << "Can't rename file. Errno: " << errno << " " << strerror(errno) << "\n"; + } + } + std::string newestFile = CreateLogFileName(m_maxLogFileNum - 1); + m_currentLogOutput.open(newestFile, std::ios::out | std::ios::trunc); } -void LogPersisterRotator::SetId(uint32_t pId) +void LogPersisterRotator::UpdateRotateNumber() { - id = pId; + m_info.index = static_cast(m_currentLogFileIdx); + WriteRecoveryInfo(); } -void LogPersisterRotator::OpenInfoFile() +void LogPersisterRotator::FinishInput() { - int nPos = fileName.find_last_of('/'); - std::string mmapPath = fileName.substr(0, nPos) + "/." + ANXILLARY_FILE_NAME + to_string(id); - if (access(fileName.substr(0, nPos).c_str(), F_OK) != 0) { - if (errno == ENOENT) { - mkdir(fileName.substr(0, nPos).c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO); - } - } - infoPath = mmapPath + ".info"; - if (restore) { - fdinfo = fopen(infoPath.c_str(), "r+"); - } else { - fdinfo = fopen(infoPath.c_str(), "w+"); - } + std::cout << __PRETTY_FUNCTION__ << "\n"; + + m_currentLogOutput.close(); + m_needRotate = true; } -void LogPersisterRotator::UpdateRotateNumber() +void LogPersisterRotator::SetFileIndex(uint32_t index, bool forceRotate) { - info.index = index; - WriteRecoveryInfo(); + m_currentLogOutput.close(); + if (index >= m_maxLogFileNum) { + m_currentLogFileIdx = m_maxLogFileNum - 1; + } else { + m_currentLogFileIdx = index; + } + if (forceRotate) { + m_needRotate = true; + } } -int LogPersisterRotator::SaveInfo(const LogPersistStartMsg& pMsg, const QueryCondition queryCondition) +int LogPersisterRotator::SetInfo(const LogPersistStartMsg& pMsg, uint16_t logType, uint8_t logLevel) { - info.msg = pMsg; - info.types = queryCondition.types; - info.levels = queryCondition.levels; - if (strcpy_s(info.msg.filePath, FILE_PATH_MAX_LEN, pMsg.filePath) != 0) { - cout << "Failed to save persister file path" << endl; + m_info.msg = pMsg; + m_info.types = logType; + m_info.levels = logLevel; + if (strcpy_s(m_info.msg.filePath, FILE_PATH_MAX_LEN, pMsg.filePath) != 0) { + std::cout << "Failed to copy persister file path\n"; return RET_FAIL; } - cout << "Saved Path=" << info.msg.filePath << endl; + std::cout << "Saving info path=" << m_info.msg.filePath << "\n"; return RET_SUCCESS; } void LogPersisterRotator::WriteRecoveryInfo() { - std::cout << "Save Info file!" << std::endl; - uint64_t hash = GetInfoHash(info); - fseek(fdinfo, 0, SEEK_SET); - fwrite(&info, sizeof(PersistRecoveryInfo), 1, fdinfo); - fwrite(&hash, sizeof(hash), 1, fdinfo); - fflush(fdinfo); - fsync(fileno(fdinfo)); -} + if (!m_infoFile.is_open()) { + std::cerr << "LogPersisterRotator has not been initialized!\n"; + return; + } -void LogPersisterRotator::SetRestore(bool flag) -{ - restore = flag; -} + std::cout << "Save Info file!\n"; + uint64_t hash = GenerateHash(m_info); -bool LogPersisterRotator::GetRestore() -{ - return restore; + m_infoFile.seekp(0); + m_infoFile.write(reinterpret_cast(&m_info), sizeof(m_info)); + m_infoFile.write(reinterpret_cast(&hash), sizeof(hash)); + m_infoFile.flush(); + m_infoFile.sync(); } } // namespace HiviewDFX } // namespace OHOS diff --git a/services/hilogd/log_querier.cpp b/services/hilogd/log_querier.cpp deleted file mode 100644 index 2ce7494189c34de61f9eddbb70251082f8dcd40c..0000000000000000000000000000000000000000 --- a/services/hilogd/log_querier.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "log_querier.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hilog/log.h" -#include "hilog_common.h" -#include "log_data.h" -#include "hilogtool_msg.h" -#include "log_buffer.h" -#include "log_persister.h" -#include "log_reader.h" - -namespace OHOS { -namespace HiviewDFX { -using namespace std; -constexpr int MAX_DATA_LEN = 2048; -string g_logPersisterDir = HILOG_FILE_DIR; -constexpr int DEFAULT_LOG_LEVEL = 1<|]" - std::regex regExpress("[\\/:*?\"<>|]"); - bool bValid = !std::regex_search(strFileName, regExpress); - return bValid; -} - -inline bool LogTypeForbidden(uint16_t queryTypes) -{ - if (queryTypes == (0b01 << LOG_KMSG) || (queryTypes & (0b01 << LOG_KMSG)) == 0) { - return true; - } else { - cout << "queryTypes can not contain app/core/init and kmsg at the same time,\ - try to -t app/core/init or -t kmsg separately" << endl; - return false; - } -} - -std::shared_ptr MakeRotator(const LogPersistStartMsg& pLogPersistStartMsg) -{ - string fileSuffix = ""; - switch (pLogPersistStartMsg.compressAlg) { - case CompressAlg::COMPRESS_TYPE_ZSTD: - fileSuffix = ".zst"; - break; - case CompressAlg::COMPRESS_TYPE_ZLIB: - fileSuffix = ".gz"; - break; - default: - break; - }; - return make_shared( - pLogPersistStartMsg.filePath, - pLogPersistStartMsg.fileSize, - pLogPersistStartMsg.fileNum, - fileSuffix); -} - -int JobLauncher(const LogPersistStartMsg& pMsg, const HilogBuffer& buffer, bool restore = false, int index = -1) -{ - std::shared_ptr rotator = MakeRotator(pMsg); - rotator->SetId(pMsg.jobId); - rotator->SetIndex(index); - std::shared_ptr persister = make_shared( - pMsg.jobId, - pMsg.filePath, - pMsg.fileSize, - pMsg.compressAlg, - SLEEP_TIME, rotator, const_cast(buffer)); - persister->queryCondition.types = pMsg.logType; - persister->queryCondition.levels = DEFAULT_LOG_LEVEL; - rotator->SetRestore(restore); - int rotatorRes = rotator->Init(); - int saveInfoRes = rotator->SaveInfo(pMsg, persister->queryCondition); - int persistRes = persister->Init(); - if (persistRes == ERR_LOG_PERSIST_TASK_FAIL) { - cout << "Log persist task is existed!" << endl; - persister.reset(); - return persistRes; - } - if (persistRes != 0) { - cout << "LogPersister failed to initialize!" << endl; - persister.reset(); - return persistRes; - } - - if (rotatorRes != 0) { - cout << "Failed to open info file!" << endl; - persister.reset(); - return rotatorRes; - } - if (saveInfoRes != 0) { - cout << "Failed to save persister file path!" << endl; - persister.reset(); - return saveInfoRes; - } - if (!restore) rotator->WriteRecoveryInfo(); - persister->Start(); - return RET_SUCCESS; -} - -void HandleLogQueryRequest(std::shared_ptr logReader, HilogBuffer& buffer) -{ - logReader->SetCmd(LOG_QUERY_RESPONSE); - buffer.AddLogReader(logReader); - buffer.Query(logReader); -} - -void HandleNextRequest(std::shared_ptr logReader, HilogBuffer& buffer) -{ - logReader->SetCmd(NEXT_RESPONSE); - buffer.Query(logReader); -} - -void HandlePersistStartRequest(char* reqMsg, std::shared_ptr logReader, HilogBuffer& buffer) -{ - char msgToSend[MAX_DATA_LEN]; - const uint16_t sendMsgLen = sizeof(LogPersistStartResult); - LogPersistStartRequest* pLogPersistStartReq - = reinterpret_cast(reqMsg); - LogPersistStartMsg* pLogPersistStartMsg - = reinterpret_cast(&pLogPersistStartReq->logPersistStartMsg); - LogPersistStartResponse* pLogPersistStartRsp - = reinterpret_cast(msgToSend); - LogPersistStartResult* pLogPersistStartRst - = reinterpret_cast(&pLogPersistStartRsp->logPersistStartRst); - - string logPersisterPath; - if (pLogPersistStartRst == nullptr) { - return; - } else if (LogTypeForbidden(pLogPersistStartMsg->logType) == false) { - pLogPersistStartRst->result = ERR_QUERY_TYPE_INVALID; - } else if (pLogPersistStartMsg->jobId <= 0) { - pLogPersistStartRst->result = ERR_LOG_PERSIST_JOBID_INVALID; - } else if (pLogPersistStartMsg->fileSize < MAX_PERSISTER_BUFFER_SIZE) { - cout << "Persist log file size less than min size" << std::endl; - pLogPersistStartRst->result = ERR_LOG_PERSIST_FILE_SIZE_INVALID; - } else if (IsValidFileName(string(pLogPersistStartMsg->filePath)) == false) { - cout << "FileName is not valid!" << endl; - pLogPersistStartRst->result = ERR_LOG_PERSIST_FILE_NAME_INVALID; - } else { - string logPersisterFileName = (pLogPersistStartMsg->logType == (0b01 << LOG_KMSG)) ? "hilog_kmsg" : "hilog"; - cout << "logPersisterFileName" << logPersisterFileName << endl; - logPersisterPath = (strlen(pLogPersistStartMsg->filePath) == 0) ? (g_logPersisterDir + logPersisterFileName) - : (g_logPersisterDir + string(pLogPersistStartMsg->filePath)); - if (strcpy_s(pLogPersistStartMsg->filePath, FILE_PATH_MAX_LEN, logPersisterPath.c_str()) != 0) { - pLogPersistStartRst->result = RET_FAIL; - } else { - pLogPersistStartRst->result = JobLauncher(*pLogPersistStartMsg, buffer); - } - } - - pLogPersistStartRst->jobId = pLogPersistStartMsg->jobId; - SetMsgHead(pLogPersistStartRsp->msgHeader, MC_RSP_LOG_PERSIST_START, sendMsgLen); - logReader->hilogtoolConnectSocket->Write(msgToSend, sendMsgLen + sizeof(MessageHeader)); -} - -void HandlePersistDeleteRequest(char* reqMsg, std::shared_ptr logReader) -{ - char msgToSend[MAX_DATA_LEN]; - LogPersistStopRequest* pLogPersistStopReq - = reinterpret_cast(reqMsg); - LogPersistStopMsg* pLogPersistStopMsg - = reinterpret_cast(&pLogPersistStopReq->logPersistStopMsg); - LogPersistStopResponse* pLogPersistStopRsp - = reinterpret_cast(msgToSend); - LogPersistStopResult* pLogPersistStopRst - = reinterpret_cast(&pLogPersistStopRsp->logPersistStopRst); - uint32_t recvMsgLen = 0; - uint32_t msgNum = 0; - uint16_t msgLen = pLogPersistStopReq->msgHeader.msgLen; - uint16_t sendMsgLen = 0; - int32_t rst = 0; - - if (msgLen > sizeof(LogPersistStopMsg) * LOG_TYPE_MAX) { - return; - } - list resultList; - list::iterator it; - rst = LogPersister::Query(DEFAULT_LOG_TYPE, resultList); - if (pLogPersistStopMsg && recvMsgLen < msgLen) { - if (pLogPersistStopMsg->jobId != JOB_ID_ALL) { - rst = LogPersister::Kill(pLogPersistStopMsg->jobId); - if (pLogPersistStopRst) { - pLogPersistStopRst->jobId = pLogPersistStopMsg->jobId; - pLogPersistStopRst->result = (rst < 0) ? rst : RET_SUCCESS; - pLogPersistStopRst++; - msgNum++; - } - } else { - for (it = resultList.begin(); it != resultList.end(); ++it) { - rst = LogPersister::Kill((*it).jobId); - if (pLogPersistStopRst) { - pLogPersistStopRst->jobId = (*it).jobId; - pLogPersistStopRst->result = (rst < 0) ? rst : RET_SUCCESS; - pLogPersistStopRst++; - msgNum++; - } - } - } - } - sendMsgLen = msgNum * sizeof(LogPersistStopResult); - SetMsgHead(pLogPersistStopRsp->msgHeader, MC_RSP_LOG_PERSIST_STOP, sendMsgLen); - logReader->hilogtoolConnectSocket->Write(msgToSend, sendMsgLen + sizeof(MessageHeader)); -} - - -void HandlePersistQueryRequest(char* reqMsg, std::shared_ptr logReader) -{ - char msgToSend[MAX_DATA_LEN]; - LogPersistQueryRequest* pLogPersistQueryReq - = reinterpret_cast(reqMsg); - LogPersistQueryMsg* pLogPersistQueryMsg - = reinterpret_cast(&pLogPersistQueryReq->logPersistQueryMsg); - LogPersistQueryResponse* pLogPersistQueryRsp - = reinterpret_cast(msgToSend); - LogPersistQueryResult* pLogPersistQueryRst - = reinterpret_cast(&pLogPersistQueryRsp->logPersistQueryRst); - uint32_t recvMsgLen = 0; - uint32_t msgNum = 0; - uint16_t msgLen = pLogPersistQueryReq->msgHeader.msgLen; - uint16_t sendMsgLen = 0; - int32_t rst = 0; - list::iterator it; - - if (msgLen > sizeof(LogPersistQueryMsg) * LOG_TYPE_MAX) { - return; - } - - while (pLogPersistQueryMsg && recvMsgLen < msgLen) { - list resultList; - cout << pLogPersistQueryMsg->logType << endl; - rst = LogPersister::Query(pLogPersistQueryMsg->logType, resultList); - for (it = resultList.begin(); it != resultList.end(); ++it) { - if (pLogPersistQueryRst) { - pLogPersistQueryRst->result = (rst < 0) ? rst : RET_SUCCESS; - pLogPersistQueryRst->jobId = (*it).jobId; - pLogPersistQueryRst->logType = (*it).logType; - pLogPersistQueryRst->compressAlg = (*it).compressAlg; - if (strcpy_s(pLogPersistQueryRst->filePath, FILE_PATH_MAX_LEN, (*it).filePath)) { - return; - } - pLogPersistQueryRst->fileSize = (*it).fileSize; - pLogPersistQueryRst->fileNum = (*it).fileNum; - pLogPersistQueryRst++; - msgNum++; - if (msgNum * sizeof(LogPersistQueryResult) + sizeof(MessageHeader) > MAX_DATA_LEN) { - msgNum--; - break; - } - } - } - pLogPersistQueryMsg++; - recvMsgLen += sizeof(LogPersistQueryMsg); - } - sendMsgLen = msgNum * sizeof(LogPersistQueryResult); - SetMsgHead(pLogPersistQueryRsp->msgHeader, MC_RSP_LOG_PERSIST_QUERY, sendMsgLen); - logReader->hilogtoolConnectSocket->Write(msgToSend, sendMsgLen + sizeof(MessageHeader)); -} - -void HandleBufferResizeRequest(char* reqMsg, std::shared_ptr logReader, HilogBuffer* buffer) -{ - char msgToSend[MAX_DATA_LEN]; - BufferResizeRequest* pBufferResizeReq = reinterpret_cast(reqMsg); - BuffResizeMsg* pBuffResizeMsg = reinterpret_cast(&pBufferResizeReq->buffResizeMsg); - BufferResizeResponse* pBufferResizeRsp = reinterpret_cast(msgToSend); - BuffResizeResult* pBuffResizeRst = reinterpret_cast(&pBufferResizeRsp->buffResizeRst); - uint32_t recvMsgLen = 0; - uint32_t msgNum = 0; - uint16_t msgLen = pBufferResizeReq->msgHeader.msgLen; - uint16_t sendMsgLen = 0; - int32_t rst = 0; - - if (msgLen > sizeof(BuffResizeMsg) * LOG_TYPE_MAX) { - return; - } - - while (pBuffResizeMsg && recvMsgLen < msgLen) { - rst = buffer->SetBuffLen(pBuffResizeMsg->logType, pBuffResizeMsg->buffSize); - if (pBuffResizeRst) { - pBuffResizeRst->logType = pBuffResizeMsg->logType; - pBuffResizeRst->buffSize = pBuffResizeMsg->buffSize; - pBuffResizeRst->result = (rst < 0) ? rst : RET_SUCCESS; - pBuffResizeRst++; - } - pBuffResizeMsg++; - recvMsgLen += sizeof(BuffResizeMsg); - msgNum++; - } - sendMsgLen = msgNum * sizeof(BuffResizeResult); - SetMsgHead(pBufferResizeRsp->msgHeader, MC_RSP_BUFFER_RESIZE, sendMsgLen); - - logReader->hilogtoolConnectSocket->Write(msgToSend, sendMsgLen + sizeof(MessageHeader)); -} - -void HandleBufferSizeRequest(char* reqMsg, std::shared_ptr logReader, HilogBuffer* buffer) -{ - char msgToSend[MAX_DATA_LEN]; - BufferSizeRequest* pBufferSizeReq = reinterpret_cast(reqMsg); - BuffSizeMsg* pBuffSizeMsg = reinterpret_cast(&pBufferSizeReq->buffSizeMsg); - BufferSizeResponse* pBufferSizeRsp = reinterpret_cast(msgToSend); - BuffSizeResult* pBuffSizeRst = reinterpret_cast(&pBufferSizeRsp->buffSizeRst); - uint32_t recvMsgLen = 0; - uint32_t msgNum = 0; - uint16_t msgLen = pBufferSizeReq->msgHeader.msgLen; - uint16_t sendMsgLen = 0; - int64_t buffLen; - - if (msgLen > sizeof(BuffSizeMsg) * LOG_TYPE_MAX) { - return; - } - - while (pBuffSizeMsg && recvMsgLen < msgLen) { - buffLen = buffer->GetBuffLen(pBuffSizeMsg->logType); - if (pBuffSizeRst) { - pBuffSizeRst->logType = pBuffSizeMsg->logType; - pBuffSizeRst->buffSize = buffLen; - pBuffSizeRst->result = (buffLen < 0) ? buffLen : RET_SUCCESS; - pBuffSizeRst++; - } - recvMsgLen += sizeof(BuffSizeMsg); - msgNum++; - pBuffSizeMsg++; - } - sendMsgLen = msgNum * sizeof(BuffSizeResult); - SetMsgHead(pBufferSizeRsp->msgHeader, MC_RSP_BUFFER_SIZE, sendMsgLen); - - logReader->hilogtoolConnectSocket->Write(msgToSend, sendMsgLen + sizeof(MessageHeader)); -} - -void HandleInfoQueryRequest(char* reqMsg, std::shared_ptr logReader, HilogBuffer* buffer) -{ - char msgToSend[MAX_DATA_LEN]; - int32_t rst = 0; - memset_s(msgToSend, MAX_DATA_LEN, 0, MAX_DATA_LEN); - StatisticInfoQueryRequest* pStatisticInfoQueryReq = reinterpret_cast(reqMsg); - StatisticInfoQueryResponse* pStatisticInfoQueryRsp = reinterpret_cast(msgToSend); - if (pStatisticInfoQueryReq->domain == 0xffffffff) { - pStatisticInfoQueryRsp->logType = pStatisticInfoQueryReq->logType; - pStatisticInfoQueryRsp->domain = pStatisticInfoQueryReq->domain; - rst = buffer->GetStatisticInfoByLog(pStatisticInfoQueryReq->logType, pStatisticInfoQueryRsp->printLen, - pStatisticInfoQueryRsp->cacheLen, pStatisticInfoQueryRsp->dropped); - pStatisticInfoQueryRsp->result = (rst < 0) ? rst : RET_SUCCESS; - } else { - pStatisticInfoQueryRsp->logType = pStatisticInfoQueryReq->logType; - pStatisticInfoQueryRsp->domain = pStatisticInfoQueryReq->domain; - rst = buffer->GetStatisticInfoByDomain(pStatisticInfoQueryReq->domain, pStatisticInfoQueryRsp->printLen, - pStatisticInfoQueryRsp->cacheLen, pStatisticInfoQueryRsp->dropped); - pStatisticInfoQueryRsp->result = (rst < 0) ? rst : RET_SUCCESS; - } - SetMsgHead(pStatisticInfoQueryRsp->msgHeader, MC_RSP_STATISTIC_INFO_QUERY, sizeof(StatisticInfoQueryResponse) - - sizeof(MessageHeader)); - logReader->hilogtoolConnectSocket->Write(msgToSend, sizeof(StatisticInfoQueryResponse)); -} - -void HandleInfoClearRequest(char* reqMsg, std::shared_ptr logReader, HilogBuffer* buffer) -{ - char msgToSend[MAX_DATA_LEN]; - int32_t rst = 0; - memset_s(msgToSend, MAX_DATA_LEN, 0, MAX_DATA_LEN); - StatisticInfoClearRequest* pStatisticInfoClearReq = reinterpret_cast(reqMsg); - StatisticInfoClearResponse* pStatisticInfoClearRsp = reinterpret_cast(msgToSend); - if (pStatisticInfoClearReq->domain == 0xffffffff) { - pStatisticInfoClearRsp->logType = pStatisticInfoClearReq->logType; - pStatisticInfoClearRsp->domain = pStatisticInfoClearReq->domain; - rst = buffer->ClearStatisticInfoByLog(pStatisticInfoClearReq->logType); - pStatisticInfoClearRsp->result = (rst < 0) ? rst : RET_SUCCESS; - } else { - pStatisticInfoClearRsp->logType = pStatisticInfoClearReq->logType; - pStatisticInfoClearRsp->domain = pStatisticInfoClearReq->domain; - rst = buffer->ClearStatisticInfoByDomain(pStatisticInfoClearReq->domain); - pStatisticInfoClearRsp->result = (rst < 0) ? rst : RET_SUCCESS; - } - SetMsgHead(pStatisticInfoClearRsp->msgHeader, MC_RSP_STATISTIC_INFO_CLEAR, sizeof(StatisticInfoClearResponse) - - sizeof(MessageHeader)); - logReader->hilogtoolConnectSocket->Write(msgToSend, sizeof(StatisticInfoClearResponse)); -} - -void HandleBufferClearRequest(char* reqMsg, std::shared_ptr logReader, HilogBuffer* buffer) -{ - char msgToSend[MAX_DATA_LEN]; - LogClearRequest* pLogClearReq = reinterpret_cast(reqMsg); - LogClearMsg* pLogClearMsg = (LogClearMsg*)&pLogClearReq->logClearMsg; - LogClearResponse* pLogClearRsp = (LogClearResponse*)msgToSend; - LogClearResult* pLogClearRst = (LogClearResult*)&pLogClearRsp->logClearRst; - uint32_t recvMsgLen = 0; - uint32_t msgNum = 0; - uint16_t msgLen = pLogClearReq->msgHeader.msgLen; - int32_t rst = 0; - - if (msgLen > sizeof(LogClearMsg) * LOG_TYPE_MAX) { - return; - } - - while (pLogClearMsg && recvMsgLen < msgLen) { - rst = buffer->Delete(pLogClearMsg->logType); - if (pLogClearRst) { - pLogClearRst->logType = pLogClearMsg->logType; - pLogClearRst->result = (rst < 0) ? rst : RET_SUCCESS; - pLogClearRst++; - } - pLogClearMsg++; - recvMsgLen += sizeof(LogClearMsg); - msgNum++; - } - - uint16_t sendMsgLen = msgNum * sizeof(LogClearResult); - SetMsgHead(pLogClearRsp->msgHeader, MC_RSP_LOG_CLEAR, sendMsgLen); - logReader->hilogtoolConnectSocket->Write(msgToSend, sendMsgLen + sizeof(MessageHeader)); -} - -void SetCondition(std::shared_ptr logReader, const LogQueryRequest& qRstMsg) -{ - logReader->queryCondition.levels = qRstMsg.levels; - logReader->queryCondition.types = qRstMsg.types; - logReader->queryCondition.nPid = qRstMsg.nPid; - logReader->queryCondition.nDomain = qRstMsg.nDomain; - logReader->queryCondition.nTag = qRstMsg.nTag; - logReader->queryCondition.noLevels = qRstMsg.noLevels; - logReader->queryCondition.noTypes = qRstMsg.noTypes; - logReader->queryCondition.nNoPid = qRstMsg.nNoPid; - logReader->queryCondition.nNoDomain = qRstMsg.nNoDomain; - logReader->queryCondition.nNoTag = qRstMsg.nNoTag; - for (int i = 0; (i < qRstMsg.nPid) && (i < MAX_PIDS); i++) { - logReader->queryCondition.pids[i] = qRstMsg.pids[i]; - } - for (int i = 0; (i < qRstMsg.nDomain) && (i < MAX_DOMAINS); i++) { - logReader->queryCondition.domains[i] = qRstMsg.domains[i]; - } - for (int i = 0; (i < qRstMsg.nTag) && (i < MAX_TAGS); i++) { - logReader->queryCondition.tags[i] = qRstMsg.tags[i]; - } - for (int i = 0; (i < qRstMsg.nNoPid) && (i < MAX_PIDS); i++) { - logReader->queryCondition.noPids[i] = qRstMsg.noPids[i]; - } - for (int i = 0; (i < qRstMsg.nNoDomain) && (i < MAX_DOMAINS); i++) { - logReader->queryCondition.noDomains[i] = qRstMsg.noDomains[i]; - } - for (int i = 0; (i < qRstMsg.nNoTag) && (i < MAX_TAGS); i++) { - logReader->queryCondition.noTags[i] = qRstMsg.noTags[i]; - } -} - -void LogQuerier::LogQuerierThreadFunc(std::shared_ptr logReader) -{ - cout << "Start log_querier !\n" << std::endl; - int readRes = 0; - LogQueryRequest* qRstMsg = nullptr; - NextRequest* nRstMsg = nullptr; - - while ((readRes = logReader->hilogtoolConnectSocket->Read(g_tempBuffer, MAX_DATA_LEN - 1)) > 0) { - MessageHeader *header = (MessageHeader *)g_tempBuffer; - switch (header->msgType) { - case LOG_QUERY_REQUEST: - qRstMsg = (LogQueryRequest*) g_tempBuffer; - SetCondition(logReader, *qRstMsg); - if (!LogTypeForbidden(logReader->queryCondition.types)) { - return; - } - HandleLogQueryRequest(logReader, *hilogBuffer); - break; - case NEXT_REQUEST: - nRstMsg = (NextRequest*) g_tempBuffer; - if (nRstMsg->sendId == SENDIDA) { - HandleNextRequest(logReader, *hilogBuffer); - } - break; - case MC_REQ_LOG_PERSIST_START: - HandlePersistStartRequest(g_tempBuffer, logReader, *hilogBuffer); - break; - case MC_REQ_LOG_PERSIST_STOP: - HandlePersistDeleteRequest(g_tempBuffer, logReader); - break; - case MC_REQ_LOG_PERSIST_QUERY: - HandlePersistQueryRequest(g_tempBuffer, logReader); - break; - case MC_REQ_BUFFER_RESIZE: - HandleBufferResizeRequest(g_tempBuffer, logReader, hilogBuffer); - break; - case MC_REQ_BUFFER_SIZE: - HandleBufferSizeRequest(g_tempBuffer, logReader, hilogBuffer); - break; - case MC_REQ_STATISTIC_INFO_QUERY: - HandleInfoQueryRequest(g_tempBuffer, logReader, hilogBuffer); - break; - case MC_REQ_STATISTIC_INFO_CLEAR: - HandleInfoClearRequest(g_tempBuffer, logReader, hilogBuffer); - break; - case MC_REQ_LOG_CLEAR: - HandleBufferClearRequest(g_tempBuffer, logReader, hilogBuffer); - break; - default: - break; - } - } - hilogBuffer->RemoveLogReader(logReader); -} - -LogQuerier::LogQuerier(std::unique_ptr handler, HilogBuffer& buffer) -{ - hilogtoolConnectSocket = std::move(handler); - hilogBuffer = &buffer; -} - -int LogQuerier::WriteData(LogQueryResponse& rsp, OptRef pData) -{ - iovec vec[3]; - vec[0].iov_base = &rsp; - vec[0].iov_len = sizeof(LogQueryResponse); - if (pData == std::nullopt) { - return hilogtoolConnectSocket->WriteV(vec, 1); - } - const HilogData& data = pData->get(); - vec[1].iov_base = data.tag; - vec[1].iov_len = data.tag_len; - vec[2].iov_base = data.content; - vec[2].iov_len = data.len - data.tag_len; - - return hilogtoolConnectSocket->WriteV(vec, 3); -} - -int LogQuerier::WriteData(OptRef pData) -{ - LogQueryResponse rsp; - MessageHeader& header = rsp.header; - HilogDataMessage& msg = rsp.data; - - /* set header */ - SetMsgHead(header, cmd, sizeof(rsp) + ((pData != std::nullopt) ? pData->get().len : 0)); - - /* set data */ - msg.sendId = sendId; - if (pData != std::nullopt) { - HilogData& data = pData->get(); - msg.length = data.len; /* data len, equals tag_len plus content length, include '\0' */ - msg.level = data.level; - msg.type = data.type; - msg.tag_len = data.tag_len; /* include '\0' */ - msg.pid = data.pid; - msg.tid = data.tid; - msg.domain = data.domain; - msg.tv_sec = data.tv_sec; - msg.tv_nsec = data.tv_nsec; - } - - /* write into socket */ - return WriteData(rsp, pData); -} - -void LogQuerier::NotifyForNewData() -{ - if (isNotified) { - return; - } - isNotified = true; - LogQueryResponse rsp; - rsp.data.sendId = SENDIDS; - rsp.data.type = -1; - /* set header */ - SetMsgHead(rsp.header, NEXT_RESPONSE, sizeof(rsp)); - if (WriteData(rsp, std::nullopt) <= 0) { - isNotified = false; - } -} - -uint8_t LogQuerier::GetType() const -{ - switch (cmd) { - case LOG_QUERY_RESPONSE: - return TYPE_QUERIER; - case NEXT_RESPONSE: - return TYPE_QUERIER; - default: - return TYPE_CONTROL; - } -} - -int LogQuerier::RestorePersistJobs(HilogBuffer& _buffer) -{ - DIR *dir; - struct dirent *ent = nullptr; - if ((dir = opendir(g_logPersisterDir.c_str())) != NULL) { - while ((ent = readdir(dir)) != NULL) { - size_t length = strlen(ent->d_name); - std::string pPath(ent->d_name, length); - if (length >= INFO_SUFFIX && pPath.substr(length - INFO_SUFFIX, length) == ".info") { - if (pPath == "hilog.info") continue; - std::cout << "Found a persist job!" << std::endl; - FILE* infile = fopen((g_logPersisterDir + pPath).c_str(), "r"); - if (infile == NULL) { - std::cout << "Error opening recovery info file!" << std::endl; - continue; - } - PersistRecoveryInfo info; - fread(&info, sizeof(PersistRecoveryInfo), 1, infile); - uint64_t hashSum = 0L; - fread(&hashSum, sizeof(hashSum), 1, infile); - fclose(infile); - uint64_t hash = GetInfoHash(info); - if (hash != hashSum) { - std::cout << "Info file checksum Failed!" << std::endl; - continue; - } - JobLauncher(info.msg, _buffer, true, info.index + 1); - std::cout << "Recovery Info:" << std::endl << - "jobId=" << (unsigned)(info.msg.jobId) << std::endl << - "filePath=" << (info.msg.filePath) << std::endl; - } - } - closedir(dir); - } else { - perror("Failed to open persister directory!"); - return ERR_LOG_PERSIST_DIR_OPEN_FAIL; - } - cout << "Finished restoring persist jobs!" << endl; - return EXIT_SUCCESS; -} -} // namespace HiviewDFX -} // namespace OHOS diff --git a/services/hilogd/log_reader.cpp b/services/hilogd/log_reader.cpp deleted file mode 100644 index b3c7b1747177e8235c159a59b08e3085d8444ba3..0000000000000000000000000000000000000000 --- a/services/hilogd/log_reader.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "log_reader.h" - -#include -#include -#include -#include -#include -#include "log_buffer.h" - -namespace OHOS { -namespace HiviewDFX { -using namespace std; - -HilogBuffer* LogReader::hilogBuffer = nullptr; -LogReader::LogReader() -{ - isNotified = false; -} - -LogReader::~LogReader() -{ - cout << "Log Reader destruct" << endl; -} - -void LogReader::NotifyReload() -{ - isReload = true; -} - -bool LogReader::GetReload() const -{ - return isReload; -} - -void LogReader::SetReload(bool flag) -{ - isReload = flag; -} - -void LogReader::SetSendId(unsigned int value) -{ - sendId = value; -} - -void LogReader::SetCmd(uint8_t value) -{ - cmd = value; -} -} // namespace HiviewDFX -} // namespace OHOS diff --git a/services/hilogd/main.cpp b/services/hilogd/main.cpp index 7ba78afc304f27b2648cbad559f1825062365620..be64a894eb1e8d1038a70054b01283f7001310df 100644 --- a/services/hilogd/main.cpp +++ b/services/hilogd/main.cpp @@ -20,13 +20,14 @@ #include #include #include + #include "cmd_executor.h" -#include "log_querier.h" +#include "flow_control_init.h" #include "hilog_input_socket_server.h" #include "log_collector.h" #include "log_kmsg.h" -#include "flow_control_init.h" #include "properties.h" +#include "service_controller.h" #ifdef DEBUG #include @@ -102,8 +103,7 @@ int HilogdEntry() auto startupCheckTask = std::async(std::launch::async, [&hilogBuffer]() { prctl(PR_SET_NAME, "hilogd.pst_res"); - std::shared_ptr logQuerier = std::make_shared(nullptr, hilogBuffer); - logQuerier->RestorePersistJobs(hilogBuffer); + RestorePersistJobs(hilogBuffer); }); auto kmsgTask = std::async(std::launch::async, [&hilogBuffer]() { LogKmsg logKmsg(hilogBuffer); diff --git a/services/hilogd/service_controller.cpp b/services/hilogd/service_controller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8da76431495d4964052f971c6cb80595d0b6fe0b --- /dev/null +++ b/services/hilogd/service_controller.cpp @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_controller.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "hilog/log.h" +#include "hilog_common.h" +#include "log_data.h" +#include "hilogtool_msg.h" +#include "log_buffer.h" +#include "log_persister.h" + +namespace OHOS { +namespace HiviewDFX { +using namespace std; +string g_logPersisterDir = HILOG_FILE_DIR; +constexpr int DEFAULT_LOG_TYPE = 1<|]" + std::regex regExpress("[\\/:*?\"<>|]"); + bool bValid = !std::regex_search(strFileName, regExpress); + return bValid; +} + +inline bool IsLogTypeForbidden(uint16_t queryTypes) +{ + if (queryTypes == (0b01 << LOG_KMSG) || (queryTypes & (0b01 << LOG_KMSG)) == 0) { + return false; + } else { + std::cout << "queryTypes can not contain app/core/init and kmsg at the same time," + "try to -t app/core/init or -t kmsg separately\n"; + return true; + } +} + +int StartPersistStoreJob(const LogPersister::InitData& initData, HilogBuffer& hilogBuffer) +{ + std::shared_ptr persister = LogPersister::CreateLogPersister(hilogBuffer); + + int persistRes = persister->Init(initData); + if (persistRes != RET_SUCCESS) { + if (persistRes == ERR_LOG_PERSIST_TASK_FAIL) { + std::cerr << __PRETTY_FUNCTION__ << " Log persist task exists!\n"; + } else { + std::cerr << __PRETTY_FUNCTION__ << " LogPersister failed to initialize!\n"; + } + return persistRes; + } + persister->Start(); + return RET_SUCCESS; +} + +void ServiceController::HandlePersistStartRequest(const PacketBuf& rawData) +{ + const LogPersistStartRequest* request = reinterpret_cast(rawData.data()); + const LogPersistStartMsg* requestMsg = reinterpret_cast(&request->logPersistStartMsg); + + PacketBuf respondRaw = {0}; + LogPersistStartResponse* respond = reinterpret_cast(respondRaw.data()); + LogPersistStartResult* respondMsg = reinterpret_cast(&respond->logPersistStartRst); + + if (respondMsg == nullptr) { + return; + } else if (IsLogTypeForbidden(requestMsg->logType)) { + respondMsg->result = ERR_QUERY_TYPE_INVALID; + } else if (requestMsg->jobId <= 0) { + respondMsg->result = ERR_LOG_PERSIST_JOBID_INVALID; + } else if (requestMsg->fileSize < MAX_PERSISTER_BUFFER_SIZE) { + std::cout << __PRETTY_FUNCTION__ << " Persist log file size less than min size\n"; + respondMsg->result = ERR_LOG_PERSIST_FILE_SIZE_INVALID; + } else if (!IsValidFileName(requestMsg->filePath)) { + std::cout << __PRETTY_FUNCTION__ << " FileName is not valid!\n"; + respondMsg->result = ERR_LOG_PERSIST_FILE_NAME_INVALID; + } else { + LogPersister::InitData initData = *requestMsg; + auto& requestMsgCpy = std::get(initData); + + bool isKmsg = (requestMsgCpy.logType == (0b01 << LOG_KMSG)); + std::string logPersisterFileName = isKmsg ? "hilog_kmsg" : "hilog"; + std::cout << __PRETTY_FUNCTION__ << " logPersisterFileName: " << logPersisterFileName << "\n"; + bool isPathEmpty = requestMsgCpy.filePath[0] == '\0' ? true : false; + std::string logPersisterPath = isPathEmpty + ? (g_logPersisterDir + logPersisterFileName) + : (g_logPersisterDir + string(requestMsgCpy.filePath)); + if (strcpy_s(requestMsgCpy.filePath, FILE_PATH_MAX_LEN, logPersisterPath.c_str()) != 0) { + std::cerr << __PRETTY_FUNCTION__ << " Can't copy request msg filePath for log persister\n"; + respondMsg->result = RET_FAIL; + } else { + respondMsg->result = StartPersistStoreJob(initData, m_hilogBuffer); + } + } + + respondMsg->jobId = requestMsg->jobId; + SetMsgHead(respond->msgHeader, MC_RSP_LOG_PERSIST_START, sizeof(*respondMsg)); + m_communicationSocket->Write(respondRaw.data(), sizeof(*respondMsg) + sizeof(MessageHeader)); +} + +void ServiceController::HandlePersistStopRequest(const PacketBuf& rawData) +{ + const LogPersistStopRequest* request = reinterpret_cast(rawData.data()); + const LogPersistStopMsg* requestMsg = reinterpret_cast(&request->logPersistStopMsg); + + PacketBuf respondRaw = {0}; + LogPersistStopResponse* respond = reinterpret_cast(respondRaw.data()); + LogPersistStopResult* respondMsg = reinterpret_cast(&respond->logPersistStopRst); + + if (request->msgHeader.msgLen > sizeof(LogPersistStopMsg) * LOG_TYPE_MAX) { + return; + } + uint32_t msgNum = 0; + list resultList; + LogPersister::Query(DEFAULT_LOG_TYPE, resultList); + if (requestMsg && sizeof(LogPersistQueryMsg) <= request->msgHeader.msgLen) { + if (requestMsg->jobId != JOB_ID_ALL) { + int32_t rst = LogPersister::Kill(requestMsg->jobId); + if (respondMsg) { + respondMsg->jobId = requestMsg->jobId; + respondMsg->result = (rst < 0) ? rst : RET_SUCCESS; + respondMsg++; + msgNum++; + } + } else { + for (auto it = resultList.begin(); it != resultList.end(); ++it) { + int32_t rst = LogPersister::Kill((*it).jobId); + if (respondMsg) { + respondMsg->jobId = (*it).jobId; + respondMsg->result = (rst < 0) ? rst : RET_SUCCESS; + respondMsg++; + msgNum++; + } + } + } + } + uint16_t resultMessagesSize = msgNum * sizeof(LogPersistStopResult); + SetMsgHead(respond->msgHeader, MC_RSP_LOG_PERSIST_STOP, resultMessagesSize); + m_communicationSocket->Write(respondRaw.data(), resultMessagesSize + sizeof(MessageHeader)); +} + +void ServiceController::HandlePersistQueryRequest(const PacketBuf& rawData) +{ + const LogPersistQueryRequest* request = reinterpret_cast(rawData.data()); + const LogPersistQueryMsg* requestMsg = reinterpret_cast(&request->logPersistQueryMsg); + + PacketBuf respondRaw = {0}; + LogPersistQueryResponse* respond = reinterpret_cast(respondRaw.data()); + LogPersistQueryResult* respondMsg = reinterpret_cast(&respond->logPersistQueryRst); + + uint32_t recvMsgLen = 0; + uint32_t respondMsgNum = 0; + + if (request->msgHeader.msgLen > sizeof(LogPersistQueryMsg) * LOG_TYPE_MAX) { + return; + } + + while (requestMsg && recvMsgLen + sizeof(LogPersistQueryMsg) <= request->msgHeader.msgLen) { + list resultList; + std::cout << requestMsg->logType << endl; + int32_t rst = LogPersister::Query(requestMsg->logType, resultList); + for (auto it = resultList.begin(); it != resultList.end(); ++it) { + if ((respondMsgNum + 1) * sizeof(LogPersistQueryResult) + sizeof(MessageHeader) > respondRaw.size()) { + break; + } + if (respondMsg) { + respondMsg->result = (rst < 0) ? rst : RET_SUCCESS; + respondMsg->jobId = (*it).jobId; + respondMsg->logType = (*it).logType; + respondMsg->compressAlg = (*it).compressAlg; + if (strcpy_s(respondMsg->filePath, FILE_PATH_MAX_LEN, (*it).filePath)) { + return; + } + respondMsg->fileSize = (*it).fileSize; + respondMsg->fileNum = (*it).fileNum; + respondMsg++; + respondMsgNum++; + } + } + requestMsg++; + recvMsgLen += sizeof(LogPersistQueryMsg); + } + uint16_t respondMsgSize = respondMsgNum * sizeof(LogPersistQueryResult); + SetMsgHead(respond->msgHeader, MC_RSP_LOG_PERSIST_QUERY, respondMsgSize); + m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader)); +} + +void ServiceController::HandleBufferResizeRequest(const PacketBuf& rawData) +{ + const BufferResizeRequest* request = reinterpret_cast(rawData.data()); + const BuffResizeMsg* requestMsg = reinterpret_cast(&request->buffResizeMsg); + + PacketBuf respondRaw = {0}; + BufferResizeResponse* respond = reinterpret_cast(respondRaw.data()); + BuffResizeResult* respondMsg = reinterpret_cast(&respond->buffResizeRst); + uint32_t recvMsgLen = 0; + uint32_t respondMsgNum = 0; + + if (request->msgHeader.msgLen > sizeof(BuffResizeMsg) * LOG_TYPE_MAX) { + return; + } + + while (requestMsg && recvMsgLen + sizeof(BuffResizeMsg) <= request->msgHeader.msgLen) { + if ((respondMsgNum + 1) * sizeof(BuffResizeResult) + sizeof(MessageHeader) > respondRaw.size()) { + break; + } + int32_t rst = m_hilogBuffer.SetBuffLen(requestMsg->logType, requestMsg->buffSize); + if (respondMsg) { + respondMsg->logType = requestMsg->logType; + respondMsg->buffSize = requestMsg->buffSize; + respondMsg->result = (rst < 0) ? rst : RET_SUCCESS; + respondMsg++; + } + requestMsg++; + recvMsgLen += sizeof(BuffResizeMsg); + respondMsgNum++; + } + uint16_t respondMsgSize = respondMsgNum * sizeof(BuffResizeResult); + SetMsgHead(respond->msgHeader, MC_RSP_BUFFER_RESIZE, respondMsgSize); + m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader)); +} + +void ServiceController::HandleBufferSizeRequest(const PacketBuf& rawData) +{ + const BufferSizeRequest* request = reinterpret_cast(rawData.data()); + const BuffSizeMsg* requestMsg = reinterpret_cast(&request->buffSizeMsg); + + PacketBuf respondRaw = {0}; + BufferSizeResponse* respond = reinterpret_cast(respondRaw.data()); + BuffSizeResult* pBuffSizeRst = reinterpret_cast(&respond->buffSizeRst); + + uint32_t recvMsgLen = 0; + uint32_t respondMsgNum = 0; + + if (request->msgHeader.msgLen > sizeof(BuffSizeMsg) * LOG_TYPE_MAX) { + return; + } + + while (requestMsg && recvMsgLen + sizeof(BuffSizeMsg) <= request->msgHeader.msgLen) { + if ((respondMsgNum + 1) * sizeof(BuffSizeResult) + sizeof(MessageHeader) > respondRaw.size()) { + break; + } + int64_t buffLen = m_hilogBuffer.GetBuffLen(requestMsg->logType); + if (pBuffSizeRst) { + pBuffSizeRst->logType = requestMsg->logType; + pBuffSizeRst->buffSize = buffLen; + pBuffSizeRst->result = (buffLen < 0) ? buffLen : RET_SUCCESS; + pBuffSizeRst++; + } + recvMsgLen += sizeof(BuffSizeMsg); + respondMsgNum++; + requestMsg++; + } + uint16_t respondMsgSize = respondMsgNum * sizeof(BuffSizeResult); + SetMsgHead(respond->msgHeader, MC_RSP_BUFFER_SIZE, respondMsgSize); + m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader)); +} + +void ServiceController::HandleInfoQueryRequest(const PacketBuf& rawData) +{ + PacketBuf respondRaw = {0}; + const StatisticInfoQueryRequest* request = reinterpret_cast(rawData.data()); + StatisticInfoQueryResponse* respond = reinterpret_cast(respondRaw.data()); + + if (request->domain == 0xffffffff) { + respond->logType = request->logType; + respond->domain = request->domain; + int32_t rst = m_hilogBuffer.GetStatisticInfoByLog(request->logType, respond->printLen, + respond->cacheLen, respond->dropped); + respond->result = (rst < 0) ? rst : RET_SUCCESS; + } else { + respond->logType = request->logType; + respond->domain = request->domain; + int32_t rst = m_hilogBuffer.GetStatisticInfoByDomain(request->domain, respond->printLen, + respond->cacheLen, respond->dropped); + respond->result = (rst < 0) ? rst : RET_SUCCESS; + } + SetMsgHead(respond->msgHeader, MC_RSP_STATISTIC_INFO_QUERY, sizeof(*respond) - sizeof(MessageHeader)); + m_communicationSocket->Write(respondRaw.data(), sizeof(*respond)); +} + +void ServiceController::HandleInfoClearRequest(const PacketBuf& rawData) +{ + PacketBuf respondRaw = {0}; + const StatisticInfoClearRequest* request = reinterpret_cast(rawData.data()); + StatisticInfoClearResponse* respond = reinterpret_cast(respondRaw.data()); + if (request->domain == 0xffffffff) { + respond->logType = request->logType; + respond->domain = request->domain; + int32_t rst = m_hilogBuffer.ClearStatisticInfoByLog(request->logType); + respond->result = (rst < 0) ? rst : RET_SUCCESS; + } else { + respond->logType = request->logType; + respond->domain = request->domain; + int32_t rst = m_hilogBuffer.ClearStatisticInfoByDomain(request->domain); + respond->result = (rst < 0) ? rst : RET_SUCCESS; + } + SetMsgHead(respond->msgHeader, MC_RSP_STATISTIC_INFO_CLEAR, sizeof(*respond) - sizeof(MessageHeader)); + m_communicationSocket->Write(respondRaw.data(), sizeof(*respond)); +} + +void ServiceController::HandleBufferClearRequest(const PacketBuf& rawData) +{ + const LogClearRequest* request = reinterpret_cast(rawData.data()); + const LogClearMsg* requestMsg = reinterpret_cast(&request->logClearMsg); + + PacketBuf respondRaw = {0}; + LogClearResponse* respond = reinterpret_cast(respondRaw.data()); + LogClearResult* respondMsg = reinterpret_cast(&respond->logClearRst); + + uint32_t recvMsgLen = 0; + uint32_t respondMsgNum = 0; + + if (request->msgHeader.msgLen > sizeof(LogClearMsg) * LOG_TYPE_MAX) { + return; + } + + while (requestMsg && recvMsgLen + sizeof(LogClearMsg) <= request->msgHeader.msgLen) { + if ((respondMsgNum + 1) * sizeof(LogClearResult) + sizeof(MessageHeader) > respondRaw.size()) { + break; + } + int32_t rst = m_hilogBuffer.Delete(requestMsg->logType); + if (respondMsg) { + respondMsg->logType = requestMsg->logType; + respondMsg->result = (rst < 0) ? rst : RET_SUCCESS; + respondMsg++; + } + requestMsg++; + recvMsgLen += sizeof(LogClearMsg); + respondMsgNum++; + } + + uint16_t respondMsgSize = respondMsgNum * sizeof(LogClearResult); + SetMsgHead(respond->msgHeader, MC_RSP_LOG_CLEAR, respondMsgSize); + m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader)); +} + + +ServiceController::ServiceController(std::unique_ptr communicationSocket, HilogBuffer& buffer) + : m_communicationSocket(std::move(communicationSocket)) + , m_hilogBuffer(buffer) +{ + m_bufReader = m_hilogBuffer.CreateBufReader([this]() { NotifyForNewData(); }); +} + +ServiceController::~ServiceController() +{ + m_hilogBuffer.RemoveBufReader(m_bufReader); + + m_notifyNewDataCv.notify_all(); +} + +void ServiceController::CommunicationLoop(const std::atomic& stopLoop) +{ + std::cout << __PRETTY_FUNCTION__ << " Begin\n"; + if (!m_communicationSocket) { + std::cerr << __PRETTY_FUNCTION__ << " Invalid socket handler!\n"; + return; + } + PacketBuf rawDataBuffer = {0}; +; + while (!stopLoop.load() && m_communicationSocket->Read(rawDataBuffer.data(), rawDataBuffer.size() - 1) > 0) { + MessageHeader *header = reinterpret_cast(rawDataBuffer.data()); + switch (header->msgType) { + case LOG_QUERY_REQUEST: + SetFilters(rawDataBuffer); + if (IsLogTypeForbidden(m_filters.inclusions.types)) { + return; + } + HandleLogQueryRequest(); + break; + case NEXT_REQUEST: + HandleNextRequest(rawDataBuffer, stopLoop); + break; + case MC_REQ_LOG_PERSIST_START: + HandlePersistStartRequest(rawDataBuffer); + break; + case MC_REQ_LOG_PERSIST_STOP: + HandlePersistStopRequest(rawDataBuffer); + break; + case MC_REQ_LOG_PERSIST_QUERY: + HandlePersistQueryRequest(rawDataBuffer); + break; + case MC_REQ_BUFFER_RESIZE: + HandleBufferResizeRequest(rawDataBuffer); + break; + case MC_REQ_BUFFER_SIZE: + HandleBufferSizeRequest(rawDataBuffer); + break; + case MC_REQ_STATISTIC_INFO_QUERY: + HandleInfoQueryRequest(rawDataBuffer); + break; + case MC_REQ_STATISTIC_INFO_CLEAR: + HandleInfoClearRequest(rawDataBuffer); + break; + case MC_REQ_LOG_CLEAR: + HandleBufferClearRequest(rawDataBuffer); + break; + default: + std::cout << __PRETTY_FUNCTION__ << " Unknown message. Skipped!\n"; + break; + } + } + std::cout << __PRETTY_FUNCTION__ << " Done\n"; +} + +void ServiceController::SetFilters(const PacketBuf& rawData) +{ + const LogQueryRequest& qRstMsg = *reinterpret_cast(rawData.data()); + m_filters.inclusions.levels = qRstMsg.levels; + m_filters.inclusions.types = qRstMsg.types; + + m_filters.inclusions.pids.resize(std::min(qRstMsg.nPid, static_cast(MAX_PIDS))); + std::copy(qRstMsg.pids, qRstMsg.pids+m_filters.inclusions.pids.size(), m_filters.inclusions.pids.begin()); + + m_filters.inclusions.domains.resize(std::min(qRstMsg.nDomain, static_cast(MAX_DOMAINS))); + std::copy(qRstMsg.domains, qRstMsg.domains+m_filters.inclusions.pids.size(), m_filters.inclusions.domains.begin()); + + m_filters.inclusions.tags.resize(std::min(qRstMsg.nTag, static_cast(MAX_TAGS))); + for (size_t i = 0; i < m_filters.inclusions.tags.size(); ++i) { + m_filters.inclusions.tags[i] = qRstMsg.tags[i]; + } + + m_filters.exclusions.levels = qRstMsg.noLevels; + m_filters.exclusions.types = qRstMsg.noTypes; + + m_filters.exclusions.pids.resize(std::min(qRstMsg.nNoPid, static_cast(MAX_PIDS))); + std::copy(qRstMsg.noPids, qRstMsg.noPids+m_filters.exclusions.pids.size(), m_filters.exclusions.pids.begin()); + + m_filters.exclusions.domains.resize(std::min(qRstMsg.nNoDomain, static_cast(MAX_DOMAINS))); + std::copy(qRstMsg.noDomains, qRstMsg.noDomains+m_filters.exclusions.pids.size(), + m_filters.exclusions.domains.begin()); + + m_filters.exclusions.tags.resize(std::min(qRstMsg.nNoTag, static_cast(MAX_TAGS))); + for (size_t i = 0; i < m_filters.exclusions.tags.size(); ++i) { + m_filters.exclusions.tags[i] = qRstMsg.noTags[i]; + } +} + +void ServiceController::HandleLogQueryRequest() +{ + auto result = m_hilogBuffer.Query(m_filters, m_bufReader, [this](const HilogData& logData) { + WriteLogQueryRespond(SENDIDA, LOG_QUERY_RESPONSE, logData); + }); + if (!result) { + WriteLogQueryRespond(SENDIDN, LOG_QUERY_RESPONSE, std::nullopt); + } +} + +void ServiceController::HandleNextRequest(const PacketBuf& rawData, const std::atomic& stopLoop) +{ + const NextRequest& nRstMsg = *reinterpret_cast(rawData.data()); + if (nRstMsg.sendId != SENDIDA) { + return; + } + + auto result = m_hilogBuffer.Query(m_filters, m_bufReader, [this](const HilogData& logData) { + WriteLogQueryRespond(SENDIDA, NEXT_RESPONSE, logData); + }); + if (!result) { + WriteLogQueryRespond(SENDIDN, NEXT_RESPONSE, std::nullopt); + } else { + return; + } + + std::unique_lock ul(m_notifyNewDataMtx); + for (;;) { + bool isStopped = stopLoop.load(); + if (isStopped) { + return; + } + + bool isNotified = m_notifyNewDataCv.wait_for(ul, 100ms) == std::cv_status::no_timeout; + if (isNotified) { + break; + } + } + LogQueryResponse rsp; + rsp.data.sendId = SENDIDS; + rsp.data.type = -1; + /* set header */ + SetMsgHead(rsp.header, NEXT_RESPONSE, sizeof(rsp)); + if (WriteData(rsp, std::nullopt) <= 0) { + std::cerr << __PRETTY_FUNCTION__ << " Can't send notification about new logs\n"; + } +} + +int ServiceController::WriteLogQueryRespond(unsigned int sendId, uint32_t respondCmd, OptCRef pData) +{ + LogQueryResponse rsp; + MessageHeader& header = rsp.header; + HilogDataMessage& msg = rsp.data; + + /* set header */ + SetMsgHead(header, respondCmd, sizeof(rsp) + ((pData != std::nullopt) ? pData->get().len : 0)); + + /* set data */ + msg.sendId = sendId; + if (pData != std::nullopt) { + const HilogData& data = pData->get(); + msg.length = data.len; /* data len, equals tag_len plus content length, include '\0' */ + msg.level = data.level; + msg.type = data.type; + msg.tag_len = data.tag_len; /* include '\0' */ + msg.pid = data.pid; + msg.tid = data.tid; + msg.domain = data.domain; + msg.tv_sec = data.tv_sec; + msg.tv_nsec = data.tv_nsec; + } + + /* write into socket */ + return WriteData(rsp, pData); +} + +int ServiceController::WriteData(LogQueryResponse& rsp, OptCRef pData) +{ + iovec vec[3]; + vec[0].iov_base = &rsp; + vec[0].iov_len = sizeof(LogQueryResponse); + if (pData == std::nullopt) { + return WriteV(vec, 1); + } + const HilogData& data = pData->get(); + vec[1].iov_base = data.tag; + vec[1].iov_len = data.tag_len; + vec[2].iov_base = data.content; + vec[2].iov_len = data.len - data.tag_len; + + return WriteV(vec, 3); +} + +int ServiceController::WriteV(const iovec* vec, size_t len) +{ + static thread_local std::vector dataBuf; + + size_t allSize = 0; + for (size_t i = 0; i < len; ++i) { + allSize += vec[i].iov_len; + } + + if (dataBuf.size() < allSize) { + dataBuf.resize(allSize); + } + + uint32_t offset = 0; + for (uint32_t i = 0; i < len; ++i) { + auto src_address = (char*)vec[i].iov_base; + std::copy(src_address, src_address + vec[i].iov_len, dataBuf.data() + offset); + offset += vec[i].iov_len; + } + return m_communicationSocket->Write(dataBuf.data(), allSize); +} + +void ServiceController::NotifyForNewData() +{ + m_notifyNewDataCv.notify_one(); +} + +int RestorePersistJobs(HilogBuffer& hilogBuffer) +{ + std::cout << __PRETTY_FUNCTION__ << " Start restoring persist jobs!\n"; + DIR *dir = opendir(g_logPersisterDir.c_str()); + struct dirent *ent = nullptr; + if (dir != nullptr) { + while ((ent = readdir(dir)) != nullptr) { + size_t length = strlen(ent->d_name); + std::string pPath(ent->d_name, length); + if (length >= INFO_SUFFIX && pPath.substr(length - INFO_SUFFIX, length) == ".info") { + if (pPath == "hilog.info") continue; + std::cout << __PRETTY_FUNCTION__ << " Found a persist job! Path: " << g_logPersisterDir + pPath << "\n"; + FILE* infile = fopen((g_logPersisterDir + pPath).c_str(), "r"); + if (infile == nullptr) { + std::cerr << __PRETTY_FUNCTION__ << " Error opening recovery info file!\n"; + continue; + } + LogPersister::InitData initData = PersistRecoveryInfo(); + auto& info = std::get(initData); + fread(&info, sizeof(PersistRecoveryInfo), 1, infile); + uint64_t hashSum = 0L; + fread(&hashSum, sizeof(hashSum), 1, infile); + fclose(infile); + uint64_t hash = GenerateHash(info); + if (hash != hashSum) { + std::cout << __PRETTY_FUNCTION__ << " Info file checksum Failed!\n"; + continue; + } + int result = StartPersistStoreJob(initData, hilogBuffer); + std::cout << __PRETTY_FUNCTION__ << " Recovery Info:\n" + << " restoring result: " << (result == RET_SUCCESS + ? std::string("Success\n") + : std::string("Failed(") + std::to_string(result) + ")\n") + << " jobId=" << (unsigned)(info.msg.jobId) << "\n" + << " filePath=" << (info.msg.filePath) << "\n"; + } + } + closedir(dir); + } else { + perror("Failed to open persister directory!"); + return ERR_LOG_PERSIST_DIR_OPEN_FAIL; + } + std::cout << __PRETTY_FUNCTION__ << " Finished restoring persist jobs!\n"; + return EXIT_SUCCESS; +} +} // namespace HiviewDFX +} // namespace OHOS