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 // start each plugin sessions
156 size_t failureCount = 0;
157 std::unique_lock<std::mutex> lock(mutex_);
158 for (auto& name : nameList) {
159 auto it = pluginSessions_.find(name);
160 if (it == pluginSessions_.end()) {
161 continue;
162 }
163 if (!it->second->Start()) {
164 HILOG_INFO(LOG_CORE, "start session %s FAILED!", it->first.c_str());
165 failureCount++;
166 }
167 }
168 return failureCount == 0;
169 }
170
StopPluginSessions(const std::vector<std::string> & nameList)171 bool PluginSessionManager::StopPluginSessions(const std::vector<std::string>& nameList)
172 {
173 // stop each plugin sessions
174 size_t failureCount = 0;
175 std::unique_lock<std::mutex> lock(mutex_);
176 for (auto& name : nameList) {
177 auto it = pluginSessions_.find(name);
178 if (it == pluginSessions_.end()) {
179 continue;
180 }
181 if (!it->second->Stop()) {
182 HILOG_INFO(LOG_CORE, "stop session %s FAILED!", it->first.c_str());
183 failureCount++;
184 }
185 }
186 return failureCount == 0;
187 }
188
CheckStatus(const std::vector<std::string> & nameList,PluginSession::State state)189 bool PluginSessionManager::CheckStatus(const std::vector<std::string>& nameList, PluginSession::State state)
190 {
191 std::unique_lock<std::mutex> lock(mutex_);
192 for (auto& name : nameList) {
193 auto it = pluginSessions_.find(name);
194 if (it == pluginSessions_.end()) {
195 continue;
196 }
197 auto actualState = it->second->GetState();
198 if (actualState != state) {
199 HILOG_INFO(LOG_CORE, "plugin %s state is %d not %d!", it->first.c_str(), actualState, state);
200 return false;
201 }
202 }
203 return true;
204 }
205
GetStatus(const std::vector<std::string> & nameList)206 std::vector<PluginSession::State> PluginSessionManager::GetStatus(const std::vector<std::string>& nameList)
207 {
208 std::vector<PluginSession::State> status;
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 status.push_back(it->second->GetState());
216 }
217 return status;
218 }
219