1 /*
2 * Copyright (c) 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 #define LOG_TAG "WaterVersionManager"
16 #include "water_version_manager.h"
17
18 #include "checker/checker_manager.h"
19 #include "cloud/cloud_sync_finished_event.h"
20 #include "device_manager_adapter.h"
21 #include "device_matrix.h"
22 #include "eventcenter/event_center.h"
23 #include "log_print.h"
24 #include "metadata/matrix_meta_data.h"
25 #include "metadata/meta_data_manager.h"
26 #include "metadata/store_meta_data.h"
27 #include "store/auto_cache.h"
28 #include "utils/anonymous.h"
29 #include "utils/constant.h"
30
31 namespace OHOS::DistributedData {
32 using DMAdapter = DeviceManagerAdapter;
33 using WaterVersionMetaData = WaterVersionManager::WaterVersionMetaData;
34
GetInstance()35 WaterVersionManager &WaterVersionManager::GetInstance()
36 {
37 static WaterVersionManager waterVersionManager;
38 return waterVersionManager;
39 }
WaterVersionManager()40 WaterVersionManager::WaterVersionManager() : waterVersions_(BUTT)
41 {
42 for (int i = 0; i < static_cast<int>(BUTT); ++i) {
43 waterVersions_[i].SetType(static_cast<Type>(i));
44 }
45 }
~WaterVersionManager()46 WaterVersionManager::~WaterVersionManager() {}
47
Init()48 void WaterVersionManager::Init()
49 {
50 std::vector<WaterVersionMetaData> metas;
51 auto stores = CheckerManager::GetInstance().GetDynamicStores();
52 for (const auto &store : stores) {
53 waterVersions_[DYNAMIC].AddKey(Merge(store.bundleName, store.storeId));
54 }
55 stores = CheckerManager::GetInstance().GetStaticStores();
56 for (const auto &store : stores) {
57 waterVersions_[STATIC].AddKey(Merge(store.bundleName, store.storeId));
58 }
59 MetaDataManager::GetInstance().LoadMeta(WaterVersionMetaData::GetPrefix(), metas, true);
60 for (auto &meta : metas) {
61 if (meta.type < BEGIN || meta.type > BUTT) {
62 ZLOGW("error meta:%{public}s", meta.ToAnonymousString().c_str());
63 continue;
64 }
65 waterVersions_[meta.type].InitWaterVersion(meta);
66 }
67 EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC_FINISHED, [this](const Event &event) {
68 auto &cloudSyncFinishedEvent = static_cast<const CloudSyncFinishedEvent &>(event);
69 auto storeMeta = cloudSyncFinishedEvent.GetStoreMeta();
70 auto store = AutoCache::GetInstance().GetStore(StoreMetaData(storeMeta), {});
71 if (store == nullptr) {
72 return;
73 }
74 auto versions = store->GetWaterVersion("");
75 for (auto &version : versions) {
76 SetWaterVersion(storeMeta.bundleName, storeMeta.storeId, version);
77 }
78 });
79 }
80
GenerateWaterVersion(const std::string & bundleName,const std::string & storeName)81 std::string WaterVersionManager::GenerateWaterVersion(const std::string &bundleName, const std::string &storeName)
82 {
83 auto type = BUTT;
84 CheckerManager::StoreInfo info;
85 info.bundleName = bundleName;
86 info.storeId = storeName;
87 if (CheckerManager::GetInstance().IsDynamic(info)) {
88 type = DYNAMIC;
89 }
90 if (CheckerManager::GetInstance().IsStatic(info)) {
91 type = STATIC;
92 }
93 if (type < BEGIN || type >= BUTT || bundleName.empty() || storeName.empty()) {
94 ZLOGE("invalid args. bundleName:%{public}s, storeName:%{public}s, type:%{public}d", bundleName.c_str(),
95 Anonymous::Change(storeName).c_str(), type);
96 return "";
97 }
98 auto [success, meta] = waterVersions_[type].GenerateWaterVersion(Merge(bundleName, storeName));
99 return success ? Serializable::Marshall(meta) : "";
100 }
101
GetWaterVersion(const std::string & bundleName,const std::string & storeName)102 std::string WaterVersionManager::GetWaterVersion(const std::string &bundleName, const std::string &storeName)
103 {
104 auto type = BUTT;
105 CheckerManager::StoreInfo info;
106 info.bundleName = bundleName;
107 info.storeId = storeName;
108 if (CheckerManager::GetInstance().IsDynamic(info)) {
109 type = DYNAMIC;
110 }
111 if (CheckerManager::GetInstance().IsStatic(info)) {
112 type = STATIC;
113 }
114 if (type < BEGIN || type >= BUTT || bundleName.empty() || storeName.empty()) {
115 ZLOGE("invalid args. bundleName:%{public}s, storeName:%{public}s, type:%{public}d", bundleName.c_str(),
116 Anonymous::Change(storeName).c_str(), type);
117 return "";
118 }
119 auto [success, meta] = waterVersions_[type].GetWaterVersion(DMAdapter::GetInstance().GetLocalDevice().uuid);
120 if (!success) {
121 return "";
122 }
123 auto target = Merge(bundleName, storeName);
124 int i = 0;
125 for (auto &key : meta.keys) {
126 if (key == target) {
127 meta.waterVersion = meta.infos[i][i];
128 return Serializable::Marshall(meta);
129 }
130 i++;
131 }
132 ZLOGE("invalid args. bundleName:%{public}s, storeName:%{public}s, meta:%{public}d", bundleName.c_str(),
133 Anonymous::Change(storeName).c_str(), type);
134 return "";
135 }
136
GetVersion(const std::string & deviceId,WaterVersionManager::Type type)137 std::pair<bool, uint64_t> WaterVersionManager::GetVersion(const std::string &deviceId,
138 WaterVersionManager::Type type)
139 {
140 if (type < BEGIN || type >= BUTT || deviceId.empty()) {
141 ZLOGE("invalid args, type:%{public}d", type);
142 return { false, 0 };
143 }
144 auto [success, waterVersion] = waterVersions_[type].GetWaterVersion(deviceId);
145 return { success, success ? waterVersion.waterVersion : 0 };
146 }
147
GetWaterVersion(const std::string & deviceId,WaterVersionManager::Type type)148 std::string WaterVersionManager::GetWaterVersion(const std::string &deviceId, WaterVersionManager::Type type)
149 {
150 if (type < BEGIN || type >= BUTT || deviceId.empty()) {
151 ZLOGE("invalid args, type:%{public}d", type);
152 return { false, 0 };
153 }
154 auto [success, waterVersion] = waterVersions_[type].GetWaterVersion(deviceId);
155 return success ? Serializable::Marshall(waterVersion) : "";
156 }
157
SetWaterVersion(const std::string & bundleName,const std::string & storeName,const std::string & waterVersion)158 bool WaterVersionManager::SetWaterVersion(const std::string &bundleName, const std::string &storeName,
159 const std::string &waterVersion)
160 {
161 WaterVersionMetaData metaData;
162 if (!Serializable::Unmarshall(waterVersion, metaData) || metaData.deviceId.empty() || !metaData.IsValid()) {
163 ZLOGE("invalid args. meta:%{public}s, bundleName:%{public}s, storeName:%{public}s",
164 metaData.ToAnonymousString().c_str(), bundleName.c_str(), Anonymous::Change(storeName).c_str());
165 return false;
166 }
167 if (metaData.deviceId == DMAdapter::GetInstance().GetLocalDevice().uuid) {
168 return false;
169 }
170 return waterVersions_[metaData.type].SetWaterVersion(Merge(bundleName, storeName), metaData);
171 }
172
DelWaterVersion(const std::string & deviceId)173 bool WaterVersionManager::DelWaterVersion(const std::string &deviceId)
174 {
175 bool res = true;
176 for (auto &waterVersion : waterVersions_) {
177 res = res && waterVersion.DelWaterVersion(deviceId);
178 }
179 return res;
180 }
181
InitMeta(WaterVersionMetaData & metaData)182 bool WaterVersionManager::InitMeta(WaterVersionMetaData &metaData)
183 {
184 metaData.waterVersion = WaterVersionMetaData::DEFAULT_VERSION;
185 std::string uuid = DMAdapter::GetInstance().GetLocalDevice().uuid;
186 for (size_t i = 0; i < metaData.keys.size(); ++i) {
187 auto key = metaData.keys[i];
188 StoreMetaData storeMetaData;
189 storeMetaData.user = std::to_string(0);
190 std::tie(storeMetaData.bundleName, storeMetaData.storeId) = Split(key);
191 storeMetaData.instanceId = 0;
192 if (!MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData, true)) {
193 ZLOGE("no store! bundleName:%{public}s, storeName:%{public}s", storeMetaData.bundleName.c_str(),
194 storeMetaData.GetStoreAlias().c_str());
195 continue;
196 }
197 auto store = AutoCache::GetInstance().GetStore(storeMetaData, {});
198 if (store == nullptr) {
199 ZLOGE("store is null! bundleName:%{public}s, storeName:%{public}s", storeMetaData.bundleName.c_str(),
200 storeMetaData.GetStoreAlias().c_str());
201 continue;
202 }
203 auto waterVersion = store->GetWaterVersion(uuid);
204 WaterVersionMetaData meta;
205 if (waterVersion.empty() || !Serializable::Unmarshall(*waterVersion.begin(), meta)) {
206 ZLOGE("GetWaterVersion failed! bundleName:%{public}s, storeName:%{public}s, meta:%{public}s",
207 storeMetaData.bundleName.c_str(), storeMetaData.GetStoreAlias().c_str(),
208 meta.ToAnonymousString().c_str());
209 continue;
210 }
211 if (meta.version != metaData.version || meta.keys != metaData.keys) {
212 meta = Upgrade(metaData.keys, meta);
213 }
214 metaData.infos[i] = meta.infos[i];
215 }
216 UpdateWaterVersion(metaData);
217 return true;
218 }
219
UpdateWaterVersion(WaterVersionMetaData & metaData)220 void WaterVersionManager::UpdateWaterVersion(WaterVersionMetaData &metaData)
221 {
222 ZLOGI("before update meta:%{public}s", metaData.ToAnonymousString().c_str());
223 uint64_t maxVersion = 0;
224 uint64_t consistentVersion = 0;
225 for (size_t i = 0; i < metaData.keys.size(); ++i) {
226 for (size_t j = 0; j < metaData.keys.size(); ++j) {
227 maxVersion = std::max(maxVersion, metaData.infos[j][j]);
228 if (metaData.infos[i][j] > metaData.infos[j][j]) {
229 break;
230 }
231 if (j == metaData.keys.size() - 1 && metaData.infos[i][i] > consistentVersion) {
232 consistentVersion = metaData.infos[i][i];
233 }
234 }
235 }
236 if (consistentVersion > metaData.waterVersion || maxVersion < metaData.waterVersion) {
237 metaData.waterVersion = consistentVersion;
238 SaveMatrix(metaData);
239 ZLOGI("after update meta:%{public}s", metaData.ToAnonymousString().c_str());
240 } else {
241 ZLOGD("after update meta:%{public}s", metaData.ToAnonymousString().c_str());
242 }
243 }
244
Merge(const std::string & bundleName,const std::string & storeName)245 std::string WaterVersionManager::Merge(const std::string &bundleName, const std::string &storeName)
246 {
247 return Constant::Join(bundleName, Constant::KEY_SEPARATOR, { storeName });
248 }
249
Split(const std::string & key)250 std::pair<std::string, std::string> WaterVersionManager::Split(const std::string &key)
251 {
252 std::vector<std::string> res;
253 size_t pos = 0;
254 std::string delim(Constant::KEY_SEPARATOR);
255 while (pos < key.size()) {
256 size_t found = key.find(delim, pos);
257 if (found == std::string::npos) {
258 res.push_back(key.substr(pos));
259 break;
260 }
261 res.push_back(key.substr(pos, found - pos));
262 pos = found + delim.size();
263 }
264 // The number of res should more than 1
265 if (res.size() <= 1) {
266 return { "", "" };
267 }
268 return { res[0], res[1] };
269 }
270
Upgrade(const std::vector<std::string> & keys,const WaterVersionMetaData & meta)271 WaterVersionMetaData WaterVersionManager::Upgrade(const std::vector<std::string> &keys,
272 const WaterVersionMetaData &meta)
273 {
274 WaterVersionMetaData newMeta;
275 newMeta.keys = keys;
276 newMeta.version = WaterVersionMetaData::DEFAULT_VERSION;
277 newMeta.deviceId = meta.deviceId;
278 newMeta.waterVersion = meta.waterVersion;
279 newMeta.type = meta.type;
280 newMeta.infos = { keys.size(), std::vector<uint64_t>(keys.size(), 0) };
281 std::map<size_t, size_t> mp;
282 for (size_t i = 0; i < keys.size(); ++i) {
283 for (size_t j = 0; j < meta.keys.size(); ++j) {
284 if (meta.keys[j] == keys[i]) {
285 mp[j] = i;
286 continue;
287 }
288 }
289 }
290 for (size_t i = 0; i < meta.keys.size(); ++i) {
291 if (!mp.count(i)) {
292 continue;
293 }
294 for (size_t j = 0; j < meta.keys.size(); ++j) {
295 if (!mp.count(j)) {
296 continue;
297 }
298 newMeta.infos[mp[i]][mp[j]] = meta.infos[i][j];
299 }
300 }
301 return newMeta;
302 }
303
SaveMatrix(const WaterVersionMetaData & metaData)304 void WaterVersionManager::SaveMatrix(const WaterVersionMetaData &metaData)
305 {
306 auto localUuid = DMAdapter::GetInstance().GetLocalDevice().uuid;
307 DeviceMatrix::GetInstance().UpdateLevel(metaData.deviceId, metaData.GetLevel(),
308 metaData.type == STATIC ? DeviceMatrix::STATICS : DeviceMatrix::DYNAMIC, metaData.deviceId != localUuid);
309 }
310
Marshal(Serializable::json & node) const311 bool WaterVersionMetaData::Marshal(Serializable::json &node) const
312 {
313 SetValue(node[GET_NAME(deviceId)], deviceId);
314 SetValue(node[GET_NAME(version)], version);
315 SetValue(node[GET_NAME(waterVersion)], waterVersion);
316 SetValue(node[GET_NAME(type)], type);
317 SetValue(node[GET_NAME(keys)], keys);
318 SetValue(node[GET_NAME(infos)], infos);
319 return true;
320 }
321
Unmarshal(const Serializable::json & node)322 bool WaterVersionMetaData::Unmarshal(const Serializable::json &node)
323 {
324 GetValue(node, GET_NAME(deviceId), deviceId);
325 GetValue(node, GET_NAME(version), version);
326 GetValue(node, GET_NAME(waterVersion), waterVersion);
327 int32_t tmp = -1;
328 GetValue(node, GET_NAME(type), tmp);
329 if (tmp < BEGIN || tmp >= BUTT) {
330 return false;
331 }
332 type = static_cast<Type>(tmp);
333 GetValue(node, GET_NAME(keys), keys);
334 GetValue(node, GET_NAME(infos), infos);
335 return true;
336 }
337
ToAnonymousString() const338 std::string WaterVersionMetaData::ToAnonymousString() const
339 {
340 json root;
341 Marshal(root);
342 SetValue(root[GET_NAME(deviceId)], Anonymous::Change(deviceId));
343 return root.dump(-1, ' ', false, error_handler_t::replace);
344 }
345
GetKey() const346 std::string WaterVersionMetaData::GetKey() const
347 {
348 return Constant::Join(KEY_PREFIX, Constant::KEY_SEPARATOR, { deviceId, std::to_string(type) });
349 }
350
GetVersion() const351 uint64_t WaterVersionMetaData::GetVersion() const
352 {
353 return waterVersion;
354 }
355
GetPrefix()356 std::string WaterVersionMetaData::GetPrefix()
357 {
358 return KEY_PREFIX;
359 }
360
IsValid()361 bool WaterVersionMetaData::IsValid()
362 {
363 if (type < BEGIN || type >= BUTT) {
364 return false;
365 }
366 if (keys.size() != infos.size()) {
367 return false;
368 }
369 for (const auto &info : infos) {
370 if (info.size() != keys.size()) {
371 return false;
372 }
373 }
374 return true;
375 }
376
SetType(WaterVersionManager::Type type)377 void WaterVersionManager::WaterVersion::SetType(WaterVersionManager::Type type)
378 {
379 type_ = type;
380 }
381
AddKey(const std::string & key)382 void WaterVersionManager::WaterVersion::AddKey(const std::string &key)
383 {
384 for (auto &tmp : keys_) {
385 if (tmp == key) {
386 return;
387 }
388 }
389 keys_.push_back(key);
390 }
391
GenerateWaterVersion(const std::string & key)392 std::pair<bool, WaterVersionMetaData> WaterVersionManager::WaterVersion::GenerateWaterVersion(const std::string &key)
393 {
394 WaterVersionMetaData metaData;
395 for (size_t i = 0; i < keys_.size(); ++i) {
396 if (keys_[i] != key) {
397 continue;
398 }
399 metaData.type = type_;
400 metaData.keys = keys_;
401 metaData.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
402 if (metaData.deviceId.empty()) {
403 ZLOGE("GetLocalDevice failed!");
404 break;
405 }
406 metaData.infos = { metaData.keys.size(), std::vector<uint64_t>(metaData.keys.size(), 0) };
407 // ensure serial execution
408 std::lock_guard<decltype(mutex_)> lock(mutex_);
409 auto status = versions_.Get(metaData.deviceId, metaData);
410 if (!status && !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)) {
411 ZLOGW("no WaterVersion, start InitMeta");
412 InitMeta(metaData);
413 }
414 metaData.waterVersion++;
415 if ((metaData.waterVersion & INVALID_VERSION) == INVALID_VERSION) {
416 metaData.waterVersion++;
417 }
418 // It has been initialized above, so there is no need to check for out of bounds
419 metaData.infos[i][i] = metaData.waterVersion;
420 for (size_t j = 0; j < metaData.keys.size(); ++j) {
421 metaData.infos[i][j] = metaData.infos[j][j];
422 }
423 ZLOGI("generate meta:%{public}s", metaData.ToAnonymousString().c_str());
424 if (MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData, true) &&
425 versions_.Set(metaData.deviceId, metaData)) {
426 SaveMatrix(metaData);
427 return { true, metaData };
428 }
429 return { false, metaData };
430 }
431 return { false, metaData };
432 }
433
GetWaterVersion(const std::string & deviceId)434 std::pair<bool, WaterVersionMetaData> WaterVersionManager::WaterVersion::GetWaterVersion(const std::string &deviceId)
435 {
436 WaterVersionMetaData meta;
437 if (versions_.Get(deviceId, meta)) {
438 return { true, meta };
439 }
440 meta.deviceId = deviceId;
441 meta.type = type_;
442 if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
443 versions_.Set(deviceId, meta);
444 return { true, meta };
445 }
446 ZLOGW("no meta. deviceId:%{public}s", Anonymous::Change(deviceId).c_str());
447 return { false, meta };
448 }
449
SetWaterVersion(const std::string & key,const WaterVersionMetaData & metaData)450 bool WaterVersionManager::WaterVersion::SetWaterVersion(const std::string &key,
451 const WaterVersionMetaData &metaData)
452 {
453 if (std::find(keys_.begin(), keys_.end(), key) == keys_.end()) {
454 ZLOGE("invalid key. meta:%{public}s", metaData.ToAnonymousString().c_str());
455 return false;
456 }
457 WaterVersionMetaData oldMeta;
458 // ensure serial execution
459 std::lock_guard<decltype(mutex_)> lock(mutex_);
460 if (!versions_.Get(metaData.deviceId, oldMeta) &&
461 !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta, true)) {
462 ZLOGI("no meta. deviceId:%{public}s", Anonymous::Change(metaData.deviceId).c_str());
463 oldMeta.version = WaterVersionMetaData::DEFAULT_VERSION;
464 oldMeta.deviceId = metaData.deviceId;
465 oldMeta.keys = keys_;
466 oldMeta.type = metaData.type;
467 oldMeta.waterVersion = 0;
468 oldMeta.infos = { keys_.size(), std::vector<uint64_t>(keys_.size(), 0) };
469 }
470
471 if (keys_ == metaData.keys) {
472 for (size_t i = 0; i < oldMeta.keys.size(); ++i) {
473 if (oldMeta.keys[i] == key) {
474 oldMeta.infos[i] = metaData.infos[i];
475 break;
476 }
477 }
478 } else {
479 auto upgradeMeta = Upgrade(keys_, metaData);
480 ZLOGI("upgrade meta. before:%{public}s, after:%{public}s", metaData.ToAnonymousString().c_str(),
481 upgradeMeta.ToAnonymousString().c_str());
482 for (size_t i = 0; i < oldMeta.keys.size(); ++i) {
483 if (oldMeta.keys[i] == key) {
484 oldMeta.infos[i] = upgradeMeta.infos[i];
485 break;
486 }
487 }
488 }
489 UpdateWaterVersion(oldMeta);
490 return MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta, true) &&
491 versions_.Set(metaData.deviceId, oldMeta);
492 }
493
DelWaterVersion(const std::string & deviceId)494 bool WaterVersionManager::WaterVersion::DelWaterVersion(const std::string &deviceId)
495 {
496 WaterVersionMetaData meta;
497 if (versions_.Get(deviceId, meta)) {
498 return versions_.Delete(deviceId) && MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true);
499 }
500 return true;
501 }
502
InitWaterVersion(const WaterVersionMetaData & metaData)503 bool WaterVersionManager::WaterVersion::InitWaterVersion(const WaterVersionMetaData &metaData)
504 {
505 if (keys_ != metaData.keys || metaData.version != WaterVersionMetaData::DEFAULT_VERSION) {
506 auto meta = Upgrade(keys_, metaData);
507 return MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true) &&
508 versions_.Set(meta.deviceId, meta);
509 }
510 return versions_.Set(metaData.deviceId, metaData);
511 }
512 } // namespace OHOS::DistributedData
513