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