1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "plugin_config.h"
16#include <fstream>
17#include <iostream>
18#include <regex>
19#include <sstream>
20#include "hiview_logger.h"
21#include "string_util.h"
22
23namespace OHOS {
24namespace HiviewDFX {
25DEFINE_LOG_TAG("HiView-PluginConfig");
26PluginConfig::PluginConfig(const std::string& file) : configPath_(file) {}
27bool PluginConfig::StartParse()
28{
29    std::ifstream in;
30    in.open(configPath_);
31    if (!in.is_open()) {
32        HIVIEW_LOGW("fail to open config file.");
33        return false;
34    }
35    int fieldCount = 0;
36    std::string field = "";
37    std::string buf = "";
38    const int fieldNameField = 1;
39    const int fieldCountField = 2;
40    while (getline(in, buf)) {
41        std::string strTmp = StringUtil::TrimStr(buf);
42        if (strTmp == "") {
43            continue;
44        }
45        std::smatch result;
46        if (fieldCount == 0) {
47            if (!regex_search(strTmp, result, std::regex("(plugins|pipelines|pipelinegroups)\\s*:\\s*(\\d+)"))) {
48                HIVIEW_LOGW("match field failed.");
49                in.close();
50                return false;
51            }
52
53            field = StringUtil::TrimStr(result[fieldNameField]);
54            fieldCount = atoi(std::string(result[fieldCountField]).c_str());
55            HIVIEW_LOGD("find field:%{public}s.", field.c_str());
56            continue;
57        }
58
59        if (field == "plugins") {
60            ParsePlugin(strTmp);
61        } else if (field == "pipelines") {
62            ParsePipeline(strTmp);
63        } else if (field == "pipelinegroups") {
64            ParsePipelineGroup(strTmp);
65        }
66        fieldCount--;
67    }
68    in.close();
69    return true;
70}
71
72void PluginConfig::ParsePlugin(const std::string& pluginStr)
73{
74    std::smatch result;
75    if (!regex_search(pluginStr, result,
76        std::regex("([^\\[]+)\\[([^\\[:]*):?([^:]*):?([^\\]]*)\\]\\s*:(\\d+)\\s+(dynamic|static)"))) {
77        HIVIEW_LOGW("no match plugin expression found! \n");
78        return;
79    }
80
81    // EventProcessorExample1[thread:t-example-2]:30 static
82    const int pluginNameField = 1;
83    const int workHandlerTypeField = 2;
84    const int workHandlerNameField = 3;
85    const int countOfThreadPoolField = 4;
86    const int loadDelayField = 5;
87    const int loadTypeField = 6;
88    PluginInfo info;
89
90    info.isStatic = (result[loadTypeField] == "static");
91    info.isEventSource = false;
92    info.loadDelay = atoi(std::string(result[loadDelayField]).c_str());
93    info.name = result[pluginNameField];
94    info.workHandlerType = result[workHandlerTypeField];
95    info.workHandlerName = result[workHandlerNameField];
96
97    // EventProcessorExample4[pool:pool-example-4:4]:0 static
98    if (result[workHandlerTypeField] == "pool") {
99        WorkPoolInfo poolInfo;
100        poolInfo.name = result[workHandlerNameField],
101        poolInfo.threadCount = atoi(std::string(result[countOfThreadPoolField]).c_str()),
102        workPoolInfoMap_[poolInfo.name] = std::move(poolInfo);
103    }
104    pluginInfoList_.push_back(std::move(info));
105}
106
107void PluginConfig::ParsePipeline(const std::string& pipelineStr)
108{
109    std::smatch result;
110    // FromTwo2Three:EventProcessorExample2 EventProcessorExample3
111    if (!regex_search(pipelineStr, result, std::regex("(\\S+)\\s*:(.+)"))) {
112        HIVIEW_LOGW("Fail to match pipeline expression.");
113        return;
114    }
115
116    const int pipelineNameField = 1;
117    const int pluginNameListField = 2;
118    PipelineInfo pipelineInfo;
119    pipelineInfo.name = result.str(pipelineNameField);
120    pipelineInfo.pluginNameList = StringUtil::SplitStr(result.str(pluginNameListField));
121    pipelineInfoList_.push_back(std::move(pipelineInfo));
122}
123
124void PluginConfig::ParsePipelineGroup(const std::string& pipelineGroup)
125{
126    std::smatch result;
127    // EventSourceExample:FromTwo2Three FromThree2Two
128    if (!regex_search(pipelineGroup, result, std::regex("(\\S+)\\s*:(.+)"))) {
129        HIVIEW_LOGW("Fail to match pipeline group expression.");
130        return;
131    }
132
133    const int pipelineGroupNameField = 1;
134    const int pipelineNameListField = 2;
135    std::string eventSourceName = StringUtil::TrimStr(result.str(pipelineGroupNameField));
136    auto ret = std::find_if(pluginInfoList_.begin(), pluginInfoList_.end(), [&](PluginInfo& info) {
137        if (info.name == eventSourceName) {
138            info.isEventSource = true;
139            info.pipelineNameList = StringUtil::SplitStr(result.str(pipelineNameListField));
140            return true;
141        }
142        return false;
143    });
144    if (ret != std::end(pluginInfoList_)) {
145        HIVIEW_LOGD("%s is an event source.", eventSourceName.c_str());
146    }
147}
148
149const std::list<PluginConfig::PluginInfo>& PluginConfig::GetPluginInfoList() const
150{
151    return pluginInfoList_;
152}
153
154const std::list<PluginConfig::PipelineInfo>& PluginConfig::GetPipelineInfoList() const
155{
156    return pipelineInfoList_;
157}
158} // namespace HiviewDFX
159} // namespace OHOS
160