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 "server_executor/include/engine_manager.h"
17
18 #include <cstring>
19
20 #include "platform/lock/include/rw_lock.h"
21 #include "plugin/i_plugin.h"
22 #include "plugin_manager/include/aie_plugin_info.h"
23 #include "plugin_manager/include/i_plugin_manager.h"
24 #include "server_executor/include/engine.h"
25 #include "utils/constants/constants.h"
26 #include "utils/log/aie_log.h"
27
28 namespace OHOS {
29 namespace AI {
30 namespace {
31 const int PLUGIN_NUM_FOR_UNLOAD = 1;
32 }
33 EngineManager::EngineManager() = default;
34
~EngineManager()35 EngineManager::~EngineManager()
36 {
37 Uninitialize();
38 }
39
Initialize()40 int EngineManager::Initialize()
41 {
42 return RETCODE_SUCCESS;
43 }
44
Uninitialize()45 void EngineManager::Uninitialize()
46 {
47 HILOGI("[EngineManager]Begin to release engine manager.");
48 engines_.clear();
49 clientEngines_.clear();
50
51 IPluginManager *pluginManager = IPluginManager::GetPluginManager();
52 if (pluginManager != nullptr) {
53 pluginManager->Destroy();
54 }
55 }
56
StartEngine(long long transactionId,const AlgorithmInfo & algoInfo,const DataInfo & inputInfo,DataInfo & outputInfo)57 int EngineManager::StartEngine(long long transactionId, const AlgorithmInfo &algoInfo, const DataInfo &inputInfo,
58 DataInfo &outputInfo)
59 {
60 std::string aid = GetAlgorithmIdByType(algoInfo.algorithmType);
61 if (aid == ALGORITHM_ID_INVALID) {
62 HILOGE("[EngineManager]Start engine failed, aid is invalid.");
63 return RETCODE_ALGORITHM_ID_INVALID;
64 }
65 EngineKey engineKey(aid, algoInfo.algorithmVersion);
66 std::shared_ptr<Engine> engine = FindEngine(engineKey);
67 if (engine == nullptr) {
68 int retCode = CreateEngineWithCheck(engineKey, engine);
69 if (retCode != RETCODE_SUCCESS) {
70 HILOGE("[EngineManager][transactionId:%lld]Create engine failed, retCode=[%d].",
71 transactionId, retCode);
72 return retCode;
73 }
74 }
75 std::shared_ptr<Plugin> plugin = engine->GetPlugin();
76 if (plugin == nullptr) {
77 HILOGE("[EngineManager]Plugin is nullptr.");
78 return RETCODE_FAILURE;
79 }
80 int retCode = plugin->GetPluginAlgorithm()->Prepare(transactionId, inputInfo, outputInfo);
81 if (retCode != RETCODE_SUCCESS) {
82 HILOGE("[EngineManager]Start engine failed, failed to prepare.");
83 return retCode;
84 }
85 engine->AddEngineReference();
86 RecordClient(transactionId, engine);
87 return RETCODE_SUCCESS;
88 }
89
StopEngine(long long transactionId,const DataInfo & inputInfo)90 int EngineManager::StopEngine(long long transactionId, const DataInfo &inputInfo)
91 {
92 std::shared_ptr<Engine> engine = FindEngine(transactionId);
93 if (engine == nullptr) {
94 HILOGE("[EngineManager]No corresponding engine was found.");
95 return RETCODE_SA_SERVICE_EXCEPTION;
96 }
97
98 std::shared_ptr<Plugin> plugin = engine->GetPlugin();
99 if (plugin == nullptr) {
100 HILOGE("[EngineManager]The plugin is null.");
101 return RETCODE_SA_SERVICE_EXCEPTION;
102 }
103
104 // only one engine remains, fully unload this plugin
105 bool isFullUnload = engine->GetEngineReference() == PLUGIN_NUM_FOR_UNLOAD;
106 int retCode = plugin->GetPluginAlgorithm()->Release(isFullUnload, transactionId, inputInfo);
107 if (retCode != RETCODE_SUCCESS) {
108 HILOGE("[EngineManager]Failed to release plugin.");
109 return retCode;
110 }
111
112 engine->DelEngineReference();
113 if (engine->GetEngineReference() == 0) {
114 HILOGI("[EngineManager]The current engine is not in use.");
115 IPluginManager *pluginManager = IPluginManager::GetPluginManager();
116 if (pluginManager == nullptr) {
117 HILOGE("[EngineManager]The pluginManager is null.");
118 return RETCODE_NULL_PARAM;
119 }
120
121 const std::string aid = plugin->GetAid();
122 long long version = plugin->GetVersion();
123 pluginManager->UnloadPlugin(aid, version);
124 EngineKey engineKey(aid, version);
125 DelEngine(engineKey);
126 }
127 UnRecordClient(transactionId);
128 return RETCODE_SUCCESS;
129 }
130
SetOption(long long transactionId,int optionType,const DataInfo & inputInfo)131 int EngineManager::SetOption(long long transactionId, int optionType, const DataInfo &inputInfo)
132 {
133 std::shared_ptr<Engine> engine = FindEngine(transactionId);
134 if (engine == nullptr) {
135 HILOGE("[EngineManager]No corresponding engine was found.");
136 return RETCODE_SA_SERVICE_EXCEPTION;
137 }
138 std::shared_ptr<Plugin> plugin = engine->GetPlugin();
139 if (plugin == nullptr) {
140 HILOGE("[EngineManager]The plugin is null.");
141 return RETCODE_SA_SERVICE_EXCEPTION;
142 }
143 return plugin->GetPluginAlgorithm()->SetOption(optionType, inputInfo);
144 }
145
GetOption(long long transactionId,int optionType,const DataInfo & inputInfo,DataInfo & outputInfo)146 int EngineManager::GetOption(long long transactionId, int optionType, const DataInfo &inputInfo,
147 DataInfo &outputInfo)
148 {
149 std::shared_ptr<Engine> engine = FindEngine(transactionId);
150 if (engine == nullptr) {
151 HILOGE("[EngineManager]No corresponding engine was found.");
152 return RETCODE_SA_SERVICE_EXCEPTION;
153 }
154 std::shared_ptr<Plugin> plugin = engine->GetPlugin();
155 if (plugin == nullptr) {
156 HILOGE("[EngineManager]The plugin is null.");
157 return RETCODE_SA_SERVICE_EXCEPTION;
158 }
159 return plugin->GetPluginAlgorithm()->GetOption(optionType, inputInfo, outputInfo);
160 }
161
FindEngine(long long transactionId)162 std::shared_ptr<Engine> EngineManager::FindEngine(long long transactionId)
163 {
164 ReadGuard<RwLock> guard(rwLock_);
165 auto iter = clientEngines_.find(transactionId);
166 if (iter == clientEngines_.end()) {
167 HILOGE("[EngineManager]No corresponding engine was found.");
168 return nullptr;
169 }
170 return iter->second;
171 }
172
RecordClient(long long transactionId,const std::shared_ptr<Engine> & engine)173 void EngineManager::RecordClient(long long transactionId, const std::shared_ptr<Engine> &engine)
174 {
175 WriteGuard<RwLock> guard(rwLock_);
176 clientEngines_[transactionId] = engine;
177 }
178
UnRecordClient(long long transactionId)179 void EngineManager::UnRecordClient(long long transactionId)
180 {
181 WriteGuard<RwLock> guard(rwLock_);
182 clientEngines_.erase(transactionId);
183 }
184
CreateEngine(const EngineKey & engineKey,std::shared_ptr<Engine> & engine)185 int EngineManager::CreateEngine(const EngineKey &engineKey, std::shared_ptr<Engine> &engine)
186 {
187 IPluginManager *pluginManager = IPluginManager::GetPluginManager();
188 if (pluginManager == nullptr) {
189 HILOGE("[EngineManager]The pluginManager is null.");
190 return RETCODE_NULL_PARAM;
191 }
192
193 std::shared_ptr<Plugin> plugin = nullptr;
194 int retCode = pluginManager->GetPlugin(engineKey.aid, engineKey.version, plugin);
195 if (retCode != RETCODE_SUCCESS) {
196 HILOGE("[EngineManager]The plugin(aid=%s, version=%lld) is not existed.",
197 engineKey.aid.c_str(), engineKey.version);
198 return retCode;
199 }
200
201 ThreadPool *threadPool = ThreadPool::GetInstance();
202 CHK_RET(threadPool == nullptr, RETCODE_OUT_OF_MEMORY);
203 std::shared_ptr<Thread> thread = threadPool->Pop();
204 if (thread == nullptr) {
205 HILOGE("[EngineManager]Failed to get thread.");
206 return RETCODE_OUT_OF_MEMORY;
207 }
208
209 QueuePool<Task> *queuePool = QueuePool<Task>::GetInstance(MAX_SYNC_MSG_NUM);
210 CHK_RET(queuePool == nullptr, RETCODE_OUT_OF_MEMORY);
211 std::shared_ptr<Queue<Task>> queue = queuePool->Pop();
212 if (queue == nullptr) {
213 HILOGE("[EngineManager]Failed to get queue.");
214 threadPool->Push(thread);
215 return RETCODE_OUT_OF_MEMORY;
216 }
217
218 Engine *newEngine = nullptr;
219 AIE_NEW(newEngine, Engine(plugin, thread, queue));
220 if (newEngine == nullptr) {
221 HILOGE("[EngineManager]Failed to create engine.");
222 queuePool->Push(queue);
223 threadPool->Push(thread);
224 return RETCODE_ENGINE_NOT_EXIST;
225 }
226
227 engine.reset(newEngine);
228 retCode = engine->Initialize();
229 if (retCode != RETCODE_SUCCESS) {
230 HILOGE("[EngineManager]Initialize engine failed.");
231 queuePool->Push(queue);
232 threadPool->Push(thread);
233 return retCode;
234 }
235 return RETCODE_SUCCESS;
236 }
237
CreateEngineWithCheck(const EngineKey & engineKey,std::shared_ptr<Engine> & engine)238 int EngineManager::CreateEngineWithCheck(const EngineKey &engineKey, std::shared_ptr<Engine> &engine)
239 {
240 HILOGI("[EngineManager]Begin to create corresponding engine.");
241 WriteGuard<RwLock> guard(rwLock_);
242 Engines::iterator iter = engines_.find(engineKey);
243 if (iter != engines_.end()) {
244 HILOGI("[EngineManager]Success to find engine.");
245 engine = iter->second;
246 return RETCODE_SUCCESS;
247 }
248
249 int retCode = CreateEngine(engineKey, engine);
250 if (retCode != RETCODE_SUCCESS) {
251 HILOGE("[EngineManager]Failed to create engine.");
252 return retCode;
253 }
254
255 engines_[engineKey] = engine;
256 return RETCODE_SUCCESS;
257 }
258
FindEngine(const EngineKey & engineKey)259 std::shared_ptr<Engine> EngineManager::FindEngine(const EngineKey &engineKey)
260 {
261 ReadGuard<RwLock> guard(rwLock_);
262 Engines::iterator iter = engines_.find(engineKey);
263 if (iter == engines_.end()) {
264 HILOGI("[EngineManager]No corresponding engine was found.");
265 return nullptr;
266 }
267 return iter->second;
268 }
269
DelEngine(const EngineKey & engineKey)270 void EngineManager::DelEngine(const EngineKey &engineKey)
271 {
272 WriteGuard<RwLock> guard(rwLock_);
273 engines_.erase(engineKey);
274 }
275 } // namespace AI
276 } // namespace OHOS