• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 "SyncManager"
16 #include "sync_manager.h"
17 
18 #include <chrono>
19 
20 #include "account/account_delegate.h"
21 #include "bootstrap.h"
22 #include "checker/checker_manager.h"
23 #include "cloud/cloud_lock_event.h"
24 #include "cloud/cloud_report.h"
25 #include "cloud/cloud_server.h"
26 #include "cloud/schema_meta.h"
27 #include "cloud_value_util.h"
28 #include "device_manager_adapter.h"
29 #include "dfx/dfx_types.h"
30 #include "dfx/reporter.h"
31 #include "eventcenter/event_center.h"
32 #include "log_print.h"
33 #include "metadata/meta_data_manager.h"
34 #include "network/network_delegate.h"
35 #include "screen/screen_manager.h"
36 #include "sync_strategies/network_sync_strategy.h"
37 #include "user_delegate.h"
38 #include "utils/anonymous.h"
39 namespace OHOS::CloudData {
40 using namespace DistributedData;
41 using namespace DistributedDataDfx;
42 using namespace DistributedKv;
43 using namespace SharingUtil;
44 using namespace std::chrono;
45 using Account = OHOS::DistributedData::AccountDelegate;
46 using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter;
47 using Defer = EventCenter::Defer;
48 std::atomic<uint32_t> SyncManager::genId_ = 0;
49 constexpr int32_t SYSTEM_USER_ID = 0;
50 static constexpr const char *FT_GET_STORE = "GET_STORE";
51 static constexpr const char *FT_CALLBACK = "CALLBACK";
SyncInfo(int32_t user,const std::string & bundleName,const Store & store,const Tables & tables,int32_t triggerMode)52 SyncManager::SyncInfo::SyncInfo(
53     int32_t user, const std::string &bundleName, const Store &store, const Tables &tables, int32_t triggerMode)
54     : user_(user), bundleName_(bundleName), triggerMode_(triggerMode)
55 {
56     if (!store.empty()) {
57         tables_[store] = tables;
58     }
59     syncId_ = SyncManager::GenerateId(user);
60 }
61 
SyncInfo(int32_t user,const std::string & bundleName,const Stores & stores)62 SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Stores &stores)
63     : user_(user), bundleName_(bundleName)
64 {
65     for (auto &store : stores) {
66         tables_[store] = {};
67     }
68     syncId_ = SyncManager::GenerateId(user);
69 }
70 
SyncInfo(int32_t user,const std::string & bundleName,const MutliStoreTables & tables)71 SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const MutliStoreTables &tables)
72     : user_(user), bundleName_(bundleName), tables_(tables)
73 {
74     tables_ = tables;
75     syncId_ = SyncManager::GenerateId(user);
76 }
77 
SyncInfo(const Param & param)78 SyncManager::SyncInfo::SyncInfo(const Param &param)
79     : user_(param.user), bundleName_(param.bundleName), triggerMode_(param.triggerMode)
80 {
81     if (!param.store.empty()) {
82         tables_[param.store] = param.tables;
83     }
84     syncId_ = SyncManager::GenerateId(param.user);
85     prepareTraceId_ = param.prepareTraceId;
86 }
87 
SetMode(int32_t mode)88 void SyncManager::SyncInfo::SetMode(int32_t mode)
89 {
90     mode_ = mode;
91 }
92 
SetWait(int32_t wait)93 void SyncManager::SyncInfo::SetWait(int32_t wait)
94 {
95     wait_ = wait;
96 }
97 
SetAsyncDetail(GenAsync asyncDetail)98 void SyncManager::SyncInfo::SetAsyncDetail(GenAsync asyncDetail)
99 {
100     async_ = std::move(asyncDetail);
101 }
102 
SetQuery(std::shared_ptr<GenQuery> query)103 void SyncManager::SyncInfo::SetQuery(std::shared_ptr<GenQuery> query)
104 {
105     query_ = query;
106 }
107 
SetCompensation(bool isCompensation)108 void SyncManager::SyncInfo::SetCompensation(bool isCompensation)
109 {
110     isCompensation_ = isCompensation;
111 }
112 
SetTriggerMode(int32_t triggerMode)113 void SyncManager::SyncInfo::SetTriggerMode(int32_t triggerMode)
114 {
115     triggerMode_ = triggerMode;
116 }
117 
SetError(int32_t code) const118 void SyncManager::SyncInfo::SetError(int32_t code) const
119 {
120     if (async_) {
121         GenDetails details;
122         auto &detail = details[id_];
123         detail.progress = GenProgress::SYNC_FINISH;
124         detail.code = code;
125         async_(std::move(details));
126     }
127 }
128 
GenerateQuery(const std::string & store,const Tables & tables)129 std::shared_ptr<GenQuery> SyncManager::SyncInfo::GenerateQuery(const std::string &store, const Tables &tables)
130 {
131     if (query_ != nullptr) {
132         return query_;
133     }
134     class SyncQuery final : public GenQuery {
135     public:
136         explicit SyncQuery(const std::vector<std::string> &tables) : tables_(tables) {}
137 
138         bool IsEqual(uint64_t tid) override
139         {
140             return false;
141         }
142 
143         std::vector<std::string> GetTables() override
144         {
145             return tables_;
146         }
147 
148     private:
149         std::vector<std::string> tables_;
150     };
151     auto it = tables_.find(store);
152     return std::make_shared<SyncQuery>(it == tables_.end() || it->second.empty() ? tables : it->second);
153 }
154 
Contains(const std::string & storeName)155 bool SyncManager::SyncInfo::Contains(const std::string &storeName)
156 {
157     return tables_.empty() || tables_.find(storeName) != tables_.end();
158 }
159 
GetLockChangeHandler()160 std::function<void(const Event &)> SyncManager::GetLockChangeHandler()
161 {
162     return [](const Event &event) {
163         auto &evt = static_cast<const CloudLockEvent &>(event);
164         auto storeInfo = evt.GetStoreInfo();
165         auto callback = evt.GetCallback();
166         if (callback == nullptr) {
167             ZLOGE("callback is nullptr. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.",
168                 storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user);
169             return;
170         }
171         CloudInfo cloud;
172         cloud.user = storeInfo.user;
173         SyncInfo info(storeInfo.user, storeInfo.bundleName);
174         auto code = IsValid(info, cloud);
175         if (code != E_OK) {
176             return;
177         }
178 
179         StoreMetaMapping meta(storeInfo);
180         meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
181         if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
182             ZLOGE("no store mapping. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.",
183                 storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user);
184             return;
185         }
186         if (!meta.cloudPath.empty() && meta.dataDir != meta.cloudPath &&
187             !MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true)) {
188             ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
189                 meta.GetStoreAlias().c_str());
190             return;
191         }
192         auto [status, store] = GetStore(meta, storeInfo.user);
193         if (store == nullptr) {
194             ZLOGE("failed to get store. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.",
195                 storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user);
196             return;
197         }
198         if (evt.GetEventId() == CloudEvent::LOCK_CLOUD_CONTAINER) {
199             auto [result, expiredTime] = store->LockCloudDB();
200             callback(result, expiredTime);
201         } else {
202             auto result = store->UnLockCloudDB();
203             callback(result, 0);
204         }
205     };
206 }
207 
SyncManager()208 SyncManager::SyncManager()
209 {
210     EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, SyncManager::GetLockChangeHandler());
211     EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, SyncManager::GetLockChangeHandler());
212     EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, GetClientChangeHandler());
213     syncStrategy_ = std::make_shared<NetworkSyncStrategy>();
214     auto metaName = Bootstrap::GetInstance().GetProcessLabel();
215     kvApps_.insert(std::move(metaName));
216     auto stores = CheckerManager::GetInstance().GetStaticStores();
217     for (auto &store : stores) {
218         kvApps_.insert(std::move(store.bundleName));
219     }
220     stores = CheckerManager::GetInstance().GetDynamicStores();
221     for (auto &store : stores) {
222         kvApps_.insert(std::move(store.bundleName));
223     }
224 }
225 
~SyncManager()226 SyncManager::~SyncManager()
227 {
228     if (executor_ != nullptr) {
229         actives_.ForEachCopies([this](auto &syncId, auto &taskId) {
230             executor_->Remove(taskId);
231             return false;
232         });
233         executor_ = nullptr;
234     }
235 }
236 
Bind(std::shared_ptr<ExecutorPool> executor)237 int32_t SyncManager::Bind(std::shared_ptr<ExecutorPool> executor)
238 {
239     executor_ = executor;
240     return E_OK;
241 }
242 
DoCloudSync(SyncInfo syncInfo)243 int32_t SyncManager::DoCloudSync(SyncInfo syncInfo)
244 {
245     if (executor_ == nullptr) {
246         return E_NOT_INIT;
247     }
248     auto syncId = GenerateId(syncInfo.user_);
249     auto ref = GenSyncRef(syncId);
250     actives_.Compute(syncId, [this, &ref, &syncInfo](const uint64_t &key, TaskId &taskId) mutable {
251         taskId = executor_->Execute(GetSyncTask(0, true, ref, std::move(syncInfo)));
252         return true;
253     });
254     return E_OK;
255 }
256 
StopCloudSync(int32_t user)257 int32_t SyncManager::StopCloudSync(int32_t user)
258 {
259     if (executor_ == nullptr) {
260         return E_NOT_INIT;
261     }
262     actives_.ForEachCopies([this, user](auto &syncId, auto &taskId) {
263         if (Compare(syncId, user) == 0) {
264             executor_->Remove(taskId);
265         }
266         return false;
267     });
268     return E_OK;
269 }
270 
IsValid(SyncInfo & info,CloudInfo & cloud)271 GeneralError SyncManager::IsValid(SyncInfo &info, CloudInfo &cloud)
272 {
273     if (!MetaDataManager::GetInstance().LoadMeta(cloud.GetKey(), cloud, true) ||
274         (info.id_ != SyncInfo::DEFAULT_ID && cloud.id != info.id_)) {
275         info.SetError(E_CLOUD_DISABLED);
276         ZLOGE("cloudInfo invalid:%{public}d, <syncId:%{public}s, metaId:%{public}s>", cloud.IsValid(),
277             Anonymous::Change(info.id_).c_str(), Anonymous::Change(cloud.id).c_str());
278         return E_CLOUD_DISABLED;
279     }
280     if (!cloud.enableCloud || (!info.bundleName_.empty() && !cloud.IsOn(info.bundleName_))) {
281         info.SetError(E_CLOUD_DISABLED);
282         ZLOGD("enable:%{public}d, bundleName:%{public}s", cloud.enableCloud, info.bundleName_.c_str());
283         return E_CLOUD_DISABLED;
284     }
285     if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) {
286         info.SetError(E_NETWORK_ERROR);
287         ZLOGD("network unavailable");
288         return E_NETWORK_ERROR;
289     }
290     if (!Account::GetInstance()->IsVerified(info.user_)) {
291         info.SetError(E_USER_UNLOCK);
292         ZLOGD("user unverified");
293         return E_ERROR;
294     }
295     return E_OK;
296 }
297 
GetPostEventTask(const std::vector<SchemaMeta> & schemas,CloudInfo & cloud,SyncInfo & info,bool retry,const TraceIds & traceIds)298 std::function<void()> SyncManager::GetPostEventTask(const std::vector<SchemaMeta> &schemas, CloudInfo &cloud,
299     SyncInfo &info, bool retry, const TraceIds &traceIds)
300 {
301     return [this, &cloud, &info, &schemas, retry, &traceIds]() {
302         bool isPostEvent = false;
303         auto syncId = info.syncId_;
304         for (auto &schema : schemas) {
305             auto it = traceIds.find(schema.bundleName);
306             if (!cloud.IsOn(schema.bundleName)) {
307                 UpdateFinishSyncInfo({ cloud.user, cloud.id, schema.bundleName, "" }, syncId, E_ERROR);
308                 SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second,
309                     SyncStage::END, E_ERROR, "!IsOn:" + schema.bundleName });
310                 continue;
311             }
312             for (const auto &database : schema.databases) {
313                 if (!info.Contains(database.name)) {
314                     UpdateFinishSyncInfo({ cloud.user, cloud.id, schema.bundleName, database.name }, syncId, E_ERROR);
315                     SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second,
316                         SyncStage::END, E_ERROR, "!Contains:" + database.name });
317                     continue;
318                 }
319                 StoreInfo storeInfo = { 0, schema.bundleName, database.name, cloud.apps[schema.bundleName].instanceId,
320                     info.user_, "", syncId };
321                 auto status = syncStrategy_->CheckSyncAction(storeInfo);
322                 if (status != SUCCESS) {
323                     ZLOGW("Verification strategy failed, status:%{public}d. %{public}d:%{public}s:%{public}s", status,
324                         storeInfo.user, storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str());
325                     UpdateFinishSyncInfo({ cloud.user, cloud.id, schema.bundleName, database.name }, syncId, status);
326                     SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second,
327                         SyncStage::END, status, "CheckSyncAction" });
328                     info.SetError(status);
329                     continue;
330                 }
331                 auto query = info.GenerateQuery(database.name, database.GetTableNames());
332                 SyncParam syncParam = { info.mode_, info.wait_, info.isCompensation_, info.triggerMode_,
333                     it == traceIds.end() ? "" : it->second, cloud.user };
334                 auto evt = std::make_unique<SyncEvent>(std::move(storeInfo),
335                     SyncEvent::EventInfo{ syncParam, retry, std::move(query), info.async_ });
336                 EventCenter::GetInstance().PostEvent(std::move(evt));
337                 isPostEvent = true;
338             }
339         }
340         if (!isPostEvent) {
341             ZLOGE("schema is invalid, user: %{public}d", cloud.user);
342             info.SetError(E_ERROR);
343         }
344     };
345 }
346 
GetSyncTask(int32_t times,bool retry,RefCount ref,SyncInfo && syncInfo)347 ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo)
348 {
349     times++;
350     return [this, times, retry, keep = std::move(ref), info = std::move(syncInfo)]() mutable {
351         activeInfos_.Erase(info.syncId_);
352         bool createdByDefaultUser = InitDefaultUser(info.user_);
353         CloudInfo cloud;
354         cloud.user = info.user_;
355 
356         auto cloudSyncInfos = GetCloudSyncInfo(info, cloud);
357         if (cloudSyncInfos.empty()) {
358             ZLOGD("get cloud info failed, user: %{public}d.", cloud.user);
359             info.SetError(E_CLOUD_DISABLED);
360             return;
361         }
362         auto traceIds = SyncManager::GetPrepareTraceId(info, cloud);
363         BatchReport(info.user_, traceIds, SyncStage::PREPARE, E_OK);
364         UpdateStartSyncInfo(cloudSyncInfos);
365         auto code = IsValid(info, cloud);
366         if (code != E_OK) {
367             BatchUpdateFinishState(cloudSyncInfos, code);
368             BatchReport(info.user_, traceIds, SyncStage::END, code, "!IsValid");
369             return;
370         }
371 
372         auto retryer = GetRetryer(times, info, cloud.user);
373         auto schemas = GetSchemaMeta(cloud, info.bundleName_);
374         if (schemas.empty()) {
375             UpdateSchema(info);
376             schemas = GetSchemaMeta(cloud, info.bundleName_);
377             if (schemas.empty()) {
378                 auto it = traceIds.find(info.bundleName_);
379                 retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT, GenStore::CLOUD_ERR_OFFSET + E_CLOUD_DISABLED,
380                     it == traceIds.end() ? "" : it->second);
381                 BatchUpdateFinishState(cloudSyncInfos, E_CLOUD_DISABLED);
382                 BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED, "empty schema:" + info.bundleName_);
383                 return;
384             }
385         }
386         Defer defer(GetSyncHandler(std::move(retryer)), CloudEvent::CLOUD_SYNC);
387         if (createdByDefaultUser) {
388             info.user_ = 0;
389         }
390         auto task = GetPostEventTask(schemas, cloud, info, retry, traceIds);
391         task();
392     };
393 }
394 
StartCloudSync(const DistributedData::SyncEvent & evt,const StoreMetaData & meta,const AutoCache::Store & store,Retryer retryer,DistributedData::GenDetails & details)395 void SyncManager::StartCloudSync(const DistributedData::SyncEvent &evt, const StoreMetaData &meta,
396     const AutoCache::Store &store, Retryer retryer, DistributedData::GenDetails &details)
397 {
398     auto &storeInfo = evt.GetStoreInfo();
399     GenAsync async = evt.GetAsyncDetail();
400     auto prepareTraceId = evt.GetPrepareTraceId();
401     auto user = evt.GetUser();
402     auto &detail = details[SyncInfo::DEFAULT_ID];
403     ReportSyncEvent(evt, BizState::BEGIN, E_OK);
404     SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId };
405     syncParam.asyncDownloadAsset = meta.asyncDownloadAsset;
406     auto [status, dbCode] = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()),
407         evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user)
408                         : GetCallback(async, storeInfo, evt.GetTriggerMode(), prepareTraceId, user), syncParam);
409     if (status != E_OK) {
410         if (async) {
411             detail.code = ConvertValidGeneralCode(status);
412             async(std::move(details));
413         }
414         UpdateFinishSyncInfo({ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName,
415             storeInfo.storeName }, storeInfo.syncId, E_ERROR);
416         if (status != GeneralError::E_NOT_SUPPORT) {
417             auto code = dbCode == 0 ? GenStore::CLOUD_ERR_OFFSET + status : dbCode;
418             ReportSyncEvent(evt, BizState::END, code);
419         }
420     }
421 }
422 
GetSyncHandler(Retryer retryer)423 std::function<void(const Event &)> SyncManager::GetSyncHandler(Retryer retryer)
424 {
425     return [this, retryer](const Event &event) {
426         auto &evt = static_cast<const SyncEvent &>(event);
427         auto &storeInfo = evt.GetStoreInfo();
428         GenAsync async = evt.GetAsyncDetail();
429         auto prepareTraceId = evt.GetPrepareTraceId();
430         GenDetails details;
431         auto &detail = details[SyncInfo::DEFAULT_ID];
432         detail.progress = GenProgress::SYNC_FINISH;
433         auto [hasMeta, meta] = GetMetaData(storeInfo);
434         if (!hasMeta) {
435             return DoExceptionalCallback(async, details, storeInfo,
436                 {0, "", prepareTraceId, SyncStage::END, GeneralError::E_ERROR, "no meta"});
437         }
438         auto [code, store] = GetStore(meta, storeInfo.user);
439         if (code == E_SCREEN_LOCKED) {
440             AddCompensateSync(meta);
441         }
442         if (store == nullptr) {
443             ZLOGE("store null, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(),
444                 prepareTraceId.c_str());
445             return DoExceptionalCallback(async, details, storeInfo,
446                 {0, "", prepareTraceId, SyncStage::END, GeneralError::E_ERROR, "store null"});
447         }
448         if (!meta.enableCloud) {
449             ZLOGW("meta.enableCloud is false, storeId:%{public}s, prepareTraceId:%{public}s",
450                 meta.GetStoreAlias().c_str(), prepareTraceId.c_str());
451             return DoExceptionalCallback(async, details, storeInfo,
452                 {0, "", prepareTraceId, SyncStage::END, E_CLOUD_DISABLED, "disable cloud"});
453         }
454         ZLOGI("database:<%{public}d:%{public}s:%{public}s:%{public}s> sync start, asyncDownloadAsset?[%{public}d]",
455               storeInfo.user, storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str(),
456               meta.asyncDownloadAsset);
457         StartCloudSync(evt, meta, store, retryer, details);
458     };
459 }
460 
ReportSyncEvent(const SyncEvent & evt,BizState bizState,int32_t code)461 void SyncManager::ReportSyncEvent(const SyncEvent &evt, BizState bizState, int32_t code)
462 {
463     auto &storeInfo = evt.GetStoreInfo();
464     if (bizState == BizState::BEGIN) {
465         RadarReporter::Report({storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC,
466             storeInfo.syncId, evt.GetTriggerMode()}, "GetSyncHandler", bizState);
467     } else {
468         RadarReporter::Report({storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC,
469             storeInfo.syncId, evt.GetTriggerMode(), code}, "GetSyncHandler", bizState);
470     }
471     SyncStage syncStage = (bizState == BizState::BEGIN) ? SyncStage::START : SyncStage::END;
472     SyncManager::Report({evt.GetUser(), storeInfo.bundleName, evt.GetPrepareTraceId(), syncStage, code,
473         "GetSyncHandler"});
474 }
475 
GetClientChangeHandler()476 std::function<void(const Event &)> SyncManager::GetClientChangeHandler()
477 {
478     return [this](const Event &event) {
479         if (executor_ == nullptr) {
480             return;
481         }
482         auto &evt = static_cast<const SyncEvent &>(event);
483         auto store = evt.GetStoreInfo();
484         SyncInfo syncInfo(store.user, store.bundleName, store.storeName);
485         syncInfo.SetMode(evt.GetMode());
486         syncInfo.SetWait(evt.GetWait());
487         syncInfo.SetAsyncDetail(evt.GetAsyncDetail());
488         syncInfo.SetQuery(evt.GetQuery());
489         syncInfo.SetCompensation(evt.IsCompensation());
490         syncInfo.SetTriggerMode(evt.GetTriggerMode());
491         auto times = evt.AutoRetry() ? RETRY_TIMES - CLIENT_RETRY_TIMES : RETRY_TIMES;
492         executor_->Execute(GetSyncTask(times, evt.AutoRetry(), RefCount(), std::move(syncInfo)));
493     };
494 }
495 
Report(const std::string & faultType,const std::string & bundleName,int32_t errCode,const std::string & appendix)496 void SyncManager::Report(
497     const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix)
498 {
499     ArkDataFaultMsg msg = { .faultType = faultType,
500         .bundleName = bundleName,
501         .moduleName = ModuleName::CLOUD_SERVER,
502         .errorType = errCode + GenStore::CLOUD_ERR_OFFSET,
503         .appendixMsg = appendix };
504     Reporter::GetInstance()->CloudSyncFault()->Report(msg);
505 }
506 
HandleRetryFinished(const SyncInfo & info,int32_t user,int32_t code,int32_t dbCode,const std::string & prepareTraceId)507 bool SyncManager::HandleRetryFinished(const SyncInfo &info, int32_t user, int32_t code, int32_t dbCode,
508     const std::string &prepareTraceId)
509 {
510     if (code == E_OK || code == E_SYNC_TASK_MERGED) {
511         return true;
512     }
513     info.SetError(code);
514     RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_,
515                             dbCode },
516         "GetRetryer", BizState::END);
517     SyncManager::Report({ user, info.bundleName_, prepareTraceId, SyncStage::END,
518         dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "GetRetryer finish" });
519     Report(FT_CALLBACK, info.bundleName_, static_cast<int32_t>(Fault::CSF_GS_CLOUD_SYNC),
520         "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast<int32_t>(dbCode)));
521     return true;
522 }
523 
GetRetryer(int32_t times,const SyncInfo & syncInfo,int32_t user)524 SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo, int32_t user)
525 {
526     if (times >= RETRY_TIMES) {
527         return [this, user, info = SyncInfo(syncInfo)](Duration, int32_t code, int32_t dbCode,
528                    const std::string &prepareTraceId) mutable {
529             return HandleRetryFinished(info, user, code, dbCode, prepareTraceId);
530         };
531     }
532     return [this, times, user, info = SyncInfo(syncInfo)](Duration interval, int32_t code, int32_t dbCode,
533                const std::string &prepareTraceId) mutable {
534         if (code == E_OK || code == E_SYNC_TASK_MERGED) {
535             return true;
536         }
537         if (code == E_NO_SPACE_FOR_ASSET || code == E_RECODE_LIMIT_EXCEEDED) {
538             info.SetError(code);
539             RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_,
540                                     dbCode },
541                 "GetRetryer", BizState::END);
542             SyncManager::Report({ user, info.bundleName_, prepareTraceId, SyncStage::END,
543                 dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "GetRetryer continue" });
544             Report(FT_CALLBACK, info.bundleName_, static_cast<int32_t>(Fault::CSF_GS_CLOUD_SYNC),
545                    "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast<int32_t>(dbCode)));
546             return true;
547         }
548 
549         if (executor_ == nullptr) {
550             return false;
551         }
552         activeInfos_.ComputeIfAbsent(info.syncId_, [this, times, interval, &info](uint64_t key) mutable {
553             auto syncId = GenerateId(info.user_);
554             auto ref = GenSyncRef(syncId);
555             actives_.Compute(syncId, [this, times, interval, &ref, &info](const uint64_t &key, TaskId &value) mutable {
556                 value = executor_->Schedule(interval, GetSyncTask(times, true, ref, std::move(info)));
557                 return true;
558             });
559             return syncId;
560         });
561         return true;
562     };
563 }
564 
GenerateId(int32_t user)565 uint64_t SyncManager::GenerateId(int32_t user)
566 {
567     uint64_t syncId = static_cast<uint64_t>(user) & 0xFFFFFFFF;
568     return (syncId << MV_BIT) | (++genId_);
569 }
570 
GenSyncRef(uint64_t syncId)571 RefCount SyncManager::GenSyncRef(uint64_t syncId)
572 {
573     return RefCount([syncId, this]() {
574         actives_.Erase(syncId);
575     });
576 }
577 
Compare(uint64_t syncId,int32_t user)578 int32_t SyncManager::Compare(uint64_t syncId, int32_t user)
579 {
580     uint64_t inner = static_cast<uint64_t>(user) & 0xFFFFFFFF;
581     return (syncId & USER_MARK) == (inner << MV_BIT);
582 }
583 
UpdateSchema(const SyncManager::SyncInfo & syncInfo)584 void SyncManager::UpdateSchema(const SyncManager::SyncInfo &syncInfo)
585 {
586     StoreInfo storeInfo;
587     storeInfo.user = syncInfo.user_;
588     storeInfo.bundleName = syncInfo.bundleName_;
589     EventCenter::GetInstance().PostEvent(std::make_unique<CloudEvent>(CloudEvent::GET_SCHEMA, storeInfo));
590 }
591 
GetBindInfos(const StoreMetaData & meta,const std::vector<int32_t> & users,const Database & schemaDatabase)592 std::map<uint32_t, GeneralStore::BindInfo> SyncManager::GetBindInfos(const StoreMetaData &meta,
593     const std::vector<int32_t> &users, const Database &schemaDatabase)
594 {
595     auto instance = CloudServer::GetInstance();
596     if (instance == nullptr) {
597         ZLOGD("not support cloud sync");
598         return {};
599     }
600     std::map<uint32_t, GeneralStore::BindInfo> bindInfos;
601     for (auto &activeUser : users) {
602         if (activeUser == 0) {
603             continue;
604         }
605         auto cloudDB = instance->ConnectCloudDB(meta.bundleName, activeUser, schemaDatabase);
606         if (cloudDB == nullptr) {
607             ZLOGE("failed, no cloud DB <%{public}d:0x%{public}x %{public}s<->%{public}s>", meta.tokenId, activeUser,
608                 Anonymous::Change(schemaDatabase.name).c_str(), Anonymous::Change(schemaDatabase.alias).c_str());
609             Report(FT_GET_STORE, meta.bundleName, static_cast<int32_t>(Fault::CSF_CONNECT_CLOUD_DB),
610                 "ConnectCloudDB failed, database=" + schemaDatabase.name);
611             return {};
612         }
613         if (meta.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN &&
614             meta.storeType <= StoreMetaData::StoreType::STORE_KV_END) {
615             bindInfos.insert_or_assign(activeUser, GeneralStore::BindInfo{ std::move(cloudDB), nullptr });
616             continue;
617         }
618         auto assetLoader = instance->ConnectAssetLoader(meta.bundleName, activeUser, schemaDatabase);
619         if (assetLoader == nullptr) {
620             ZLOGE("failed, no cloud DB <%{public}d:0x%{public}x %{public}s<->%{public}s>", meta.tokenId, activeUser,
621                 Anonymous::Change(schemaDatabase.name).c_str(), Anonymous::Change(schemaDatabase.alias).c_str());
622             Report(FT_GET_STORE, meta.bundleName, static_cast<int32_t>(Fault::CSF_CONNECT_CLOUD_ASSET_LOADER),
623                 "ConnectAssetLoader failed, database=" + schemaDatabase.name);
624             return {};
625         }
626         bindInfos.insert_or_assign(activeUser, GeneralStore::BindInfo{ std::move(cloudDB), std::move(assetLoader) });
627     }
628     return bindInfos;
629 }
630 
GetStore(const StoreMetaData & meta,int32_t user,bool mustBind)631 std::pair<int32_t, AutoCache::Store> SyncManager::GetStore(const StoreMetaData &meta, int32_t user, bool mustBind)
632 {
633     if (user != 0 && !Account::GetInstance()->IsVerified(user)) {
634         ZLOGW("user:%{public}d is locked!", user);
635         return { E_USER_UNLOCK, nullptr };
636     }
637     if (CloudServer::GetInstance() == nullptr) {
638         return { E_NOT_SUPPORT, nullptr };
639     }
640     auto [status, store] = AutoCache::GetInstance().GetDBStore(meta, {});
641     if (status == E_SCREEN_LOCKED) {
642         return { E_SCREEN_LOCKED, nullptr };
643     } else if (store == nullptr) {
644         return { E_ERROR, nullptr };
645     }
646     CloudInfo info;
647     info.user = user;
648     std::vector<int32_t> users{};
649     if (info.user == SYSTEM_USER_ID) {
650         AccountDelegate::GetInstance()->QueryForegroundUsers(users);
651         info.user = users.empty() ? SYSTEM_USER_ID : users[0];
652     } else {
653         users.push_back(user);
654     }
655     if (info.user == SYSTEM_USER_ID) {
656         ZLOGE("invalid cloud users, bundleName:%{public}s", meta.bundleName.c_str());
657         return { E_ERROR, nullptr };
658     }
659     if (!store->IsBound(info.user)) {
660         SchemaMeta schemaMeta;
661         std::string schemaKey = info.GetSchemaKey(meta.bundleName, meta.instanceId);
662         if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) {
663             ZLOGE("failed, no schema bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
664                 meta.GetStoreAlias().c_str());
665             return { E_ERROR, nullptr };
666         }
667         auto dbMeta = schemaMeta.GetDataBase(meta.storeId);
668         std::map<uint32_t, GeneralStore::BindInfo> bindInfos = GetBindInfos(meta, users, dbMeta);
669         if (mustBind && bindInfos.size() != users.size()) {
670             return { E_ERROR, nullptr };
671         }
672         GeneralStore::CloudConfig config;
673         if (MetaDataManager::GetInstance().LoadMeta(info.GetKey(), info, true)) {
674             config.maxNumber = info.maxNumber;
675             config.maxSize = info.maxSize;
676             config.isSupportEncrypt = schemaMeta.e2eeEnable;
677         }
678         store->Bind(dbMeta, bindInfos, config);
679     }
680     return { E_OK, store };
681 }
682 
Report(const ReportParam & reportParam)683 void SyncManager::Report(const ReportParam &reportParam)
684 {
685     auto cloudReport = CloudReport::GetInstance();
686     if (cloudReport == nullptr) {
687         return;
688     }
689     cloudReport->Report(reportParam);
690 }
691 
GetPrepareTraceId(const SyncInfo & info,const CloudInfo & cloud)692 SyncManager::TraceIds SyncManager::GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud)
693 {
694     TraceIds traceIds;
695     if (!info.prepareTraceId_.empty()) {
696         traceIds.emplace(info.bundleName_, info.prepareTraceId_);
697         return traceIds;
698     }
699     auto cloudReport = CloudReport::GetInstance();
700     if (cloudReport == nullptr) {
701         return traceIds;
702     }
703     if (info.bundleName_.empty()) {
704         for (const auto &it : cloud.apps) {
705             traceIds.emplace(it.first, cloudReport->GetPrepareTraceId(info.user_));
706         }
707     } else {
708         traceIds.emplace(info.bundleName_, cloudReport->GetPrepareTraceId(info.user_));
709     }
710     return traceIds;
711 }
712 
NeedGetCloudInfo(CloudInfo & cloud)713 bool SyncManager::NeedGetCloudInfo(CloudInfo &cloud)
714 {
715     return (!MetaDataManager::GetInstance().LoadMeta(cloud.GetKey(), cloud, true) || !cloud.enableCloud) &&
716            NetworkDelegate::GetInstance()->IsNetworkAvailable() && Account::GetInstance()->IsLoginAccount();
717 }
718 
GetCloudSyncInfo(const SyncInfo & info,CloudInfo & cloud)719 std::vector<std::tuple<QueryKey, uint64_t>> SyncManager::GetCloudSyncInfo(const SyncInfo &info, CloudInfo &cloud)
720 {
721     std::vector<std::tuple<QueryKey, uint64_t>> cloudSyncInfos;
722     if (NeedGetCloudInfo(cloud)) {
723         ZLOGI("get cloud info from server, user: %{public}d.", cloud.user);
724         auto instance = CloudServer::GetInstance();
725         if (instance == nullptr) {
726             return cloudSyncInfos;
727         }
728         int32_t errCode = SUCCESS;
729         std::tie(errCode, cloud) = instance->GetServerInfo(cloud.user, false);
730         if (!cloud.IsValid()) {
731             ZLOGE("cloud is empty, user: %{public}d", cloud.user);
732             return cloudSyncInfos;
733         }
734         if (!MetaDataManager::GetInstance().SaveMeta(cloud.GetKey(), cloud, true)) {
735             ZLOGW("save cloud info fail, user: %{public}d", cloud.user);
736         }
737     }
738     auto schemaKey = CloudInfo::GetSchemaKey(cloud.user, info.bundleName_);
739     SchemaMeta schemaMeta;
740     if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) {
741         ZLOGE("load schema fail, bundleName: %{public}s, user %{public}d", info.bundleName_.c_str(), info.user_);
742         return cloudSyncInfos;
743     }
744     auto stores = schemaMeta.GetStores();
745     for (auto &storeId : stores) {
746         QueryKey queryKey{ cloud.user, cloud.id, info.bundleName_, std::move(storeId) };
747         cloudSyncInfos.emplace_back(std::make_tuple(std::move(queryKey), info.syncId_));
748     }
749     return cloudSyncInfos;
750 }
751 
GetLastResults(std::map<SyncId,CloudLastSyncInfo> & infos)752 std::pair<int32_t, CloudLastSyncInfo> SyncManager::GetLastResults(std::map<SyncId, CloudLastSyncInfo> &infos)
753 {
754     auto iter = infos.rbegin();
755     if (iter != infos.rend() && iter->second.code != -1) {
756         return { SUCCESS, iter->second };
757     }
758     return { E_ERROR, {} };
759 }
760 
NeedSaveSyncInfo(const QueryKey & queryKey)761 bool SyncManager::NeedSaveSyncInfo(const QueryKey &queryKey)
762 {
763     if (queryKey.accountId.empty()) {
764         return false;
765     }
766     return kvApps_.find(queryKey.bundleName) == kvApps_.end();
767 }
768 
QueryLastSyncInfo(const std::vector<QueryKey> & queryKeys)769 std::pair<int32_t, std::map<std::string, CloudLastSyncInfo>> SyncManager::QueryLastSyncInfo(
770     const std::vector<QueryKey> &queryKeys)
771 {
772     std::map<std::string, CloudLastSyncInfo> lastSyncInfoMap;
773     for (const auto &queryKey : queryKeys) {
774         std::string storeId = queryKey.storeId;
775         QueryKey key{ queryKey.user, queryKey.accountId, queryKey.bundleName, queryKey.storeId };
776         lastSyncInfos_.ComputeIfPresent(
777             key, [&storeId, &lastSyncInfoMap](auto &key, std::map<SyncId, CloudLastSyncInfo> &vals) {
778                 auto [status, syncInfo] = GetLastResults(vals);
779                 if (status == SUCCESS) {
780                     lastSyncInfoMap.insert(std::make_pair(std::move(storeId), std::move(syncInfo)));
781                 }
782                 return !vals.empty();
783             });
784         if (lastSyncInfoMap.find(queryKey.storeId) != lastSyncInfoMap.end()) {
785             continue;
786         }
787         auto [status, syncInfo] = SyncManager::GetLastSyncInfoFromMeta(queryKey);
788         if (status == SUCCESS) {
789             lastSyncInfoMap.insert(std::make_pair(std::move(syncInfo.storeId), std::move(syncInfo)));
790         }
791     }
792     return { SUCCESS, lastSyncInfoMap };
793 }
794 
UpdateStartSyncInfo(const std::vector<std::tuple<QueryKey,uint64_t>> & cloudSyncInfos)795 void SyncManager::UpdateStartSyncInfo(const std::vector<std::tuple<QueryKey, uint64_t>> &cloudSyncInfos)
796 {
797     int64_t startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
798     for (const auto &[queryKey, syncId] : cloudSyncInfos) {
799         if (!NeedSaveSyncInfo(queryKey)) {
800             continue;
801         }
802         lastSyncInfos_.Compute(queryKey, [id = syncId, startTime](auto &key, std::map<SyncId, CloudLastSyncInfo> &val) {
803             CloudLastSyncInfo syncInfo;
804             syncInfo.id = key.accountId;
805             syncInfo.storeId = key.storeId;
806             syncInfo.startTime = startTime;
807             syncInfo.code = 0;
808             val[id] = std::move(syncInfo);
809             return !val.empty();
810         });
811     }
812 }
813 
UpdateFinishSyncInfo(const QueryKey & queryKey,uint64_t syncId,int32_t code)814 void SyncManager::UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId, int32_t code)
815 {
816     if (!NeedSaveSyncInfo(queryKey)) {
817         return;
818     }
819     lastSyncInfos_.ComputeIfPresent(queryKey, [syncId, code](auto &key, std::map<SyncId, CloudLastSyncInfo> &val) {
820         auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
821         for (auto iter = val.begin(); iter != val.end();) {
822             bool isExpired = ((now - iter->second.startTime) >= EXPIRATION_TIME) && iter->second.code == -1;
823             if ((iter->first != syncId && ((iter->second.code != -1) || isExpired))) {
824                 iter = val.erase(iter);
825             } else if (iter->first == syncId) {
826                 iter->second.finishTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
827                 iter->second.code = ConvertValidGeneralCode(code);
828                 iter->second.syncStatus = SyncStatus::FINISHED;
829                 SaveLastSyncInfo(key, std::move(iter->second));
830                 iter = val.erase(iter);
831             } else {
832                 iter++;
833             }
834         }
835         return true;
836     });
837 }
838 
GetCallback(const GenAsync & async,const StoreInfo & storeInfo,int32_t triggerMode,const std::string & prepareTraceId,int32_t user)839 std::function<void(const GenDetails &result)> SyncManager::GetCallback(const GenAsync &async,
840     const StoreInfo &storeInfo, int32_t triggerMode, const std::string &prepareTraceId, int32_t user)
841 {
842     return [this, async, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &result) {
843         if (async != nullptr) {
844             async(ConvertGenDetailsCode(result));
845         }
846 
847         if (result.empty()) {
848             ZLOGE("result is empty");
849             return;
850         }
851 
852         if (result.begin()->second.progress != GenProgress::SYNC_FINISH) {
853             return;
854         }
855 
856         int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode;
857         RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode,
858                                 dbCode, result.begin()->second.changeCount },
859             "GetCallback", BizState::END);
860         SyncManager::Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode, "GetCallback" });
861         if (dbCode != 0) {
862             Report(FT_CALLBACK, storeInfo.bundleName, static_cast<int32_t>(Fault::CSF_GS_CLOUD_SYNC),
863                 "callback failed, dbCode=" + std::to_string(dbCode));
864         }
865         auto id = GetAccountId(storeInfo.user);
866         if (id.empty()) {
867             ZLOGD("account id is empty");
868             return;
869         }
870         int32_t code = result.begin()->second.code;
871         UpdateFinishSyncInfo({ user, id, storeInfo.bundleName, storeInfo.storeName }, storeInfo.syncId, code);
872     };
873 }
874 
GetAccountId(int32_t user)875 std::string SyncManager::GetAccountId(int32_t user)
876 {
877     CloudInfo cloudInfo;
878     cloudInfo.user = user;
879     if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) {
880         ZLOGE("not exist meta, user:%{public}d.", cloudInfo.user);
881         return "";
882     }
883     return cloudInfo.id;
884 }
885 
GetInterval(int32_t code)886 ExecutorPool::Duration SyncManager::GetInterval(int32_t code)
887 {
888     switch (code) {
889         case E_LOCKED_BY_OTHERS:
890             return LOCKED_INTERVAL;
891         case E_BUSY:
892             return BUSY_INTERVAL;
893         default:
894             return RETRY_INTERVAL;
895     }
896 }
897 
GetSchemaMeta(const CloudInfo & cloud,const std::string & bundleName)898 std::vector<SchemaMeta> SyncManager::GetSchemaMeta(const CloudInfo &cloud, const std::string &bundleName)
899 {
900     std::vector<SchemaMeta> schemas;
901     auto key = cloud.GetSchemaPrefix(bundleName);
902     MetaDataManager::GetInstance().LoadMeta(key, schemas, true);
903     return schemas;
904 }
905 
DoExceptionalCallback(const GenAsync & async,GenDetails & details,const StoreInfo & storeInfo,const ReportParam & param)906 void SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo,
907     const ReportParam &param)
908 {
909     if (async) {
910         details[SyncInfo::DEFAULT_ID].code = param.errCode;
911         async(details);
912     }
913     QueryKey queryKey{ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, storeInfo.storeName };
914     UpdateFinishSyncInfo(queryKey, storeInfo.syncId, param.errCode);
915     SyncManager::Report({ storeInfo.user, storeInfo.bundleName, param.prepareTraceId, SyncStage::END,
916         param.errCode, param.message });
917 }
918 
InitDefaultUser(int32_t & user)919 bool SyncManager::InitDefaultUser(int32_t &user)
920 {
921     if (user != 0) {
922         return false;
923     }
924     std::vector<int32_t> users;
925     AccountDelegate::GetInstance()->QueryUsers(users);
926     if (!users.empty()) {
927         user = users[0];
928     }
929     return true;
930 }
931 
RetryCallback(const StoreInfo & storeInfo,Retryer retryer,int32_t triggerMode,const std::string & prepareTraceId,int32_t user)932 std::function<void(const DistributedData::GenDetails &result)> SyncManager::RetryCallback(const StoreInfo &storeInfo,
933     Retryer retryer, int32_t triggerMode, const std::string &prepareTraceId, int32_t user)
934 {
935     return [this, retryer, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &details) {
936         if (details.empty()) {
937             ZLOGE("retry, details empty");
938             return;
939         }
940         int32_t code = details.begin()->second.code;
941         int32_t dbCode = details.begin()->second.dbCode;
942         if (details.begin()->second.progress == GenProgress::SYNC_FINISH) {
943             auto user = storeInfo.user;
944             QueryKey queryKey{ user, GetAccountId(user), storeInfo.bundleName, storeInfo.storeName };
945             UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code);
946             if (code == E_OK) {
947                 RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId,
948                                         triggerMode, code, details.begin()->second.changeCount },
949                     "RetryCallback", BizState::END);
950                 SyncManager::Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END,
951                     dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "RetryCallback" });
952             }
953         }
954         retryer(GetInterval(code), code, dbCode, prepareTraceId);
955     };
956 }
957 
BatchUpdateFinishState(const std::vector<std::tuple<QueryKey,uint64_t>> & cloudSyncInfos,int32_t code)958 void SyncManager::BatchUpdateFinishState(const std::vector<std::tuple<QueryKey, uint64_t>> &cloudSyncInfos,
959     int32_t code)
960 {
961     for (const auto &[queryKey, syncId] : cloudSyncInfos) {
962         UpdateFinishSyncInfo(queryKey, syncId, code);
963     }
964 }
965 
BatchReport(int32_t userId,const TraceIds & traceIds,SyncStage syncStage,int32_t errCode,const std::string & message)966 void SyncManager::BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode,
967     const std::string &message)
968 {
969     for (const auto &[bundle, id] : traceIds) {
970         SyncManager::Report({ userId, bundle, id, syncStage, errCode, message });
971     }
972 }
973 
GetPath(const StoreMetaData & meta)974 std::string SyncManager::GetPath(const StoreMetaData &meta)
975 {
976     StoreMetaMapping mapping(meta);
977     MetaDataManager::GetInstance().LoadMeta(mapping.GetKey(), mapping, true);
978     return mapping.cloudPath.empty() ? mapping.dataDir : mapping.cloudPath;
979 }
980 
GetMetaData(const StoreInfo & storeInfo)981 std::pair<bool, StoreMetaData> SyncManager::GetMetaData(const StoreInfo &storeInfo)
982 {
983     StoreMetaData meta(storeInfo);
984     meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
985     meta.dataDir = GetPath(meta);
986     if (!meta.dataDir.empty() && MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
987         return { true, meta };
988     }
989     meta.user = "0"; // check if it is a public store.
990     meta.dataDir = GetPath(meta);
991     if (meta.dataDir.empty() || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
992         ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
993             meta.GetStoreAlias().c_str());
994         return { false, meta };
995     }
996     StoreMetaDataLocal localMetaData;
997     if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || !localMetaData.isPublic) {
998         ZLOGE("failed, no store LocalMeta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
999             meta.GetStoreAlias().c_str());
1000         return { false, meta };
1001     }
1002     return { true, meta };
1003 }
1004 
OnScreenUnlocked(int32_t user)1005 void SyncManager::OnScreenUnlocked(int32_t user)
1006 {
1007     std::vector<SyncInfo> infos;
1008     compensateSyncInfos_.ComputeIfPresent(user,
1009         [&infos](auto &userId, const std::map<std::string, std::set<std::string>> &apps) {
1010             for (const auto &[bundle, storeIds] : apps) {
1011                 std::vector<std::string> stores(storeIds.begin(), storeIds.end());
1012                 infos.push_back(SyncInfo(userId, bundle, stores));
1013             }
1014             return false;
1015         });
1016     compensateSyncInfos_.ComputeIfPresent(SYSTEM_USER_ID,
1017         [&infos](auto &userId, const std::map<std::string, std::set<std::string>> &apps) {
1018             for (const auto &[bundle, storeIds] : apps) {
1019                 std::vector<std::string> stores(storeIds.begin(), storeIds.end());
1020                 infos.push_back(SyncInfo(userId, bundle, stores));
1021             }
1022             return false;
1023         });
1024     for (auto &info : infos) {
1025         info.SetTriggerMode(MODE_UNLOCK);
1026         DoCloudSync(info);
1027     }
1028 }
1029 
CleanCompensateSync(int32_t userId)1030 void SyncManager::CleanCompensateSync(int32_t userId)
1031 {
1032     compensateSyncInfos_.Erase(userId);
1033 }
1034 
AddCompensateSync(const StoreMetaData & meta)1035 void SyncManager::AddCompensateSync(const StoreMetaData &meta)
1036 {
1037     compensateSyncInfos_.Compute(std::atoi(meta.user.c_str()),
1038         [&meta](auto &, std::map<std::string, std::set<std::string>> &apps) {
1039             apps[meta.bundleName].insert(meta.storeId);
1040             return true;
1041         });
1042 }
1043 
GetLastSyncInfoFromMeta(const QueryKey & queryKey)1044 std::pair<int32_t, CloudLastSyncInfo> SyncManager::GetLastSyncInfoFromMeta(const QueryKey &queryKey)
1045 {
1046     CloudLastSyncInfo lastSyncInfo;
1047     if (!MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(queryKey.user, queryKey.bundleName,
1048         queryKey.storeId), lastSyncInfo, true)) {
1049         ZLOGE("load last sync info fail, bundleName: %{public}s, user:%{public}d",
1050               queryKey.bundleName.c_str(), queryKey.user);
1051         return { E_ERROR, lastSyncInfo };
1052     }
1053     if (queryKey.accountId != lastSyncInfo.id || (!queryKey.storeId.empty() &&
1054         queryKey.storeId != lastSyncInfo.storeId)) {
1055         return { E_ERROR, lastSyncInfo };
1056     }
1057     return { SUCCESS, std::move(lastSyncInfo) };
1058 }
1059 
SaveLastSyncInfo(const QueryKey & queryKey,CloudLastSyncInfo && info)1060 void SyncManager::SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info)
1061 {
1062     if (!MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(queryKey.user,
1063         queryKey.bundleName, queryKey.storeId), info, true)) {
1064         ZLOGE("save cloud last info fail, bundleName: %{public}s, user:%{public}d",
1065               queryKey.bundleName.c_str(), queryKey.user);
1066     }
1067 }
1068 
ConvertGenDetailsCode(const GenDetails & details)1069 GenDetails SyncManager::ConvertGenDetailsCode(const GenDetails &details)
1070 {
1071     GenDetails newDetails;
1072     for (const auto &it : details) {
1073         GenProgressDetail detail = it.second;
1074         detail.code = ConvertValidGeneralCode(detail.code);
1075         newDetails.emplace(std::make_pair(it.first, std::move(detail)));
1076     }
1077     return newDetails;
1078 }
1079 
ConvertValidGeneralCode(int32_t code)1080 int32_t SyncManager::ConvertValidGeneralCode(int32_t code)
1081 {
1082     return (code >= E_OK && code < E_BUSY) ? code : E_ERROR;
1083 }
1084 } // namespace OHOS::CloudData