• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "service_controller.h"
17 
18 #include <algorithm>
19 #include <array>
20 #include <chrono>
21 #include <cstdio>
22 #include <cstring>
23 #include <ctime>
24 #include <fcntl.h>
25 #include <iostream>
26 #include <memory>
27 #include <optional>
28 #include <regex>
29 #include <sstream>
30 #include <sys/mman.h>
31 #include <sys/prctl.h>
32 #include <thread>
33 
34 #include <unistd.h>
35 #include <dirent.h>
36 
37 #include <securec.h>
38 #include "hilog/log.h"
39 #include "hilog_common.h"
40 #include "log_data.h"
41 #include "hilogtool_msg.h"
42 #include "log_buffer.h"
43 #include "log_persister.h"
44 
45 namespace OHOS {
46 namespace HiviewDFX {
47 using namespace std;
48 string g_logPersisterDir = HILOG_FILE_DIR;
49 constexpr int DEFAULT_LOG_TYPE = 1<<LOG_INIT | 1<<LOG_APP | 1<<LOG_CORE | 1<<LOG_KMSG;
50 
51 constexpr int INFO_SUFFIX = 5;
52 
SetMsgHead(MessageHeader & msgHeader,uint8_t msgCmd,uint16_t msgLen)53 inline void SetMsgHead(MessageHeader& msgHeader, uint8_t msgCmd, uint16_t msgLen)
54 {
55     msgHeader.version = 0;
56     msgHeader.msgType = msgCmd;
57     msgHeader.msgLen = msgLen;
58 }
59 
IsValidFileName(const std::string & strFileName)60 inline bool IsValidFileName(const std::string& strFileName)
61 {
62     // File name shouldn't contain "[\\/:*?\"<>|]"
63     std::regex regExpress("[\\/:*?\"<>|]");
64     bool bValid = !std::regex_search(strFileName, regExpress);
65     return bValid;
66 }
67 
IsLogTypeForbidden(uint16_t queryTypes)68 inline bool IsLogTypeForbidden(uint16_t queryTypes)
69 {
70     if (queryTypes == (0b01 << LOG_KMSG) || (queryTypes & (0b01 << LOG_KMSG)) == 0) {
71         return false;
72     } else {
73         std::cout << "queryTypes can not contain app/core/init and kmsg at the same time,"
74             "try to -t app/core/init or -t kmsg separately\n";
75         return true;
76     }
77 }
78 
StartPersistStoreJob(const LogPersister::InitData & initData,HilogBuffer & hilogBuffer)79 int StartPersistStoreJob(const LogPersister::InitData& initData, HilogBuffer& hilogBuffer)
80 {
81     std::shared_ptr<LogPersister> persister = LogPersister::CreateLogPersister(hilogBuffer);
82 
83     int persistRes = persister->Init(initData);
84     if (persistRes != RET_SUCCESS) {
85         if (persistRes == ERR_LOG_PERSIST_TASK_FAIL) {
86             std::cerr << __PRETTY_FUNCTION__ << " Log persist task exists!\n";
87         } else {
88             std::cerr << __PRETTY_FUNCTION__ << " LogPersister failed to initialize!\n";
89         }
90         return persistRes;
91     }
92     persister->Start();
93     return RET_SUCCESS;
94 }
95 
HandlePersistStartRequest(const PacketBuf & rawData)96 void ServiceController::HandlePersistStartRequest(const PacketBuf& rawData)
97 {
98     const LogPersistStartRequest* request = reinterpret_cast<const LogPersistStartRequest*>(rawData.data());
99     const LogPersistStartMsg* requestMsg = reinterpret_cast<const LogPersistStartMsg*>(&request->logPersistStartMsg);
100 
101     PacketBuf respondRaw = {0};
102     LogPersistStartResponse* respond = reinterpret_cast<LogPersistStartResponse*>(respondRaw.data());
103     LogPersistStartResult* respondMsg = reinterpret_cast<LogPersistStartResult*>(&respond->logPersistStartRst);
104 
105     if (respondMsg == nullptr) {
106         return;
107     } else if (IsLogTypeForbidden(requestMsg->logType)) {
108         respondMsg->result = ERR_QUERY_TYPE_INVALID;
109     } else if (requestMsg->jobId  <= 0) {
110         respondMsg->result = ERR_LOG_PERSIST_JOBID_INVALID;
111     } else if (requestMsg->fileSize < MAX_PERSISTER_BUFFER_SIZE) {
112         std::cout << __PRETTY_FUNCTION__ << " Persist log file size less than min size\n";
113         respondMsg->result = ERR_LOG_PERSIST_FILE_SIZE_INVALID;
114     } else if (!IsValidFileName(requestMsg->filePath)) {
115         std::cout << __PRETTY_FUNCTION__ << " FileName is not valid!\n";
116         respondMsg->result = ERR_LOG_PERSIST_FILE_NAME_INVALID;
117     } else if (requestMsg->fileNum > MAX_LOG_FILE_NUM || requestMsg->fileNum < MIN_LOG_FILE_NUM) {
118         cout << "File number is not valid!" << endl;
119         respondMsg->result = ERR_LOG_FILE_NUM_INVALID;
120     } else {
121         LogPersister::InitData initData = *requestMsg;
122         auto& requestMsgCpy = std::get<LogPersistStartMsg>(initData);
123 
124         bool isKmsg = (requestMsgCpy.logType == (0b01 << LOG_KMSG));
125         std::string logPersisterFileName = isKmsg ? "hilog_kmsg" : "hilog";
126         std::cout << __PRETTY_FUNCTION__ << " logPersisterFileName: " << logPersisterFileName << "\n";
127         bool isPathEmpty = requestMsgCpy.filePath[0] == '\0' ? true : false;
128         std::string logPersisterPath = isPathEmpty
129             ? (g_logPersisterDir + logPersisterFileName)
130             : (g_logPersisterDir + string(requestMsgCpy.filePath));
131         if (strcpy_s(requestMsgCpy.filePath, FILE_PATH_MAX_LEN, logPersisterPath.c_str()) != 0) {
132             std::cerr << __PRETTY_FUNCTION__ << " Can't copy request msg filePath for log persister\n";
133             respondMsg->result = RET_FAIL;
134         } else {
135             respondMsg->result = StartPersistStoreJob(initData, m_hilogBuffer);
136         }
137     }
138 
139     respondMsg->jobId = requestMsg->jobId;
140     SetMsgHead(respond->msgHeader, MC_RSP_LOG_PERSIST_START, sizeof(*respondMsg));
141     m_communicationSocket->Write(respondRaw.data(), sizeof(*respondMsg) + sizeof(MessageHeader));
142 }
143 
HandlePersistStopRequest(const PacketBuf & rawData)144 void ServiceController::HandlePersistStopRequest(const PacketBuf& rawData)
145 {
146     const LogPersistStopRequest* request = reinterpret_cast<const LogPersistStopRequest*>(rawData.data());
147     const LogPersistStopMsg* requestMsg = reinterpret_cast<const LogPersistStopMsg*>(&request->logPersistStopMsg);
148 
149     PacketBuf respondRaw = {0};
150     LogPersistStopResponse* respond = reinterpret_cast<LogPersistStopResponse*>(respondRaw.data());
151     LogPersistStopResult* respondMsg = reinterpret_cast<LogPersistStopResult*>(&respond->logPersistStopRst);
152 
153     if (request->msgHeader.msgLen > sizeof(LogPersistStopMsg) * LOG_TYPE_MAX) {
154         return;
155     }
156     uint32_t msgNum = 0;
157     list<LogPersistQueryResult> resultList;
158     LogPersister::Query(DEFAULT_LOG_TYPE, resultList);
159     if (requestMsg && sizeof(LogPersistQueryMsg) <= request->msgHeader.msgLen) {
160         if (requestMsg->jobId != JOB_ID_ALL) {
161             int32_t rst = LogPersister::Kill(requestMsg->jobId);
162             if (respondMsg) {
163                 respondMsg->jobId = requestMsg->jobId;
164                 respondMsg->result = (rst < 0) ? rst : RET_SUCCESS;
165                 respondMsg++;
166                 msgNum++;
167             }
168         }  else {
169             for (auto it = resultList.begin(); it != resultList.end(); ++it) {
170                 int32_t rst = LogPersister::Kill((*it).jobId);
171                 if (respondMsg) {
172                     respondMsg->jobId = (*it).jobId;
173                     respondMsg->result = (rst < 0) ? rst : RET_SUCCESS;
174                     respondMsg++;
175                     msgNum++;
176                 }
177             }
178         }
179     }
180     uint16_t resultMessagesSize = msgNum * sizeof(LogPersistStopResult);
181     SetMsgHead(respond->msgHeader, MC_RSP_LOG_PERSIST_STOP, resultMessagesSize);
182     m_communicationSocket->Write(respondRaw.data(), resultMessagesSize + sizeof(MessageHeader));
183 }
184 
HandlePersistQueryRequest(const PacketBuf & rawData)185 void ServiceController::HandlePersistQueryRequest(const PacketBuf& rawData)
186 {
187     const LogPersistQueryRequest* request = reinterpret_cast<const LogPersistQueryRequest*>(rawData.data());
188     const LogPersistQueryMsg* requestMsg = reinterpret_cast<const LogPersistQueryMsg*>(&request->logPersistQueryMsg);
189 
190     PacketBuf respondRaw = {0};
191     LogPersistQueryResponse* respond = reinterpret_cast<LogPersistQueryResponse*>(respondRaw.data());
192     LogPersistQueryResult* respondMsg = reinterpret_cast<LogPersistQueryResult*>(&respond->logPersistQueryRst);
193 
194     uint32_t recvMsgLen = 0;
195     uint32_t respondMsgNum = 0;
196 
197     if (request->msgHeader.msgLen > sizeof(LogPersistQueryMsg) * LOG_TYPE_MAX) {
198         return;
199     }
200 
201     while (requestMsg && recvMsgLen + sizeof(LogPersistQueryMsg) <= request->msgHeader.msgLen) {
202         list<LogPersistQueryResult> resultList;
203         std::cout << requestMsg->logType << endl;
204         int32_t rst = LogPersister::Query(requestMsg->logType, resultList);
205         for (auto it = resultList.begin(); it != resultList.end(); ++it) {
206             if ((respondMsgNum + 1) * sizeof(LogPersistQueryResult) + sizeof(MessageHeader) > respondRaw.size()) {
207                 break;
208             }
209             if (respondMsg) {
210                 respondMsg->result = (rst < 0) ? rst : RET_SUCCESS;
211                 respondMsg->jobId = (*it).jobId;
212                 respondMsg->logType = (*it).logType;
213                 respondMsg->compressAlg = (*it).compressAlg;
214                 if (strcpy_s(respondMsg->filePath, FILE_PATH_MAX_LEN, (*it).filePath)) {
215                     return;
216                 }
217                 respondMsg->fileSize = (*it).fileSize;
218                 respondMsg->fileNum = (*it).fileNum;
219                 respondMsg++;
220                 respondMsgNum++;
221             }
222         }
223         requestMsg++;
224         recvMsgLen += sizeof(LogPersistQueryMsg);
225     }
226     uint16_t respondMsgSize = respondMsgNum * sizeof(LogPersistQueryResult);
227     SetMsgHead(respond->msgHeader, MC_RSP_LOG_PERSIST_QUERY, respondMsgSize);
228     m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader));
229 }
230 
HandleBufferResizeRequest(const PacketBuf & rawData)231 void ServiceController::HandleBufferResizeRequest(const PacketBuf& rawData)
232 {
233     const BufferResizeRequest* request = reinterpret_cast<const BufferResizeRequest*>(rawData.data());
234     const BuffResizeMsg* requestMsg = reinterpret_cast<const BuffResizeMsg*>(&request->buffResizeMsg);
235 
236     PacketBuf respondRaw = {0};
237     BufferResizeResponse* respond = reinterpret_cast<BufferResizeResponse*>(respondRaw.data());
238     BuffResizeResult* respondMsg = reinterpret_cast<BuffResizeResult*>(&respond->buffResizeRst);
239     uint32_t recvMsgLen = 0;
240     uint32_t respondMsgNum = 0;
241 
242     if (request->msgHeader.msgLen > sizeof(BuffResizeMsg) * LOG_TYPE_MAX) {
243         return;
244     }
245 
246     while (requestMsg && recvMsgLen + sizeof(BuffResizeMsg) <= request->msgHeader.msgLen) {
247         if ((respondMsgNum + 1) * sizeof(BuffResizeResult) + sizeof(MessageHeader) > respondRaw.size()) {
248             break;
249         }
250         int32_t rst = m_hilogBuffer.SetBuffLen(requestMsg->logType, requestMsg->buffSize);
251         if (respondMsg) {
252             respondMsg->logType = requestMsg->logType;
253             respondMsg->buffSize = requestMsg->buffSize;
254             respondMsg->result = (rst < 0) ? rst : RET_SUCCESS;
255             respondMsg++;
256         }
257         requestMsg++;
258         recvMsgLen += sizeof(BuffResizeMsg);
259         respondMsgNum++;
260     }
261     uint16_t respondMsgSize = respondMsgNum * sizeof(BuffResizeResult);
262     SetMsgHead(respond->msgHeader, MC_RSP_BUFFER_RESIZE, respondMsgSize);
263     m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader));
264 }
265 
HandleBufferSizeRequest(const PacketBuf & rawData)266 void ServiceController::HandleBufferSizeRequest(const PacketBuf& rawData)
267 {
268     const BufferSizeRequest* request = reinterpret_cast<const BufferSizeRequest*>(rawData.data());
269     const BuffSizeMsg* requestMsg = reinterpret_cast<const BuffSizeMsg*>(&request->buffSizeMsg);
270 
271     PacketBuf respondRaw = {0};
272     BufferSizeResponse* respond = reinterpret_cast<BufferSizeResponse*>(respondRaw.data());
273     BuffSizeResult* pBuffSizeRst = reinterpret_cast<BuffSizeResult*>(&respond->buffSizeRst);
274 
275     uint32_t recvMsgLen = 0;
276     uint32_t respondMsgNum = 0;
277 
278     if (request->msgHeader.msgLen > sizeof(BuffSizeMsg) * LOG_TYPE_MAX) {
279         return;
280     }
281 
282     while (requestMsg && recvMsgLen + sizeof(BuffSizeMsg) <= request->msgHeader.msgLen) {
283         if ((respondMsgNum + 1) * sizeof(BuffSizeResult) + sizeof(MessageHeader) > respondRaw.size()) {
284             break;
285         }
286         int64_t buffLen = m_hilogBuffer.GetBuffLen(requestMsg->logType);
287         if (pBuffSizeRst) {
288             pBuffSizeRst->logType = requestMsg->logType;
289             pBuffSizeRst->buffSize = static_cast<uint64_t>(buffLen);
290             pBuffSizeRst->result = (buffLen < 0) ? buffLen : RET_SUCCESS;
291             pBuffSizeRst++;
292         }
293         recvMsgLen += sizeof(BuffSizeMsg);
294         respondMsgNum++;
295         requestMsg++;
296     }
297     uint16_t respondMsgSize = respondMsgNum * sizeof(BuffSizeResult);
298     SetMsgHead(respond->msgHeader, MC_RSP_BUFFER_SIZE, respondMsgSize);
299     m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader));
300 }
301 
HandleInfoQueryRequest(const PacketBuf & rawData)302 void ServiceController::HandleInfoQueryRequest(const PacketBuf& rawData)
303 {
304     PacketBuf respondRaw = {0};
305     const StatisticInfoQueryRequest* request = reinterpret_cast<const StatisticInfoQueryRequest*>(rawData.data());
306     StatisticInfoQueryResponse* respond = reinterpret_cast<StatisticInfoQueryResponse*>(respondRaw.data());
307 
308     if (request->domain == 0xffffffff) {
309         respond->logType = request->logType;
310         respond->domain = request->domain;
311         int32_t rst = m_hilogBuffer.GetStatisticInfoByLog(request->logType, respond->printLen,
312             respond->cacheLen, respond->dropped);
313         respond->result = (rst < 0) ? rst : RET_SUCCESS;
314     } else {
315         respond->logType = request->logType;
316         respond->domain = request->domain;
317         int32_t rst = m_hilogBuffer.GetStatisticInfoByDomain(request->domain, respond->printLen,
318             respond->cacheLen, respond->dropped);
319         respond->result = (rst < 0) ? rst : RET_SUCCESS;
320     }
321     SetMsgHead(respond->msgHeader, MC_RSP_STATISTIC_INFO_QUERY, sizeof(*respond) - sizeof(MessageHeader));
322     m_communicationSocket->Write(respondRaw.data(), sizeof(*respond));
323 }
324 
HandleInfoClearRequest(const PacketBuf & rawData)325 void ServiceController::HandleInfoClearRequest(const PacketBuf& rawData)
326 {
327     PacketBuf respondRaw = {0};
328     const StatisticInfoClearRequest* request = reinterpret_cast<const StatisticInfoClearRequest*>(rawData.data());
329     StatisticInfoClearResponse* respond = reinterpret_cast<StatisticInfoClearResponse*>(respondRaw.data());
330     if (request->domain == 0xffffffff) {
331         respond->logType = request->logType;
332         respond->domain = request->domain;
333         int32_t rst = m_hilogBuffer.ClearStatisticInfoByLog(request->logType);
334         respond->result = (rst < 0) ? rst : RET_SUCCESS;
335     } else {
336         respond->logType = request->logType;
337         respond->domain = request->domain;
338         int32_t rst = m_hilogBuffer.ClearStatisticInfoByDomain(request->domain);
339         respond->result = (rst < 0) ? rst : RET_SUCCESS;
340     }
341     SetMsgHead(respond->msgHeader, MC_RSP_STATISTIC_INFO_CLEAR, sizeof(*respond) - sizeof(MessageHeader));
342     m_communicationSocket->Write(respondRaw.data(), sizeof(*respond));
343 }
344 
HandleBufferClearRequest(const PacketBuf & rawData)345 void ServiceController::HandleBufferClearRequest(const PacketBuf& rawData)
346 {
347     const LogClearRequest* request = reinterpret_cast<const LogClearRequest*>(rawData.data());
348     const LogClearMsg* requestMsg = reinterpret_cast<const LogClearMsg*>(&request->logClearMsg);
349 
350     PacketBuf respondRaw = {0};
351     LogClearResponse* respond = reinterpret_cast<LogClearResponse*>(respondRaw.data());
352     LogClearResult* respondMsg = reinterpret_cast<LogClearResult*>(&respond->logClearRst);
353 
354     uint32_t recvMsgLen = 0;
355     uint32_t respondMsgNum = 0;
356 
357     if (request->msgHeader.msgLen > sizeof(LogClearMsg) * LOG_TYPE_MAX) {
358         return;
359     }
360 
361     while (requestMsg && recvMsgLen + sizeof(LogClearMsg) <= request->msgHeader.msgLen) {
362         if ((respondMsgNum + 1) * sizeof(LogClearResult) + sizeof(MessageHeader) > respondRaw.size()) {
363             break;
364         }
365         int32_t rst = m_hilogBuffer.Delete(requestMsg->logType);
366         if (respondMsg) {
367             respondMsg->logType = requestMsg->logType;
368             respondMsg->result = (rst < 0) ? rst : RET_SUCCESS;
369             respondMsg++;
370         }
371         requestMsg++;
372         recvMsgLen += sizeof(LogClearMsg);
373         respondMsgNum++;
374     }
375 
376     uint16_t respondMsgSize = respondMsgNum * sizeof(LogClearResult);
377     SetMsgHead(respond->msgHeader, MC_RSP_LOG_CLEAR, respondMsgSize);
378     m_communicationSocket->Write(respondRaw.data(), respondMsgSize + sizeof(MessageHeader));
379 }
380 
381 
ServiceController(std::unique_ptr<Socket> communicationSocket,HilogBuffer & buffer)382 ServiceController::ServiceController(std::unique_ptr<Socket> communicationSocket, HilogBuffer& buffer)
383     : m_communicationSocket(std::move(communicationSocket))
384     , m_hilogBuffer(buffer)
385 {
386     m_bufReader = m_hilogBuffer.CreateBufReader([this]() { NotifyForNewData(); });
387 }
388 
~ServiceController()389 ServiceController::~ServiceController()
390 {
391     m_hilogBuffer.RemoveBufReader(m_bufReader);
392 
393     m_notifyNewDataCv.notify_all();
394 }
395 
CommunicationLoop(const std::atomic<bool> & stopLoop)396 void ServiceController::CommunicationLoop(const std::atomic<bool>& stopLoop)
397 {
398     std::cout << __PRETTY_FUNCTION__ << " Begin\n";
399     if (!m_communicationSocket) {
400         std::cerr << __PRETTY_FUNCTION__ << " Invalid socket handler!\n";
401         return;
402     }
403     PacketBuf rawDataBuffer = {0};
404 ;
405     while (!stopLoop.load() && m_communicationSocket->Read(rawDataBuffer.data(), rawDataBuffer.size() - 1) > 0) {
406         MessageHeader *header = reinterpret_cast<MessageHeader *>(rawDataBuffer.data());
407         switch (header->msgType) {
408             case LOG_QUERY_REQUEST:
409                 SetFilters(rawDataBuffer);
410                 if (IsLogTypeForbidden(m_filters.inclusions.types)) {
411                     return;
412                 }
413                 HandleLogQueryRequest();
414                 break;
415             case NEXT_REQUEST:
416                 HandleNextRequest(rawDataBuffer, stopLoop);
417                 break;
418             case MC_REQ_LOG_PERSIST_START:
419                 HandlePersistStartRequest(rawDataBuffer);
420                 break;
421             case MC_REQ_LOG_PERSIST_STOP:
422                 HandlePersistStopRequest(rawDataBuffer);
423                 break;
424             case MC_REQ_LOG_PERSIST_QUERY:
425                 HandlePersistQueryRequest(rawDataBuffer);
426                 break;
427             case MC_REQ_BUFFER_RESIZE:
428                 HandleBufferResizeRequest(rawDataBuffer);
429                 break;
430             case MC_REQ_BUFFER_SIZE:
431                 HandleBufferSizeRequest(rawDataBuffer);
432                 break;
433             case MC_REQ_STATISTIC_INFO_QUERY:
434                 HandleInfoQueryRequest(rawDataBuffer);
435                 break;
436             case MC_REQ_STATISTIC_INFO_CLEAR:
437                 HandleInfoClearRequest(rawDataBuffer);
438                 break;
439             case MC_REQ_LOG_CLEAR:
440                 HandleBufferClearRequest(rawDataBuffer);
441                 break;
442             default:
443                 std::cout << __PRETTY_FUNCTION__ << " Unknown message. Skipped!\n";
444                 break;
445         }
446     }
447     std::cout << __PRETTY_FUNCTION__ << " Done\n";
448 }
449 
SetFilters(const PacketBuf & rawData)450 void ServiceController::SetFilters(const PacketBuf& rawData)
451 {
452     const LogQueryRequest& qRstMsg = *reinterpret_cast<const LogQueryRequest*>(rawData.data());
453     m_filters.inclusions.levels = qRstMsg.levels;
454     m_filters.inclusions.types = qRstMsg.types;
455 
456     m_filters.inclusions.pids.resize(std::min(qRstMsg.nPid, static_cast<uint8_t>(MAX_PIDS)));
457     std::copy(qRstMsg.pids, qRstMsg.pids+m_filters.inclusions.pids.size(), m_filters.inclusions.pids.begin());
458 
459     m_filters.inclusions.domains.resize(std::min(qRstMsg.nDomain, static_cast<uint8_t>(MAX_DOMAINS)));
460     std::copy(qRstMsg.domains, qRstMsg.domains+m_filters.inclusions.domains.size(),
461         m_filters.inclusions.domains.begin());
462 
463     m_filters.inclusions.tags.resize(std::min(qRstMsg.nTag, static_cast<uint8_t>(MAX_TAGS)));
464     for (size_t i = 0; i < m_filters.inclusions.tags.size(); ++i) {
465         m_filters.inclusions.tags[i] = qRstMsg.tags[i];
466     }
467 
468     m_filters.exclusions.levels = qRstMsg.noLevels;
469     m_filters.exclusions.types = qRstMsg.noTypes;
470 
471     m_filters.exclusions.pids.resize(std::min(qRstMsg.nNoPid, static_cast<uint8_t>(MAX_PIDS)));
472     std::copy(qRstMsg.noPids, qRstMsg.noPids+m_filters.exclusions.pids.size(), m_filters.exclusions.pids.begin());
473 
474     m_filters.exclusions.domains.resize(std::min(qRstMsg.nNoDomain, static_cast<uint8_t>(MAX_DOMAINS)));
475     std::copy(qRstMsg.noDomains, qRstMsg.noDomains+m_filters.exclusions.domains.size(),
476         m_filters.exclusions.domains.begin());
477 
478     m_filters.exclusions.tags.resize(std::min(qRstMsg.nNoTag, static_cast<uint8_t>(MAX_TAGS)));
479     for (size_t i = 0; i < m_filters.exclusions.tags.size(); ++i) {
480         m_filters.exclusions.tags[i] = qRstMsg.noTags[i];
481     }
482 }
483 
HandleLogQueryRequest()484 void ServiceController::HandleLogQueryRequest()
485 {
486     auto result = m_hilogBuffer.Query(m_filters, m_bufReader, [this](const HilogData& logData) {
487         WriteLogQueryRespond(SENDIDA, LOG_QUERY_RESPONSE, logData);
488     });
489     if (!result) {
490         WriteLogQueryRespond(SENDIDN, LOG_QUERY_RESPONSE, std::nullopt);
491     }
492 }
493 
HandleNextRequest(const PacketBuf & rawData,const std::atomic<bool> & stopLoop)494 void ServiceController::HandleNextRequest(const PacketBuf& rawData, const std::atomic<bool>& stopLoop)
495 {
496     const NextRequest& nRstMsg = *reinterpret_cast<const NextRequest*>(rawData.data());
497     if (nRstMsg.sendId != SENDIDA) {
498         return;
499     }
500 
501     auto result = m_hilogBuffer.Query(m_filters, m_bufReader, [this](const HilogData& logData) {
502         WriteLogQueryRespond(SENDIDA, NEXT_RESPONSE, logData);
503     });
504     if (!result) {
505         WriteLogQueryRespond(SENDIDN, NEXT_RESPONSE, std::nullopt);
506     } else {
507         return;
508     }
509 
510     std::unique_lock<decltype(m_notifyNewDataMtx)> ul(m_notifyNewDataMtx);
511     for (;;) {
512         bool isStopped = stopLoop.load();
513         if (isStopped) {
514             return;
515         }
516 
517         bool isNotified = m_notifyNewDataCv.wait_for(ul, 100ms) == std::cv_status::no_timeout;
518         if (isNotified) {
519             break;
520         }
521     }
522     LogQueryResponse rsp;
523     rsp.data.sendId = SENDIDS;
524     rsp.data.type = -1;
525     /* set header */
526     SetMsgHead(rsp.header, NEXT_RESPONSE, sizeof(rsp));
527     if (WriteData(rsp, std::nullopt) <= 0) {
528         std::cerr << __PRETTY_FUNCTION__ << " Can't send notification about new logs\n";
529     }
530 }
531 
WriteLogQueryRespond(unsigned int sendId,uint32_t respondCmd,OptCRef<HilogData> pData)532 int ServiceController::WriteLogQueryRespond(unsigned int sendId, uint32_t respondCmd, OptCRef<HilogData> pData)
533 {
534     LogQueryResponse rsp;
535     MessageHeader& header = rsp.header;
536     HilogDataMessage& msg = rsp.data;
537 
538     /* set header */
539     SetMsgHead(header, respondCmd, sizeof(rsp) + ((pData != std::nullopt) ? pData->get().len : 0));
540 
541     /* set data */
542     msg.sendId = sendId;
543     if (pData != std::nullopt) {
544         const HilogData& data = pData->get();
545         msg.length = data.len; /* data len, equals tag_len plus content length, include '\0' */
546         msg.level = data.level;
547         msg.type = data.type;
548         msg.tag_len = data.tag_len; /* include '\0' */
549         msg.pid = data.pid;
550         msg.tid = data.tid;
551         msg.domain = data.domain;
552         msg.tv_sec = data.tv_sec;
553         msg.tv_nsec = data.tv_nsec;
554     }
555 
556     /* write into socket */
557     return WriteData(rsp, pData);
558 }
559 
WriteData(LogQueryResponse & rsp,OptCRef<HilogData> pData)560 int ServiceController::WriteData(LogQueryResponse& rsp, OptCRef<HilogData> pData)
561 {
562     iovec vec[3];
563     vec[0].iov_base = &rsp;
564     vec[0].iov_len = sizeof(LogQueryResponse);
565     if (pData == std::nullopt) {
566         return WriteV(vec, 1);
567     }
568     const HilogData& data = pData->get();
569     vec[1].iov_base = data.tag;
570     vec[1].iov_len = data.tag_len;
571     vec[2].iov_base = data.content;
572     vec[2].iov_len = data.len - data.tag_len;
573 
574     return WriteV(vec, 3);
575 }
576 
WriteV(const iovec * vec,size_t len)577 int ServiceController::WriteV(const iovec* vec, size_t len)
578 {
579     static thread_local std::vector<char> dataBuf;
580 
581     size_t allSize = 0;
582     for (size_t i = 0; i < len; ++i) {
583         allSize += vec[i].iov_len;
584     }
585 
586     if (dataBuf.size() < allSize) {
587         dataBuf.resize(allSize);
588     }
589 
590     uint32_t offset = 0;
591     for (uint32_t i = 0; i < len; ++i) {
592         auto src_address = (char*)vec[i].iov_base;
593         std::copy(src_address, src_address + vec[i].iov_len, dataBuf.data() + offset);
594         offset += vec[i].iov_len;
595     }
596     return m_communicationSocket->Write(dataBuf.data(), allSize);
597 }
598 
NotifyForNewData()599 void ServiceController::NotifyForNewData()
600 {
601     m_notifyNewDataCv.notify_one();
602 }
603 
RestorePersistJobs(HilogBuffer & hilogBuffer)604 int RestorePersistJobs(HilogBuffer& hilogBuffer)
605 {
606     std::cout << __PRETTY_FUNCTION__ << " Start restoring persist jobs!\n";
607     DIR *dir = opendir(g_logPersisterDir.c_str());
608     struct dirent *ent = nullptr;
609     if (dir != nullptr) {
610         while ((ent = readdir(dir)) != nullptr) {
611             size_t length = strlen(ent->d_name);
612             std::string pPath(ent->d_name, length);
613             if (length >= INFO_SUFFIX && pPath.substr(length - INFO_SUFFIX, length) == ".info") {
614                 if (pPath == "hilog.info") continue;
615                 std::cout << __PRETTY_FUNCTION__ << " Found a persist job! Path: " << g_logPersisterDir + pPath << "\n";
616                 FILE* infile = fopen((g_logPersisterDir + pPath).c_str(), "r");
617                 if (infile == nullptr) {
618                     std::cerr << __PRETTY_FUNCTION__ << " Error opening recovery info file!\n";
619                     continue;
620                 }
621                 LogPersister::InitData initData = PersistRecoveryInfo();
622                 auto& info = std::get<PersistRecoveryInfo>(initData);
623                 fread(&info, sizeof(PersistRecoveryInfo), 1, infile);
624                 uint64_t hashSum = 0L;
625                 fread(&hashSum, sizeof(hashSum), 1, infile);
626                 fclose(infile);
627                 uint64_t hash = GenerateHash(info);
628                 if (hash != hashSum) {
629                     std::cout << __PRETTY_FUNCTION__ << " Info file checksum Failed!\n";
630                     continue;
631                 }
632                 int result = StartPersistStoreJob(initData, hilogBuffer);
633                 std::cout << __PRETTY_FUNCTION__ << " Recovery Info:\n"
634                     << "  restoring result: " << (result == RET_SUCCESS
635                         ? std::string("Success\n")
636                         : std::string("Failed(") + std::to_string(result) + ")\n")
637                     << "  jobId=" << (unsigned)(info.msg.jobId) << "\n"
638                     << "  filePath=" << (info.msg.filePath) << "\n"
639                     << "  index=" << (info.index) << "\n";
640             }
641         }
642         closedir(dir);
643     } else {
644         perror("Failed to open persister directory!");
645         return ERR_LOG_PERSIST_DIR_OPEN_FAIL;
646     }
647     std::cout << __PRETTY_FUNCTION__ << " Finished restoring persist jobs!\n";
648     return EXIT_SUCCESS;
649 }
650 } // namespace HiviewDFX
651 } // namespace OHOS
652