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 ¶m)
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 ¶m)
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