1 /*
2 * Copyright (c) 2022-2024 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 "version_info_manager.h"
17
18 #include "anonymous_string.h"
19 #include "constants.h"
20 #include "dh_context.h"
21 #include "dh_utils_tool.h"
22 #include "distributed_hardware_errno.h"
23 #include "distributed_hardware_log.h"
24 #include "task_executor.h"
25 #include "task_factory.h"
26 #include "version_manager.h"
27
28 class DBAdapter;
29 namespace OHOS {
30 namespace DistributedHardware {
31 #undef DH_LOG_TAG
32 #define DH_LOG_TAG "VersionInfoManager"
33
VersionInfoManager()34 VersionInfoManager::VersionInfoManager() : dbAdapterPtr_(nullptr)
35 {}
36
~VersionInfoManager()37 VersionInfoManager::~VersionInfoManager()
38 {
39 DHLOGI("VersionInfoManager Destruction!");
40 }
41
VersionInfoManagerEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,std::shared_ptr<VersionInfoManager> versionInfoMgrPtr)42 VersionInfoManager::VersionInfoManagerEventHandler::VersionInfoManagerEventHandler(
43 const std::shared_ptr<AppExecFwk::EventRunner> runner, std::shared_ptr<VersionInfoManager> versionInfoMgrPtr)
44 : AppExecFwk::EventHandler(runner)
45 {
46 DHLOGI("Ctor VersionInfoManagerEventHandler");
47 versionInfoMgrWPtr_ = versionInfoMgrPtr;
48 }
49
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)50 void VersionInfoManager::VersionInfoManagerEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
51 {
52 uint32_t eventId = event->GetInnerEventId();
53 auto selfPtr = versionInfoMgrWPtr_.lock();
54 if (!selfPtr) {
55 DHLOGE("Can not get strong self ptr");
56 return;
57 }
58 switch (eventId) {
59 case EVENT_VERSION_INFO_DB_RECOVER:
60 selfPtr->SyncRemoteVersionInfos();
61 break;
62 default:
63 DHLOGE("event is undefined, id is %{public}d", eventId);
64 break;
65 }
66 }
67
GetEventHandler()68 std::shared_ptr<VersionInfoManager::VersionInfoManagerEventHandler> VersionInfoManager::GetEventHandler()
69 {
70 return this->eventHandler_;
71 }
72
GetInstance()73 std::shared_ptr<VersionInfoManager> VersionInfoManager::GetInstance()
74 {
75 static std::shared_ptr<VersionInfoManager> instance = std::make_shared<VersionInfoManager>();
76 return instance;
77 }
78
Init()79 int32_t VersionInfoManager::Init()
80 {
81 DHLOGI("VersionInfoManager instance init!");
82 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
83 dbAdapterPtr_ = std::make_shared<DBAdapter>(APP_ID, GLOBAL_VERSION_ID, shared_from_this());
84 if (dbAdapterPtr_->Init(false, DistributedKv::DataType::TYPE_DYNAMICAL) != DH_FWK_SUCCESS) {
85 DHLOGE("Init dbAdapterPtr_ failed");
86 return ERR_DH_FWK_RESOURCE_INIT_DB_FAILED;
87 }
88
89 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true);
90 eventHandler_ = std::make_shared<VersionInfoManager::VersionInfoManagerEventHandler>(
91 runner, shared_from_this());
92 DHLOGI("VersionInfoManager instance init success");
93 return DH_FWK_SUCCESS;
94 }
95
UnInit()96 int32_t VersionInfoManager::UnInit()
97 {
98 DHLOGI("VersionInfoManager UnInit");
99 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
100 if (dbAdapterPtr_ == nullptr) {
101 DHLOGE("dbAdapterPtr_ is null");
102 return ERR_DH_FWK_RESOURCE_UNINIT_DB_FAILED;
103 }
104 dbAdapterPtr_->UnInit();
105 dbAdapterPtr_.reset();
106 return DH_FWK_SUCCESS;
107 }
108
AddVersion(const VersionInfo & versionInfo)109 int32_t VersionInfoManager::AddVersion(const VersionInfo &versionInfo)
110 {
111 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
112 if (dbAdapterPtr_ == nullptr) {
113 DHLOGE("dbAdapterPtr_ is null");
114 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
115 }
116
117 std::string data("");
118 dbAdapterPtr_->GetDataByKey(versionInfo.deviceId, data);
119 if (data.compare(versionInfo.ToJsonString()) == 0) {
120 DHLOGI("dhversion already stored, Key: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
121 return DH_FWK_SUCCESS;
122 }
123
124 std::string key = versionInfo.deviceId;
125 std::string value = versionInfo.ToJsonString();
126 DHLOGI("AddVersion, Key: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
127 if (dbAdapterPtr_->PutData(key, value) != DH_FWK_SUCCESS) {
128 DHLOGE("Fail to storage to kv");
129 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
130 }
131 return DH_FWK_SUCCESS;
132 }
133
GetVersionInfoByDeviceId(const std::string & deviceId,VersionInfo & versionInfo)134 int32_t VersionInfoManager::GetVersionInfoByDeviceId(const std::string &deviceId, VersionInfo &versionInfo)
135 {
136 if (!IsIdLengthValid(deviceId)) {
137 return ERR_DH_FWK_PARA_INVALID;
138 }
139 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
140 if (dbAdapterPtr_ == nullptr) {
141 DHLOGE("dbAdapterPtr_ is null");
142 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
143 }
144 std::string data("");
145 if (dbAdapterPtr_->GetDataByKey(deviceId, data) != DH_FWK_SUCCESS) {
146 DHLOGE("Query data from DB by deviceId failed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
147 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
148 }
149 return versionInfo.FromJsonString(data);
150 }
151
UpdateVersionCache(const VersionInfo & versionInfo)152 void VersionInfoManager::UpdateVersionCache(const VersionInfo &versionInfo)
153 {
154 std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(versionInfo.deviceId);
155 if (uuid.empty()) {
156 DHLOGI("Find uuid failed, deviceId: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
157 return;
158 }
159 DHVersion dhVersion;
160 dhVersion.uuid = uuid;
161 dhVersion.dhVersion = versionInfo.dhVersion;
162 dhVersion.compVersions = versionInfo.compVersions;
163 VersionManager::GetInstance().AddDHVersion(uuid, dhVersion);
164 }
165
RemoveVersionInfoByDeviceId(const std::string & deviceId)166 int32_t VersionInfoManager::RemoveVersionInfoByDeviceId(const std::string &deviceId)
167 {
168 if (!IsIdLengthValid(deviceId)) {
169 return ERR_DH_FWK_PARA_INVALID;
170 }
171 DHLOGI("Remove version device info, key: %{public}s", GetAnonyString(deviceId).c_str());
172 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
173 if (dbAdapterPtr_ == nullptr) {
174 DHLOGE("dbAdapterPtr_ is null");
175 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
176 }
177
178 if (dbAdapterPtr_->RemoveDataByKey(deviceId) != DH_FWK_SUCCESS) {
179 DHLOGE("Remove version info failed, key: %{public}s", GetAnonyString(deviceId).c_str());
180 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
181 }
182
183 std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(deviceId);
184 if (uuid.empty()) {
185 DHLOGI("Find uuid failed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
186 return ERR_DH_FWK_RESOURCE_UUID_NOT_FOUND;
187 }
188 DHLOGI("Delete version ,uuid: %{public}s", GetAnonyString(uuid).c_str());
189 VersionManager::GetInstance().RemoveDHVersion(uuid);
190
191 return DH_FWK_SUCCESS;
192 }
193
SyncVersionInfoFromDB(const std::string & deviceId)194 int32_t VersionInfoManager::SyncVersionInfoFromDB(const std::string &deviceId)
195 {
196 if (!IsIdLengthValid(deviceId)) {
197 return ERR_DH_FWK_PARA_INVALID;
198 }
199 DHLOGI("Sync versionInfo from DB, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
200 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
201 if (dbAdapterPtr_ == nullptr) {
202 DHLOGE("dbAdapterPtr_ is null");
203 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
204 }
205 std::string data("");
206 if (dbAdapterPtr_->GetDataByKey(deviceId, data) != DH_FWK_SUCCESS) {
207 DHLOGE("Query data from DB by deviceId failed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
208 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
209 }
210
211 DHLOGI("Query data from DB by deviceId success, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
212 VersionInfo versionInfo;
213 int32_t ret = versionInfo.FromJsonString(data);
214 if (ret != DH_FWK_SUCCESS) {
215 return ret;
216 }
217 UpdateVersionCache(versionInfo);
218 return DH_FWK_SUCCESS;
219 }
220
SyncRemoteVersionInfos()221 int32_t VersionInfoManager::SyncRemoteVersionInfos()
222 {
223 DHLOGI("Sync full remote version info from DB");
224 std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
225 if (dbAdapterPtr_ == nullptr) {
226 DHLOGE("dbAdapterPtr_ is null");
227 return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
228 }
229 std::vector<std::string> deviceIdVec;
230 DHContext::GetInstance().GetOnlineDeviceDeviceId(deviceIdVec);
231 for (const auto &deviceId : deviceIdVec) {
232 std::vector<std::string> dataVector;
233 if (dbAdapterPtr_->GetDataByKeyPrefix(deviceId, dataVector) != DH_FWK_SUCCESS) {
234 DHLOGE("Query the deviceId: %{public}s data from DB failed", GetAnonyString(deviceId).c_str());
235 continue;
236 }
237 if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) {
238 DHLOGE("dataVector size: %{public}zu is invalid, maybe empty or too large.", dataVector.size());
239 continue;
240 }
241 for (const auto &data : dataVector) {
242 VersionInfo versionInfo;
243 if (versionInfo.FromJsonString(data) != DH_FWK_SUCCESS) {
244 continue;
245 }
246 const std::string &deviceId = versionInfo.deviceId;
247 const std::string &localDeviceId = DHContext::GetInstance().GetDeviceInfo().deviceId;
248 if (deviceId.compare(localDeviceId) == 0) {
249 DHLOGE("Local device info not need sync from db");
250 continue;
251 }
252 UpdateVersionCache(versionInfo);
253 }
254 }
255 return DH_FWK_SUCCESS;
256 }
257
OnChange(const DistributedKv::ChangeNotification & changeNotification)258 void VersionInfoManager::OnChange(const DistributedKv::ChangeNotification &changeNotification)
259 {
260 DHLOGI("DB data OnChange");
261 if (!changeNotification.GetInsertEntries().empty() &&
262 changeNotification.GetInsertEntries().size() <= MAX_DB_RECORD_SIZE) {
263 DHLOGI("Handle version data add change");
264 HandleVersionAddChange(changeNotification.GetInsertEntries());
265 }
266 if (!changeNotification.GetUpdateEntries().empty() &&
267 changeNotification.GetUpdateEntries().size() <= MAX_DB_RECORD_SIZE) {
268 DHLOGI("Handle version data update change");
269 HandleVersionUpdateChange(changeNotification.GetUpdateEntries());
270 }
271 if (!changeNotification.GetDeleteEntries().empty() &&
272 changeNotification.GetDeleteEntries().size() <= MAX_DB_RECORD_SIZE) {
273 DHLOGI("Handle version data delete change");
274 HandleVersionDeleteChange(changeNotification.GetDeleteEntries());
275 }
276 }
277
HandleVersionAddChange(const std::vector<DistributedKv::Entry> & insertRecords)278 void VersionInfoManager::HandleVersionAddChange(const std::vector<DistributedKv::Entry> &insertRecords)
279 {
280 DHLOGI("Version add change");
281 for (const auto &item : insertRecords) {
282 const std::string value = item.value.ToString();
283 VersionInfo versionInfo;
284 if (versionInfo.FromJsonString(value) != DH_FWK_SUCCESS) {
285 continue;
286 }
287 UpdateVersionCache(versionInfo);
288 }
289 }
290
HandleVersionUpdateChange(const std::vector<DistributedKv::Entry> & updateRecords)291 void VersionInfoManager::HandleVersionUpdateChange(const std::vector<DistributedKv::Entry> &updateRecords)
292 {
293 DHLOGI("Version update change");
294 for (const auto &item : updateRecords) {
295 const std::string value = item.value.ToString();
296 VersionInfo versionInfo;
297 if (versionInfo.FromJsonString(value) != DH_FWK_SUCCESS) {
298 continue;
299 }
300 UpdateVersionCache(versionInfo);
301 }
302 }
303
HandleVersionDeleteChange(const std::vector<DistributedKv::Entry> & deleteRecords)304 void VersionInfoManager::HandleVersionDeleteChange(const std::vector<DistributedKv::Entry> &deleteRecords)
305 {
306 DHLOGI("Version delete change");
307 for (const auto &item : deleteRecords) {
308 const std::string value = item.value.ToString();
309 VersionInfo versionInfo;
310 if (versionInfo.FromJsonString(value) != DH_FWK_SUCCESS) {
311 continue;
312 }
313 std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(versionInfo.deviceId);
314 if (uuid.empty()) {
315 DHLOGI("Find uuid failed, deviceId: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
316 continue;
317 }
318 DHLOGI("Delete version ,uuid: %{public}s", GetAnonyString(uuid).c_str());
319 VersionManager::GetInstance().RemoveDHVersion(uuid);
320 }
321 }
322 } // namespace DistributedHardware
323 } // namespace OHOS
324