• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "script_manager_impl.h"
16 #include <cstring>
17 #include <dlfcn.h>
18 #include "pkg_manager.h"
19 #include "script_instructionhelper.h"
20 #include "script_interpreter.h"
21 #include "script_utils.h"
22 #include "thread_pool.h"
23 
24 using namespace hpackage;
25 
26 namespace uscript {
27 const std::string LOAD_SCRIPT_NAME = "loadScript.us";
28 const std::string REGISTER_CMD_SCRIPT_NAME = "registerCmd.us";
29 
30 static ScriptManagerImpl* g_scriptManager = nullptr;
GetScriptManager(UScriptEnv * env)31 ScriptManager* ScriptManager::GetScriptManager(UScriptEnv *env)
32 {
33     USCRIPT_CHECK(env != nullptr, return nullptr, "Env null");
34 
35     if (g_scriptManager == nullptr) {
36         g_scriptManager = new ScriptManagerImpl(env);
37         (void)g_scriptManager->Init();
38     }
39     return g_scriptManager;
40 }
41 
ReleaseScriptManager()42 void ScriptManager::ReleaseScriptManager()
43 {
44     if (g_scriptManager != nullptr) {
45         delete g_scriptManager;
46     }
47     g_scriptManager = nullptr;
48 }
49 
~ScriptManagerImpl()50 ScriptManagerImpl::~ScriptManagerImpl()
51 {
52     if (threadPool_) {
53         ThreadPool::Destroy();
54         threadPool_ = nullptr;
55     }
56     for (int i = 0; i < MAX_PRIORITY; i++) {
57         scriptFiles_[i].clear();
58     }
59     auto iter1 = scriptInstructions_.begin();
60     while (iter1 != scriptInstructions_.end()) {
61         UScriptInstructionPtr inst = (*iter1).second;
62         delete inst;
63         iter1 = scriptInstructions_.erase(iter1);
64     }
65     scriptInstructions_.clear();
66     ScriptInstructionHelper::ReleaseBasicInstructionHelper();
67 }
68 
Init()69 int32_t ScriptManagerImpl::Init()
70 {
71     USCRIPT_CHECK(scriptEnv_ != nullptr, return USCRIPT_INVALID_PARAM, "Env null");
72 
73     threadPool_ = ThreadPool::CreateThreadPool(MAX_PRIORITY);
74     USCRIPT_CHECK(threadPool_ != nullptr, return USCRIPT_INVALID_PARAM, "Failed to create thread pool");
75 
76     // Register system reserved instructions
77     ScriptInstructionHelper* helper = ScriptInstructionHelper::GetBasicInstructionHelper(this);
78     USCRIPT_CHECK(helper != nullptr, return USCRIPT_INVALID_PARAM, "Failed to get helper");
79     helper->RegisterInstructions();
80 
81     // Register customized instructions
82     RegisterInstruction(*helper);
83 
84     PkgManager::PkgManagerPtr manager = scriptEnv_->GetPkgManager();
85     USCRIPT_CHECK(manager != nullptr, return USCRIPT_INVALID_PARAM, "Failed to get pkg manager");
86 
87     // Register other instructions from scripts
88     int32_t ret = USCRIPT_SUCCESS;
89     const FileInfo *info = manager->GetFileInfo(REGISTER_CMD_SCRIPT_NAME);
90     if (info != nullptr) {
91         ret = ExtractAndExecuteScript(manager, REGISTER_CMD_SCRIPT_NAME);
92     }
93     // Collect scripts
94     ret |= ExtractAndExecuteScript(manager, LOAD_SCRIPT_NAME);
95     USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to extract and execute script ");
96     return USCRIPT_SUCCESS;
97 }
98 
RegisterInstruction(ScriptInstructionHelper & helper)99 int32_t ScriptManagerImpl::RegisterInstruction(ScriptInstructionHelper &helper)
100 {
101     uscript::UScriptInstructionFactoryPtr factory = scriptEnv_->GetInstructionFactory();
102     USCRIPT_CHECK(factory != nullptr, return USCRIPT_SUCCESS, "None factory");
103 
104     for (auto instrName : scriptEnv_->GetInstructionNames()) {
105         // Create instructions and register it.
106         UScriptInstructionPtr instr = nullptr;
107         int32_t ret = factory->CreateInstructionInstance(instr, instrName);
108         USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to create instruction for %s", instrName.c_str());
109         helper.AddInstruction(instrName, instr);
110         USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to add instruction for %s", instrName.c_str());
111     }
112     return USCRIPT_SUCCESS;
113 }
114 
ExtractAndExecuteScript(PkgManager::PkgManagerPtr manager,const std::string & scriptName)115 int32_t ScriptManagerImpl::ExtractAndExecuteScript(PkgManager::PkgManagerPtr manager,
116     const std::string &scriptName)
117 {
118     PkgManager::StreamPtr outStream = nullptr;
119     int32_t ret = manager->CreatePkgStream(outStream, scriptName, 0, PkgStream::PkgStreamType_Write);
120     USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to create script stream %s", scriptName.c_str());
121     ret = manager->ExtractFile(scriptName, outStream);
122     USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to extract script stream %s", scriptName.c_str());
123 
124     ret = ScriptInterpreter::ExecuteScript(this, outStream);
125     manager->ClosePkgStream(outStream);
126     USCRIPT_CHECK(ret == USCRIPT_SUCCESS, return ret, "Failed to ExecuteScript %s", scriptName.c_str());
127     return ret;
128 }
129 
ExecuteScript(int32_t priority)130 int32_t ScriptManagerImpl::ExecuteScript(int32_t priority)
131 {
132     USCRIPT_CHECK(priority < MAX_PRIORITY && priority >= 0,
133         return USCRIPT_INVALID_PRIORITY, "ExecuteScript priority not support %d", priority);
134     PkgManager::PkgManagerPtr manager = scriptEnv_->GetPkgManager();
135     USCRIPT_CHECK(manager != nullptr, return USCRIPT_INVALID_PARAM, "Failed to get pkg manager");
136     if (scriptFiles_[priority].size() == 0) {
137         return USCRIPT_SUCCESS;
138     }
139 
140     // Execute scripts
141     int32_t threadNumber = threadPool_->GetThreadNumber();
142     Task task;
143     int32_t ret = USCRIPT_SUCCESS;
144     int32_t retCode = USCRIPT_SUCCESS;
145     task.workSize = threadNumber;
146     task.processor = [&](int iter) {
147         for (size_t i = iter; i < scriptFiles_[priority].size(); i += threadNumber) {
148             ret = ExtractAndExecuteScript(manager, scriptFiles_[priority][i]);
149             if (ret != USCRIPT_SUCCESS) {
150                 USCRIPT_LOGE("Failed to execute script %s", scriptFiles_[priority][i].c_str());
151                 retCode = ret;
152             }
153         }
154     };
155     ThreadPool::AddTask(std::move(task));
156     return retCode;
157 }
158 
AddInstruction(const std::string & instrName,const UScriptInstructionPtr instruction)159 int32_t ScriptManagerImpl::AddInstruction(const std::string &instrName, const UScriptInstructionPtr instruction)
160 {
161     USCRIPT_LOGI("AddInstruction instrName: %s ", instrName.c_str());
162     if (scriptInstructions_.find(instrName) != scriptInstructions_.end()) {
163         USCRIPT_LOGW("Instruction: %s exist", instrName.c_str());
164         // New instruction has the same name
165         // with already registered instruction,
166         // just override it.
167         delete scriptInstructions_[instrName];
168     }
169     scriptInstructions_[instrName] = instruction;
170     return USCRIPT_SUCCESS;
171 }
172 
AddScript(const std::string & scriptName,int32_t priority)173 int32_t ScriptManagerImpl::AddScript(const std::string &scriptName, int32_t priority)
174 {
175     USCRIPT_CHECK(priority < MAX_PRIORITY, return USCRIPT_INVALID_PRIORITY, "Invalid priority %d", priority);
176 
177     PkgManager::PkgManagerPtr manager = scriptEnv_->GetPkgManager();
178     USCRIPT_CHECK(manager != nullptr, return USCRIPT_INVALID_PARAM, "Failed to get pkg manager");
179 
180     if (manager->GetFileInfo(scriptName) == nullptr) {
181         USCRIPT_LOGE("Failed to access script %s", scriptName.c_str());
182         return USCRIPT_SUCCESS;
183     }
184     scriptFiles_[priority].push_back(scriptName);
185     return USCRIPT_SUCCESS;
186 }
187 
FindInstruction(const std::string & instrName)188 UScriptInstruction* ScriptManagerImpl::FindInstruction(const std::string &instrName)
189 {
190     if (scriptInstructions_.find(instrName) == scriptInstructions_.end()) {
191         return nullptr;
192     }
193     return scriptInstructions_[instrName];
194 }
195 
GetScriptEnv(const std::string & instrName) const196 UScriptEnv* ScriptManagerImpl::GetScriptEnv(const std::string &instrName) const
197 {
198     return scriptEnv_;
199 }
200 } // namespace uscript
201