• 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     // enable ftrace event switches
280     if (traceCategories_.size() > 0) {
281         traceOps_->EnableCategories(traceCategories_, hitraceTime_);
282     }
283 
284     // hitrace will reset trace buffer size, so reset user config after hitrace
285     FtraceFsOps::GetInstance().SetBufferSizeKb(bufferSizeKb_);
286     EnableTraceEvents();
287     return 0;
288 }
289 
CaptureWork()290 void FlowController::CaptureWork()
291 {
292     pthread_setname_np(pthread_self(), "TraceReader");
293     HILOG_INFO(LOG_CORE, "FlowController::CaptureWork start!");
294 
295     auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
296     std::vector<long> rawDataBytes(platformCpuNum_, 0);
297 
298     while (keepRunning_) {
299         std::this_thread::sleep_for(tracePeriod);
300 
301         // read data from percpu trace_pipe_raw, consume kernel ring buffers
302         for (size_t i = 0; i < rawDataBytes.size(); i++) {
303             if (flushCacheData_ && !keepRunning_) {
304                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
305                 return;
306             }
307             long nbytes = ReadEventData(i);
308             rawDataBytes[i] = nbytes;
309         }
310 
311         // append buffer data to cache
312         for (size_t i = 0; i < rawDataDumpFile_.size(); i++) {
313             if (flushCacheData_ && !keepRunning_) {
314                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
315                 return;
316             }
317             auto& file = rawDataDumpFile_[i];
318             size_t writen = fwrite(ftraceBuffers_[i].get(), sizeof(uint8_t), rawDataBytes[i], file.get());
319             if (rawDataBytes[i] == 0) {
320                 HILOG_INFO(LOG_CORE, "Append raw data to cache[%zu]: %zu/%ld bytes", i, writen, rawDataBytes[i]);
321             }
322         }
323 
324         // parse ftrace metadata
325         ftraceParser_->ParseSavedTgid(FtraceFsOps::GetInstance().GetSavedTgids());
326         ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
327 
328         // parse ftrace percpu event data
329         for (size_t i = 0; i < rawDataBytes.size(); i++) {
330             if (flushCacheData_ && !keepRunning_) {
331                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
332                 return;
333             }
334             ParseEventData(i, rawDataBytes[i]);
335             if (rawDataBytes[i] == 0) {
336                 HILOG_INFO(LOG_CORE, "Parse raw data for CPU%zu: %ld bytes...", i, rawDataBytes[i]);
337             }
338         }
339     }
340 
341     tansporter_->Flush();
342     HILOG_DEBUG(LOG_CORE, "FlowController::CaptureWork done!");
343 }
344 
ReadEventData(int cpuid)345 long FlowController::ReadEventData(int cpuid)
346 {
347     auto buffer = ftraceBuffers_[cpuid].get();
348     auto reader = ftraceReaders_[cpuid].get();
349     auto bufferSize = static_cast<long>(memPool_->GetBlockSize());
350     (void)memset_s(buffer, bufferSize, 0, bufferSize);
351 
352     long nbytes = 0;
353     long used = 0;
354     long rest = bufferSize;
355     while ((nbytes = reader->Read(&buffer[used], rest)) > 0 && used < bufferSize) {
356         CHECK_TRUE(used % PAGE_SIZE == 0, used, "used invalid!");
357         used += nbytes;
358         rest -= nbytes;
359     }
360     return used;
361 }
362 
ParseEventData(int cpuid,long dataSize)363 bool FlowController::ParseEventData(int cpuid, long dataSize)
364 {
365     auto buffer = ftraceBuffers_[cpuid].get();
366     auto endPtr = buffer + dataSize;
367 
368     for (auto page = buffer; page < endPtr; page += PAGE_SIZE) {
369         CHECK_TRUE(ParseFtraceEvent(cpuid, page), false, "parse raw event for cpu-%d failed!", cpuid);
370     }
371     return true;
372 }
373 
StopCapture(void)374 int FlowController::StopCapture(void)
375 {
376     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
377     CHECK_NOTNULL(tansporter_, -1, "crate ResultTransporter FAILED!");
378     CHECK_NOTNULL(traceOps_, -1, "create TraceOps FAILED!");
379 
380     if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
381         HILOG_INFO(LOG_CORE, "StopCapture: ftrace event is not set, return false");
382         return -1;
383     }
384 
385     // disable ftrace event switches
386     DisableTraceEvents();
387 
388     // stop ftrace event data polling thread
389     keepRunning_ = false;
390     if (pollThread_.joinable()) {
391         HILOG_INFO(LOG_CORE, "join thread start!\n");
392         pollThread_.join();
393         HILOG_INFO(LOG_CORE, "join thread  done!\n");
394     }
395 
396     // parse per cpu stats
397     CHECK_TRUE(ParsePerCpuStatus(TRACE_END), -1, "parse TRACE_END stats failed!");
398 
399     // disable userspace trace triggers
400     // because trace cmd will read trace buffer,
401     // so we to this action after polling thread exit.
402     if (traceCategories_.size() > 0) {
403         traceOps_->DisableCategories();
404     }
405     tansporter_->Flush();
406 
407     // release resources
408     rawDataDumpFile_.clear(); // close raw data dump files
409     ftraceReaders_.clear();   // release ftrace data readers
410     ftraceBuffers_.clear();   // release ftrace event read buffers
411     memPool_.reset();         // release memory pool
412     return 0;
413 }
414 
ParsePerCpuStatus(int stage)415 bool FlowController::ParsePerCpuStatus(int stage)
416 {
417     auto tracePacket = std::make_unique<TracePluginResult>();
418     CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
419 
420     auto cpuStatsMsg = tracePacket->add_ftrace_cpu_stats();
421     if (stage == TRACE_START) {
422         cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_START);
423     } else {
424         cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_END);
425     }
426 
427     std::string traceClock = FtraceFsOps::GetInstance().GetTraceClock();
428     if (traceClock.size() > 0) {
429         cpuStatsMsg->set_trace_clock(traceClock);
430     }
431 
432     for (int i = 0; i < platformCpuNum_; i++) {
433         HILOG_INFO(LOG_CORE, "[%d] ParsePerCpuStatus %d!", i, stage);
434         PerCpuStats stats = {};
435         stats.cpuIndex = i;
436         ftraceParser_->ParsePerCpuStatus(stats, FtraceFsOps::GetInstance().GetPerCpuStats(i));
437         auto perCpuMsg = cpuStatsMsg->add_per_cpu_stats();
438         perCpuMsg->set_cpu(stats.cpuIndex);
439         perCpuMsg->set_entries(stats.entries);
440         perCpuMsg->set_overrun(stats.overrun);
441         perCpuMsg->set_commit_overrun(stats.commitOverrun);
442         perCpuMsg->set_bytes(stats.bytes);
443         perCpuMsg->set_oldest_event_ts(stats.oldestEventTs);
444         perCpuMsg->set_now_ts(stats.nowTs);
445         perCpuMsg->set_dropped_events(stats.droppedEvents);
446         perCpuMsg->set_read_events(stats.readEvents);
447     }
448 
449     return tansporter_->Submit(std::move(tracePacket));
450 }
451 
ReportClockTimes()452 bool FlowController::ReportClockTimes()
453 {
454     auto traceResult = std::make_unique<TracePluginResult>();
455     CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
456 
457     std::map<clockid_t, ClockDetailMsg::ClockId> clocksMap = {
458         {CLOCK_REALTIME, ClockDetailMsg::REALTIME},
459         {CLOCK_REALTIME_COARSE, ClockDetailMsg::REALTIME_COARSE},
460         {CLOCK_MONOTONIC, ClockDetailMsg::MONOTONIC},
461         {CLOCK_MONOTONIC_COARSE, ClockDetailMsg::MONOTONIC_COARSE},
462         {CLOCK_MONOTONIC_RAW, ClockDetailMsg::MONOTONIC_RAW},
463         {CLOCK_BOOTTIME, ClockDetailMsg::BOOTTIME},
464     };
465     for (auto& entry : clocksMap) {
466         struct timespec ts = {};
467         clock_gettime(entry.first, &ts);
468         auto clockMsg = traceResult->add_clocks_detail();
469         CHECK_NOTNULL(clockMsg, false, "add clock_detail failed for %d!", entry.first);
470         clockMsg->set_id(entry.second);
471         auto timeMsg = clockMsg->mutable_time();
472         timeMsg->set_tv_sec(ts.tv_sec);
473         timeMsg->set_tv_nsec(ts.tv_nsec);
474 
475         struct timespec tsResolution = {};
476         clock_getres(entry.first, &tsResolution);
477         auto resolutionMsg = clockMsg->mutable_resolution();
478         resolutionMsg->set_tv_sec(tsResolution.tv_sec);
479         resolutionMsg->set_tv_nsec(tsResolution.tv_nsec);
480     }
481     return tansporter_->Submit(std::move(traceResult));
482 }
483 
ParseKernelSymbols()484 bool FlowController::ParseKernelSymbols()
485 {
486     auto traceResult = std::make_unique<TracePluginResult>();
487     CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
488 
489     ksymsParser_->Accept([&traceResult](const KernelSymbol& symbol) {
490         auto symbolDetail = traceResult->add_symbols_detail();
491         symbolDetail->set_symbol_addr(symbol.addr);
492         symbolDetail->set_symbol_name(symbol.name);
493     });
494     HILOG_INFO(LOG_CORE, "parse kernel symbol message done!");
495     return tansporter_->Submit(std::move(traceResult));
496 }
497 
ParseFtraceEvent(int cpuid,uint8_t page[])498 bool FlowController::ParseFtraceEvent(int cpuid, uint8_t page[])
499 {
500     auto tracePacket = std::make_unique<TracePluginResult>();
501     CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
502 
503     auto cpudetail = tracePacket->add_ftrace_cpu_detail();
504     cpudetail->set_cpu(static_cast<uint32_t>(cpuid));
505 
506     CHECK_TRUE(ftraceParser_->ParsePage(*cpudetail, page, PAGE_SIZE), false, "parse page failed!");
507 
508     return tansporter_->Submit(std::move(tracePacket));
509 }
510 
AddPlatformEventsToParser(void)511 bool FlowController::AddPlatformEventsToParser(void)
512 {
513     CHECK_TRUE(ftraceSupported_, false, "current kernel not support ftrace!");
514 
515     HILOG_INFO(LOG_CORE, "Add platform events to parser start!");
516     for (auto& typeName : FtraceFsOps::GetInstance().GetPlatformEvents()) {
517         std::string type = typeName.first;
518         std::string name = typeName.second;
519         if (ftraceParser_->SetupEvent(type, name)) {
520             supportedEvents_.push_back(typeName);
521         }
522     }
523     HILOG_INFO(LOG_CORE, "Add platform events to parser done, events: %zu!", supportedEvents_.size());
524     return true;
525 }
526 
LoadConfig(const uint8_t configData[],uint32_t size)527 int FlowController::LoadConfig(const uint8_t configData[], uint32_t size)
528 {
529     CHECK_TRUE(size > 0, -1, "config data size is zero!");
530     CHECK_NOTNULL(configData, -1, "config data is null!");
531     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
532     CHECK_NOTNULL(tansporter_, -1, "ResultTransporter crated FAILED!");
533 
534     TracePluginConfig traceConfig;
535     CHECK_TRUE(traceConfig.ParseFromArray(configData, size), -1, "parse %u bytes configData failed!", size);
536 
537     // sort and save user requested trace events
538     std::set<std::string> events(traceConfig.ftrace_events().begin(), traceConfig.ftrace_events().end());
539     for (auto ftraceEvent : events) {
540         requestEvents_.push_back(ftraceEvent);
541     }
542 
543     traceApps_.assign(traceConfig.hitrace_apps().begin(), traceConfig.hitrace_apps().end());
544     traceCategories_.assign(traceConfig.hitrace_categories().begin(), traceConfig.hitrace_categories().end());
545 
546     if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
547         HILOG_INFO(LOG_CORE, "LoadConfig: ftrace event is not set, return false");
548         return -1;
549     }
550 
551     // setup trace clock
552     if (g_availableClocks.count(traceConfig.clock()) > 0) {
553         FtraceFsOps::GetInstance().SetTraceClock(traceConfig.clock());
554     }
555 
556     // setup parse kernel symbol option
557     parseKsyms_ = traceConfig.parse_ksyms();
558 
559     // setup trace buffer size
560     SetupTraceBufferSize(traceConfig.buffer_size_kb());
561 
562     // setup transporter flush params
563     SetupTransporterFlushParams(traceConfig.flush_interval_ms(), traceConfig.flush_threshold_kb());
564 
565     // generate raw data file names
566     GenerateRawDataFileNames(traceConfig.raw_data_prefix());
567 
568     // setup trace period param
569     SetupTraceReadPeriod(traceConfig.trace_period_ms());
570     flushCacheData_ = traceConfig.discard_cache_data();
571     hitraceTime_ = traceConfig.hitrace_time();
572     return 0;
573 }
574 
SetupTraceBufferSize(uint32_t sizeKb)575 void FlowController::SetupTraceBufferSize(uint32_t sizeKb)
576 {
577     if (sizeKb < MIN_BUFFER_SIZE_KB) {
578         bufferSizeKb_ = MIN_BUFFER_SIZE_KB;
579     } else if (sizeKb > MAX_BUFFER_SIZE_KB) {
580         bufferSizeKb_ = MAX_BUFFER_SIZE_KB;
581     } else {
582         bufferSizeKb_ = sizeKb / KB_PER_PAGE * KB_PER_PAGE;
583     }
584 }
585 
SetupTransporterFlushParams(uint32_t flushInterval,uint32_t flushThresholdKb)586 void FlowController::SetupTransporterFlushParams(uint32_t flushInterval, uint32_t flushThresholdKb)
587 {
588     if (flushInterval > 0 && flushInterval <= MAX_FLUSH_INTERVAL) {
589         tansporter_->SetFlushInterval(flushInterval);
590     }
591     if (flushThresholdKb > 0 && flushThresholdKb <= MAX_FLUSH_THRESHOLD) {
592         tansporter_->SetFlushThreshold(flushThresholdKb * BYTE_PER_KB);
593     }
594 }
595 
GenerateRawDataFileNames(const std::string & prefix)596 void FlowController::GenerateRawDataFileNames(const std::string& prefix)
597 {
598     if (prefix.size() > 0) {
599         for (int i = 0; i < platformCpuNum_; i++) {
600             std::string path = prefix + std::to_string(i);
601             rawDataDumpPath_.push_back(path);
602         }
603     }
604 }
605 
SetupTraceReadPeriod(uint32_t tracePeriod)606 void FlowController::SetupTraceReadPeriod(uint32_t tracePeriod)
607 {
608     if (tracePeriod > 0 && tracePeriod <= MAX_TRACE_PERIOD_MS) {
609         tracePeriodMs_ = tracePeriod;
610     } else {
611         tracePeriodMs_ = DEFAULT_TRACE_PERIOD_MS;
612     }
613 }
614 
EnableTraceEvents(void)615 void FlowController::EnableTraceEvents(void)
616 {
617     std::unordered_set<std::string> userEventSet(requestEvents_.begin(), requestEvents_.end());
618     for (auto& event : supportedEvents_) {
619         std::string type = event.first;
620         std::string name = event.second;
621         if (userEventSet.count(type + "/" + name)) { // user config format
622             if (FtraceFsOps::GetInstance().EnableEvent(type, name)) {
623                 FtraceFsOps::GetInstance().AppendSetEvent(type, name);
624                 enabledEvents_.push_back(event);
625             }
626         }
627     }
628     FtraceFsOps::GetInstance().EnableTracing();
629 }
630 
DisableTraceEvents(void)631 void FlowController::DisableTraceEvents(void)
632 {
633     FtraceFsOps::GetInstance().DisableTracing();
634     for (auto& event : enabledEvents_) {
635         std::string type = event.first;
636         std::string name = event.second;
637         FtraceFsOps::GetInstance().DisableEvent(type, name);
638     }
639     enabledEvents_.clear();
640 }
641 
DisableAllCategories(void)642 void FlowController::DisableAllCategories(void)
643 {
644     for (auto& event : supportedEvents_) {
645         std::string type = event.first;
646         std::string name = event.second;
647         FtraceFsOps::GetInstance().DisableCategories(type);
648     }
649 }
650 FTRACE_NS_END
651