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