• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: FlowController implements
16  */
17 #include "flow_controller.h"
18 
19 #include <algorithm>
20 #include <cinttypes>
21 #include <set>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <regex>
26 
27 #include "hitrace_ops.h"
28 #include "file_utils.h"
29 #include "ftrace_field_parser.h"
30 #include "ftrace_fs_ops.h"
31 #include "logging.h"
32 
33 namespace {
34 #ifndef PAGE_SIZE
35     constexpr uint32_t PAGE_SIZE = 4096;
36 #endif
37     constexpr int KB_PER_PAGE = PAGE_SIZE / 1024;
38     constexpr uint32_t BYTE_PER_KB = 1024;
39     constexpr uint32_t MAX_FLUSH_INTERVAL = 1800 * 1000;
40     constexpr uint32_t MAX_FLUSH_THRESHOLD = 128 * 1024 * 1024;
41     constexpr uint32_t MAX_TRACE_PERIOD_MS = 720 * 1000;
42     constexpr uint32_t MAX_BUFFER_SIZE_KB = 64 * 1024; // 64MB
43     constexpr uint32_t MIN_BUFFER_SIZE_KB = 1024;      // 1 MB
44     constexpr uint32_t DEFAULT_TRACE_PERIOD_MS = 250;  // 250 ms
45     constexpr uint32_t MAX_BLOCK_SIZE_PAGES = 4096;    // 16 MB
46     constexpr uint32_t MIN_BLOCK_SIZE_PAGES = 256;     // 1  MB
47     const std::set<std::string> g_availableClocks = { "boot", "global", "local", "mono" };
48 
GetProcessorNumFromString(char * str)49     int GetProcessorNumFromString(char *str)
50     {
51         int processorNum = 0;
52         int lastNum = -1;
53         char *s = str;
54         while (*s != '\0') {
55             if (isdigit(*s)) {
56                 int currentNum = strtol(s, &s, 10);
57                 if (lastNum == -1) {
58                     processorNum++;
59                 } else {
60                     processorNum += currentNum - lastNum;
61                 }
62                 lastNum = currentNum;
63             } else {
64                 if (*s == ',') {
65                     lastNum = -1;
66                 }
67                 s++;
68             }
69         }
70         return processorNum;
71     }
72 
GetProcessorNum()73     int GetProcessorNum()
74     {
75         FILE *fp = fopen("/sys/devices/system/cpu/online", "r");
76         if (fp == nullptr) {
77             HILOG_ERROR(LOG_CORE, "/sys/devices/system/cpu/online not exist, use sysconf()");
78             return sysconf(_SC_NPROCESSORS_CONF);
79         }
80 
81         int processorNum = 0;
82         char *line = nullptr;
83         size_t len = 0;
84         if (getline(&line, &len, fp) != -1) {
85             processorNum = GetProcessorNumFromString(line);
86             free(line);
87         }
88         fclose(fp);
89 
90         if (processorNum <= 0) {
91             HILOG_ERROR(LOG_CORE, "parse processor num fail, use sysconf()");
92             return sysconf(_SC_NPROCESSORS_CONF);
93         }
94         return processorNum;
95     }
96 } // namespace
97 
98 FTRACE_NS_BEGIN
GetTraceOps()99 std::unique_ptr<TraceOps> FlowController::GetTraceOps()
100 {
101     std::vector<std::unique_ptr<TraceOps>> traceOps;
102     traceOps.emplace_back(std::make_unique<HitraceOps>());
103 
104     for (size_t i = 0; i < traceOps.size(); i++) {
105         auto& ops = traceOps[i];
106         CHECK_TRUE(ops != nullptr, nullptr, "traceOps[%zu] is null!", i);
107         if (ops->IsSupported()) {
108             return std::move(ops);
109         }
110     }
111     return nullptr;
112 }
113 
FlowController()114 FlowController::FlowController()
115 {
116     ftraceParser_ = std::make_unique<FtraceParser>();
117     ksymsParser_ = std::make_unique<KernelSymbolsParser>();
118     ftraceSupported_ = FtraceFsOps::GetInstance().GetFtraceRoot().size() > 0;
119 }
120 
~FlowController(void)121 FlowController::~FlowController(void)
122 {
123     HILOG_INFO(LOG_CORE, "FlowController destroy!");
124 }
125 
SetWriter(const WriterStructPtr & writer)126 int FlowController::SetWriter(const WriterStructPtr& writer)
127 {
128     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
129     CHECK_TRUE(resultWriter_ == nullptr, 0, "writer already setted!");
130 
131     CHECK_NOTNULL(writer, -1, "writer null!");
132     auto transmiter = std::make_unique<ResultTransporter>("Transporter", writer);
133     CHECK_NOTNULL(transmiter, -1, "create ResultTransporter FAILED!");
134 
135     // get CPU core numbers
136     int nprocs = GetProcessorNum();
137     CHECK_TRUE(nprocs > 0, -1, "get processor number failed!");
138     platformCpuNum_ = nprocs;
139 
140     auto traceOps = GetTraceOps();
141     CHECK_NOTNULL(traceOps, -1, "get trace ops failed!");
142 
143     // init FtraceParser
144     CHECK_NOTNULL(ftraceParser_, 0, "FtraceParser create FAILED!");
145     CHECK_TRUE(ftraceParser_->Init(), -1, "ftrace parser init failed!");
146 
147     // init KernelSymbolsParser
148     CHECK_NOTNULL(ksymsParser_, 0, "KernelSymbolsParser create FAILED!");
149     ksymsParser_->Parse(FtraceFsOps::GetInstance().GetKernelSymbols());
150 
151     CHECK_TRUE(AddPlatformEventsToParser(), -1, "add platform events to parser failed!");
152     // disable all trace events
153     DisableAllCategories();
154 
155     resultWriter_ = writer;
156     tansporter_ = std::move(transmiter);
157     traceOps_ = std::move(traceOps);
158     return 0;
159 }
160 
CreateRawDataReaders()161 bool FlowController::CreateRawDataReaders()
162 {
163     for (int i = 0; i < platformCpuNum_; i++) {
164         auto reader = std::make_unique<FtraceDataReader>(FtraceFsOps::GetInstance().GetRawTracePath(i));
165         CHECK_NOTNULL(reader, false, "create reader %d FAILED!", i);
166         ftraceReaders_.emplace_back(std::move(reader));
167     }
168     return true;
169 }
170 
CreatePagedMemoryPool()171 bool FlowController::CreatePagedMemoryPool()
172 {
173     HILOG_INFO(LOG_CORE, "create memory pool, buffer_size_kb = %u", bufferSizeKb_);
174     size_t bufferSizePages = bufferSizeKb_ / KB_PER_PAGE;
175     size_t pagesPerBlock = bufferSizePages / static_cast<size_t>(platformCpuNum_);
176     if (pagesPerBlock < MIN_BLOCK_SIZE_PAGES) {
177         pagesPerBlock = MIN_BLOCK_SIZE_PAGES;
178     }
179     if (pagesPerBlock > MAX_BLOCK_SIZE_PAGES) {
180         pagesPerBlock = MAX_BLOCK_SIZE_PAGES;
181     }
182     memPool_ = std::make_unique<PagedMemPool>(pagesPerBlock, platformCpuNum_);
183     CHECK_NOTNULL(memPool_, false, "create PagedMemPool FAILED!");
184     return true;
185 }
186 
CreateRawDataBuffers()187 bool FlowController::CreateRawDataBuffers()
188 {
189     for (int i = 0; i < platformCpuNum_; i++) {
190         using u8ptr = std::unique_ptr<uint8_t>::pointer;
191         auto buffer = std::shared_ptr<uint8_t>(reinterpret_cast<u8ptr>(memPool_->Allocate()),
192             [&](u8ptr block) { this->memPool_->Recycle(block); });
193         CHECK_NOTNULL(buffer, false, "create buffer %d failed!", i);
194         ftraceBuffers_.push_back(buffer);
195     };
196     return true;
197 }
198 
CreateRawDataCaches()199 bool FlowController::CreateRawDataCaches()
200 {
201     for (size_t i = 0; i < rawDataDumpPath_.size(); i++) {
202         auto& path = rawDataDumpPath_[i];
203         HILOG_INFO(LOG_CORE, "create raw data cache[%zu]: %s", i, path.c_str());
204 
205         if (path.empty() || (path.length() >= PATH_MAX)) {
206             HILOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
207             return false;
208         }
209 
210         std::regex dirNameRegex("[.~-]");
211         std::regex fileNameRegex("[\\/:*?\"<>|]");
212         size_t pos = path.rfind("/");
213         if (pos != std::string::npos) {
214             std::string dirName = path.substr(0, pos + 1);
215             std::string fileName = path.substr(pos + 1, path.length() - pos - 1);
216             if (std::regex_search(dirName, dirNameRegex) || std::regex_search(fileName, fileNameRegex)) {
217                 HILOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
218                 return false;
219             }
220         } else {
221             if (std::regex_search(path, fileNameRegex)) {
222                 HILOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
223                 return false;
224             }
225         }
226 
227         auto cache = std::shared_ptr<FILE>(fopen(path.c_str(), "wb+"), [](FILE* fp) { fclose(fp); });
228         CHECK_NOTNULL(cache, false, "create cache[%zu]: %s failed!", i, path.c_str());
229         rawDataDumpFile_.emplace_back(std::move(cache));
230     }
231     return true;
232 }
233 
ParseBasicData()234 bool FlowController::ParseBasicData()
235 {
236     // get clock times
237     if (getClockTimes_) {
238         CHECK_TRUE(ReportClockTimes(), -1, "report clock times FAILED!");
239     }
240 
241     // parse kernel symbols
242     if (parseKsyms_) {
243         CHECK_TRUE(ParseKernelSymbols(), -1, "parse kernel symbols FAILED!");
244     }
245 
246     // parse per cpu stats
247     CHECK_TRUE(ParsePerCpuStatus(TRACE_START), -1, "parse TRACE_START stats failed!");
248 
249     return 0;
250 }
251 
StartCapture(void)252 int FlowController::StartCapture(void)
253 {
254     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
255     CHECK_NOTNULL(ftraceParser_, -1, "create FtraceParser FAILED!");
256     CHECK_NOTNULL(ksymsParser_, -1, "create KernelSymbolsParser FAILED!");
257     CHECK_NOTNULL(tansporter_, -1, "crated ResultTransporter FAILED!");
258     CHECK_NOTNULL(traceOps_, -1, "create TraceOps FAILED!");
259 
260     CHECK_TRUE(ParseBasicData() == 0, -1, "parse basic data failed!");
261 
262     // create memory pool, and raw data readers, buffers, caches.
263     CHECK_TRUE(CreatePagedMemoryPool(), -1, "create paged memory pool failed!");
264     CHECK_TRUE(CreateRawDataReaders(), -1, "create raw data readers failed!");
265     CHECK_TRUE(CreateRawDataBuffers(), -1, "create raw data buffers failed!");
266     CHECK_TRUE(CreateRawDataCaches(), -1, "create raw data caches failed!");
267 
268     // clear old trace
269     FtraceFsOps::GetInstance().ClearTraceBuffer();
270 
271     // enable additional record options
272     FtraceFsOps::GetInstance().SetRecordCmdOption(true);
273     FtraceFsOps::GetInstance().SetRecordTgidOption(true);
274 
275     // start ftrace event data polling thread
276     keepRunning_ = true;
277     pollThread_ = std::thread(&FlowController::CaptureWork, this);
278 
279     // set trace_clock
280     traceOps_->SetTraceClock(traceClock_);
281     // enable ftrace event switches
282     if (traceCategories_.size() > 0) {
283         traceOps_->EnableCategories(traceCategories_, hitraceTime_);
284     }
285 
286     // hitrace will reset trace buffer size, so reset user config after hitrace
287     FtraceFsOps::GetInstance().SetBufferSizeKb(bufferSizeKb_);
288     EnableTraceEvents();
289     return 0;
290 }
291 
CaptureWork()292 void FlowController::CaptureWork()
293 {
294     pthread_setname_np(pthread_self(), "TraceReader");
295     HILOG_INFO(LOG_CORE, "FlowController::CaptureWork start!");
296 
297     auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
298     std::vector<long> rawDataBytes(platformCpuNum_, 0);
299 
300     while (keepRunning_) {
301         std::this_thread::sleep_for(tracePeriod);
302 
303         // read data from percpu trace_pipe_raw, consume kernel ring buffers
304         for (size_t i = 0; i < rawDataBytes.size(); i++) {
305             if (flushCacheData_ && !keepRunning_) {
306                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
307                 return;
308             }
309             long nbytes = ReadEventData(i);
310             rawDataBytes[i] = nbytes;
311         }
312 
313         // append buffer data to cache
314         for (size_t i = 0; i < rawDataDumpFile_.size(); i++) {
315             if (flushCacheData_ && !keepRunning_) {
316                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
317                 return;
318             }
319             auto& file = rawDataDumpFile_[i];
320             size_t writen = fwrite(ftraceBuffers_[i].get(), sizeof(uint8_t), rawDataBytes[i], file.get());
321             if (rawDataBytes[i] == 0) {
322                 HILOG_INFO(LOG_CORE, "Append raw data to cache[%zu]: %zu/%ld bytes", i, writen, rawDataBytes[i]);
323             }
324         }
325 
326         // parse ftrace metadata
327         ftraceParser_->ParseSavedTgid(FtraceFsOps::GetInstance().GetSavedTgids());
328         ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
329 
330         // parse ftrace percpu event data
331         for (size_t i = 0; i < rawDataBytes.size(); i++) {
332             if (flushCacheData_ && !keepRunning_) {
333                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
334                 return;
335             }
336             ParseEventData(i, rawDataBytes[i]);
337             if (rawDataBytes[i] == 0) {
338                 HILOG_INFO(LOG_CORE, "Parse raw data for CPU%zu: %ld bytes...", i, rawDataBytes[i]);
339             }
340         }
341     }
342 
343     tansporter_->Flush();
344     HILOG_DEBUG(LOG_CORE, "FlowController::CaptureWork done!");
345 }
346 
ReadEventData(int cpuid)347 long FlowController::ReadEventData(int cpuid)
348 {
349     auto buffer = ftraceBuffers_[cpuid].get();
350     auto reader = ftraceReaders_[cpuid].get();
351     auto bufferSize = static_cast<long>(memPool_->GetBlockSize());
352     (void)memset_s(buffer, bufferSize, 0, bufferSize);
353 
354     long nbytes = 0;
355     long used = 0;
356     long rest = bufferSize;
357     while ((nbytes = reader->Read(&buffer[used], rest)) > 0 && used < bufferSize) {
358         CHECK_TRUE(used % PAGE_SIZE == 0, used, "used invalid!");
359         used += nbytes;
360         rest -= nbytes;
361     }
362     return used;
363 }
364 
ParseEventData(int cpuid,long dataSize)365 bool FlowController::ParseEventData(int cpuid, long dataSize)
366 {
367     auto buffer = ftraceBuffers_[cpuid].get();
368     auto endPtr = buffer + dataSize;
369 
370     for (auto page = buffer; page < endPtr; page += PAGE_SIZE) {
371         CHECK_TRUE(ParseFtraceEvent(cpuid, page), false, "parse raw event for cpu-%d failed!", cpuid);
372     }
373     return true;
374 }
375 
StopCapture(void)376 int FlowController::StopCapture(void)
377 {
378     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
379     CHECK_NOTNULL(tansporter_, -1, "crate ResultTransporter FAILED!");
380     CHECK_NOTNULL(traceOps_, -1, "create TraceOps FAILED!");
381 
382     if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
383         HILOG_INFO(LOG_CORE, "StopCapture: ftrace event is not set, return false");
384         return -1;
385     }
386 
387     // disable ftrace event switches
388     DisableTraceEvents();
389 
390     // stop ftrace event data polling thread
391     keepRunning_ = false;
392     if (pollThread_.joinable()) {
393         HILOG_INFO(LOG_CORE, "join thread start!\n");
394         pollThread_.join();
395         HILOG_INFO(LOG_CORE, "join thread  done!\n");
396     }
397 
398     // parse per cpu stats
399     CHECK_TRUE(ParsePerCpuStatus(TRACE_END), -1, "parse TRACE_END stats failed!");
400 
401     // disable userspace trace triggers
402     // because trace cmd will read trace buffer,
403     // so we to this action after polling thread exit.
404     if (traceCategories_.size() > 0) {
405         traceOps_->DisableCategories();
406     }
407     tansporter_->Flush();
408 
409     // release resources
410     rawDataDumpFile_.clear(); // close raw data dump files
411     ftraceReaders_.clear();   // release ftrace data readers
412     ftraceBuffers_.clear();   // release ftrace event read buffers
413     memPool_.reset();         // release memory pool
414     return 0;
415 }
416 
ParsePerCpuStatus(int stage)417 bool FlowController::ParsePerCpuStatus(int stage)
418 {
419     auto tracePacket = std::make_unique<TracePluginResult>();
420     CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
421 
422     auto cpuStatsMsg = tracePacket->add_ftrace_cpu_stats();
423     if (stage == TRACE_START) {
424         cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_START);
425     } else {
426         cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_END);
427     }
428 
429     std::string traceClock = FtraceFsOps::GetInstance().GetTraceClock();
430     if (traceClock.size() > 0) {
431         cpuStatsMsg->set_trace_clock(traceClock);
432     }
433 
434     for (int i = 0; i < platformCpuNum_; i++) {
435         HILOG_INFO(LOG_CORE, "[%d] ParsePerCpuStatus %d!", i, stage);
436         PerCpuStats stats = {};
437         stats.cpuIndex = i;
438         ftraceParser_->ParsePerCpuStatus(stats, FtraceFsOps::GetInstance().GetPerCpuStats(i));
439         auto perCpuMsg = cpuStatsMsg->add_per_cpu_stats();
440         perCpuMsg->set_cpu(stats.cpuIndex);
441         perCpuMsg->set_entries(stats.entries);
442         perCpuMsg->set_overrun(stats.overrun);
443         perCpuMsg->set_commit_overrun(stats.commitOverrun);
444         perCpuMsg->set_bytes(stats.bytes);
445         perCpuMsg->set_oldest_event_ts(stats.oldestEventTs);
446         perCpuMsg->set_now_ts(stats.nowTs);
447         perCpuMsg->set_dropped_events(stats.droppedEvents);
448         perCpuMsg->set_read_events(stats.readEvents);
449     }
450 
451     return tansporter_->Submit(std::move(tracePacket));
452 }
453 
ReportClockTimes()454 bool FlowController::ReportClockTimes()
455 {
456     auto traceResult = std::make_unique<TracePluginResult>();
457     CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
458 
459     std::map<clockid_t, ClockDetailMsg::ClockId> clocksMap = {
460         {CLOCK_REALTIME, ClockDetailMsg::REALTIME},
461         {CLOCK_REALTIME_COARSE, ClockDetailMsg::REALTIME_COARSE},
462         {CLOCK_MONOTONIC, ClockDetailMsg::MONOTONIC},
463         {CLOCK_MONOTONIC_COARSE, ClockDetailMsg::MONOTONIC_COARSE},
464         {CLOCK_MONOTONIC_RAW, ClockDetailMsg::MONOTONIC_RAW},
465         {CLOCK_BOOTTIME, ClockDetailMsg::BOOTTIME},
466     };
467     for (auto& entry : clocksMap) {
468         struct timespec ts = {};
469         clock_gettime(entry.first, &ts);
470         auto clockMsg = traceResult->add_clocks_detail();
471         CHECK_NOTNULL(clockMsg, false, "add clock_detail failed for %d!", entry.first);
472         clockMsg->set_id(entry.second);
473         auto timeMsg = clockMsg->mutable_time();
474         timeMsg->set_tv_sec(ts.tv_sec);
475         timeMsg->set_tv_nsec(ts.tv_nsec);
476 
477         struct timespec tsResolution = {};
478         clock_getres(entry.first, &tsResolution);
479         auto resolutionMsg = clockMsg->mutable_resolution();
480         resolutionMsg->set_tv_sec(tsResolution.tv_sec);
481         resolutionMsg->set_tv_nsec(tsResolution.tv_nsec);
482     }
483     return tansporter_->Submit(std::move(traceResult));
484 }
485 
ParseKernelSymbols()486 bool FlowController::ParseKernelSymbols()
487 {
488     auto traceResult = std::make_unique<TracePluginResult>();
489     CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
490 
491     ksymsParser_->Accept([&traceResult](const KernelSymbol& symbol) {
492         auto symbolDetail = traceResult->add_symbols_detail();
493         symbolDetail->set_symbol_addr(symbol.addr);
494         symbolDetail->set_symbol_name(symbol.name);
495     });
496     HILOG_INFO(LOG_CORE, "parse kernel symbol message done!");
497     return tansporter_->Submit(std::move(traceResult));
498 }
499 
ParseFtraceEvent(int cpuid,uint8_t page[])500 bool FlowController::ParseFtraceEvent(int cpuid, uint8_t page[])
501 {
502     auto tracePacket = std::make_unique<TracePluginResult>();
503     CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
504 
505     auto cpudetail = tracePacket->add_ftrace_cpu_detail();
506     cpudetail->set_cpu(static_cast<uint32_t>(cpuid));
507 
508     CHECK_TRUE(ftraceParser_->ParsePage(*cpudetail, page, PAGE_SIZE), false, "parse page failed!");
509 
510     return tansporter_->Submit(std::move(tracePacket));
511 }
512 
AddPlatformEventsToParser(void)513 bool FlowController::AddPlatformEventsToParser(void)
514 {
515     CHECK_TRUE(ftraceSupported_, false, "current kernel not support ftrace!");
516 
517     HILOG_INFO(LOG_CORE, "Add platform events to parser start!");
518     for (auto& typeName : FtraceFsOps::GetInstance().GetPlatformEvents()) {
519         std::string type = typeName.first;
520         std::string name = typeName.second;
521         if (ftraceParser_->SetupEvent(type, name)) {
522             supportedEvents_.push_back(typeName);
523         }
524     }
525     HILOG_INFO(LOG_CORE, "Add platform events to parser done, events: %zu!", supportedEvents_.size());
526     return true;
527 }
528 
LoadConfig(const uint8_t configData[],uint32_t size)529 int FlowController::LoadConfig(const uint8_t configData[], uint32_t size)
530 {
531     CHECK_TRUE(size > 0, -1, "config data size is zero!");
532     CHECK_NOTNULL(configData, -1, "config data is null!");
533     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
534     CHECK_NOTNULL(tansporter_, -1, "ResultTransporter crated FAILED!");
535 
536     TracePluginConfig traceConfig;
537     CHECK_TRUE(traceConfig.ParseFromArray(configData, size), -1, "parse %u bytes configData failed!", size);
538 
539     // sort and save user requested trace events
540     std::set<std::string> events(traceConfig.ftrace_events().begin(), traceConfig.ftrace_events().end());
541     for (auto ftraceEvent : events) {
542         requestEvents_.push_back(ftraceEvent);
543     }
544 
545     traceApps_.assign(traceConfig.hitrace_apps().begin(), traceConfig.hitrace_apps().end());
546     traceCategories_.assign(traceConfig.hitrace_categories().begin(), traceConfig.hitrace_categories().end());
547 
548     if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
549         HILOG_INFO(LOG_CORE, "LoadConfig: ftrace event is not set, return false");
550         return -1;
551     }
552 
553     // setup trace clock
554     if (g_availableClocks.count(traceConfig.clock()) > 0) {
555         traceClock_ = traceConfig.clock();
556         FtraceFsOps::GetInstance().SetTraceClock(traceConfig.clock());
557     }
558 
559     // setup parse kernel symbol option
560     parseKsyms_ = traceConfig.parse_ksyms();
561 
562     // setup trace buffer size
563     SetupTraceBufferSize(traceConfig.buffer_size_kb());
564 
565     // setup transporter flush params
566     SetupTransporterFlushParams(traceConfig.flush_interval_ms(), traceConfig.flush_threshold_kb());
567 
568     // generate raw data file names
569     GenerateRawDataFileNames(traceConfig.raw_data_prefix());
570 
571     // setup trace period param
572     SetupTraceReadPeriod(traceConfig.trace_period_ms());
573     flushCacheData_ = traceConfig.discard_cache_data();
574     hitraceTime_ = traceConfig.hitrace_time();
575     return 0;
576 }
577 
SetupTraceBufferSize(uint32_t sizeKb)578 void FlowController::SetupTraceBufferSize(uint32_t sizeKb)
579 {
580     if (sizeKb < MIN_BUFFER_SIZE_KB) {
581         bufferSizeKb_ = MIN_BUFFER_SIZE_KB;
582     } else if (sizeKb > MAX_BUFFER_SIZE_KB) {
583         bufferSizeKb_ = MAX_BUFFER_SIZE_KB;
584     } else {
585         bufferSizeKb_ = sizeKb / KB_PER_PAGE * KB_PER_PAGE;
586     }
587 }
588 
SetupTransporterFlushParams(uint32_t flushInterval,uint32_t flushThresholdKb)589 void FlowController::SetupTransporterFlushParams(uint32_t flushInterval, uint32_t flushThresholdKb)
590 {
591     if (flushInterval > 0 && flushInterval <= MAX_FLUSH_INTERVAL) {
592         tansporter_->SetFlushInterval(flushInterval);
593     }
594     if (flushThresholdKb > 0 && flushThresholdKb <= MAX_FLUSH_THRESHOLD) {
595         tansporter_->SetFlushThreshold(flushThresholdKb * BYTE_PER_KB);
596     }
597 }
598 
GenerateRawDataFileNames(const std::string & prefix)599 void FlowController::GenerateRawDataFileNames(const std::string& prefix)
600 {
601     if (prefix.size() > 0) {
602         for (int i = 0; i < platformCpuNum_; i++) {
603             std::string path = prefix + std::to_string(i);
604             rawDataDumpPath_.push_back(path);
605         }
606     }
607 }
608 
SetupTraceReadPeriod(uint32_t tracePeriod)609 void FlowController::SetupTraceReadPeriod(uint32_t tracePeriod)
610 {
611     if (tracePeriod > 0 && tracePeriod <= MAX_TRACE_PERIOD_MS) {
612         tracePeriodMs_ = tracePeriod;
613     } else {
614         tracePeriodMs_ = DEFAULT_TRACE_PERIOD_MS;
615     }
616 }
617 
EnableTraceEvents(void)618 void FlowController::EnableTraceEvents(void)
619 {
620     std::unordered_set<std::string> userEventSet(requestEvents_.begin(), requestEvents_.end());
621     for (auto& event : supportedEvents_) {
622         std::string type = event.first;
623         std::string name = event.second;
624         if (userEventSet.count(type + "/" + name)) { // user config format
625             if (FtraceFsOps::GetInstance().EnableEvent(type, name)) {
626                 FtraceFsOps::GetInstance().AppendSetEvent(type, name);
627                 enabledEvents_.push_back(event);
628             }
629         }
630     }
631     FtraceFsOps::GetInstance().EnableTracing();
632 }
633 
DisableTraceEvents(void)634 void FlowController::DisableTraceEvents(void)
635 {
636     FtraceFsOps::GetInstance().DisableTracing();
637     for (auto& event : enabledEvents_) {
638         std::string type = event.first;
639         std::string name = event.second;
640         FtraceFsOps::GetInstance().DisableEvent(type, name);
641     }
642     enabledEvents_.clear();
643 }
644 
DisableAllCategories(void)645 void FlowController::DisableAllCategories(void)
646 {
647     for (auto& event : supportedEvents_) {
648         std::string type = event.first;
649         std::string name = event.second;
650         FtraceFsOps::GetInstance().DisableCategories(type);
651     }
652 }
653 FTRACE_NS_END
654