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
16 #include "plugin_session_manager.h"
17
18 namespace {
19 constexpr uint32_t MAX_BUFFER_PAGES = 512 * 1024 * 1024 / 4096;
20 }
21
PluginSessionManager(const PluginServiceWeakPtr & pluginService)22 PluginSessionManager::PluginSessionManager(const PluginServiceWeakPtr& pluginService) : pluginService_(pluginService) {}
23
~PluginSessionManager()24 PluginSessionManager::~PluginSessionManager() {}
25
CheckBufferConfig(const ProfilerSessionConfig::BufferConfig & bufferConfig)26 bool PluginSessionManager::CheckBufferConfig(const ProfilerSessionConfig::BufferConfig& bufferConfig)
27 {
28 const uint32_t pages = bufferConfig.pages();
29 const auto policy = bufferConfig.policy();
30 return pages > 0 && pages <= MAX_BUFFER_PAGES &&
31 (policy == ProfilerSessionConfig::BufferConfig::RECYCLE ||
32 policy == ProfilerSessionConfig::BufferConfig::FLATTEN);
33 }
34
CheckPluginSha256(const ProfilerPluginConfig & pluginConfig)35 bool PluginSessionManager::CheckPluginSha256(const ProfilerPluginConfig& pluginConfig)
36 {
37 std::string reqSha = pluginConfig.plugin_sha256();
38 if (reqSha.size() > 0) { // only check when SHA256 provided in request
39 auto pluginSvc = pluginService_.lock();
40 CHECK_NOTNULL(pluginSvc, false, "plugin service null!");
41
42 PluginInfo info = {};
43 std::string name = pluginConfig.name();
44 CHECK_TRUE(pluginSvc->GetPluginInfo(name, info), false, "get plugin info %s failed!", name.c_str());
45
46 std::string devSha = info.sha256;
47 CHECK_TRUE(devSha == reqSha, false, "SHA256 mismatch: %s, %s!", devSha.c_str(), reqSha.c_str());
48 }
49 return true;
50 }
51
CreatePluginSession(const ProfilerPluginConfig & pluginConfig,const ProfilerSessionConfig::BufferConfig & bufferConfig,const ProfilerDataRepeaterPtr & dataRepeater)52 PluginSessionPtr PluginSessionManager::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
53 const ProfilerSessionConfig::BufferConfig& bufferConfig,
54 const ProfilerDataRepeaterPtr& dataRepeater)
55 {
56 auto name = pluginConfig.name();
57 CHECK_TRUE(pluginSessions_.count(name) == 0, nullptr, "plugin name %s exists!", name.c_str());
58 CHECK_TRUE(CheckBufferConfig(bufferConfig), nullptr, "buffer config invalid!");
59 CHECK_TRUE(CheckPluginSha256(pluginConfig), nullptr, "SHA256 check failed!");
60
61 auto session = std::make_shared<PluginSession>(pluginConfig, bufferConfig, pluginService_, dataRepeater);
62 CHECK_NOTNULL(session, nullptr, "allocate plugin session for %s failed!", name.c_str());
63 CHECK_TRUE(session->IsAvailable(), nullptr, "config plugin for %s failed!", name.c_str());
64 return session;
65 }
66
CreatePluginSession(const ProfilerPluginConfig & pluginConfig,const ProfilerDataRepeaterPtr & dataRepeater)67 PluginSessionPtr PluginSessionManager::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
68 const ProfilerDataRepeaterPtr& dataRepeater)
69 {
70 auto name = pluginConfig.name();
71 CHECK_TRUE(pluginSessions_.count(name) == 0, nullptr, "plugin name %s exists!", name.c_str());
72 CHECK_TRUE(CheckPluginSha256(pluginConfig), nullptr, "SHA256 check failed!");
73
74 auto session = std::make_shared<PluginSession>(pluginConfig, pluginService_, dataRepeater);
75 CHECK_NOTNULL(session, nullptr, "allocate plugin session for %s failed!", name.c_str());
76 CHECK_TRUE(session->IsAvailable(), nullptr, "config plugin for %s failed!", name.c_str());
77 return session;
78 }
79
CreatePluginSessions(const std::vector<ProfilerPluginConfig> & pluginConfigs,const std::vector<ProfilerSessionConfig::BufferConfig> & bufferConfigs,const ProfilerDataRepeaterPtr & dataRepeater)80 bool PluginSessionManager::CreatePluginSessions(const std::vector<ProfilerPluginConfig>& pluginConfigs,
81 const std::vector<ProfilerSessionConfig::BufferConfig>& bufferConfigs,
82 const ProfilerDataRepeaterPtr& dataRepeater)
83 {
84 CHECK_TRUE(pluginConfigs.size() == bufferConfigs.size(), false, "buffer and config vector size mismatch %zu, %zu",
85 bufferConfigs.size(), pluginConfigs.size());
86
87 std::map<std::string, PluginSessionPtr> tmpPluginSessions;
88 for (size_t i = 0; i < pluginConfigs.size(); i++) {
89 auto session = CreatePluginSession(pluginConfigs[i], bufferConfigs[i], dataRepeater);
90
91 // tmpPluginSessions will released if some plugin session create failed
92 CHECK_NOTNULL(session, false, "create plugin-%zu session failed!", i);
93 tmpPluginSessions[pluginConfigs[i].name()] = session;
94 }
95
96 // insert all plugin session to pluginSessions_ map
97 std::unique_lock<std::mutex> lock(mutex_);
98 for (auto& entry : tmpPluginSessions) {
99 pluginSessions_.insert(entry);
100 }
101 return true;
102 }
103
CreatePluginSessions(const std::vector<ProfilerPluginConfig> & pluginConfigs,const ProfilerDataRepeaterPtr & dataRepeater)104 bool PluginSessionManager::CreatePluginSessions(const std::vector<ProfilerPluginConfig>& pluginConfigs,
105 const ProfilerDataRepeaterPtr& dataRepeater)
106 {
107 std::map<std::string, PluginSessionPtr> tmpPluginSessions;
108 for (size_t i = 0; i < pluginConfigs.size(); i++) {
109 auto session = CreatePluginSession(pluginConfigs[i], dataRepeater);
110
111 // tmpPluginSessions will released if some plugin session create failed
112 CHECK_NOTNULL(session, false, "create plugin-%zu session without shmem buffer failed!", i);
113 tmpPluginSessions[pluginConfigs[i].name()] = session;
114 }
115
116 // insert all plugin session to pluginSessions_ map
117 std::unique_lock<std::mutex> lock(mutex_);
118 for (auto& entry : tmpPluginSessions) {
119 pluginSessions_.insert(entry);
120 }
121 return true;
122 }
123
RemovePluginSessions(const std::vector<std::string> & nameList)124 bool PluginSessionManager::RemovePluginSessions(const std::vector<std::string>& nameList)
125 {
126 CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
127 std::unique_lock<std::mutex> lock(mutex_);
128 for (auto& name : nameList) {
129 auto it = pluginSessions_.find(name);
130 if (it == pluginSessions_.end()) {
131 continue;
132 }
133 pluginSessions_.erase(it);
134 }
135 return true;
136 }
137
InvalidatePluginSessions(const std::vector<std::string> & nameList)138 bool PluginSessionManager::InvalidatePluginSessions(const std::vector<std::string>& nameList)
139 {
140 CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
141 std::unique_lock<std::mutex> lock(mutex_);
142 for (auto& name : nameList) {
143 auto it = pluginSessions_.find(name);
144 if (it == pluginSessions_.end()) {
145 continue;
146 }
147 it->second->Invalidate();
148 }
149 return true;
150 }
151
StartPluginSessions(const std::vector<std::string> & nameList)152 bool PluginSessionManager::StartPluginSessions(const std::vector<std::string>& nameList)
153 {
154 CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
155 pluginNameList_ = std::move(nameList);
156 // start each plugin sessions
157 size_t failureCount = 0;
158 std::unique_lock<std::mutex> lock(mutex_);
159 for (auto& name : nameList) {
160 auto it = pluginSessions_.find(name);
161 if (it == pluginSessions_.end()) {
162 continue;
163 }
164 if (!it->second->Start()) {
165 HILOG_INFO(LOG_CORE, "start session %s FAILED!", it->first.c_str());
166 failureCount++;
167 }
168 }
169 return failureCount == 0;
170 }
171
StopPluginSessions(const std::vector<std::string> & nameList)172 bool PluginSessionManager::StopPluginSessions(const std::vector<std::string>& nameList)
173 {
174 // stop each plugin sessions
175 size_t failureCount = 0;
176 std::unique_lock<std::mutex> lock(mutex_);
177 for (auto& name : nameList) {
178 auto it = pluginSessions_.find(name);
179 if (it == pluginSessions_.end()) {
180 continue;
181 }
182 if (!it->second->Stop()) {
183 HILOG_INFO(LOG_CORE, "stop session %s FAILED!", it->first.c_str());
184 failureCount++;
185 }
186 }
187 return failureCount == 0;
188 }
189
RefreshPluginSession()190 bool PluginSessionManager::RefreshPluginSession()
191 {
192 size_t failureCount = 0;
193 std::unique_lock<std::mutex> lock(mutex_);
194 for (auto& name : pluginNameList_) {
195 auto it = pluginSessions_.find(name);
196 if (it == pluginSessions_.end()) {
197 continue;
198 }
199 if (!it->second->Refresh()) {
200 HILOG_INFO(LOG_CORE, "refresh data %s FAILED!", it->first.c_str());
201 failureCount++;
202 }
203 }
204 return failureCount == 0;
205 }
206
CheckStatus(const std::vector<std::string> & nameList,PluginSession::State state)207 bool PluginSessionManager::CheckStatus(const std::vector<std::string>& nameList, PluginSession::State state)
208 {
209 std::unique_lock<std::mutex> lock(mutex_);
210 for (auto& name : nameList) {
211 auto it = pluginSessions_.find(name);
212 if (it == pluginSessions_.end()) {
213 continue;
214 }
215 auto actualState = it->second->GetState();
216 if (actualState != state) {
217 HILOG_INFO(LOG_CORE, "plugin %s state is %d not %d!", it->first.c_str(), actualState, state);
218 return false;
219 }
220 }
221 return true;
222 }
223
GetStatus(const std::vector<std::string> & nameList)224 std::vector<PluginSession::State> PluginSessionManager::GetStatus(const std::vector<std::string>& nameList)
225 {
226 std::vector<PluginSession::State> status;
227 std::unique_lock<std::mutex> lock(mutex_);
228 for (auto& name : nameList) {
229 auto it = pluginSessions_.find(name);
230 if (it == pluginSessions_.end()) {
231 continue;
232 }
233 status.push_back(it->second->GetState());
234 }
235 return status;
236 }
237