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