• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2025 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 
16 #include "hitrace_dump.h"
17 
18 #include <algorithm>
19 #include <atomic>
20 #include <cinttypes>
21 #include <csignal>
22 #include <fstream>
23 #include <map>
24 #include <memory>
25 #include <mutex>
26 #include <set>
27 #include <sys/epoll.h>
28 #include <sys/file.h>
29 #include <sys/prctl.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32 #include <thread>
33 #include <unistd.h>
34 #include <unordered_map>
35 #include <functional>
36 #include <map>
37 
38 #include "common_define.h"
39 #include "common_utils.h"
40 #include "dynamic_buffer.h"
41 #include "file_ageing_utils.h"
42 #include "hitrace_meter.h"
43 #include "hitrace_option/hitrace_option.h"
44 #include "hilog/log.h"
45 #include "parameters.h"
46 #include "securec.h"
47 #include "trace_dump_executor.h"
48 #include "trace_dump_pipe.h"
49 #include "trace_file_utils.h"
50 #include "trace_json_parser.h"
51 
52 namespace OHOS {
53 namespace HiviewDFX {
54 namespace Hitrace {
55 #ifdef LOG_DOMAIN
56 #undef LOG_DOMAIN
57 #define LOG_DOMAIN 0xD002D33
58 #endif
59 #ifdef LOG_TAG
60 #undef LOG_TAG
61 #define LOG_TAG "HitraceDump"
62 #endif
63 namespace {
64 struct TraceParams {
65     std::vector<std::string> tags;
66     std::vector<std::string> tagGroups;
67     std::vector<std::string> filterPids;
68     std::string bufferSize;
69     std::string clockType;
70     std::string isOverWrite;
71     std::string outputFile;
72     int fileLimit;
73     int fileSize;
74     int appPid;
75 };
76 
77 const int SAVED_CMDLINES_SIZE = 3072; // 3M
78 const int BYTE_PER_MB = 1024 * 1024;
79 constexpr int32_t MAX_RATIO_UNIT = 1000;
80 constexpr uint32_t DURATION_TOLERANCE = 100;
81 constexpr int DEFAULT_FULL_TRACE_LENGTH = 30;
82 constexpr uint64_t SNAPSHOT_MIN_REMAINING_SPACE = 300 * 1024 * 1024;     // 300M
83 constexpr uint64_t DEFAULT_ASYNC_TRACE_SIZE = 50 * 1024 * 1024;          // 50M
84 constexpr int HUNDRED_MILLISECONDS = 100 * 1000; // 100ms
85 constexpr int ASYNC_WAIT_EMPTY_LOOP_MS = 15 * 1000; // 15 seconds
86 
87 std::atomic<pid_t> g_traceDumpTaskPid(-1);
88 
89 std::mutex g_traceMutex;
90 bool g_serviceThreadIsStart = false;
91 uint64_t g_sysInitParamTags = 0;
92 uint8_t g_traceMode = TraceMode::CLOSE;
93 std::string g_traceRootPath;
94 uint64_t g_totalFileSizeLimit = 0;
95 uint64_t g_sliceMaxDuration = 0;
96 uint64_t g_traceStartTime = 0;
97 uint64_t g_traceEndTime = std::numeric_limits<uint64_t>::max(); // in nano seconds
98 uint64_t g_firstPageTimestamp = std::numeric_limits<uint64_t>::max();
99 uint64_t g_lastPageTimestamp = 0;
100 uint64_t g_utDestTraceStartTime = 0;
101 uint64_t g_utDestTraceEndTime = 0;
102 uint8_t g_dumpStatus(TraceErrorCode::UNSET);
103 std::vector<TraceFileInfo> g_traceFileVec{};
104 
105 TraceParams g_currentTraceParams = {};
106 
107 std::mutex g_traceRetAndCallbackMutex;
108 std::map<uint64_t, std::function<void(TraceRetInfo)>> g_callbacks;
109 std::map<uint64_t, TraceRetInfo> g_traceRetInfos;
110 
111 const std::string TELEMETRY_APP_PARAM = "debug.hitrace.telemetry.app";
112 
IsTraceOpen()113 bool IsTraceOpen()
114 {
115     return (g_traceMode & TraceMode::OPEN) != 0;
116 }
117 
IsRecordOn()118 bool IsRecordOn()
119 {
120     return (g_traceMode & TraceMode::RECORD) != 0;
121 }
122 
IsCacheOn()123 bool IsCacheOn()
124 {
125     return (g_traceMode & TraceMode::CACHE) != 0;
126 }
127 
Split(const std::string & str,char delimiter)128 std::vector<std::string> Split(const std::string& str, char delimiter)
129 {
130     std::vector<std::string> res;
131     size_t startPos = 0;
132     for (size_t i = 0; i < str.size(); i++) {
133         if (str[i] == delimiter) {
134             res.push_back(str.substr(startPos, i - startPos));
135             startPos = i + 1;
136         }
137     }
138     if (startPos < str.size()) {
139         res.push_back(str.substr(startPos));
140     }
141     return res;
142 }
143 
CheckTags(const std::vector<std::string> & tags,const std::map<std::string,TraceTag> & allTags)144 bool CheckTags(const std::vector<std::string>& tags, const std::map<std::string, TraceTag>& allTags)
145 {
146     for (const auto &tag : tags) {
147         if (allTags.find(tag) == allTags.end()) {
148             HILOG_ERROR(LOG_CORE, "CheckTags: %{public}s is not provided.", tag.c_str());
149             return false;
150         }
151     }
152     return true;
153 }
154 
CheckTagGroup(const std::vector<std::string> & tagGroups,const std::map<std::string,std::vector<std::string>> & tagGroupTable)155 bool CheckTagGroup(const std::vector<std::string>& tagGroups,
156                    const std::map<std::string, std::vector<std::string>>& tagGroupTable)
157 {
158     for (auto groupName : tagGroups) {
159         if (tagGroupTable.find(groupName) == tagGroupTable.end()) {
160             HILOG_ERROR(LOG_CORE, "CheckTagGroup: %{public}s is not provided.", groupName.c_str());
161             return false;
162         }
163     }
164     return true;
165 }
166 
WriteStrToFileInner(const std::string & filename,const std::string & str)167 bool WriteStrToFileInner(const std::string& filename, const std::string& str)
168 {
169     std::ofstream out;
170     out.open(filename, std::ios::out);
171     if (out.fail()) {
172         HILOG_ERROR(LOG_CORE, "WriteStrToFile: %{public}s open failed.", filename.c_str());
173         return false;
174     }
175     out << str;
176     if (out.bad()) {
177         HILOG_ERROR(LOG_CORE, "WriteStrToFile: %{public}s write failed.", filename.c_str());
178         out.close();
179         return false;
180     }
181     out.flush();
182     out.close();
183     return true;
184 }
185 
WriteStrToFile(const std::string & filename,const std::string & str)186 bool WriteStrToFile(const std::string& filename, const std::string& str)
187 {
188     if (access((g_traceRootPath + filename).c_str(), W_OK) < 0) {
189         HILOG_WARN(LOG_CORE, "WriteStrToFile: Failed to access %{public}s, errno(%{public}d).",
190             (g_traceRootPath + filename).c_str(), errno);
191         return false;
192     }
193     return WriteStrToFileInner(g_traceRootPath + filename, str);
194 }
195 
SetTraceNodeStatus(const std::string & path,bool enabled)196 bool SetTraceNodeStatus(const std::string &path, bool enabled)
197 {
198     return WriteStrToFile(path, enabled ? "1" : "0");
199 }
200 
TruncateFile(const std::string & path)201 void TruncateFile(const std::string& path)
202 {
203     int fd = creat((g_traceRootPath + path).c_str(), 0);
204     if (fd == -1) {
205         HILOG_ERROR(LOG_CORE, "TruncateFile: clear old trace failed.");
206         return;
207     }
208     close(fd);
209     return;
210 }
211 
SetProperty(const std::string & property,const std::string & value)212 bool SetProperty(const std::string& property, const std::string& value)
213 {
214     bool result = OHOS::system::SetParameter(property, value);
215     if (!result) {
216         HILOG_ERROR(LOG_CORE, "SetProperty: set %{public}s failed.", value.c_str());
217     } else {
218         HILOG_INFO(LOG_CORE, "SetProperty: set %{public}s success.", value.c_str());
219     }
220     return result;
221 }
222 
ClearFilterParam()223 void ClearFilterParam()
224 {
225     bool ok = true;
226     if (!OHOS::system::SetParameter(TELEMETRY_APP_PARAM, "")) {
227         HILOG_ERROR(LOG_CORE, "ClearFilterParam: clear param fail");
228         ok = false;
229     }
230     if (ClearFilterPid() != HITRACE_NO_ERROR) {
231         HILOG_ERROR(LOG_CORE, "ClearFilterParam: clear pid fail");
232         ok = false;
233     }
234 
235     HILOG_INFO(LOG_CORE, "ClearFilterParam %{public}d.", ok);
236 }
237 
238 // close all trace node
TraceInit(const std::map<std::string,TraceTag> & allTags)239 void TraceInit(const std::map<std::string, TraceTag>& allTags)
240 {
241     // close all ftrace events
242     for (auto it = allTags.begin(); it != allTags.end(); it++) {
243         if (it->second.type != 1) {
244             continue;
245         }
246         for (size_t i = 0; i < it->second.enablePath.size(); i++) {
247             if (!SetTraceNodeStatus(it->second.enablePath[i], false)) {
248                 HILOG_ERROR(LOG_CORE, "TraceInit: SetTraceNodeStatus fail");
249             }
250         }
251     }
252     // close all user tags
253     SetProperty(TRACE_TAG_ENABLE_FLAGS, std::to_string(0));
254 
255     // set buffer_size_kb 1
256     if (!WriteStrToFile("buffer_size_kb", "1")) {
257         HILOG_ERROR(LOG_CORE, "TraceInit: WriteStrToFile fail");
258     }
259 
260     // close tracing_on
261     SetTraceNodeStatus(TRACING_ON_NODE, false);
262 }
263 
264 // Open specific trace node
SetAllTags(const TraceParams & traceParams,const std::map<std::string,TraceTag> & allTags,const std::map<std::string,std::vector<std::string>> & tagGroupTable,std::vector<std::string> & tagFmts)265 void SetAllTags(const TraceParams& traceParams, const std::map<std::string, TraceTag>& allTags,
266                 const std::map<std::string, std::vector<std::string>>& tagGroupTable,
267                 std::vector<std::string>& tagFmts)
268 {
269     std::set<std::string> readyEnableTagList;
270     for (std::string tagName : traceParams.tags) {
271         readyEnableTagList.insert(tagName);
272     }
273 
274     for (std::string groupName : traceParams.tagGroups) {
275         auto iter = tagGroupTable.find(groupName);
276         if (iter == tagGroupTable.end()) {
277             continue;
278         }
279         for (std::string tag : iter->second) {
280             readyEnableTagList.insert(tag);
281         }
282     }
283 
284     uint64_t enabledUserTags = 0;
285     for (std::string tagName : readyEnableTagList) {
286         auto iter = allTags.find(tagName);
287         if (iter == allTags.end()) {
288             HILOG_ERROR(LOG_CORE, "tag<%{public}s> is invalid.", tagName.c_str());
289             continue;
290         }
291 
292         if (iter->second.type == 0) {
293             enabledUserTags |= iter->second.tag;
294         }
295 
296         if (iter->second.type == 1) {
297             for (const auto& path : iter->second.enablePath) {
298                 if (!SetTraceNodeStatus(path, true)) {
299                     HILOG_ERROR(LOG_CORE, "SetAllTags: SetTraceNodeStatus fail");
300                 }
301             }
302             for (const auto& format : iter->second.formatPath) {
303                 tagFmts.emplace_back(format);
304             }
305         }
306     }
307     SetProperty(TRACE_TAG_ENABLE_FLAGS, std::to_string(enabledUserTags));
308 }
309 
SetClock(const std::string & clockType)310 void SetClock(const std::string& clockType)
311 {
312     const std::string traceClockPath = "trace_clock";
313     if (clockType.size() == 0) {
314         if (!WriteStrToFile(traceClockPath, "boot")) { // set default: boot
315             HILOG_ERROR(LOG_CORE, "SetClock: WriteStrToFile fail.");
316         }
317         return;
318     }
319     std::string allClocks = ReadFile(traceClockPath, g_traceRootPath);
320     if (allClocks.find(clockType) == std::string::npos) {
321         HILOG_ERROR(LOG_CORE, "SetClock: %{public}s is non-existent, set to boot", clockType.c_str());
322         if (!WriteStrToFile(traceClockPath, "boot")) { // set default: boot
323             HILOG_ERROR(LOG_CORE, "SetClock: WriteStrToFile fail.");
324         }
325         return;
326     }
327 
328     allClocks.erase(allClocks.find_last_not_of(" \n") + 1);
329     allClocks.push_back(' ');
330 
331     std::set<std::string> allClockTypes;
332     size_t curPos = 0;
333     for (size_t i = 0; i < allClocks.size(); i++) {
334         if (allClocks[i] == ' ') {
335             allClockTypes.insert(allClocks.substr(curPos, i - curPos));
336             curPos = i + 1;
337         }
338     }
339 
340     std::string currentClockType;
341     for (auto i : allClockTypes) {
342         if (clockType.compare(i) == 0) {
343             HILOG_INFO(LOG_CORE, "SetClock: set clock %{public}s success.", clockType.c_str());
344             if (!WriteStrToFile(traceClockPath, clockType)) {
345                 HILOG_ERROR(LOG_CORE, "SetClock: WriteStrToFile fail.");
346             }
347             return;
348         }
349         if (i[0] == '[') {
350             currentClockType = i;
351         }
352     }
353 
354     const int marks = 2;
355     if (clockType.compare(currentClockType.substr(1, currentClockType.size() - marks)) == 0) {
356         HILOG_INFO(LOG_CORE, "SetClock: set clock %{public}s success.", clockType.c_str());
357         return;
358     }
359 
360     HILOG_INFO(LOG_CORE, "SetClock: unknown %{public}s, change to default clock_type: boot.", clockType.c_str());
361     if (!WriteStrToFile(traceClockPath, "boot")) { // set default: boot
362         HILOG_ERROR(LOG_CORE, "SetClock: WriteStrToFile fail.");
363     }
364     return;
365 }
366 
SetTraceSetting(const TraceParams & traceParams,const std::map<std::string,TraceTag> & allTags,const std::map<std::string,std::vector<std::string>> & tagGroupTable,std::vector<std::string> & tagFmts)367 bool SetTraceSetting(const TraceParams& traceParams, const std::map<std::string, TraceTag>& allTags,
368                      const std::map<std::string, std::vector<std::string>>& tagGroupTable,
369                      std::vector<std::string>& tagFmts)
370 {
371     AddFilterPids(traceParams.filterPids);
372     if (!traceParams.filterPids.empty()) {
373         TruncateFile("trace_pipe_raw");
374     }
375     TraceInit(allTags);
376 
377     TruncateFile(TRACE_NODE);
378 
379     SetAllTags(traceParams, allTags, tagGroupTable, tagFmts);
380 
381     if (!WriteStrToFile("current_tracer", "nop")) {
382         HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
383     }
384     if (!WriteStrToFile("buffer_size_kb", traceParams.bufferSize)) {
385         HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
386     }
387 
388     SetClock(traceParams.clockType);
389 
390     if (traceParams.isOverWrite == "1") {
391         if (!WriteStrToFile("options/overwrite", "1")) {
392             HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
393         }
394     } else {
395         if (!WriteStrToFile("options/overwrite", "0")) {
396             HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
397         }
398     }
399 
400     if (!WriteStrToFile("saved_cmdlines_size", std::to_string(SAVED_CMDLINES_SIZE))) {
401         HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
402     }
403     if (!WriteStrToFile("options/record-tgid", "1")) {
404         HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
405     }
406     if (!WriteStrToFile("options/record-cmd", "1")) {
407         HILOG_ERROR(LOG_CORE, "SetTraceSetting: WriteStrToFile fail.");
408     }
409     return true;
410 }
411 
SetTimeIntervalBoundary(int inputMaxDuration,uint64_t utTraceEndTime)412 TraceErrorCode SetTimeIntervalBoundary(int inputMaxDuration, uint64_t utTraceEndTime)
413 {
414     uint64_t utNow = static_cast<uint64_t>(std::time(nullptr));
415     if (utTraceEndTime >= utNow) {
416         HILOG_WARN(LOG_CORE, "DumpTrace: Warning: traceEndTime is later than current time, set to current.");
417         utTraceEndTime = 0;
418     }
419     struct timespec bts = {0, 0};
420     clock_gettime(CLOCK_BOOTTIME, &bts);
421     uint64_t btNow = static_cast<uint64_t>(bts.tv_sec) + (static_cast<uint64_t>(bts.tv_nsec) != 0 ? 1 : 0);
422     uint64_t utBootTime = utNow - btNow;
423     if (utTraceEndTime == 0) {
424         g_traceEndTime = static_cast<uint64_t>(bts.tv_sec * S_TO_NS + bts.tv_nsec);
425     } else if (utTraceEndTime > utBootTime) {
426         // beware of input precision of seconds: add an extra second of tolerance
427         g_traceEndTime = (utTraceEndTime - utBootTime + 1) * S_TO_NS;
428     } else {
429         HILOG_ERROR(LOG_CORE,
430             "DumpTrace: traceEndTime:(%{public}" PRIu64 ") is earlier than boot_time:(%{public}" PRIu64 ").",
431             utTraceEndTime, utBootTime);
432         return OUT_OF_TIME;
433     }
434 
435     uint64_t maxDuration = inputMaxDuration > 0 ? static_cast<uint64_t>(inputMaxDuration) + 1 : 0;
436     if (maxDuration > g_traceEndTime / S_TO_NS) {
437         HILOG_WARN(LOG_CORE, "maxDuration is larger than TraceEndTime boot clock.");
438         maxDuration = 0;
439     }
440     if (maxDuration > 0) {
441         g_traceStartTime = g_traceEndTime - maxDuration * S_TO_NS;
442     } else {
443         g_traceStartTime = 0;
444     }
445     return SUCCESS;
446 }
447 
RestoreTimeIntervalBoundary()448 void RestoreTimeIntervalBoundary()
449 {
450     g_traceStartTime = 0;
451     g_traceEndTime = std::numeric_limits<uint64_t>::max();
452 }
453 
GetTraceFileFromVec(const uint64_t & inputTraceStartTime,const uint64_t & inputTraceEndTime,std::vector<TraceFileInfo> & fileVec,std::vector<TraceFileInfo> & targetFiles)454 int32_t GetTraceFileFromVec(const uint64_t& inputTraceStartTime, const uint64_t& inputTraceEndTime,
455     std::vector<TraceFileInfo>& fileVec, std::vector<TraceFileInfo>& targetFiles)
456 {
457     int32_t coverDuration = 0;
458     uint64_t utTargetStartTimeMs = inputTraceStartTime * S_TO_MS;
459     uint64_t utTargetEndTimeMs = inputTraceEndTime * S_TO_MS;
460     for (auto it = fileVec.begin(); it != fileVec.end(); it++) {
461         if (access(it->filename.c_str(), F_OK) != 0) {
462             HILOG_ERROR(LOG_CORE, "GetTraceFileFromVec: %{public}s is not exist.", it->filename.c_str());
463             continue;
464         }
465         HILOG_INFO(LOG_CORE, "GetTraceFileFromVec: %{public}s, [%{public}" PRIu64 ", %{public}" PRIu64 "].",
466             it->filename.c_str(), it->traceStartTime, it->traceEndTime);
467         if (((it->traceEndTime >= utTargetStartTimeMs && it->traceStartTime <= utTargetEndTimeMs)) &&
468             (it->traceEndTime - it->traceStartTime < 2000 * S_TO_MS)) { // 2000 : max trace duration 2000s
469             targetFiles.push_back(*it);
470             coverDuration += static_cast<int32_t>(std::min(it->traceEndTime, utTargetEndTimeMs + DURATION_TOLERANCE) -
471                 std::max(it->traceStartTime, utTargetStartTimeMs - DURATION_TOLERANCE));
472         }
473     }
474     return coverDuration;
475 }
476 
SearchTraceFiles(const uint64_t & inputTraceStartTime,const uint64_t & inputTraceEndTime,TraceRetInfo & traceRetInfo)477 void SearchTraceFiles(const uint64_t& inputTraceStartTime, const uint64_t& inputTraceEndTime,
478     TraceRetInfo& traceRetInfo)
479 {
480     HILOG_INFO(LOG_CORE, "target trace time: [%{public}" PRIu64 ", %{public}" PRIu64 "].",
481         inputTraceStartTime, inputTraceEndTime);
482     uint64_t curTime = GetCurUnixTimeMs();
483     HILOG_INFO(LOG_CORE, "current time: %{public}" PRIu64 ".", curTime);
484     int32_t coverDuration = 0;
485     std::vector<TraceFileInfo> targetFiles;
486     coverDuration += GetTraceFileFromVec(inputTraceStartTime, inputTraceEndTime, g_traceFileVec, targetFiles);
487     auto inputCacheFiles = TraceDumpExecutor::GetInstance().GetCacheTraceFiles();
488     coverDuration += GetTraceFileFromVec(inputTraceStartTime, inputTraceEndTime, inputCacheFiles, targetFiles);
489     for (auto& file : targetFiles) {
490         if (file.filename.find(CACHE_FILE_PREFIX) != std::string::npos) {
491             file.filename = RenameCacheFile(file.filename);
492             auto it = std::find_if(inputCacheFiles.begin(), inputCacheFiles.end(),
493                 [&file](const TraceFileInfo& cacheFile) {
494                     return cacheFile.filename == file.filename;
495                 });
496             if (it != inputCacheFiles.end()) {
497                 g_traceFileVec.push_back(file);
498             }
499         }
500         traceRetInfo.outputFiles.push_back(file.filename);
501         traceRetInfo.fileSize += file.fileSize;
502     }
503     traceRetInfo.coverDuration += coverDuration;
504 }
505 
ProcessCacheTask()506 void ProcessCacheTask()
507 {
508     const std::string threadName = "CacheTraceTask";
509     prctl(PR_SET_NAME, threadName.c_str());
510     struct TraceDumpParam param = {
511         TraceDumpType::TRACE_CACHE,
512         g_currentTraceParams.outputFile,
513         g_currentTraceParams.fileLimit,
514         g_currentTraceParams.fileSize,
515         0,
516         std::numeric_limits<uint64_t>::max()
517     };
518     if (!TraceDumpExecutor::GetInstance().StartCacheTraceLoop(param, g_totalFileSizeLimit, g_sliceMaxDuration)) {
519         HILOG_ERROR(LOG_CORE, "ProcessCacheTask: StartCacheTraceLoop failed.");
520         return;
521     }
522     HILOG_INFO(LOG_CORE, "ProcessCacheTask: trace cache thread exit.");
523 }
524 
ProcessRecordTask()525 void ProcessRecordTask()
526 {
527     const std::string threadName = "RecordTraceTask";
528     prctl(PR_SET_NAME, threadName.c_str());
529     struct TraceDumpParam param = {
530         TraceDumpType::TRACE_RECORDING,
531         g_currentTraceParams.outputFile,
532         g_currentTraceParams.fileLimit,
533         g_currentTraceParams.fileSize,
534         0,
535         std::numeric_limits<uint64_t>::max()
536 
537     };
538     TraceDumpExecutor::GetInstance().StartDumpTraceLoop(param);
539 }
540 
SetProcessName(std::string & processName)541 void SetProcessName(std::string& processName)
542 {
543     if (processName.size() <= 0) {
544         return;
545     }
546 
547     const int maxNameLen = 16;
548     std::string setName;
549     if (processName.size() > maxNameLen) {
550         setName = processName.substr(0, maxNameLen);
551     } else {
552         setName = processName;
553     }
554 
555     prctl(PR_SET_NAME, setName.c_str(), nullptr, nullptr, nullptr);
556     HILOG_INFO(LOG_CORE, "New process: %{public}s.", setName.c_str());
557 }
558 
TimeoutSignalHandler(int signum)559 void TimeoutSignalHandler(int signum)
560 {
561     if (signum == SIGUSR1) {
562         _exit(EXIT_SUCCESS);
563     } else if (signum == SIGCHLD) {
564         pid_t pid;
565         do {
566             pid = waitpid(-1, nullptr, WNOHANG);
567         } while (pid > 0);
568     }
569 }
570 
EpollWaitforChildProcess(pid_t & pid,int & pipefd,std::string & reOutPath)571 bool EpollWaitforChildProcess(pid_t& pid, int& pipefd, std::string& reOutPath)
572 {
573     int epollfd = epoll_create1(0);
574     if (epollfd == -1) {
575         HILOG_ERROR(LOG_CORE, "epoll_create1 error.");
576         return false;
577     }
578 
579     struct epoll_event event;
580     event.events = EPOLLIN;
581     event.data.fd = pipefd;
582     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd, &event) == -1) {
583         HILOG_ERROR(LOG_CORE, "epoll_ctl error.");
584         close(epollfd);
585         return false;
586     }
587 
588     struct epoll_event events[1];
589     constexpr int waitTimeoutMs = 10000; // 10000ms = 10s
590     int numEvents = TEMP_FAILURE_RETRY(epoll_wait(epollfd, events, 1, waitTimeoutMs));
591     if (numEvents <= 0) {
592         if (numEvents == -1) {
593             HILOG_ERROR(LOG_CORE, "epoll_wait error, error: (%{public}s).", strerror(errno));
594         } else {
595             HILOG_ERROR(LOG_CORE, "epoll_wait timeout.");
596         }
597         if (waitpid(pid, nullptr, WNOHANG) <= 0) {
598             HILOG_ERROR(LOG_CORE, "kill timeout child process.");
599             kill(pid, SIGUSR1);
600         }
601         close(epollfd);
602         return false;
603     }
604     TraceDumpRet retVal;
605     read(pipefd, &retVal, sizeof(retVal));
606     HILOG_INFO(LOG_CORE,
607         "Epoll wait read : %{public}d, outputFile: %{public}s, [%{public}" PRIu64 ", %{public}" PRIu64 "].",
608         retVal.code, retVal.outputFile, retVal.traceStartTime, retVal.traceEndTime);
609     g_dumpStatus = retVal.code;
610     reOutPath = retVal.outputFile;
611     g_firstPageTimestamp = retVal.traceStartTime;
612     g_lastPageTimestamp = retVal.traceEndTime;
613 
614     close(epollfd);
615     if (waitpid(pid, nullptr, 0) <= 0) {
616         HILOG_ERROR(LOG_CORE, "wait HitraceDump(%{public}d) exit failed, errno: (%{public}d)", pid, errno);
617     }
618     return true;
619 }
620 
HandleDumpResult(std::string & reOutPath,TraceRetInfo & traceRetInfo)621 TraceErrorCode HandleDumpResult(std::string& reOutPath, TraceRetInfo& traceRetInfo)
622 {
623     SearchTraceFiles(g_utDestTraceStartTime, g_utDestTraceEndTime, traceRetInfo);
624     if (g_dumpStatus) {
625         if (remove(reOutPath.c_str()) == 0) {
626             HILOG_INFO(LOG_CORE, "Delete outpath:%{public}s success.", reOutPath.c_str());
627         } else {
628             HILOG_INFO(LOG_CORE, "Delete outpath:%{public}s failed.", reOutPath.c_str());
629         }
630     } else if (access(reOutPath.c_str(), F_OK) != 0) { // trace access error
631         HILOG_ERROR(LOG_CORE, "ProcessDump: write %{public}s failed.", reOutPath.c_str());
632     } else {
633         HILOG_INFO(LOG_CORE, "Output: %{public}s.", reOutPath.c_str());
634         TraceFileInfo traceFileInfo;
635         if (!SetFileInfo(true, reOutPath, g_firstPageTimestamp, g_lastPageTimestamp, traceFileInfo)) {
636             // trace rename error
637             HILOG_ERROR(LOG_CORE, "SetFileInfo: set %{public}s info failed.", reOutPath.c_str());
638             RemoveFile(reOutPath);
639         } else { // success
640             g_traceFileVec.push_back(traceFileInfo);
641             traceRetInfo.outputFiles.push_back(traceFileInfo.filename);
642             traceRetInfo.coverDuration +=
643                 static_cast<int32_t>(traceFileInfo.traceEndTime - traceFileInfo.traceStartTime);
644             traceRetInfo.fileSize += traceFileInfo.fileSize;
645         }
646     }
647 
648     if (traceRetInfo.outputFiles.empty()) {
649         return (g_dumpStatus != 0) ? static_cast<TraceErrorCode>(g_dumpStatus) : TraceErrorCode::FILE_ERROR;
650     }
651     return TraceErrorCode::SUCCESS;
652 }
653 
HandleAsyncDumpResult(TraceDumpTask & task,TraceRetInfo & traceRetInfo)654 void HandleAsyncDumpResult(TraceDumpTask& task, TraceRetInfo& traceRetInfo)
655 {
656     SearchTraceFiles(g_utDestTraceStartTime, g_utDestTraceEndTime, traceRetInfo);
657     TraceFileInfo traceFileInfo;
658     if (task.code == TraceErrorCode::SUCCESS) {
659         if (!SetFileInfo(false, std::string(task.outputFile),
660             g_firstPageTimestamp, g_lastPageTimestamp, traceFileInfo)) {
661             // trace rename error
662             HILOG_ERROR(LOG_CORE, "SetFileInfo: set %{public}s info failed.", task.outputFile);
663         } else { // success
664             traceFileInfo.fileSize = task.fileSize;
665             g_traceFileVec.push_back(traceFileInfo);
666             traceRetInfo.outputFiles.push_back(traceFileInfo.filename);
667             traceRetInfo.coverDuration +=
668                 static_cast<int32_t>(traceFileInfo.traceEndTime - traceFileInfo.traceStartTime);
669             traceRetInfo.fileSize += traceFileInfo.fileSize;
670         }
671         traceRetInfo.errorCode = task.code;
672     } else {
673         traceRetInfo.errorCode = traceRetInfo.outputFiles.empty() ? task.code : TraceErrorCode::SUCCESS;
674     }
675     if (task.isFileSizeOverLimit || traceRetInfo.fileSize > task.fileSizeLimit) {
676         traceRetInfo.isOverflowControl = true;
677     }
678 }
679 
ProcessDumpSync(TraceRetInfo & traceRetInfo)680 TraceErrorCode ProcessDumpSync(TraceRetInfo& traceRetInfo)
681 {
682     auto taskCnt = TraceDumpExecutor::GetInstance().GetTraceDumpTaskCount();
683     if (GetRemainingSpace("/data") <= SNAPSHOT_MIN_REMAINING_SPACE + taskCnt * DEFAULT_ASYNC_TRACE_SIZE) {
684         HILOG_ERROR(LOG_CORE, "ProcessDumpSync: remaining space not enough");
685         return TraceErrorCode::FILE_ERROR;
686     }
687 
688     int pipefd[2];
689     if (pipe(pipefd) == -1) {
690         HILOG_ERROR(LOG_CORE, "ProcessDumpSync: pipe creation error.");
691         return TraceErrorCode::PIPE_CREATE_ERROR;
692     }
693 
694     g_dumpStatus = TraceErrorCode::UNSET;
695     /*Child process handles task, Father process wait.*/
696     pid_t pid = fork();
697     if (pid < 0) {
698         HILOG_ERROR(LOG_CORE, "fork error.");
699         return TraceErrorCode::FORK_ERROR;
700     } else if (pid == 0) {
701         signal(SIGUSR1, TimeoutSignalHandler);
702         close(pipefd[0]);
703         std::string processName = "HitraceDump";
704         SetProcessName(processName);
705         struct TraceDumpParam param = { TRACE_SNAPSHOT, "", 0, 0, g_traceStartTime, g_traceEndTime };
706         TraceDumpRet ret = TraceDumpExecutor::GetInstance().DumpTrace(param);
707         HILOG_INFO(LOG_CORE,
708             "TraceDumpRet : %{public}d, outputFile: %{public}s, [%{public}" PRIu64 ", %{public}" PRIu64 "].",
709             ret.code, ret.outputFile, ret.traceStartTime, ret.traceEndTime);
710         write(pipefd[1], &ret, sizeof(ret));
711         _exit(EXIT_SUCCESS);
712     } else {
713         close(pipefd[1]);
714     }
715 
716     std::string reOutPath;
717     if (!EpollWaitforChildProcess(pid, pipefd[0], reOutPath)) {
718         close(pipefd[0]);
719         return TraceErrorCode::EPOLL_WAIT_ERROR;
720     }
721 
722     close(pipefd[0]);
723     return HandleDumpResult(reOutPath, traceRetInfo);
724 }
725 
LoadDumpRet(TraceRetInfo & ret,int32_t committedDuration)726 void LoadDumpRet(TraceRetInfo& ret, int32_t committedDuration)
727 {
728     ret.mode = g_traceMode;
729     committedDuration = committedDuration <= 0 ? DEFAULT_FULL_TRACE_LENGTH : committedDuration;
730     ret.coverRatio = ret.coverDuration / committedDuration;
731     ret.tags.reserve(g_currentTraceParams.tagGroups.size() + g_currentTraceParams.tags.size());
732     ret.tags.insert(ret.tags.end(), g_currentTraceParams.tagGroups.begin(), g_currentTraceParams.tagGroups.end());
733     ret.tags.insert(ret.tags.end(), g_currentTraceParams.tags.begin(), g_currentTraceParams.tags.end());
734 }
735 
SanitizeRetInfo(TraceRetInfo & traceRetInfo)736 void SanitizeRetInfo(TraceRetInfo& traceRetInfo)
737 {
738     traceRetInfo.coverDuration =
739         std::min(traceRetInfo.coverDuration, static_cast<int>(DEFAULT_FULL_TRACE_LENGTH * S_TO_MS));
740     traceRetInfo.coverRatio = std::min(traceRetInfo.coverRatio, MAX_RATIO_UNIT);
741 }
742 
WaitSyncDumpRetLoop(const pid_t pid,const std::shared_ptr<HitraceDumpPipe> pipe)743 TraceDumpTask WaitSyncDumpRetLoop(const pid_t pid, const std::shared_ptr<HitraceDumpPipe> pipe)
744 {
745     HILOG_INFO(LOG_CORE, "WaitSyncDumpRetLoop: start.");
746     TraceDumpTask task;
747     if (pipe->ReadSyncDumpRet(10, task)) { // 10 : 10 seconds
748         g_firstPageTimestamp = task.traceStartTime;
749         g_lastPageTimestamp = task.traceEndTime;
750         g_dumpStatus = task.code;
751         if (task.status == TraceDumpStatus::WRITE_DONE) {
752             task.status = TraceDumpStatus::FINISH;
753             TraceDumpExecutor::GetInstance().RemoveTraceDumpTask(task.time);
754             HILOG_INFO(LOG_CORE, "WaitSyncDumpRetLoop: task finished.");
755         } else {
756             HILOG_ERROR(LOG_CORE, "WaitSyncDumpRetLoop: task status is not FINISH.");
757             TraceDumpExecutor::GetInstance().UpdateTraceDumpTask(task);
758         }
759     } else {
760         task.code = TraceErrorCode::TRACE_TASK_DUMP_TIMEOUT;
761         TraceDumpExecutor::GetInstance().ClearTraceDumpTask();
762         kill(pid, SIGUSR1);
763         HILOG_WARN(LOG_CORE, "WaitSyncDumpRetLoop: wait timeout, clear task and kill dump process.");
764     }
765     HILOG_INFO(LOG_CORE, "WaitSyncDumpRetLoop: exit.");
766     return task;
767 }
768 
WaitAsyncDumpRetLoop(const std::shared_ptr<HitraceDumpPipe> pipe)769 void WaitAsyncDumpRetLoop(const std::shared_ptr<HitraceDumpPipe> pipe)
770 {
771     HILOG_INFO(LOG_CORE, "WaitAsyncDumpRetLoop: start.");
772     int emptyLoopMs = 0;
773     do {
774         HILOG_INFO(LOG_CORE, "WaitAsyncDumpRetLoop: loop start.");
775         if (TraceDumpExecutor::GetInstance().IsTraceDumpTaskEmpty() && emptyLoopMs >= ASYNC_WAIT_EMPTY_LOOP_MS) {
776             HILOG_INFO(LOG_CORE, "WaitAsyncDumpRetLoop: task queue is empty.");
777             HitraceDumpPipe::ClearTraceDumpPipe();
778             break;
779         }
780         TraceDumpTask task;
781         if (!pipe->ReadAsyncDumpRet(1, task)) {
782             usleep(HUNDRED_MILLISECONDS);
783             emptyLoopMs += HUNDRED_MILLISECONDS / 1000; // 1000 : us to ms ratio
784             continue;
785         }
786         emptyLoopMs = 0;
787         if (task.status == TraceDumpStatus::WRITE_DONE) {
788             task.status = TraceDumpStatus::FINISH;
789             HILOG_INFO(LOG_CORE, "WaitAsyncDumpRetLoop: task finished.");
790             std::lock_guard<std::mutex> lock(g_traceRetAndCallbackMutex);
791             auto traceRetInfo = g_traceRetInfos[task.time];
792             traceRetInfo.fileSize = 0;
793             for (auto& file : traceRetInfo.outputFiles) {
794                 traceRetInfo.fileSize += GetFileSize(file);
795             }
796             if (traceRetInfo.fileSize > task.fileSizeLimit) {
797                 traceRetInfo.isOverflowControl = true;
798             }
799             if (g_callbacks[task.time] != nullptr) {
800                 g_callbacks[task.time](traceRetInfo);
801                 HILOG_INFO(LOG_CORE, "WaitAsyncDumpRetLoop: call callback func done, taskid[%{public}" PRIu64 "]",
802                     task.time);
803             }
804             g_callbacks.erase(task.time);
805             g_traceRetInfos.erase(task.time);
806         } else {
807             HILOG_ERROR(LOG_CORE, "WaitAsyncDumpRetLoop: task status is not FINISH.");
808         }
809         TraceDumpExecutor::GetInstance().RemoveTraceDumpTask(task.time);
810     } while (true);
811     HILOG_INFO(LOG_CORE, "WaitAsyncDumpRetLoop: exit.");
812 }
813 
SubmitTaskAndWaitReturn(const TraceDumpTask & task,const bool cloneAsyncThread,TraceRetInfo & traceRetInfo)814 TraceErrorCode SubmitTaskAndWaitReturn(const TraceDumpTask& task, const bool cloneAsyncThread,
815     TraceRetInfo& traceRetInfo)
816 {
817     TraceDumpExecutor::GetInstance().AddTraceDumpTask(task);
818     auto dumpPipe = std::make_shared<HitraceDumpPipe>(true);
819     if (!dumpPipe->SubmitTraceDumpTask(task)) {
820         return TraceErrorCode::TRACE_TASK_SUBMIT_ERROR;
821     }
822     auto taskRet = WaitSyncDumpRetLoop(g_traceDumpTaskPid.load(), dumpPipe);
823     HandleAsyncDumpResult(taskRet, traceRetInfo);
824     if (taskRet.status == TraceDumpStatus::FINISH) {
825         HILOG_INFO(LOG_CORE, "SubmitTaskAndWaitReturn: task finished.");
826         return traceRetInfo.errorCode;
827     } else if (taskRet.code != TraceErrorCode::TRACE_TASK_DUMP_TIMEOUT) {
828         HILOG_ERROR(LOG_CORE, "SubmitTaskAndWaitReturn: task status is not FINISH.");
829         if (cloneAsyncThread) {
830             std::thread asyncThread(WaitAsyncDumpRetLoop, std::move(dumpPipe));
831             asyncThread.detach();
832         }
833         return TraceErrorCode::ASYNC_DUMP;
834     }
835     return TraceErrorCode::TRACE_TASK_DUMP_TIMEOUT;
836 }
837 
SetSigChldHandler()838 bool SetSigChldHandler()
839 {
840     struct sigaction sa;
841     sa.sa_handler = TimeoutSignalHandler;
842     sigemptyset(&sa.sa_mask);
843     sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
844     if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
845         HILOG_ERROR(LOG_CORE, "ProcessDumpAsync: Failed to setup SIGCHLD handler.");
846         return false;
847     }
848     return true;
849 }
850 
ProcessDumpAsync(const uint64_t taskid,const int64_t fileSizeLimit,TraceRetInfo & traceRetInfo)851 TraceErrorCode ProcessDumpAsync(const uint64_t taskid, const int64_t fileSizeLimit, TraceRetInfo& traceRetInfo)
852 {
853     auto taskCnt = TraceDumpExecutor::GetInstance().GetTraceDumpTaskCount();
854     if (GetRemainingSpace("/data") <= SNAPSHOT_MIN_REMAINING_SPACE + taskCnt * DEFAULT_ASYNC_TRACE_SIZE) {
855         HILOG_ERROR(LOG_CORE, "ProcessDumpAsync: remaining space not enough");
856         return TraceErrorCode::FILE_ERROR;
857     }
858     if (!SetSigChldHandler()) {
859         return TraceErrorCode::FORK_ERROR;
860     }
861 
862     TraceDumpTask task = {
863         .time = taskid,
864         .traceStartTime = g_traceStartTime,
865         .traceEndTime = g_traceEndTime,
866         .fileSizeLimit = fileSizeLimit
867     };
868     HILOG_INFO(LOG_CORE, "ProcessDumpAsync: new task id[%{public}" PRIu64 "]", task.time);
869     if (taskCnt > 0) {
870         // must have a trace dump process running, just submit trace dump task, or need check child process is alive.
871         HILOG_INFO(LOG_CORE, "ProcessDumpAsync: task queue is not empty, do not fork new process.");
872         return SubmitTaskAndWaitReturn(task, false, traceRetInfo);
873     }
874     HitraceDumpPipe::ClearTraceDumpPipe();
875     if (!HitraceDumpPipe::InitTraceDumpPipe()) {
876         HILOG_ERROR(LOG_CORE, "ProcessDumpAsync: create fifo failed.");
877         return TraceErrorCode::PIPE_CREATE_ERROR;
878     }
879     pid_t pid = fork();
880     if (pid < 0) {
881         HILOG_ERROR(LOG_CORE, "ProcessDumpAsync: fork failed.");
882         return TraceErrorCode::FORK_ERROR;
883     }
884     if (pid == 0) {
885         signal(SIGUSR1, TimeoutSignalHandler);
886         std::string processName = "HitraceDumpAsync";
887         SetProcessName(processName);
888         // create loop read thread and loop write thread.
889         auto& traceDumpExecutor = TraceDumpExecutor::GetInstance();
890         std::thread loopReadThrad(&TraceDumpExecutor::ReadRawTraceLoop, std::ref(traceDumpExecutor));
891         std::thread loopWriteThread(&TraceDumpExecutor::WriteTraceLoop, std::ref(traceDumpExecutor));
892         traceDumpExecutor.TraceDumpTaskMonitor();
893         loopReadThrad.join();
894         loopWriteThread.join();
895         _exit(EXIT_SUCCESS);
896     }
897     g_traceDumpTaskPid.store(pid);
898     return SubmitTaskAndWaitReturn(task, true, traceRetInfo);
899 }
900 
GetSysParamTags()901 uint64_t GetSysParamTags()
902 {
903     return OHOS::system::GetUintParameter<uint64_t>(TRACE_TAG_ENABLE_FLAGS, 0);
904 }
905 
CheckParam()906 bool CheckParam()
907 {
908     uint64_t currentTags = GetSysParamTags();
909     if (currentTags == g_sysInitParamTags) {
910         return true;
911     }
912 
913     if (currentTags == 0) {
914         HILOG_ERROR(LOG_CORE, "allowed tags are cleared, should restart.");
915         return false;
916     }
917     HILOG_ERROR(LOG_CORE, "trace is being used, should restart.");
918     return false;
919 }
920 
921 /**
922  * SERVICE_MODE is running, check param and tracing_on.
923 */
CheckServiceRunning()924 bool CheckServiceRunning()
925 {
926     if (CheckParam() && IsTracingOn(g_traceRootPath)) {
927         return true;
928     }
929     return false;
930 }
931 
CpuBufferBalanceTask()932 void CpuBufferBalanceTask()
933 {
934     g_serviceThreadIsStart = true;
935     const std::string threadName = "CpuBufferBalancer";
936     prctl(PR_SET_NAME, threadName.c_str());
937     HILOG_INFO(LOG_CORE, "CpuBufferBalanceTask: monitor thread start.");
938     const int intervalTime = 15;
939     while (IsTraceOpen() && CheckServiceRunning()) {
940         sleep(intervalTime);
941 
942         const int cpuNums = GetCpuProcessors();
943         std::vector<int> result;
944         std::unique_ptr<DynamicBuffer> dynamicBuffer = std::make_unique<DynamicBuffer>(g_traceRootPath, cpuNums);
945         dynamicBuffer->CalculateBufferSize(result);
946 
947         if (static_cast<int>(result.size()) != cpuNums) {
948             HILOG_ERROR(LOG_CORE, "CalculateAllNewBufferSize failed.");
949             break;
950         }
951 
952         for (size_t i = 0; i < result.size(); i++) {
953             HILOG_DEBUG(LOG_CORE, "cpu%{public}zu set size %{public}d.", i, result[i]);
954             std::string path = "per_cpu/cpu" + std::to_string(i) + "/buffer_size_kb";
955             if (!WriteStrToFile(path, std::to_string(result[i]))) {
956                 HILOG_ERROR(LOG_CORE, "CpuBufferBalanceTask: WriteStrToFile failed.");
957             }
958         }
959     }
960     HILOG_INFO(LOG_CORE, "CpuBufferBalanceTask: monitor thread exit.");
961     g_serviceThreadIsStart = false;
962 }
963 
StartCpuBufferBalanceService()964 void StartCpuBufferBalanceService()
965 {
966     if (!IsHmKernel() && !g_serviceThreadIsStart) {
967         // open monitor thread
968         auto it = []() {
969             CpuBufferBalanceTask();
970         };
971         std::thread auxiliaryTask(it);
972         auxiliaryTask.detach();
973     }
974 }
975 
PreWriteEventsFormat(const std::vector<std::string> & eventFormats)976 bool PreWriteEventsFormat(const std::vector<std::string>& eventFormats)
977 {
978     DelSavedEventsFormat();
979     const std::string savedEventsFormatPath = TRACE_FILE_DEFAULT_DIR + TRACE_SAVED_EVENTS_FORMAT;
980     int fd = open(savedEventsFormatPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644); // 0644:-rw-r--r--
981     if (fd < 0) {
982         HILOG_ERROR(LOG_CORE, "PreWriteEventsFormat: open %{public}s failed.", savedEventsFormatPath.c_str());
983         return false;
984     }
985     for (auto& format : eventFormats) {
986         std::string srcPath = g_traceRootPath + format;
987         if (access(srcPath.c_str(), R_OK) != -1) {
988             WriteEventFile(srcPath, fd);
989         }
990     }
991     close(fd);
992     HILOG_INFO(LOG_CORE, "PreWriteEventsFormat end.");
993     return true;
994 }
995 
HandleTraceOpen(const TraceParams & traceParams,const std::map<std::string,TraceTag> & allTags,const std::map<std::string,std::vector<std::string>> & tagGroupTable,std::vector<std::string> & tagFmts)996 TraceErrorCode HandleTraceOpen(const TraceParams& traceParams,
997                                const std::map<std::string, TraceTag>& allTags,
998                                const std::map<std::string, std::vector<std::string>>& tagGroupTable,
999                                std::vector<std::string>& tagFmts)
1000 {
1001     if (!SetTraceSetting(traceParams, allTags, tagGroupTable, tagFmts)) {
1002         return TraceErrorCode::FILE_ERROR;
1003     }
1004     SetTraceNodeStatus(TRACING_ON_NODE, true);
1005     PreWriteEventsFormat(tagFmts);
1006     g_currentTraceParams = traceParams;
1007     return TraceErrorCode::SUCCESS;
1008 }
1009 
HandleDefaultTraceOpen(const std::vector<std::string> & tagGroups)1010 TraceErrorCode HandleDefaultTraceOpen(const std::vector<std::string>& tagGroups)
1011 {
1012     TraceJsonParser& traceJsonParser = TraceJsonParser::Instance();
1013     const std::map<std::string, TraceTag>& allTags = traceJsonParser.GetAllTagInfos();
1014     const std::map<std::string, std::vector<std::string>>& tagGroupTable = traceJsonParser.GetTagGroups();
1015     std::vector<std::string> tagFmts = traceJsonParser.GetBaseFmtPath();
1016 
1017     if (tagGroups.size() == 0 || !CheckTagGroup(tagGroups, tagGroupTable)) {
1018         HILOG_ERROR(LOG_CORE, "OpenTrace: TAG_ERROR.");
1019         return TAG_ERROR;
1020     }
1021 
1022     TraceParams defaultTraceParams;
1023     defaultTraceParams.tagGroups = tagGroups;
1024     defaultTraceParams.bufferSize = std::to_string(traceJsonParser.GetSnapshotDefaultBufferSizeKb());
1025     defaultTraceParams.clockType = "boot";
1026     defaultTraceParams.isOverWrite = "1";
1027     defaultTraceParams.fileSize = DEFAULT_FILE_SIZE;
1028     return HandleTraceOpen(defaultTraceParams, allTags, tagGroupTable, tagFmts);
1029 }
1030 
RemoveUnSpace(std::string str,std::string & args)1031 void RemoveUnSpace(std::string str, std::string& args)
1032 {
1033     int maxCircleTimes = 30;
1034     int curTimes = 0;
1035     const size_t symbolAndSpaceLen = 2;
1036     std::string strSpace = str + " ";
1037     while (curTimes < maxCircleTimes) {
1038         curTimes++;
1039         std::string::size_type index = args.find(strSpace);
1040         if (index != std::string::npos) {
1041             args.replace(index, symbolAndSpaceLen, str);
1042         } else {
1043             break;
1044         }
1045     }
1046 }
1047 
SetCmdTraceIntParams(const std::string & traceParamsStr,int & traceParams)1048 void SetCmdTraceIntParams(const std::string& traceParamsStr, int& traceParams)
1049 {
1050     if (!OHOS::HiviewDFX::Hitrace::StringToInt(traceParamsStr, traceParams)) {
1051         traceParams = 0;
1052         return;
1053     }
1054     if (traceParams <= 0) {
1055         HILOG_WARN(LOG_CORE, "Illegal input, traceParams initialized to null.");
1056         traceParams = 0;
1057     }
1058 }
1059 
SetDestTraceTimeAndDuration(int maxDuration,const uint64_t & utTraceEndTime)1060 void SetDestTraceTimeAndDuration(int maxDuration, const uint64_t& utTraceEndTime)
1061 {
1062     if (utTraceEndTime == 0) {
1063         time_t currentTime;
1064         time(&currentTime);
1065         g_utDestTraceEndTime = static_cast<uint64_t>(currentTime);
1066     } else {
1067         g_utDestTraceEndTime = utTraceEndTime;
1068     }
1069     if (maxDuration <= 0) {
1070         maxDuration = DEFAULT_FULL_TRACE_LENGTH;
1071     }
1072     if (g_utDestTraceEndTime <= static_cast<uint64_t>(maxDuration)) {
1073         g_utDestTraceStartTime = 1; // theoretical impossible value, to avoid overflow while minus tolerance 100ms
1074     } else {
1075         g_utDestTraceStartTime = g_utDestTraceEndTime - static_cast<uint64_t>(maxDuration);
1076     }
1077     HILOG_INFO(LOG_CORE, "g_utDestTraceStartTime:(%{public}" PRIu64 "), g_utDestTraceEndTime:(%{public}" PRIu64 ").",
1078         g_utDestTraceStartTime, g_utDestTraceEndTime);
1079 }
1080 
1081 /**
1082  * args: tags:tag1,tags2... tagGroups:group1,group2... clockType:boot bufferSize:1024 overwrite:1 output:filename
1083  * traceParams:  Save the above parameters
1084 */
ParseArgs(std::string args,TraceParams & traceParams,const std::map<std::string,TraceTag> & allTags,const std::map<std::string,std::vector<std::string>> & tagGroupTable)1085 bool ParseArgs(std::string args, TraceParams& traceParams, const std::map<std::string, TraceTag>& allTags,
1086                const std::map<std::string, std::vector<std::string>>& tagGroupTable)
1087 {
1088     RemoveUnSpace(":", args);
1089     RemoveUnSpace(",", args);
1090     std::vector<std::string> argList = Split(args, ' ');
1091     for (std::string item : argList) {
1092         size_t pos = item.find(":");
1093         if (pos == std::string::npos) {
1094             HILOG_ERROR(LOG_CORE, "trace command line without colon appears: %{public}s, continue.", item.c_str());
1095             continue;
1096         }
1097         std::string itemName = item.substr(0, pos);
1098         if (itemName == "tags") {
1099             traceParams.tags = Split(item.substr(pos + 1), ',');
1100         } else if (itemName == "tagGroups") {
1101             traceParams.tagGroups = Split(item.substr(pos + 1), ',');
1102         } else if (itemName == "clockType") {
1103             traceParams.clockType = item.substr(pos + 1);
1104         } else if (itemName == "bufferSize") {
1105             traceParams.bufferSize = item.substr(pos + 1);
1106         } else if (itemName == "overwrite") {
1107             traceParams.isOverWrite = item.substr(pos + 1);
1108         } else if (itemName == "output") {
1109             traceParams.outputFile = item.substr(pos + 1);
1110         } else if (itemName == "fileSize") {
1111             std::string fileSizeStr = item.substr(pos + 1);
1112             SetCmdTraceIntParams(fileSizeStr, traceParams.fileSize);
1113         } else if (itemName == "fileLimit") {
1114             std::string fileLimitStr = item.substr(pos + 1);
1115             SetCmdTraceIntParams(fileLimitStr, traceParams.fileLimit);
1116         } else if (itemName == "appPid") {
1117             std::string pidStr = item.substr(pos + 1);
1118             SetCmdTraceIntParams(pidStr, traceParams.appPid);
1119             if (traceParams.appPid == 0) {
1120                 HILOG_ERROR(LOG_CORE, "Illegal input, appPid(%{public}s) must be number and greater than 0.",
1121                     pidStr.c_str());
1122                 return false;
1123             }
1124             OHOS::system::SetParameter(TRACE_KEY_APP_PID, pidStr);
1125         } else if (itemName == "filterPids") {
1126             traceParams.filterPids = Split(item.substr(pos + 1), ',');
1127         } else {
1128             HILOG_ERROR(LOG_CORE, "Extra trace command line options appear when ParseArgs: %{public}s, return false.",
1129                 itemName.c_str());
1130             return false;
1131         }
1132     }
1133     return CheckTags(traceParams.tags, allTags) && CheckTagGroup(traceParams.tagGroups, tagGroupTable);
1134 }
1135 
WriteCpuFreqTrace()1136 void WriteCpuFreqTrace()
1137 {
1138     std::string freqsfmt = "cpu frequency: ";
1139     ReadCurrentCpuFrequencies(freqsfmt);
1140     HILOG_INFO(LOG_CORE, "hitracedump write trace(%{public}s)", freqsfmt.c_str());
1141     HITRACE_METER_NAME(HITRACE_TAG_OHOS, freqsfmt);
1142 }
1143 
SetTotalFileSizeLimitAndSliceMaxDuration(const uint64_t & totalFileSize,const uint64_t & sliceMaxDuration)1144 void SetTotalFileSizeLimitAndSliceMaxDuration(const uint64_t& totalFileSize, const uint64_t& sliceMaxDuration)
1145 {
1146     if (totalFileSize == 0) {
1147         g_totalFileSizeLimit = DEFAULT_TOTAL_CACHE_FILE_SIZE * BYTE_PER_MB;
1148     } else {
1149         g_totalFileSizeLimit = totalFileSize * BYTE_PER_MB;
1150     }
1151     if (sliceMaxDuration == 0) {
1152         g_sliceMaxDuration = DEFAULT_TRACE_SLICE_DURATION;
1153     } else {
1154         g_sliceMaxDuration = sliceMaxDuration;
1155     }
1156 }
1157 
GetFileInCache(TraceRetInfo & traceRetInfo)1158 void GetFileInCache(TraceRetInfo& traceRetInfo)
1159 {
1160     HILOG_INFO(LOG_CORE, "DumpTrace: Trace is caching, get cache file.");
1161     SearchTraceFiles(g_utDestTraceStartTime, g_utDestTraceEndTime, traceRetInfo);
1162     if (traceRetInfo.outputFiles.empty()) {
1163         HILOG_ERROR(LOG_CORE, "DumpTrace: Trace is caching, but failed to retrieve target trace file.");
1164         traceRetInfo.errorCode = OUT_OF_TIME;
1165     } else {
1166         for (const auto& file: traceRetInfo.outputFiles) {
1167             HILOG_INFO(LOG_CORE, "dumptrace file is %{public}s.", file.c_str());
1168         }
1169         traceRetInfo.errorCode = SUCCESS;
1170     }
1171 }
1172 
CheckTraceDumpStatus(const int maxDuration,const uint64_t utTraceEndTime,TraceRetInfo & ret)1173 bool CheckTraceDumpStatus(const int maxDuration, const uint64_t utTraceEndTime, TraceRetInfo& ret)
1174 {
1175     if (!IsTraceOpen() || IsRecordOn()) {
1176         HILOG_ERROR(LOG_CORE, "CheckTraceDumpStatus: WRONG_TRACE_MODE, current trace mode: %{public}u.",
1177             static_cast<uint32_t>(g_traceMode));
1178         ret.errorCode = WRONG_TRACE_MODE;
1179         return false;
1180     }
1181     if (maxDuration < 0) {
1182         HILOG_ERROR(LOG_CORE, "CheckTraceDumpStatus: Illegal input: maxDuration = %{public}d < 0.", maxDuration);
1183         ret.errorCode = INVALID_MAX_DURATION;
1184         return false;
1185     }
1186 
1187     if (!CheckServiceRunning()) {
1188         HILOG_ERROR(LOG_CORE, "CheckTraceDumpStatus: TRACE_IS_OCCUPIED.");
1189         ret.errorCode = TRACE_IS_OCCUPIED;
1190         return false;
1191     }
1192     return true;
1193 }
1194 } // namespace
1195 
1196 #ifdef HITRACE_UNITTEST
SetSysInitParamTags(uint64_t sysInitParamTags)1197 void SetSysInitParamTags(uint64_t sysInitParamTags)
1198 {
1199     g_sysInitParamTags = sysInitParamTags;
1200 }
1201 
SetCheckParam()1202 bool SetCheckParam()
1203 {
1204     int ret = CheckParam();
1205     return ret;
1206 }
1207 #endif
1208 
GetTraceMode()1209 uint8_t GetTraceMode()
1210 {
1211     std::lock_guard<std::mutex> lock(g_traceMutex);
1212     return g_traceMode;
1213 }
1214 
OpenTrace(const std::vector<std::string> & tagGroups)1215 TraceErrorCode OpenTrace(const std::vector<std::string>& tagGroups)
1216 {
1217     std::lock_guard<std::mutex> lock(g_traceMutex);
1218     ClearFilterParam();
1219     if (g_traceMode != TraceMode::CLOSE) {
1220         HILOG_ERROR(LOG_CORE, "OpenTrace: WRONG_TRACE_MODE, current trace mode: %{public}u.",
1221             static_cast<uint32_t>(g_traceMode));
1222         return WRONG_TRACE_MODE;
1223     }
1224     if (!IsTraceMounted(g_traceRootPath)) {
1225         HILOG_ERROR(LOG_CORE, "OpenTrace: TRACE_NOT_SUPPORTED.");
1226         return TRACE_NOT_SUPPORTED;
1227     }
1228 
1229     TraceErrorCode ret = HandleDefaultTraceOpen(tagGroups);
1230     if (ret != SUCCESS) {
1231         HILOG_ERROR(LOG_CORE, "OpenTrace: failed.");
1232         return ret;
1233     }
1234     RefreshTraceVec(g_traceFileVec, TRACE_SNAPSHOT);
1235     std::vector<TraceFileInfo> cacheFileVec;
1236     RefreshTraceVec(cacheFileVec, TRACE_CACHE);
1237     ClearCacheTraceFileByDuration(cacheFileVec);
1238     g_sysInitParamTags = GetSysParamTags();
1239     g_traceMode = TraceMode::OPEN;
1240     HILOG_INFO(LOG_CORE, "OpenTrace: open by tag group success.");
1241     StartCpuBufferBalanceService();
1242     return ret;
1243 }
1244 
OpenTrace(const std::string & args)1245 TraceErrorCode OpenTrace(const std::string& args)
1246 {
1247     std::lock_guard<std::mutex> lock(g_traceMutex);
1248     if (g_traceMode != TraceMode::CLOSE) {
1249         HILOG_ERROR(LOG_CORE, "OpenTrace: WRONG_TRACE_MODE, current trace mode: %{public}u.",
1250             static_cast<uint32_t>(g_traceMode));
1251         return WRONG_TRACE_MODE;
1252     }
1253 
1254     if (!IsTraceMounted(g_traceRootPath)) {
1255         HILOG_ERROR(LOG_CORE, "OpenTrace: TRACE_NOT_SUPPORTED.");
1256         return TRACE_NOT_SUPPORTED;
1257     }
1258 
1259     TraceJsonParser& traceJsonParser = TraceJsonParser::Instance();
1260     const std::map<std::string, TraceTag>& allTags = traceJsonParser.GetAllTagInfos();
1261     const std::map<std::string, std::vector<std::string>>& tagGroupTable = traceJsonParser.GetTagGroups();
1262     std::vector<std::string> traceFormats = traceJsonParser.GetBaseFmtPath();
1263 
1264     if (allTags.size() == 0 || tagGroupTable.size() == 0) {
1265         HILOG_ERROR(LOG_CORE, "OpenTrace: ParseTagInfo TAG_ERROR.");
1266         return TAG_ERROR;
1267     }
1268     // parse args
1269     TraceParams traceParams;
1270     if (!ParseArgs(args, traceParams, allTags, tagGroupTable)) {
1271         HILOG_ERROR(LOG_CORE, "OpenTrace: TAG_ERROR.");
1272         return TAG_ERROR;
1273     }
1274 
1275     TraceErrorCode ret = HandleTraceOpen(traceParams, allTags, tagGroupTable, traceFormats);
1276     if (ret != SUCCESS) {
1277         HILOG_ERROR(LOG_CORE, "OpenTrace: open by args failed.");
1278         return FILE_ERROR;
1279     }
1280     g_sysInitParamTags = GetSysParamTags();
1281     g_traceMode = TraceMode::OPEN;
1282     HILOG_INFO(LOG_CORE, "OpenTrace: open by args success, args:%{public}s.", args.c_str());
1283     StartCpuBufferBalanceService();
1284     return ret;
1285 }
1286 
CacheTraceOn(uint64_t totalFileSize,uint64_t sliceMaxDuration)1287 TraceErrorCode CacheTraceOn(uint64_t totalFileSize, uint64_t sliceMaxDuration)
1288 {
1289     std::lock_guard<std::mutex> lock(g_traceMutex);
1290     if (g_traceMode != TraceMode::OPEN) {
1291         HILOG_ERROR(LOG_CORE, "CacheTraceOn: WRONG_TRACE_MODE, current trace mode: %{public}u.",
1292             static_cast<uint32_t>(g_traceMode));
1293         return WRONG_TRACE_MODE;
1294     }
1295     if (!TraceDumpExecutor::GetInstance().PreCheckDumpTraceLoopStatus()) {
1296         HILOG_ERROR(LOG_CORE, "CacheTraceOn: cache trace is dumping now.");
1297         return WRONG_TRACE_MODE;
1298     }
1299     SetTotalFileSizeLimitAndSliceMaxDuration(totalFileSize, sliceMaxDuration);
1300     auto it = []() {
1301         ProcessCacheTask();
1302     };
1303     std::thread task(it);
1304     task.detach();
1305     HILOG_INFO(LOG_CORE, "Caching trace on.");
1306     g_traceMode |= TraceMode::CACHE;
1307     return SUCCESS;
1308 }
1309 
CacheTraceOff()1310 TraceErrorCode CacheTraceOff()
1311 {
1312     std::lock_guard<std::mutex> lock(g_traceMutex);
1313     if (g_traceMode != (TraceMode::OPEN | TraceMode::CACHE)) {
1314         HILOG_ERROR(LOG_CORE,
1315             "CacheTraceOff: WRONG_TRACE_MODE, current trace mode: %{public}u.", static_cast<uint32_t>(g_traceMode));
1316         return WRONG_TRACE_MODE;
1317     }
1318     TraceDumpExecutor::GetInstance().StopCacheTraceLoop();
1319     HILOG_INFO(LOG_CORE, "Caching trace off.");
1320     g_traceMode &= ~TraceMode::CACHE;
1321     return SUCCESS;
1322 }
1323 
DumpTrace(int maxDuration,uint64_t utTraceEndTime)1324 TraceRetInfo DumpTrace(int maxDuration, uint64_t utTraceEndTime)
1325 {
1326     std::lock_guard<std::mutex> lock(g_traceMutex);
1327     TraceRetInfo ret;
1328     ret.mode = g_traceMode;
1329     if (!CheckTraceDumpStatus(maxDuration, utTraceEndTime, ret)) {
1330         return ret;
1331     }
1332     FileAgeingUtils::HandleAgeing(g_traceFileVec, TraceDumpType::TRACE_SNAPSHOT);
1333     HILOG_INFO(LOG_CORE, "DumpTrace start, target duration is %{public}d, target endtime is (%{public}" PRIu64 ").",
1334         maxDuration, utTraceEndTime);
1335     SetDestTraceTimeAndDuration(maxDuration, utTraceEndTime);
1336     int32_t committedDuration =
1337         std::min(DEFAULT_FULL_TRACE_LENGTH, static_cast<int32_t>(g_utDestTraceEndTime - g_utDestTraceStartTime));
1338     if (UNEXPECTANTLY(IsCacheOn())) {
1339         GetFileInCache(ret);
1340         LoadDumpRet(ret, committedDuration);
1341         SanitizeRetInfo(ret);
1342         return ret;
1343     }
1344 
1345     ret.errorCode = SetTimeIntervalBoundary(maxDuration, utTraceEndTime);
1346     if (ret.errorCode != SUCCESS) {
1347         return ret;
1348     }
1349     g_firstPageTimestamp = UINT64_MAX;
1350     g_lastPageTimestamp = 0;
1351 
1352     ret.errorCode = ProcessDumpSync(ret);
1353     LoadDumpRet(ret, committedDuration);
1354     RestoreTimeIntervalBoundary();
1355     SanitizeRetInfo(ret);
1356     HILOG_INFO(LOG_CORE, "DumpTrace with time limit done.");
1357     return ret;
1358 }
1359 
DumpTraceAsync(int maxDuration,uint64_t utTraceEndTime,int64_t fileSizeLimit,std::function<void (TraceRetInfo)> asyncCallback)1360 TraceRetInfo DumpTraceAsync(int maxDuration, uint64_t utTraceEndTime, int64_t fileSizeLimit,
1361     std::function<void(TraceRetInfo)> asyncCallback)
1362 {
1363     std::lock_guard<std::mutex> lock(g_traceMutex);
1364     TraceRetInfo ret;
1365     ret.mode = g_traceMode;
1366     if (!CheckTraceDumpStatus(maxDuration, utTraceEndTime, ret)) {
1367         return ret;
1368     }
1369     FileAgeingUtils::HandleAgeing(g_traceFileVec, TraceDumpType::TRACE_SNAPSHOT);
1370 
1371     HILOG_INFO(LOG_CORE, "DumpTraceAsync start, target duration is %{public}d, target endtime is %{public}" PRIu64 ".",
1372         maxDuration, utTraceEndTime);
1373     SetDestTraceTimeAndDuration(maxDuration, utTraceEndTime);
1374     int32_t committedDuration =
1375         std::min(DEFAULT_FULL_TRACE_LENGTH, static_cast<int32_t>(g_utDestTraceEndTime - g_utDestTraceStartTime));
1376     if (UNEXPECTANTLY(IsCacheOn())) {
1377         GetFileInCache(ret);
1378         LoadDumpRet(ret, committedDuration);
1379         SanitizeRetInfo(ret);
1380         if (asyncCallback != nullptr) {
1381             asyncCallback(ret);
1382         }
1383         return ret;
1384     }
1385     ret.errorCode = SetTimeIntervalBoundary(maxDuration, utTraceEndTime);
1386     if (ret.errorCode != SUCCESS) {
1387         return ret;
1388     }
1389     g_firstPageTimestamp = UINT64_MAX;
1390     g_lastPageTimestamp = 0;
1391     auto taskid = GetCurBootTime();
1392     std::unique_lock<std::mutex> retLck(g_traceRetAndCallbackMutex);
1393     g_callbacks[taskid] = asyncCallback;
1394     ret.errorCode = ProcessDumpAsync(taskid, fileSizeLimit, ret);
1395     if (ret.errorCode != TraceErrorCode::ASYNC_DUMP) {
1396         LoadDumpRet(ret, committedDuration);
1397         SanitizeRetInfo(ret);
1398         if (g_callbacks[taskid] != nullptr) {
1399             g_callbacks[taskid](ret);
1400         }
1401         g_callbacks.erase(taskid);
1402     } else {
1403         ret.errorCode = TraceErrorCode::SUCCESS;
1404         g_traceRetInfos[taskid] = ret;
1405     }
1406     retLck.unlock();
1407     RestoreTimeIntervalBoundary();
1408     HILOG_INFO(LOG_CORE, "DumpTraceAsync with time limit done. output file size: %{public}zu", ret.outputFiles.size());
1409     return ret;
1410 }
1411 
RecordTraceOn()1412 TraceErrorCode RecordTraceOn()
1413 {
1414     std::lock_guard<std::mutex> lock(g_traceMutex);
1415     // check current trace status
1416     if (g_traceMode != TraceMode::OPEN) {
1417         HILOG_ERROR(LOG_CORE, "RecordTraceOn: WRONG_TRACE_MODE, current trace mode: %{public}u.",
1418             static_cast<uint32_t>(g_traceMode));
1419         return WRONG_TRACE_MODE;
1420     }
1421     if (!TraceDumpExecutor::GetInstance().PreCheckDumpTraceLoopStatus()) {
1422         HILOG_ERROR(LOG_CORE, "RecordTraceOn: record trace is dumping now.");
1423         return WRONG_TRACE_MODE;
1424     }
1425     auto it = []() {
1426         ProcessRecordTask();
1427     };
1428     std::thread task(it);
1429     task.detach();
1430     WriteCpuFreqTrace();
1431     HILOG_INFO(LOG_CORE, "Recording trace on.");
1432     g_traceMode |= TraceMode::RECORD;
1433     return SUCCESS;
1434 }
1435 
RecordTraceOff()1436 TraceRetInfo RecordTraceOff()
1437 {
1438     std::lock_guard<std::mutex> lock(g_traceMutex);
1439     TraceRetInfo ret;
1440     // check current trace status
1441     if (!IsRecordOn()) {
1442         HILOG_ERROR(LOG_CORE, "RecordTraceOff: The current state is %{public}u, data exception.",
1443             static_cast<uint32_t>(g_traceMode));
1444         ret.errorCode = WRONG_TRACE_MODE;
1445         return ret;
1446     }
1447 
1448     ret.outputFiles = TraceDumpExecutor::GetInstance().StopDumpTraceLoop();
1449     ret.errorCode = SUCCESS;
1450     HILOG_INFO(LOG_CORE, "Recording trace off.");
1451     g_traceMode &= ~TraceMode::RECORD;
1452     return ret;
1453 }
1454 
CloseTrace()1455 TraceErrorCode CloseTrace()
1456 {
1457     std::lock_guard<std::mutex> lock(g_traceMutex);
1458     ClearFilterParam();
1459     HILOG_INFO(LOG_CORE, "CloseTrace start.");
1460     if (g_traceMode == TraceMode::CLOSE) {
1461         HILOG_INFO(LOG_CORE, "Trace has already been closed.");
1462         return SUCCESS;
1463     }
1464     if (IsRecordOn() || IsCacheOn()) {
1465         TraceDumpExecutor::GetInstance().StopDumpTraceLoop();
1466     }
1467     g_traceMode = TraceMode::CLOSE;
1468     OHOS::system::SetParameter(TRACE_KEY_APP_PID, "-1");
1469 
1470     const std::map<std::string, TraceTag>& allTags = TraceJsonParser::Instance().GetAllTagInfos();
1471 
1472     if (allTags.size() == 0) {
1473         HILOG_ERROR(LOG_CORE, "CloseTrace: ParseTagInfo TAG_ERROR.");
1474         return TAG_ERROR;
1475     }
1476 
1477     TraceInit(allTags);
1478     TruncateFile(TRACE_NODE);
1479     HILOG_INFO(LOG_CORE, "CloseTrace done.");
1480     return SUCCESS;
1481 }
1482 
SetTraceStatus(bool enable)1483 TraceErrorCode SetTraceStatus(bool enable)
1484 {
1485     HILOG_INFO(LOG_CORE, "SetTraceStatus %{public}d", enable);
1486     std::lock_guard<std::mutex> lock(g_traceMutex);
1487     if (g_traceRootPath.empty()) {
1488         if (!IsTraceMounted(g_traceRootPath)) {
1489             HILOG_ERROR(LOG_CORE, "SetTraceStatus: TRACE_NOT_SUPPORTED.");
1490             return TRACE_NOT_SUPPORTED;
1491         }
1492     }
1493 
1494     if (!SetTraceNodeStatus(TRACING_ON_NODE, enable)) {
1495         return WRITE_TRACE_INFO_ERROR;
1496     };
1497 
1498     return SUCCESS;
1499 }
1500 } // namespace Hitrace
1501 } // namespace HiviewDFX
1502 } // namespace OHOS
1503