• 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 #include <algorithm>
16 #include <array>
17 #include <chrono>
18 #include <cstdio>
19 #include <cstring>
20 #include <ctime>
21 #include <fcntl.h>
22 #include <iostream>
23 #include <memory>
24 #include <optional>
25 #include <regex>
26 #include <sstream>
27 #include <sys/mman.h>
28 #include <sys/prctl.h>
29 #include <sys/stat.h>
30 #include <thread>
31 #include <unistd.h>
32 #include <dirent.h>
33 
34 #include <securec.h>
35 #include <hilog/log.h>
36 #include <hilog_common.h>
37 #include <log_utils.h>
38 #include <properties.h>
39 
40 #include "log_data.h"
41 #include "log_buffer.h"
42 #include "log_kmsg.h"
43 
44 #include "service_controller.h"
45 
46 namespace OHOS {
47 namespace HiviewDFX {
48 using namespace std;
49 static const string LOG_PERSISTER_DIR = HILOG_FILE_DIR;
50 static constexpr uint16_t DEFAULT_LOG_TYPES = ((0b01 << LOG_APP) | (0b01 << LOG_CORE) | (0b01 << LOG_INIT));
51 static constexpr uint16_t DEFAULT_REMOVE_LOG_TYPES = ((0b01 << LOG_APP) | (0b01 << LOG_CORE));
52 static constexpr uint32_t DEFAULT_PERSIST_FILE_NUM = 10;
53 static constexpr uint32_t DEFAULT_PERSIST_FILE_SIZE = (4 * 1024 * 1024);
54 static constexpr uint32_t DEFAULT_PERSIST_NORMAL_JOB_ID = 1;
55 static constexpr uint32_t DEFAULT_PERSIST_KMSG_JOB_ID = 2;
56 static constexpr int INFO_SUFFIX = 5;
57 static const uid_t SHELL_UID = 2000;
58 static const uid_t ROOT_UID = 0;
59 
ServiceController(std::unique_ptr<Socket> communicationSocket,LogCollector & collector,HilogBuffer & buffer)60 ServiceController::ServiceController(std::unique_ptr<Socket> communicationSocket,
61     LogCollector& collector, HilogBuffer& buffer)
62     : m_communicationSocket(std::move(communicationSocket))
63     , m_logCollector(collector)
64     , m_hilogBuffer(buffer)
65 {
66     m_bufReader = m_hilogBuffer.CreateBufReader([this]() { NotifyForNewData(); });
67 }
68 
~ServiceController()69 ServiceController::~ServiceController()
70 {
71     m_hilogBuffer.RemoveBufReader(m_bufReader);
72     m_notifyNewDataCv.notify_all();
73 }
74 
IsValidFileName(const std::string & strFileName)75 inline bool IsValidFileName(const std::string& strFileName)
76 {
77     // File name shouldn't contain "[\\/:*?\"<>|]"
78     std::regex regExpress("[\\/:*?\"<>|]");
79     bool bValid = !std::regex_search(strFileName, regExpress);
80     return bValid;
81 }
82 
GetMsgHeader(MsgHeader & hdr)83 int ServiceController::GetMsgHeader(MsgHeader& hdr)
84 {
85     if (!m_communicationSocket) {
86         std::cerr << " Invalid socket handler!" << std::endl;
87         return RET_FAIL;
88     }
89     int ret = m_communicationSocket->Read(reinterpret_cast<char *>(&hdr), sizeof(MsgHeader));
90     if (ret < static_cast<int>(sizeof(MsgHeader))) {
91         std::cerr << "Read MsgHeader error!" << std::endl;
92         return RET_FAIL;
93     }
94     return RET_SUCCESS;
95 }
96 
GetRqst(const MsgHeader & hdr,char * rqst,int expectedLen)97 int ServiceController::GetRqst(const MsgHeader& hdr, char* rqst, int expectedLen)
98 {
99     if (hdr.len !=  expectedLen) {
100         std::cout << "Invalid MsgHeader! hdr.len:" << hdr.len << ", expectedLen:" << expectedLen << endl;
101         return RET_FAIL;
102     }
103     int ret = m_communicationSocket->Read(rqst, hdr.len);
104     if (ret <= 0) {
105         std::cout << "Read socket error! " << ret << endl;
106         return RET_FAIL;
107     }
108     return RET_SUCCESS;
109 }
110 
WriteRspHeader(IoctlCmd cmd,size_t len)111 void ServiceController::WriteRspHeader(IoctlCmd cmd, size_t len)
112 {
113     MsgHeader header = {MSG_VER, static_cast<uint8_t>(cmd), 0, static_cast<uint16_t>(len)};
114     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&header), sizeof(MsgHeader));
115     return;
116 }
117 
WriteErrorRsp(int code)118 void ServiceController::WriteErrorRsp(int code)
119 {
120     MsgHeader header = {MSG_VER, static_cast<uint8_t>(IoctlCmd::RSP_ERROR), code, 0};
121     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&header), sizeof(MsgHeader));
122     return;
123 }
124 
WriteQueryResponse(OptCRef<HilogData> pData)125 int ServiceController::WriteQueryResponse(OptCRef<HilogData> pData)
126 {
127     OutputRsp rsp;
128     if (pData == std::nullopt) {
129         rsp.end = true; // tell client it's the last messsage
130         return m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
131     }
132     const HilogData& data = pData->get();
133     rsp.len = data.len; /* data len, equals tag_len plus content length, include '\0' */
134     rsp.level = data.level;
135     rsp.type = data.type;
136     rsp.tagLen = data.tag_len; /* include '\0' */
137     rsp.pid = data.pid;
138     rsp.tid = data.tid;
139     rsp.domain = data.domain;
140     rsp.tv_sec = data.tv_sec;
141     rsp.tv_nsec = data.tv_nsec;
142     rsp.mono_sec = data.mono_sec;
143     rsp.end = false;
144     static const int vec_num = 2;
145     iovec vec[vec_num];
146     vec[0].iov_base = &rsp;
147     vec[0].iov_len = sizeof(OutputRsp);
148     vec[1].iov_base = data.tag;
149     vec[1].iov_len = data.len;
150     return m_communicationSocket->WriteV(vec, vec_num);
151 }
152 
StatsEntry2StatsRsp(const StatsEntry & entry,StatsRsp & rsp)153 static void StatsEntry2StatsRsp(const StatsEntry &entry, StatsRsp &rsp)
154 {
155     // can't use std::copy, because StatsRsp is a packet struct
156     int i = 0;
157     for (i = 0; i < LevelNum; i++) {
158         rsp.lines[i] = entry.lines[i];
159         rsp.len[i] = entry.len[i];
160     }
161     rsp.dropped = entry.dropped;
162     rsp.freqMax = entry.GetFreqMax();
163     rsp.freqMaxSec = entry.realTimeFreqMax.tv_sec;
164     rsp.freqMaxNsec = entry.realTimeFreqMax.tv_nsec;
165     rsp.throughputMax = entry.GetThroughputMax();
166     rsp.tpMaxSec = entry.realTimeThroughputMax.tv_sec;
167     rsp.tpMaxNsec = entry.realTimeThroughputMax.tv_nsec;
168 }
169 
SendOverallStats(const LogStats & stats)170 void ServiceController::SendOverallStats(const LogStats& stats)
171 {
172     StatsQueryRsp rsp;
173     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
174     const PidTable& pTable = stats.GetPidTable();
175     const LogTimeStamp tsBegin = stats.GetBeginTs();
176     rsp.tsBeginSec = tsBegin.tv_sec;
177     rsp.tsBeginNsec = tsBegin.tv_nsec;
178     const LogTimeStamp monoBegin = stats.GetBeginMono();
179     LogTimeStamp monoNow(CLOCK_MONOTONIC);
180     monoNow -= monoBegin;
181     rsp.durationSec = monoNow.tv_sec;
182     rsp.durationNsec = monoNow.tv_nsec;
183     stats.GetTotalLines(rsp.totalLines);
184     stats.GetTotalLens(rsp.totalLens);
185     rsp.typeNum = 0;
186     for (const DomainTable &dt : ldTable) {
187         if (dt.size() == 0) {
188             continue;
189         }
190         rsp.typeNum++;
191     }
192     rsp.ldStats = nullptr;
193     rsp.procNum = pTable.size();
194     rsp.pStats = nullptr;
195     m_communicationSocket->Write(reinterpret_cast<char *>(&rsp), sizeof(StatsQueryRsp));
196 }
197 
SendLogTypeDomainStats(const LogStats & stats)198 void ServiceController::SendLogTypeDomainStats(const LogStats& stats)
199 {
200     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
201     int typeNum = 0;
202     for (const DomainTable &dt : ldTable) {
203         if (dt.size() == 0) {
204             continue;
205         }
206         typeNum++;
207     }
208     int msgSize = typeNum * sizeof(LogTypeDomainStatsRsp);
209     if (msgSize == 0) {
210         return;
211     }
212     char* tmp = new (std::nothrow) char[msgSize];
213     if (tmp == nullptr) {
214         return;
215     }
216     if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
217         delete []tmp;
218         tmp = nullptr;
219         return;
220     }
221     LogTypeDomainStatsRsp *ldStats = reinterpret_cast<LogTypeDomainStatsRsp *>(tmp);
222     int i = 0;
223     int j = 0;
224     for (const DomainTable &dt : ldTable) {
225         j++;
226         if (dt.size() == 0) {
227             continue;
228         }
229         ldStats[i].type = (j - 1);
230         ldStats[i].domainNum = dt.size();
231         i++;
232     }
233     m_communicationSocket->Write(tmp, msgSize);
234     delete []tmp;
235     tmp = nullptr;
236 }
237 
SendDomainStats(const LogStats & stats)238 void ServiceController::SendDomainStats(const LogStats& stats)
239 {
240     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
241     for (const DomainTable &dt : ldTable) {
242         if (dt.size() == 0) {
243             continue;
244         }
245         int msgSize = dt.size() * sizeof(DomainStatsRsp);
246         char *tmp = new (std::nothrow) char[msgSize];
247         if (tmp == nullptr) {
248             return;
249         }
250         if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
251             delete []tmp;
252             tmp = nullptr;
253             return;
254         }
255         DomainStatsRsp *dStats = reinterpret_cast<DomainStatsRsp *>(tmp);
256         int i = 0;
257         for (auto &it : dt) {
258             dStats[i].domain = it.first;
259             if (!stats.IsTagEnable()) {
260                 dStats[i].tagNum = 0;
261             } else {
262                 dStats[i].tagNum = it.second.tagStats.size();
263             }
264             if (dStats[i].tagNum == 0) {
265                 dStats[i].tStats = nullptr;
266             }
267             StatsEntry2StatsRsp(it.second.stats, dStats[i].stats);
268             i++;
269         }
270         m_communicationSocket->Write(tmp, msgSize);
271         delete []tmp;
272         tmp = nullptr;
273     }
274 }
275 
SendDomainTagStats(const LogStats & stats)276 void ServiceController::SendDomainTagStats(const LogStats& stats)
277 {
278     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
279     for (const DomainTable &dt : ldTable) {
280         if (dt.size() == 0) {
281             continue;
282         }
283         for (auto &it : dt) {
284             SendTagStats(it.second.tagStats);
285         }
286     }
287 }
288 
SendProcStats(const LogStats & stats)289 void ServiceController::SendProcStats(const LogStats& stats)
290 {
291     const PidTable& pTable = stats.GetPidTable();
292     int msgSize =  pTable.size() * sizeof(ProcStatsRsp);
293     if (msgSize == 0) {
294         return;
295     }
296     char* tmp = new (std::nothrow) char[msgSize];
297     if (tmp == nullptr) {
298         return;
299     }
300     if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
301         delete []tmp;
302         tmp = nullptr;
303         return;
304     }
305     ProcStatsRsp *pStats = reinterpret_cast<ProcStatsRsp *>(tmp);
306     int i = 0;
307     for (auto &it : pTable) {
308         ProcStatsRsp &procStats = pStats[i];
309         i++;
310         procStats.pid = it.first;
311         if (strncpy_s(procStats.name, MAX_PROC_NAME_LEN, it.second.name.c_str(), MAX_PROC_NAME_LEN - 1) != 0) {
312             continue;
313         }
314         StatsEntry2StatsRsp(it.second.statsAll, procStats.stats);
315         procStats.typeNum = 0;
316         for (auto &itt : it.second.stats) {
317             if (itt.GetTotalLines() == 0) {
318                 continue;
319             }
320             procStats.typeNum++;
321         }
322         if (!stats.IsTagEnable()) {
323             procStats.tagNum = 0;
324         } else {
325             procStats.tagNum = it.second.tagStats.size();
326         }
327         if (procStats.tagNum == 0) {
328             procStats.tStats = nullptr;
329         }
330     }
331     m_communicationSocket->Write(tmp, msgSize);
332     delete []tmp;
333     tmp = nullptr;
334 }
335 
SendProcLogTypeStats(const LogStats & stats)336 void ServiceController::SendProcLogTypeStats(const LogStats& stats)
337 {
338     const PidTable& pTable = stats.GetPidTable();
339     for (auto &it : pTable) {
340         int typeNum = 0;
341         for (auto &itt : it.second.stats) {
342             if (itt.GetTotalLines() == 0) {
343                 continue;
344             }
345             typeNum++;
346         }
347         int msgSize =  typeNum * sizeof(LogTypeStatsRsp);
348         if (msgSize == 0) {
349             return;
350         }
351         char* tmp = new (std::nothrow) char[msgSize];
352         if (tmp == nullptr) {
353             return;
354         }
355         if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
356             delete []tmp;
357             tmp = nullptr;
358             return;
359         }
360         LogTypeStatsRsp *lStats = reinterpret_cast<LogTypeStatsRsp *>(tmp);
361         int i = 0;
362         int j = 0;
363         for (auto &itt : it.second.stats) {
364             j++;
365             if (itt.GetTotalLines() == 0) {
366                 continue;
367             }
368             LogTypeStatsRsp &logTypeStats = lStats[i];
369             logTypeStats.type = (j - 1);
370             StatsEntry2StatsRsp(itt, logTypeStats.stats);
371             i++;
372         }
373         m_communicationSocket->Write(tmp, msgSize);
374         delete []tmp;
375         tmp = nullptr;
376     }
377 }
378 
SendProcTagStats(const LogStats & stats)379 void ServiceController::SendProcTagStats(const LogStats& stats)
380 {
381     const PidTable& pTable = stats.GetPidTable();
382     for (auto &it : pTable) {
383         SendTagStats(it.second.tagStats);
384     }
385 }
386 
SendTagStats(const TagTable & tagTable)387 void ServiceController::SendTagStats(const TagTable &tagTable)
388 {
389     int msgSize =  tagTable.size() * sizeof(TagStatsRsp);
390     if (msgSize == 0) {
391         return;
392     }
393     char* tmp = new (std::nothrow) char[msgSize];
394     if (tmp == nullptr) {
395         return;
396     }
397     if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
398         delete []tmp;
399         tmp = nullptr;
400         return;
401     }
402     TagStatsRsp *tStats = reinterpret_cast<TagStatsRsp *>(tmp);
403     int i = 0;
404     for (auto &itt : tagTable) {
405         TagStatsRsp &tagStats = tStats[i];
406         if (strncpy_s(tagStats.tag, MAX_TAG_LEN, itt.first.c_str(), MAX_TAG_LEN - 1) != 0) {
407             continue;
408         }
409         i++;
410         StatsEntry2StatsRsp(itt.second, tagStats.stats);
411     }
412     m_communicationSocket->Write(tmp, msgSize);
413     delete []tmp;
414     tmp = nullptr;
415 }
416 
CheckOutputRqst(const OutputRqst & rqst)417 int ServiceController::CheckOutputRqst(const OutputRqst& rqst)
418 {
419     if (((rqst.types & (0b01 << LOG_KMSG)) != 0) && (GetBitsCount(rqst.types) > 1)) {
420         return ERR_QUERY_TYPE_INVALID;
421     }
422     if (rqst.domainCount > MAX_DOMAINS) {
423         return ERR_TOO_MANY_DOMAINS;
424     }
425     if (rqst.tagCount > MAX_TAGS) {
426         return ERR_TOO_MANY_TAGS;
427     }
428     if (rqst.pidCount > MAX_PIDS) {
429         return ERR_TOO_MANY_PIDS;
430     }
431     // Check Uid permission
432     uid_t uid = m_communicationSocket->GetUid();
433     if (uid != ROOT_UID && uid != SHELL_UID && rqst.pidCount > 0) {
434         return ERR_NO_PID_PERMISSION;
435     }
436     return RET_SUCCESS;
437 }
438 
LogFilterFromOutputRqst(const OutputRqst & rqst,LogFilter & filter)439 void ServiceController::LogFilterFromOutputRqst(const OutputRqst& rqst, LogFilter& filter)
440 {
441     if (rqst.types == 0) {
442         filter.types = DEFAULT_LOG_TYPES;
443     } else {
444         filter.types = rqst.types;
445     }
446     if (rqst.levels == 0) {
447         filter.levels = ~rqst.levels; // 0 means all
448     } else {
449         filter.levels = rqst.levels;
450     }
451     int i;
452     filter.blackDomain = rqst.blackDomain;
453     filter.domainCount = rqst.domainCount;
454     for (i = 0; i < rqst.domainCount; i++) {
455         filter.domains[i] = rqst.domains[i];
456     }
457     filter.blackTag = rqst.blackTag;
458     filter.tagCount = rqst.tagCount;
459     for (i = 0; i < rqst.tagCount; i++) {
460         (void)strncpy_s(filter.tags[i], MAX_TAG_LEN, rqst.tags[i], MAX_TAG_LEN - 1);
461     }
462     filter.blackPid = rqst.blackPid;
463     filter.pidCount = rqst.pidCount;
464     for (i = 0; i < rqst.pidCount; i++) {
465         filter.pids[i] = rqst.pids[i];
466     }
467     (void)strncpy_s(filter.regex, MAX_REGEX_STR_LEN, rqst.regex, MAX_REGEX_STR_LEN - 1);
468     filter.Print();
469     // Permission check
470     uid_t uid = m_communicationSocket->GetUid();
471     uint32_t pid = static_cast<uint32_t>(m_communicationSocket->GetPid());
472     if (uid != ROOT_UID && uid != SHELL_UID) {
473         filter.blackPid = false;
474         filter.pidCount = 1;
475         filter.pids[0] = pid;
476         uint32_t ppid = GetPPidByPid(pid);
477         if (ppid > 0) {
478             filter.pidCount++;
479             filter.pids[1] = ppid;
480         }
481     }
482 }
483 
HandleOutputRqst(const OutputRqst & rqst)484 void ServiceController::HandleOutputRqst(const OutputRqst &rqst)
485 {
486     // check OutputRqst
487     int ret = CheckOutputRqst(rqst);
488     if (ret != RET_SUCCESS) {
489         WriteErrorRsp(ret);
490         return;
491     }
492     LogFilter filter = {0};
493     LogFilterFromOutputRqst(rqst, filter);
494     int lines = rqst.headLines ? rqst.headLines : rqst.tailLines;
495     int tailCount = rqst.tailLines;
496     int linesCountDown = lines;
497 
498     WriteRspHeader(IoctlCmd::OUTPUT_RSP, sizeof(OutputRsp));
499     for (;;) {
500         std::optional<HilogData> data = m_hilogBuffer.Query(filter, m_bufReader, tailCount);
501         if (!data.has_value()) {
502             if (rqst.noBlock) {
503                 // reach the end of buffer and don't block
504                 (void)WriteQueryResponse(std::nullopt);
505                 break;
506             }
507             std::unique_lock<decltype(m_notifyNewDataMtx)> ul(m_notifyNewDataMtx);
508             m_notifyNewDataCv.wait(ul);
509             continue;
510         }
511         int ret = WriteQueryResponse(data.value());
512         if (ret < 0) { // write socket failed, it means that client has disconnected
513             std::cerr << "Client disconnect" << std::endl;
514             break;
515         }
516         if (lines && (--linesCountDown) <= 0) {
517             (void)WriteQueryResponse(std::nullopt);
518             sleep(1); // let client receive all messages and exit gracefully
519             break;
520         }
521     }
522 }
523 
CheckPersistStartRqst(const PersistStartRqst & rqst)524 int ServiceController::CheckPersistStartRqst(const PersistStartRqst &rqst)
525 {
526     // check OutputFilter
527     int ret = CheckOutputRqst(rqst.outputFilter);
528     if (ret != RET_SUCCESS) {
529         return ret;
530     }
531     if (rqst.jobId && (rqst.jobId < JOB_ID_MIN || rqst.jobId == JOB_ID_MAX)) {
532         return ERR_LOG_PERSIST_JOBID_INVALID;
533     }
534     if (rqst.fileSize && (rqst.fileSize < MIN_LOG_FILE_SIZE || rqst.fileSize > MAX_LOG_FILE_SIZE)) {
535         return ERR_LOG_PERSIST_FILE_SIZE_INVALID;
536     }
537     if (rqst.fileName[0] && IsValidFileName(rqst.fileName) == false) {
538         return ERR_LOG_PERSIST_FILE_NAME_INVALID;
539     }
540     if (rqst.fileNum && (rqst.fileNum > MAX_LOG_FILE_NUM || rqst.fileNum < MIN_LOG_FILE_NUM)) {
541         return ERR_LOG_FILE_NUM_INVALID;
542     }
543     return RET_SUCCESS;
544 }
545 
PersistStartRqst2Msg(const PersistStartRqst & rqst,LogPersistStartMsg & msg)546 void ServiceController::PersistStartRqst2Msg(const PersistStartRqst &rqst, LogPersistStartMsg &msg)
547 {
548     LogFilterFromOutputRqst(rqst.outputFilter, msg.filter);
549     bool isKmsgType = rqst.outputFilter.types == (0b01 << LOG_KMSG);
550     msg.compressAlg = LogCompress::Str2CompressType(rqst.stream);
551     msg.fileSize = rqst.fileSize == 0 ? DEFAULT_PERSIST_FILE_SIZE : rqst.fileSize;
552     msg.fileNum = rqst.fileNum == 0 ? DEFAULT_PERSIST_FILE_NUM : rqst.fileNum;
553     msg.jobId = rqst.jobId;
554     if (msg.jobId == 0) {
555         msg.jobId = isKmsgType ? DEFAULT_PERSIST_KMSG_JOB_ID : DEFAULT_PERSIST_NORMAL_JOB_ID;
556     }
557     string fileName = rqst.fileName;
558     if (fileName == "") {
559         fileName = (isKmsgType ? "hilog_kmsg" : "hilog");
560     }
561     string filePath = LOG_PERSISTER_DIR + fileName;
562     (void)strncpy_s(msg.filePath, FILE_PATH_MAX_LEN, filePath.c_str(), filePath.length());
563 }
564 
StartPersistStoreJob(const PersistRecoveryInfo & info,HilogBuffer & hilogBuffer,bool restore)565 int StartPersistStoreJob(const PersistRecoveryInfo& info, HilogBuffer& hilogBuffer, bool restore)
566 {
567     std::shared_ptr<LogPersister> persister = LogPersister::CreateLogPersister(hilogBuffer);
568     if (persister == nullptr) {
569         return RET_FAIL;
570     }
571     int ret = persister->Init(info, restore);
572     if (ret != RET_SUCCESS) {
573         return ret;
574     }
575     persister->Start();
576     return RET_SUCCESS;
577 }
578 
HandlePersistStartRqst(const PersistStartRqst & rqst)579 void ServiceController::HandlePersistStartRqst(const PersistStartRqst &rqst)
580 {
581     int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) {
582         struct stat s;
583         if (stat(path.c_str(), &s) != -1) {
584             return RET_SUCCESS;
585         }
586         return RET_FAIL;
587     });
588     if (ret != RET_SUCCESS) {
589         WriteErrorRsp(ERR_LOG_PERSIST_FILE_PATH_INVALID);
590         return;
591     }
592     ret = CheckPersistStartRqst(rqst);
593     if (ret != RET_SUCCESS) {
594         WriteErrorRsp(ret);
595         return;
596     }
597     list<LogPersistQueryResult> resultList;
598     LogPersister::Query(resultList);
599     if (resultList.size() >= MAX_JOBS) {
600         WriteErrorRsp(ERR_TOO_MANY_JOBS);
601         return;
602     }
603     LogPersistStartMsg msg = { 0 };
604     PersistStartRqst2Msg(rqst, msg);
605     PersistRecoveryInfo info = {0, msg};
606     ret = StartPersistStoreJob(info, m_hilogBuffer, false);
607     if (ret != RET_SUCCESS) {
608         WriteErrorRsp(ret);
609         return;
610     }
611     PersistStartRsp rsp = { msg.jobId };
612     WriteRspHeader(IoctlCmd::PERSIST_START_RSP, sizeof(rsp));
613     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
614 }
615 
HandlePersistStopRqst(const PersistStopRqst & rqst)616 void ServiceController::HandlePersistStopRqst(const PersistStopRqst &rqst)
617 {
618     PersistStopRsp rsp = { 0 };
619     list<LogPersistQueryResult> resultList;
620     LogPersister::Query(resultList);
621     if (rqst.jobId == 0 && resultList.empty()) {
622         WriteErrorRsp(ERR_PERSIST_TASK_EMPTY);
623         return;
624     }
625     for (auto it = resultList.begin(); it != resultList.end() && rsp.jobNum < MAX_JOBS; ++it) {
626         uint32_t jobId = it->jobId;
627         if (rqst.jobId == 0 || rqst.jobId == jobId) {
628             (void)LogPersister::Kill(jobId);
629             rsp.jobId[rsp.jobNum] = jobId;
630             rsp.jobNum++;
631         }
632     }
633     if (rsp.jobNum == 0) {
634         WriteErrorRsp(ERR_JOBID_NOT_EXSIST);
635         return;
636     }
637     WriteRspHeader(IoctlCmd::PERSIST_STOP_RSP, sizeof(rsp));
638     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
639 }
640 
HandlePersistQueryRqst(const PersistQueryRqst & rqst)641 void ServiceController::HandlePersistQueryRqst(const PersistQueryRqst& rqst)
642 {
643     list<LogPersistQueryResult> resultList;
644     LogPersister::Query(resultList);
645     if (resultList.size() == 0) {
646         WriteErrorRsp(ERR_NO_RUNNING_TASK);
647         return;
648     }
649     PersistQueryRsp rsp = { 0 };
650     for (auto it = resultList.begin(); it != resultList.end() && rsp.jobNum < MAX_JOBS; ++it) {
651         PersistTaskInfo &task = rsp.taskInfo[rsp.jobNum];
652         task.jobId = it->jobId;
653         task.fileNum = it->fileNum;
654         task.fileSize = it->fileSize;
655         task.outputFilter.types = it->logType;
656         (void)strncpy_s(task.fileName, MAX_FILE_NAME_LEN, it->filePath, MAX_FILE_NAME_LEN - 1);
657         (void)strncpy_s(task.stream, MAX_STREAM_NAME_LEN,
658                         LogCompress::CompressType2Str(it->compressAlg).c_str(), MAX_STREAM_NAME_LEN - 1);
659         rsp.jobNum++;
660     }
661     WriteRspHeader(IoctlCmd::PERSIST_QUERY_RSP, sizeof(rsp));
662     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
663 }
664 
HandleBufferSizeGetRqst(const BufferSizeGetRqst & rqst)665 void ServiceController::HandleBufferSizeGetRqst(const BufferSizeGetRqst& rqst)
666 {
667     vector<uint16_t> allTypes = GetAllLogTypes();
668     uint16_t types = rqst.types;
669     if (types == 0) {
670         types = DEFAULT_LOG_TYPES;
671     }
672     int i = 0;
673     BufferSizeGetRsp rsp = { 0 };
674     for (uint16_t t : allTypes) {
675         if ((1 << t) & types) {
676             rsp.size[t] = static_cast<uint32_t>(m_hilogBuffer.GetBuffLen(t));
677             i++;
678         }
679     }
680     if (i == 0) {
681         WriteErrorRsp(ERR_LOG_TYPE_INVALID);
682         return;
683     }
684     WriteRspHeader(IoctlCmd::BUFFERSIZE_GET_RSP, sizeof(rsp));
685     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
686 }
687 
HandleBufferSizeSetRqst(const BufferSizeSetRqst & rqst)688 void ServiceController::HandleBufferSizeSetRqst(const BufferSizeSetRqst& rqst)
689 {
690     vector<uint16_t> allTypes = GetAllLogTypes();
691     uint16_t types = rqst.types;
692     if (types == 0) {
693         types = DEFAULT_LOG_TYPES;
694     }
695     int i = 0;
696     BufferSizeSetRsp rsp = { 0 };
697     for (uint16_t t : allTypes) {
698         if ((1 << t) & types) {
699             int ret = m_hilogBuffer.SetBuffLen(t, rqst.size);
700             if (ret != RET_SUCCESS) {
701                 rsp.size[t] = ret;
702             } else {
703                 SetBufferSize(t, true, rqst.size);
704                 rsp.size[t] = rqst.size;
705             }
706             i++;
707         }
708     }
709     if (i == 0) {
710         WriteErrorRsp(ERR_LOG_TYPE_INVALID);
711         return;
712     }
713     WriteRspHeader(IoctlCmd::BUFFERSIZE_SET_RSP, sizeof(rsp));
714     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
715 }
716 
HandleStatsQueryRqst(const StatsQueryRqst & rqst)717 void ServiceController::HandleStatsQueryRqst(const StatsQueryRqst& rqst)
718 {
719     LogStats& stats = m_hilogBuffer.GetStatsInfo();
720     if (!stats.IsEnable()) {
721         WriteErrorRsp(ERR_STATS_NOT_ENABLE);
722         return;
723     }
724     std::unique_lock<std::mutex> lk(stats.GetLock());
725 
726     WriteRspHeader(IoctlCmd::STATS_QUERY_RSP, sizeof(StatsQueryRsp));
727     SendOverallStats(stats);
728     SendLogTypeDomainStats(stats);
729     SendDomainStats(stats);
730     if (stats.IsTagEnable()) {
731         SendDomainTagStats(stats);
732     }
733     SendProcStats(stats);
734     SendProcLogTypeStats(stats);
735     if (stats.IsTagEnable()) {
736         SendProcTagStats(stats);
737     }
738 }
739 
HandleStatsClearRqst(const StatsClearRqst & rqst)740 void ServiceController::HandleStatsClearRqst(const StatsClearRqst& rqst)
741 {
742     m_hilogBuffer.ResetStats();
743     StatsClearRsp rsp = { 0 };
744     WriteRspHeader(IoctlCmd::STATS_CLEAR_RSP, sizeof(rsp));
745     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
746 }
747 
HandleDomainFlowCtrlRqst(const DomainFlowCtrlRqst & rqst)748 void ServiceController::HandleDomainFlowCtrlRqst(const DomainFlowCtrlRqst& rqst)
749 {
750     SetDomainSwitchOn(rqst.on);
751     m_logCollector.SetLogFlowControl(rqst.on);
752     // set domain flow control later
753     DomainFlowCtrlRsp rsp = { 0 };
754     WriteRspHeader(IoctlCmd::DOMAIN_FLOWCTRL_RSP, sizeof(rsp));
755     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
756 }
757 
HandleLogRemoveRqst(const LogRemoveRqst & rqst)758 void ServiceController::HandleLogRemoveRqst(const LogRemoveRqst& rqst)
759 {
760     vector<uint16_t> allTypes = GetAllLogTypes();
761     uint16_t types = rqst.types;
762     if (types == 0) {
763         types = DEFAULT_REMOVE_LOG_TYPES;
764     }
765     int i = 0;
766     LogRemoveRsp rsp = { types };
767     for (uint16_t t : allTypes) {
768         if ((1 << t) & types) {
769             (void)m_hilogBuffer.Delete(t);
770             i++;
771         }
772     }
773     if (i == 0) {
774         WriteErrorRsp(ERR_LOG_TYPE_INVALID);
775         return;
776     }
777     WriteRspHeader(IoctlCmd::LOG_REMOVE_RSP, sizeof(rsp));
778     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
779 }
780 
HandleLogKmsgEnableRqst(const KmsgEnableRqst & rqst)781 void ServiceController::HandleLogKmsgEnableRqst(const KmsgEnableRqst& rqst)
782 {
783     SetKmsgSwitchOn(rqst.on);
784 
785     LogKmsg& logKmsg = LogKmsg::GetInstance(m_hilogBuffer);
786     if (rqst.on) {
787         logKmsg.Start();
788     } else {
789         logKmsg.Stop();
790     }
791     // set domain flow control later
792     KmsgEnableRsp rsp = { 0 };
793     WriteRspHeader(IoctlCmd::KMSG_ENABLE_RSP, sizeof(rsp));
794     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
795 }
796 
IsValidCmd(const CmdList & list,IoctlCmd cmd)797 bool ServiceController::IsValidCmd(const CmdList& list, IoctlCmd cmd)
798 {
799     auto it = find(list.begin(), list.end(), cmd);
800     return (it != list.end());
801 }
802 
CommunicationLoop(std::atomic<bool> & stopLoop,const CmdList & list)803 void ServiceController::CommunicationLoop(std::atomic<bool>& stopLoop, const CmdList& list)
804 {
805     std::cout << "ServiceController Loop Begin" << std::endl;
806     MsgHeader hdr;
807     int ret = GetMsgHeader(hdr);
808     if (ret != RET_SUCCESS) {
809         return;
810     }
811     IoctlCmd cmd = static_cast<IoctlCmd>(hdr.cmd);
812     std::cout << "Receive cmd: " << static_cast<int>(cmd) << endl;
813     if (!IsValidCmd(list, cmd)) {
814         cout << "Not valid cmd for this executor" << endl;
815         WriteErrorRsp(ERR_INVALID_RQST_CMD);
816         return;
817     }
818     switch (cmd) {
819         case IoctlCmd::OUTPUT_RQST: {
820             RequestHandler<OutputRqst>(hdr, [this](const OutputRqst& rqst) {
821                 HandleOutputRqst(rqst);
822             });
823             break;
824         }
825         case IoctlCmd::PERSIST_START_RQST: {
826             RequestHandler<PersistStartRqst>(hdr, [this](const PersistStartRqst& rqst) {
827                 HandlePersistStartRqst(rqst);
828             });
829             break;
830         }
831         case IoctlCmd::PERSIST_STOP_RQST: {
832             RequestHandler<PersistStopRqst>(hdr, [this](const PersistStopRqst& rqst) {
833                 HandlePersistStopRqst(rqst);
834             });
835             break;
836         }
837         case IoctlCmd::PERSIST_QUERY_RQST: {
838             RequestHandler<PersistQueryRqst>(hdr, [this](const PersistQueryRqst& rqst) {
839                 HandlePersistQueryRqst(rqst);
840             });
841             break;
842         }
843         case IoctlCmd::BUFFERSIZE_GET_RQST: {
844             RequestHandler<BufferSizeGetRqst>(hdr, [this](const BufferSizeGetRqst& rqst) {
845                 HandleBufferSizeGetRqst(rqst);
846             });
847             break;
848         }
849         case IoctlCmd::BUFFERSIZE_SET_RQST: {
850             RequestHandler<BufferSizeSetRqst>(hdr, [this](const BufferSizeSetRqst& rqst) {
851                 HandleBufferSizeSetRqst(rqst);
852             });
853             break;
854         }
855         case IoctlCmd::STATS_QUERY_RQST: {
856             RequestHandler<StatsQueryRqst>(hdr, [this](const StatsQueryRqst& rqst) {
857                 HandleStatsQueryRqst(rqst);
858             });
859             break;
860         }
861         case IoctlCmd::STATS_CLEAR_RQST: {
862             RequestHandler<StatsClearRqst>(hdr, [this](const StatsClearRqst& rqst) {
863                 HandleStatsClearRqst(rqst);
864             });
865             break;
866         }
867         case IoctlCmd::DOMAIN_FLOWCTRL_RQST: {
868             RequestHandler<DomainFlowCtrlRqst>(hdr, [this](const DomainFlowCtrlRqst& rqst) {
869                 HandleDomainFlowCtrlRqst(rqst);
870             });
871             break;
872         }
873         case IoctlCmd::LOG_REMOVE_RQST: {
874             RequestHandler<LogRemoveRqst>(hdr, [this](const LogRemoveRqst& rqst) {
875                 HandleLogRemoveRqst(rqst);
876             });
877             break;
878         }
879         case IoctlCmd::KMSG_ENABLE_RQST: {
880             RequestHandler<KmsgEnableRqst>(hdr, [this](const KmsgEnableRqst& rqst) {
881                 HandleLogKmsgEnableRqst(rqst);
882             });
883             break;
884         }
885         default: {
886             std::cerr << " Unknown message. Skipped!" << endl;
887             break;
888         }
889     }
890     stopLoop.store(true);
891     std::cout << " ServiceController Loop End" << endl;
892 }
893 
NotifyForNewData()894 void ServiceController::NotifyForNewData()
895 {
896     m_notifyNewDataCv.notify_one();
897 }
898 
RestorePersistJobs(HilogBuffer & hilogBuffer)899 int RestorePersistJobs(HilogBuffer& hilogBuffer)
900 {
901     std::cout << " Start restoring persist jobs!\n";
902     DIR *dir = opendir(LOG_PERSISTER_DIR.c_str());
903     struct dirent *ent = nullptr;
904     if (dir == nullptr) {
905         perror("Failed to open persister directory!");
906         return ERR_LOG_PERSIST_DIR_OPEN_FAIL;
907     }
908     while ((ent = readdir(dir)) != nullptr) {
909         size_t length = strlen(ent->d_name);
910         std::string pPath(ent->d_name, length);
911         if (length >= INFO_SUFFIX && pPath.substr(length - INFO_SUFFIX, length) == ".info") {
912             if (pPath == "hilog.info") {
913                 continue;
914             }
915             std::cout << " Found a persist job! Path: " << LOG_PERSISTER_DIR + pPath << "\n";
916             FILE* infile = fopen((LOG_PERSISTER_DIR + pPath).c_str(), "r");
917             if (infile == nullptr) {
918                 std::cerr << " Error opening recovery info file!\n";
919                 continue;
920             }
921             PersistRecoveryInfo info = { 0 };
922             fread(&info, sizeof(PersistRecoveryInfo), 1, infile);
923             uint64_t hashSum = 0L;
924             fread(&hashSum, sizeof(hashSum), 1, infile);
925             fclose(infile);
926             uint64_t hash = GenerateHash(reinterpret_cast<char *>(&info), sizeof(PersistRecoveryInfo));
927             if (hash != hashSum) {
928                 std::cout << " Info file checksum Failed!\n";
929                 continue;
930             }
931             int result = StartPersistStoreJob(info, hilogBuffer, true);
932             std::cout << " Recovery Info:\n"
933                 << "  restoring result: " << (result == RET_SUCCESS
934                     ? std::string("Success\n")
935                     : std::string("Failed(") + std::to_string(result) + ")\n")
936                 << "  jobId=" << (unsigned)(info.msg.jobId) << "\n"
937                 << "  filePath=" << (info.msg.filePath) << "\n"
938                 << "  index=" << (info.index) << "\n";
939         }
940     }
941     closedir(dir);
942     std::cout << " Finished restoring persist jobs!\n";
943     return EXIT_SUCCESS;
944 }
945 } // namespace HiviewDFX
946 } // namespace OHOS
947