148f512ceSopenharmony_ci/* 248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 448f512ceSopenharmony_ci * you may not use this file except in compliance with the License. 548f512ceSopenharmony_ci * You may obtain a copy of the License at 648f512ceSopenharmony_ci * 748f512ceSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 848f512ceSopenharmony_ci * 948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and 1348f512ceSopenharmony_ci * limitations under the License. 1448f512ceSopenharmony_ci */ 1548f512ceSopenharmony_ci 1648f512ceSopenharmony_ci#include "subcommand.h" 1748f512ceSopenharmony_ci#include <mutex> 1848f512ceSopenharmony_ci#include "debug_logger.h" 1948f512ceSopenharmony_ci#include "option.h" 2048f512ceSopenharmony_ci 2148f512ceSopenharmony_ciusing namespace std; 2248f512ceSopenharmony_cinamespace OHOS { 2348f512ceSopenharmony_cinamespace Developtools { 2448f512ceSopenharmony_cinamespace HiPerf { 2548f512ceSopenharmony_cistatic std::map<std::string, std::unique_ptr<SubCommand>> g_SubCommandsMap; 2648f512ceSopenharmony_cistd::mutex g_subCommandMutex; 2748f512ceSopenharmony_ci 2848f512ceSopenharmony_ci// parse option first 2948f512ceSopenharmony_cibool SubCommand::OnSubCommandOptions(std::vector<std::string> args) 3048f512ceSopenharmony_ci{ 3148f512ceSopenharmony_ci // parse common first 3248f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--dumpoptions", dumpOptions_)) { 3348f512ceSopenharmony_ci return false; 3448f512ceSopenharmony_ci } 3548f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--help", showHelp_) 3648f512ceSopenharmony_ci || !Option::GetOptionValue(args, "-h", showHelp_)) { 3748f512ceSopenharmony_ci return false; 3848f512ceSopenharmony_ci } 3948f512ceSopenharmony_ci 4048f512ceSopenharmony_ci if (showHelp_) { 4148f512ceSopenharmony_ci if (!args.empty()) { 4248f512ceSopenharmony_ci printf("unknown option '%s'\n", args.front().c_str()); 4348f512ceSopenharmony_ci return false; 4448f512ceSopenharmony_ci } 4548f512ceSopenharmony_ci if (OnPreSubCommand()) { 4648f512ceSopenharmony_ci return false; 4748f512ceSopenharmony_ci } 4848f512ceSopenharmony_ci } 4948f512ceSopenharmony_ci 5048f512ceSopenharmony_ci if (ParseOption(args)) { 5148f512ceSopenharmony_ci if (dumpOptions_) { 5248f512ceSopenharmony_ci DumpOptions(); 5348f512ceSopenharmony_ci } 5448f512ceSopenharmony_ci HLOGD(" args left over: (%zu): %s", args.size(), VectorToString(args).c_str()); 5548f512ceSopenharmony_ci if (!args.empty()) { 5648f512ceSopenharmony_ci printf("unknown option '%s'\n", args.front().c_str()); 5748f512ceSopenharmony_ci return false; 5848f512ceSopenharmony_ci } 5948f512ceSopenharmony_ci } else { 6048f512ceSopenharmony_ci HLOGD("incorrect option(s)\n"); 6148f512ceSopenharmony_ci return false; 6248f512ceSopenharmony_ci } 6348f512ceSopenharmony_ci return true; 6448f512ceSopenharmony_ci} 6548f512ceSopenharmony_ci 6648f512ceSopenharmony_cibool SubCommand::CheckRestartOption(std::string &appPackage, bool targetSystemWide, bool restart, 6748f512ceSopenharmony_ci std::vector<pid_t> &selectPids) 6848f512ceSopenharmony_ci{ 6948f512ceSopenharmony_ci if (!restart) { 7048f512ceSopenharmony_ci return true; 7148f512ceSopenharmony_ci } 7248f512ceSopenharmony_ci if (appPackage.empty()) { 7348f512ceSopenharmony_ci printf("to detect the performance of application startup, --app option must be given\n"); 7448f512ceSopenharmony_ci return false; 7548f512ceSopenharmony_ci } 7648f512ceSopenharmony_ci if (targetSystemWide || !selectPids.empty()) { 7748f512ceSopenharmony_ci printf("option --restart and -p/-a is conflict, please check usage\n"); 7848f512ceSopenharmony_ci return false; 7948f512ceSopenharmony_ci } 8048f512ceSopenharmony_ci 8148f512ceSopenharmony_ci if (!appPackage.empty()) { 8248f512ceSopenharmony_ci return IsRestarted(appPackage); 8348f512ceSopenharmony_ci } 8448f512ceSopenharmony_ci return false; 8548f512ceSopenharmony_ci} 8648f512ceSopenharmony_ci 8748f512ceSopenharmony_cibool SubCommand::HandleSubCommandExclude(const std::vector<pid_t> &excludeTids, const std::vector<std::string> 8848f512ceSopenharmony_ci &excludeThreadNames, std::vector<pid_t> &selectTids) 8948f512ceSopenharmony_ci{ 9048f512ceSopenharmony_ci if (!excludeTids.empty() && !excludeThreadNames.empty()) { 9148f512ceSopenharmony_ci printf("option --exclude-thread and --exclude-tid is conflict, please check usage\n"); 9248f512ceSopenharmony_ci return false; 9348f512ceSopenharmony_ci } 9448f512ceSopenharmony_ci if (excludeTids.empty() && excludeThreadNames.empty()) { 9548f512ceSopenharmony_ci return true; 9648f512ceSopenharmony_ci } 9748f512ceSopenharmony_ci if (selectTids.empty()) { 9848f512ceSopenharmony_ci printf("No thread is Monitored, while attempt to exclude some threads.\n"); 9948f512ceSopenharmony_ci return true; 10048f512ceSopenharmony_ci } 10148f512ceSopenharmony_ci if (!excludeTids.empty()) { 10248f512ceSopenharmony_ci ExcludeTidsFromSelectTids(excludeTids, selectTids); 10348f512ceSopenharmony_ci return true; 10448f512ceSopenharmony_ci } 10548f512ceSopenharmony_ci ExcludeThreadsFromSelectTids(excludeThreadNames, selectTids); 10648f512ceSopenharmony_ci return true; 10748f512ceSopenharmony_ci} 10848f512ceSopenharmony_ci 10948f512ceSopenharmony_civoid SubCommand::ExcludeTidsFromSelectTids(const std::vector<pid_t> &excludeTids, std::vector<pid_t> &selectTids) 11048f512ceSopenharmony_ci{ 11148f512ceSopenharmony_ci for (auto excludeTid : excludeTids) { 11248f512ceSopenharmony_ci bool hasExclude = false; 11348f512ceSopenharmony_ci auto pos = selectTids.begin(); 11448f512ceSopenharmony_ci while (pos != selectTids.end()) { 11548f512ceSopenharmony_ci if (excludeTid == *pos) { 11648f512ceSopenharmony_ci pos = selectTids.erase(pos); 11748f512ceSopenharmony_ci hasExclude = true; 11848f512ceSopenharmony_ci continue; 11948f512ceSopenharmony_ci } 12048f512ceSopenharmony_ci ++pos; 12148f512ceSopenharmony_ci } 12248f512ceSopenharmony_ci if (!hasExclude) { 12348f512ceSopenharmony_ci printf("No thread id %d was found to exclude.\n", excludeTid); 12448f512ceSopenharmony_ci } 12548f512ceSopenharmony_ci } 12648f512ceSopenharmony_ci} 12748f512ceSopenharmony_ci 12848f512ceSopenharmony_civoid SubCommand::ExcludeThreadsFromSelectTids(const std::vector<std::string> &excludeThreadNames, 12948f512ceSopenharmony_ci std::vector<pid_t> &selectTids) 13048f512ceSopenharmony_ci{ 13148f512ceSopenharmony_ci for (auto excludeName : excludeThreadNames) { 13248f512ceSopenharmony_ci bool hasExclude = false; 13348f512ceSopenharmony_ci auto pos = selectTids.begin(); 13448f512ceSopenharmony_ci while (pos != selectTids.end()) { 13548f512ceSopenharmony_ci std::string threadName = virtualRuntime_.ReadThreadName(*pos, true); 13648f512ceSopenharmony_ci if (excludeName == threadName) { 13748f512ceSopenharmony_ci pos = selectTids.erase(pos); 13848f512ceSopenharmony_ci hasExclude = true; 13948f512ceSopenharmony_ci continue; 14048f512ceSopenharmony_ci } 14148f512ceSopenharmony_ci ++pos; 14248f512ceSopenharmony_ci } 14348f512ceSopenharmony_ci if (!hasExclude) { 14448f512ceSopenharmony_ci printf("No thread named %s was found to exclude.\n", excludeName.c_str()); 14548f512ceSopenharmony_ci } 14648f512ceSopenharmony_ci } 14748f512ceSopenharmony_ci} 14848f512ceSopenharmony_ci 14948f512ceSopenharmony_cibool SubCommand::RegisterSubCommand(std::string cmdName, std::unique_ptr<SubCommand> subCommand) 15048f512ceSopenharmony_ci{ 15148f512ceSopenharmony_ci HLOGV("%s", cmdName.c_str()); 15248f512ceSopenharmony_ci if (cmdName.empty()) { 15348f512ceSopenharmony_ci HLOGE("unable to register empty subcommand!"); 15448f512ceSopenharmony_ci return false; 15548f512ceSopenharmony_ci } 15648f512ceSopenharmony_ci if (cmdName.front() == '-') { 15748f512ceSopenharmony_ci HLOGE("unable use '-' at the begin of subcommand '%s'", cmdName.c_str()); 15848f512ceSopenharmony_ci return false; 15948f512ceSopenharmony_ci } 16048f512ceSopenharmony_ci 16148f512ceSopenharmony_ci if (g_SubCommandsMap.count(cmdName) == 0) { 16248f512ceSopenharmony_ci std::lock_guard<std::mutex> lock(g_subCommandMutex); 16348f512ceSopenharmony_ci g_SubCommandsMap.insert(std::make_pair(cmdName, std::move(subCommand))); 16448f512ceSopenharmony_ci return true; 16548f512ceSopenharmony_ci } else { 16648f512ceSopenharmony_ci HLOGE("subcommand '%s' already registered!", cmdName.c_str()); 16748f512ceSopenharmony_ci return false; 16848f512ceSopenharmony_ci } 16948f512ceSopenharmony_ci} 17048f512ceSopenharmony_ci 17148f512ceSopenharmony_civoid SubCommand::ClearSubCommands() 17248f512ceSopenharmony_ci{ 17348f512ceSopenharmony_ci std::lock_guard<std::mutex> lock(g_subCommandMutex); 17448f512ceSopenharmony_ci g_SubCommandsMap.clear(); 17548f512ceSopenharmony_ci} 17648f512ceSopenharmony_ci 17748f512ceSopenharmony_ciconst std::map<std::string, std::unique_ptr<SubCommand>> &SubCommand::GetSubCommands() 17848f512ceSopenharmony_ci{ 17948f512ceSopenharmony_ci return g_SubCommandsMap; 18048f512ceSopenharmony_ci} 18148f512ceSopenharmony_ci 18248f512ceSopenharmony_ciSubCommand *SubCommand::FindSubCommand(std::string &cmdName) 18348f512ceSopenharmony_ci{ 18448f512ceSopenharmony_ci HLOGV("%s", cmdName.c_str()); 18548f512ceSopenharmony_ci std::lock_guard<std::mutex> lock(g_subCommandMutex); 18648f512ceSopenharmony_ci auto found = g_SubCommandsMap.find(cmdName); 18748f512ceSopenharmony_ci if (found != g_SubCommandsMap.end()) { 18848f512ceSopenharmony_ci // remove the subcmd itself 18948f512ceSopenharmony_ci return found->second.get(); 19048f512ceSopenharmony_ci } else { 19148f512ceSopenharmony_ci return nullptr; 19248f512ceSopenharmony_ci } 19348f512ceSopenharmony_ci} 19448f512ceSopenharmony_ci} // namespace HiPerf 19548f512ceSopenharmony_ci} // namespace Developtools 19648f512ceSopenharmony_ci} // namespace OHOS 197