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