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