1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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,const ProfilerStateRepeaterPtr & stateRepeater)52 PluginSessionPtr PluginSessionManager::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
53 const ProfilerSessionConfig::BufferConfig& bufferConfig,
54 const ProfilerDataRepeaterPtr& dataRepeater,
55 const ProfilerStateRepeaterPtr& stateRepeater)
56 {
57 auto name = pluginConfig.name();
58 CHECK_TRUE(pluginSessions_.count(name) == 0, nullptr, "plugin name %s exists!", name.c_str());
59 CHECK_TRUE(CheckBufferConfig(bufferConfig), nullptr, "buffer config invalid!");
60 CHECK_TRUE(CheckPluginSha256(pluginConfig), nullptr, "SHA256 check failed!");
61
62 auto session = std::make_shared<PluginSession>(pluginConfig, bufferConfig, pluginService_,
63 dataRepeater, stateRepeater);
64 CHECK_NOTNULL(session, nullptr, "allocate plugin session for %s failed!", name.c_str());
65 CHECK_TRUE(session->IsAvailable(), nullptr, "config plugin for %s failed!", name.c_str());
66 return session;
67 }
68
CreatePluginSession(const ProfilerPluginConfig & pluginConfig,const ProfilerDataRepeaterPtr & dataRepeater,const ProfilerStateRepeaterPtr & stateRepeater)69 PluginSessionPtr PluginSessionManager::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
70 const ProfilerDataRepeaterPtr& dataRepeater,
71 const ProfilerStateRepeaterPtr& stateRepeater)
72 {
73 auto name = pluginConfig.name();
74 CHECK_TRUE(pluginSessions_.count(name) == 0, nullptr, "plugin name %s exists!", name.c_str());
75 CHECK_TRUE(CheckPluginSha256(pluginConfig), nullptr, "SHA256 check failed!");
76
77 auto session = std::make_shared<PluginSession>(pluginConfig, pluginService_, dataRepeater, stateRepeater);
78 CHECK_NOTNULL(session, nullptr, "allocate plugin session for %s failed!", name.c_str());
79 CHECK_TRUE(session->IsAvailable(), nullptr, "config plugin for %s failed!", name.c_str());
80 return session;
81 }
82
CreatePluginSessions(const std::vector<ProfilerPluginConfig> & pluginConfigs,const std::vector<ProfilerSessionConfig::BufferConfig> & bufferConfigs,const ProfilerDataRepeaterPtr & dataRepeater,const ProfilerStateRepeaterPtr & stateRepeater)83 bool PluginSessionManager::CreatePluginSessions(const std::vector<ProfilerPluginConfig>& pluginConfigs,
84 const std::vector<ProfilerSessionConfig::BufferConfig>& bufferConfigs,
85 const ProfilerDataRepeaterPtr& dataRepeater,
86 const ProfilerStateRepeaterPtr& stateRepeater)
87 {
88 CHECK_TRUE(pluginConfigs.size() == bufferConfigs.size(), false, "buffer and config vector size mismatch %zu, %zu",
89 bufferConfigs.size(), pluginConfigs.size());
90
91 std::map<std::string, PluginSessionPtr> tmpPluginSessions;
92 for (size_t i = 0; i < pluginConfigs.size(); i++) {
93 auto session = CreatePluginSession(pluginConfigs[i], bufferConfigs[i], dataRepeater, stateRepeater);
94
95 // tmpPluginSessions will released if some plugin session create failed
96 CHECK_NOTNULL(session, false, "create plugin-%zu session failed!", i);
97 tmpPluginSessions[pluginConfigs[i].name()] = session;
98 }
99
100 // insert all plugin session to pluginSessions_ map
101 std::unique_lock<std::mutex> lock(mutex_);
102 for (auto& entry : tmpPluginSessions) {
103 pluginSessions_.insert(entry);
104 }
105 return true;
106 }
107
CreatePluginSessions(const std::vector<ProfilerPluginConfig> & pluginConfigs,const ProfilerDataRepeaterPtr & dataRepeater,const ProfilerStateRepeaterPtr & stateRepeater)108 bool PluginSessionManager::CreatePluginSessions(const std::vector<ProfilerPluginConfig>& pluginConfigs,
109 const ProfilerDataRepeaterPtr& dataRepeater,
110 const ProfilerStateRepeaterPtr& stateRepeater)
111 {
112 std::map<std::string, PluginSessionPtr> tmpPluginSessions;
113 for (size_t i = 0; i < pluginConfigs.size(); i++) {
114 auto session = CreatePluginSession(pluginConfigs[i], dataRepeater, stateRepeater);
115
116 // tmpPluginSessions will released if some plugin session create failed
117 CHECK_NOTNULL(session, false, "create plugin-%zu session without shmem buffer failed!", i);
118 tmpPluginSessions[pluginConfigs[i].name()] = session;
119 }
120
121 // insert all plugin session to pluginSessions_ map
122 std::unique_lock<std::mutex> lock(mutex_);
123 for (auto& entry : tmpPluginSessions) {
124 pluginSessions_.insert(entry);
125 }
126 return true;
127 }
128
RemovePluginSessions(const std::vector<std::string> & nameList)129 bool PluginSessionManager::RemovePluginSessions(const std::vector<std::string>& nameList)
130 {
131 CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
132 std::unique_lock<std::mutex> lock(mutex_);
133 for (auto& name : nameList) {
134 auto it = pluginSessions_.find(name);
135 if (it == pluginSessions_.end()) {
136 continue;
137 }
138 pluginSessions_.erase(it);
139 }
140 return true;
141 }
142
InvalidatePluginSessions(const std::vector<std::string> & nameList)143 bool PluginSessionManager::InvalidatePluginSessions(const std::vector<std::string>& nameList)
144 {
145 CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
146 std::unique_lock<std::mutex> lock(mutex_);
147 for (auto& name : nameList) {
148 auto it = pluginSessions_.find(name);
149 if (it == pluginSessions_.end()) {
150 continue;
151 }
152 it->second->Invalidate();
153 }
154 return true;
155 }
156
StartPluginSessions(const std::vector<std::string> & nameList)157 bool PluginSessionManager::StartPluginSessions(const std::vector<std::string>& nameList)
158 {
159 CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
160 pluginNameList_ = std::move(nameList);
161 // start each plugin sessions
162 size_t failureCount = 0;
163 std::unique_lock<std::mutex> lock(mutex_);
164 for (auto& name : nameList) {
165 auto it = pluginSessions_.find(name);
166 if (it == pluginSessions_.end()) {
167 continue;
168 }
169 if (!it->second->Start()) {
170 PROFILER_LOG_INFO(LOG_CORE, "start session %s FAILED!", it->first.c_str());
171 failureCount++;
172 }
173 }
174 return failureCount == 0;
175 }
176
StopPluginSessions(const std::vector<std::string> & nameList)177 bool PluginSessionManager::StopPluginSessions(const std::vector<std::string>& nameList)
178 {
179 // stop each plugin sessions
180 size_t failureCount = 0;
181 std::unique_lock<std::mutex> lock(mutex_);
182 for (auto& name : nameList) {
183 auto it = pluginSessions_.find(name);
184 if (it == pluginSessions_.end()) {
185 continue;
186 }
187 if (!it->second->Stop()) {
188 PROFILER_LOG_INFO(LOG_CORE, "stop session %s FAILED!", it->first.c_str());
189 failureCount++;
190 }
191 }
192 return failureCount == 0;
193 }
194
RefreshPluginSession()195 bool PluginSessionManager::RefreshPluginSession()
196 {
197 size_t failureCount = 0;
198 std::unique_lock<std::mutex> lock(mutex_);
199 for (auto& name : pluginNameList_) {
200 auto it = pluginSessions_.find(name);
201 if (it == pluginSessions_.end()) {
202 continue;
203 }
204 if (!it->second->Refresh()) {
205 PROFILER_LOG_INFO(LOG_CORE, "refresh data %s FAILED!", it->first.c_str());
206 failureCount++;
207 }
208 }
209 return failureCount == 0;
210 }
211
CheckStatus(const std::vector<std::string> & nameList,PluginSession::State state)212 bool PluginSessionManager::CheckStatus(const std::vector<std::string>& nameList, PluginSession::State state)
213 {
214 std::unique_lock<std::mutex> lock(mutex_);
215 for (auto& name : nameList) {
216 auto it = pluginSessions_.find(name);
217 if (it == pluginSessions_.end()) {
218 continue;
219 }
220 auto actualState = it->second->GetState();
221 if (actualState != state) {
222 PROFILER_LOG_INFO(LOG_CORE, "plugin %s state is %d not %d!", it->first.c_str(), actualState, state);
223 return false;
224 }
225 }
226 return true;
227 }
228
GetStatus(const std::vector<std::string> & nameList)229 std::vector<PluginSession::State> PluginSessionManager::GetStatus(const std::vector<std::string>& nameList)
230 {
231 std::vector<PluginSession::State> status;
232 std::unique_lock<std::mutex> lock(mutex_);
233 for (auto& name : nameList) {
234 auto it = pluginSessions_.find(name);
235 if (it == pluginSessions_.end()) {
236 continue;
237 }
238 status.push_back(it->second->GetState());
239 }
240 return status;
241 }
242