153c3577eSopenharmony_ci/* 253c3577eSopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 353c3577eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 453c3577eSopenharmony_ci * you may not use this file except in compliance with the License. 553c3577eSopenharmony_ci * You may obtain a copy of the License at 653c3577eSopenharmony_ci * 753c3577eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 853c3577eSopenharmony_ci * 953c3577eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1053c3577eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1153c3577eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1253c3577eSopenharmony_ci * See the License for the specific language governing permissions and 1353c3577eSopenharmony_ci * limitations under the License. 1453c3577eSopenharmony_ci */ 1553c3577eSopenharmony_ci#define LOG_TAG "SyncManager" 1653c3577eSopenharmony_ci#include "sync_manager.h" 1753c3577eSopenharmony_ci 1853c3577eSopenharmony_ci#include <chrono> 1953c3577eSopenharmony_ci 2053c3577eSopenharmony_ci#include "account/account_delegate.h" 2153c3577eSopenharmony_ci#include "bootstrap.h" 2253c3577eSopenharmony_ci#include "checker/checker_manager.h" 2353c3577eSopenharmony_ci#include "cloud/cloud_lock_event.h" 2453c3577eSopenharmony_ci#include "cloud/cloud_report.h" 2553c3577eSopenharmony_ci#include "cloud/cloud_server.h" 2653c3577eSopenharmony_ci#include "cloud/schema_meta.h" 2753c3577eSopenharmony_ci#include "cloud/sync_event.h" 2853c3577eSopenharmony_ci#include "cloud_value_util.h" 2953c3577eSopenharmony_ci#include "device_manager_adapter.h" 3053c3577eSopenharmony_ci#include "dfx/radar_reporter.h" 3153c3577eSopenharmony_ci#include "eventcenter/event_center.h" 3253c3577eSopenharmony_ci#include "log_print.h" 3353c3577eSopenharmony_ci#include "metadata/meta_data_manager.h" 3453c3577eSopenharmony_ci#include "sync_strategies/network_sync_strategy.h" 3553c3577eSopenharmony_ci#include "user_delegate.h" 3653c3577eSopenharmony_ci#include "utils/anonymous.h" 3753c3577eSopenharmony_cinamespace OHOS::CloudData { 3853c3577eSopenharmony_ciusing namespace DistributedData; 3953c3577eSopenharmony_ciusing namespace DistributedDataDfx; 4053c3577eSopenharmony_ciusing namespace DistributedKv; 4153c3577eSopenharmony_ciusing namespace SharingUtil; 4253c3577eSopenharmony_ciusing namespace std::chrono; 4353c3577eSopenharmony_ciusing Account = OHOS::DistributedKv::AccountDelegate; 4453c3577eSopenharmony_ciusing DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; 4553c3577eSopenharmony_ciusing Defer = EventCenter::Defer; 4653c3577eSopenharmony_cistd::atomic<uint32_t> SyncManager::genId_ = 0; 4753c3577eSopenharmony_ciSyncManager::SyncInfo::SyncInfo( 4853c3577eSopenharmony_ci int32_t user, const std::string &bundleName, const Store &store, const Tables &tables, int32_t triggerMode) 4953c3577eSopenharmony_ci : user_(user), bundleName_(bundleName), triggerMode_(triggerMode) 5053c3577eSopenharmony_ci{ 5153c3577eSopenharmony_ci if (!store.empty()) { 5253c3577eSopenharmony_ci tables_[store] = tables; 5353c3577eSopenharmony_ci } 5453c3577eSopenharmony_ci syncId_ = SyncManager::GenerateId(user); 5553c3577eSopenharmony_ci} 5653c3577eSopenharmony_ci 5753c3577eSopenharmony_ciSyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Stores &stores) 5853c3577eSopenharmony_ci : user_(user), bundleName_(bundleName) 5953c3577eSopenharmony_ci{ 6053c3577eSopenharmony_ci for (auto &store : stores) { 6153c3577eSopenharmony_ci tables_[store] = {}; 6253c3577eSopenharmony_ci } 6353c3577eSopenharmony_ci syncId_ = SyncManager::GenerateId(user); 6453c3577eSopenharmony_ci} 6553c3577eSopenharmony_ci 6653c3577eSopenharmony_ciSyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const MutliStoreTables &tables) 6753c3577eSopenharmony_ci : user_(user), bundleName_(bundleName), tables_(tables) 6853c3577eSopenharmony_ci{ 6953c3577eSopenharmony_ci tables_ = tables; 7053c3577eSopenharmony_ci syncId_ = SyncManager::GenerateId(user); 7153c3577eSopenharmony_ci} 7253c3577eSopenharmony_ci 7353c3577eSopenharmony_ciSyncManager::SyncInfo::SyncInfo(const Param ¶m) 7453c3577eSopenharmony_ci : user_(param.user), bundleName_(param.bundleName), triggerMode_(param.triggerMode) 7553c3577eSopenharmony_ci{ 7653c3577eSopenharmony_ci if (!param.store.empty()) { 7753c3577eSopenharmony_ci tables_[param.store] = param.tables; 7853c3577eSopenharmony_ci } 7953c3577eSopenharmony_ci syncId_ = SyncManager::GenerateId(param.user); 8053c3577eSopenharmony_ci prepareTraceId_ = param.prepareTraceId; 8153c3577eSopenharmony_ci} 8253c3577eSopenharmony_ci 8353c3577eSopenharmony_civoid SyncManager::SyncInfo::SetMode(int32_t mode) 8453c3577eSopenharmony_ci{ 8553c3577eSopenharmony_ci mode_ = mode; 8653c3577eSopenharmony_ci} 8753c3577eSopenharmony_ci 8853c3577eSopenharmony_civoid SyncManager::SyncInfo::SetWait(int32_t wait) 8953c3577eSopenharmony_ci{ 9053c3577eSopenharmony_ci wait_ = wait; 9153c3577eSopenharmony_ci} 9253c3577eSopenharmony_ci 9353c3577eSopenharmony_civoid SyncManager::SyncInfo::SetAsyncDetail(GenAsync asyncDetail) 9453c3577eSopenharmony_ci{ 9553c3577eSopenharmony_ci async_ = std::move(asyncDetail); 9653c3577eSopenharmony_ci} 9753c3577eSopenharmony_ci 9853c3577eSopenharmony_civoid SyncManager::SyncInfo::SetQuery(std::shared_ptr<GenQuery> query) 9953c3577eSopenharmony_ci{ 10053c3577eSopenharmony_ci query_ = query; 10153c3577eSopenharmony_ci} 10253c3577eSopenharmony_ci 10353c3577eSopenharmony_civoid SyncManager::SyncInfo::SetCompensation(bool isCompensation) 10453c3577eSopenharmony_ci{ 10553c3577eSopenharmony_ci isCompensation_ = isCompensation; 10653c3577eSopenharmony_ci} 10753c3577eSopenharmony_ci 10853c3577eSopenharmony_civoid SyncManager::SyncInfo::SetTriggerMode(int32_t triggerMode) 10953c3577eSopenharmony_ci{ 11053c3577eSopenharmony_ci triggerMode_ = triggerMode; 11153c3577eSopenharmony_ci} 11253c3577eSopenharmony_ci 11353c3577eSopenharmony_civoid SyncManager::SyncInfo::SetError(int32_t code) const 11453c3577eSopenharmony_ci{ 11553c3577eSopenharmony_ci if (async_) { 11653c3577eSopenharmony_ci GenDetails details; 11753c3577eSopenharmony_ci auto &detail = details[id_]; 11853c3577eSopenharmony_ci detail.progress = GenProgress::SYNC_FINISH; 11953c3577eSopenharmony_ci detail.code = code; 12053c3577eSopenharmony_ci async_(std::move(details)); 12153c3577eSopenharmony_ci } 12253c3577eSopenharmony_ci} 12353c3577eSopenharmony_ci 12453c3577eSopenharmony_cistd::shared_ptr<GenQuery> SyncManager::SyncInfo::GenerateQuery(const std::string &store, const Tables &tables) 12553c3577eSopenharmony_ci{ 12653c3577eSopenharmony_ci if (query_ != nullptr) { 12753c3577eSopenharmony_ci return query_; 12853c3577eSopenharmony_ci } 12953c3577eSopenharmony_ci class SyncQuery final : public GenQuery { 13053c3577eSopenharmony_ci public: 13153c3577eSopenharmony_ci explicit SyncQuery(const std::vector<std::string> &tables) : tables_(tables) {} 13253c3577eSopenharmony_ci 13353c3577eSopenharmony_ci bool IsEqual(uint64_t tid) override 13453c3577eSopenharmony_ci { 13553c3577eSopenharmony_ci return false; 13653c3577eSopenharmony_ci } 13753c3577eSopenharmony_ci 13853c3577eSopenharmony_ci std::vector<std::string> GetTables() override 13953c3577eSopenharmony_ci { 14053c3577eSopenharmony_ci return tables_; 14153c3577eSopenharmony_ci } 14253c3577eSopenharmony_ci 14353c3577eSopenharmony_ci private: 14453c3577eSopenharmony_ci std::vector<std::string> tables_; 14553c3577eSopenharmony_ci }; 14653c3577eSopenharmony_ci auto it = tables_.find(store); 14753c3577eSopenharmony_ci return std::make_shared<SyncQuery>(it == tables_.end() || it->second.empty() ? tables : it->second); 14853c3577eSopenharmony_ci} 14953c3577eSopenharmony_ci 15053c3577eSopenharmony_cibool SyncManager::SyncInfo::Contains(const std::string &storeName) 15153c3577eSopenharmony_ci{ 15253c3577eSopenharmony_ci return tables_.empty() || tables_.find(storeName) != tables_.end(); 15353c3577eSopenharmony_ci} 15453c3577eSopenharmony_ci 15553c3577eSopenharmony_cistd::function<void(const Event &)> SyncManager::GetLockChangeHandler() 15653c3577eSopenharmony_ci{ 15753c3577eSopenharmony_ci return [](const Event &event) { 15853c3577eSopenharmony_ci auto &evt = static_cast<const CloudLockEvent &>(event); 15953c3577eSopenharmony_ci auto storeInfo = evt.GetStoreInfo(); 16053c3577eSopenharmony_ci auto callback = evt.GetCallback(); 16153c3577eSopenharmony_ci if (callback == nullptr) { 16253c3577eSopenharmony_ci ZLOGE("callback is nullptr. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", 16353c3577eSopenharmony_ci storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); 16453c3577eSopenharmony_ci return; 16553c3577eSopenharmony_ci } 16653c3577eSopenharmony_ci CloudInfo cloud; 16753c3577eSopenharmony_ci cloud.user = storeInfo.user; 16853c3577eSopenharmony_ci SyncInfo info(storeInfo.user, storeInfo.bundleName); 16953c3577eSopenharmony_ci auto code = IsValid(info, cloud); 17053c3577eSopenharmony_ci if (code != E_OK) { 17153c3577eSopenharmony_ci return; 17253c3577eSopenharmony_ci } 17353c3577eSopenharmony_ci 17453c3577eSopenharmony_ci StoreMetaData meta(storeInfo); 17553c3577eSopenharmony_ci meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; 17653c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { 17753c3577eSopenharmony_ci ZLOGE("not found meta. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", 17853c3577eSopenharmony_ci storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); 17953c3577eSopenharmony_ci return; 18053c3577eSopenharmony_ci } 18153c3577eSopenharmony_ci auto store = GetStore(meta, storeInfo.user); 18253c3577eSopenharmony_ci if (store == nullptr) { 18353c3577eSopenharmony_ci ZLOGE("failed to get store. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", 18453c3577eSopenharmony_ci storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); 18553c3577eSopenharmony_ci return; 18653c3577eSopenharmony_ci } 18753c3577eSopenharmony_ci if (evt.GetEventId() == CloudEvent::LOCK_CLOUD_CONTAINER) { 18853c3577eSopenharmony_ci auto [result, expiredTime] = store->LockCloudDB(); 18953c3577eSopenharmony_ci callback(result, expiredTime); 19053c3577eSopenharmony_ci } else { 19153c3577eSopenharmony_ci auto result = store->UnLockCloudDB(); 19253c3577eSopenharmony_ci callback(result, 0); 19353c3577eSopenharmony_ci } 19453c3577eSopenharmony_ci }; 19553c3577eSopenharmony_ci} 19653c3577eSopenharmony_ci 19753c3577eSopenharmony_ciSyncManager::SyncManager() 19853c3577eSopenharmony_ci{ 19953c3577eSopenharmony_ci EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, GetLockChangeHandler()); 20053c3577eSopenharmony_ci EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, GetLockChangeHandler()); 20153c3577eSopenharmony_ci EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, GetClientChangeHandler()); 20253c3577eSopenharmony_ci syncStrategy_ = std::make_shared<NetworkSyncStrategy>(); 20353c3577eSopenharmony_ci auto metaName = Bootstrap::GetInstance().GetProcessLabel(); 20453c3577eSopenharmony_ci kvApps_.insert(std::move(metaName)); 20553c3577eSopenharmony_ci auto stores = CheckerManager::GetInstance().GetStaticStores(); 20653c3577eSopenharmony_ci for (auto &store : stores) { 20753c3577eSopenharmony_ci kvApps_.insert(std::move(store.bundleName)); 20853c3577eSopenharmony_ci } 20953c3577eSopenharmony_ci stores = CheckerManager::GetInstance().GetDynamicStores(); 21053c3577eSopenharmony_ci for (auto &store : stores) { 21153c3577eSopenharmony_ci kvApps_.insert(std::move(store.bundleName)); 21253c3577eSopenharmony_ci } 21353c3577eSopenharmony_ci} 21453c3577eSopenharmony_ci 21553c3577eSopenharmony_ciSyncManager::~SyncManager() 21653c3577eSopenharmony_ci{ 21753c3577eSopenharmony_ci if (executor_ != nullptr) { 21853c3577eSopenharmony_ci actives_.ForEachCopies([this](auto &syncId, auto &taskId) { 21953c3577eSopenharmony_ci executor_->Remove(taskId); 22053c3577eSopenharmony_ci return false; 22153c3577eSopenharmony_ci }); 22253c3577eSopenharmony_ci executor_ = nullptr; 22353c3577eSopenharmony_ci } 22453c3577eSopenharmony_ci} 22553c3577eSopenharmony_ci 22653c3577eSopenharmony_ciint32_t SyncManager::Bind(std::shared_ptr<ExecutorPool> executor) 22753c3577eSopenharmony_ci{ 22853c3577eSopenharmony_ci executor_ = executor; 22953c3577eSopenharmony_ci return E_OK; 23053c3577eSopenharmony_ci} 23153c3577eSopenharmony_ci 23253c3577eSopenharmony_ciint32_t SyncManager::DoCloudSync(SyncInfo syncInfo) 23353c3577eSopenharmony_ci{ 23453c3577eSopenharmony_ci if (executor_ == nullptr) { 23553c3577eSopenharmony_ci return E_NOT_INIT; 23653c3577eSopenharmony_ci } 23753c3577eSopenharmony_ci auto syncId = GenerateId(syncInfo.user_); 23853c3577eSopenharmony_ci auto ref = GenSyncRef(syncId); 23953c3577eSopenharmony_ci actives_.Compute(syncId, [this, &ref, &syncInfo](const uint64_t &key, TaskId &taskId) mutable { 24053c3577eSopenharmony_ci taskId = executor_->Execute(GetSyncTask(0, true, ref, std::move(syncInfo))); 24153c3577eSopenharmony_ci return true; 24253c3577eSopenharmony_ci }); 24353c3577eSopenharmony_ci return E_OK; 24453c3577eSopenharmony_ci} 24553c3577eSopenharmony_ci 24653c3577eSopenharmony_ciint32_t SyncManager::StopCloudSync(int32_t user) 24753c3577eSopenharmony_ci{ 24853c3577eSopenharmony_ci if (executor_ == nullptr) { 24953c3577eSopenharmony_ci return E_NOT_INIT; 25053c3577eSopenharmony_ci } 25153c3577eSopenharmony_ci actives_.ForEachCopies([this, user](auto &syncId, auto &taskId) { 25253c3577eSopenharmony_ci if (Compare(syncId, user) == 0) { 25353c3577eSopenharmony_ci executor_->Remove(taskId); 25453c3577eSopenharmony_ci } 25553c3577eSopenharmony_ci return false; 25653c3577eSopenharmony_ci }); 25753c3577eSopenharmony_ci return E_OK; 25853c3577eSopenharmony_ci} 25953c3577eSopenharmony_ci 26053c3577eSopenharmony_ciGeneralError SyncManager::IsValid(SyncInfo &info, CloudInfo &cloud) 26153c3577eSopenharmony_ci{ 26253c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().LoadMeta(cloud.GetKey(), cloud, true) || 26353c3577eSopenharmony_ci (info.id_ != SyncInfo::DEFAULT_ID && cloud.id != info.id_)) { 26453c3577eSopenharmony_ci info.SetError(E_CLOUD_DISABLED); 26553c3577eSopenharmony_ci ZLOGE("cloudInfo invalid:%{public}d, <syncId:%{public}s, metaId:%{public}s>", cloud.IsValid(), 26653c3577eSopenharmony_ci Anonymous::Change(info.id_).c_str(), Anonymous::Change(cloud.id).c_str()); 26753c3577eSopenharmony_ci return E_CLOUD_DISABLED; 26853c3577eSopenharmony_ci } 26953c3577eSopenharmony_ci if (!cloud.enableCloud || (!info.bundleName_.empty() && !cloud.IsOn(info.bundleName_))) { 27053c3577eSopenharmony_ci info.SetError(E_CLOUD_DISABLED); 27153c3577eSopenharmony_ci ZLOGD("enable:%{public}d, bundleName:%{public}s", cloud.enableCloud, info.bundleName_.c_str()); 27253c3577eSopenharmony_ci return E_CLOUD_DISABLED; 27353c3577eSopenharmony_ci } 27453c3577eSopenharmony_ci if (!DmAdapter::GetInstance().IsNetworkAvailable()) { 27553c3577eSopenharmony_ci info.SetError(E_NETWORK_ERROR); 27653c3577eSopenharmony_ci ZLOGD("network unavailable"); 27753c3577eSopenharmony_ci return E_NETWORK_ERROR; 27853c3577eSopenharmony_ci } 27953c3577eSopenharmony_ci if (!Account::GetInstance()->IsVerified(info.user_)) { 28053c3577eSopenharmony_ci info.SetError(E_USER_UNLOCK); 28153c3577eSopenharmony_ci ZLOGD("user unverified"); 28253c3577eSopenharmony_ci return E_ERROR; 28353c3577eSopenharmony_ci } 28453c3577eSopenharmony_ci return E_OK; 28553c3577eSopenharmony_ci} 28653c3577eSopenharmony_ci 28753c3577eSopenharmony_cistd::function<void()> SyncManager::GetPostEventTask(const std::vector<SchemaMeta> &schemas, CloudInfo &cloud, 28853c3577eSopenharmony_ci SyncInfo &info, bool retry, const TraceIds &traceIds) 28953c3577eSopenharmony_ci{ 29053c3577eSopenharmony_ci return [this, &cloud, &info, &schemas, retry, &traceIds]() { 29153c3577eSopenharmony_ci bool isPostEvent = false; 29253c3577eSopenharmony_ci for (auto &schema : schemas) { 29353c3577eSopenharmony_ci auto it = traceIds.find(schema.bundleName); 29453c3577eSopenharmony_ci if (!cloud.IsOn(schema.bundleName)) { 29553c3577eSopenharmony_ci UpdateFinishSyncInfo({ cloud.id, schema.bundleName, "" }, info.syncId_, E_ERROR); 29653c3577eSopenharmony_ci Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, 29753c3577eSopenharmony_ci E_ERROR }); 29853c3577eSopenharmony_ci continue; 29953c3577eSopenharmony_ci } 30053c3577eSopenharmony_ci for (const auto &database : schema.databases) { 30153c3577eSopenharmony_ci if (!info.Contains(database.name)) { 30253c3577eSopenharmony_ci UpdateFinishSyncInfo({ cloud.id, schema.bundleName, "" }, info.syncId_, E_ERROR); 30353c3577eSopenharmony_ci Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, 30453c3577eSopenharmony_ci E_ERROR }); 30553c3577eSopenharmony_ci continue; 30653c3577eSopenharmony_ci } 30753c3577eSopenharmony_ci StoreInfo storeInfo = { 0, schema.bundleName, database.name, cloud.apps[schema.bundleName].instanceId, 30853c3577eSopenharmony_ci info.user_, "", info.syncId_ }; 30953c3577eSopenharmony_ci auto status = syncStrategy_->CheckSyncAction(storeInfo); 31053c3577eSopenharmony_ci if (status != SUCCESS) { 31153c3577eSopenharmony_ci ZLOGW("Verification strategy failed, status:%{public}d. %{public}d:%{public}s:%{public}s", status, 31253c3577eSopenharmony_ci storeInfo.user, storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str()); 31353c3577eSopenharmony_ci UpdateFinishSyncInfo({ cloud.id, schema.bundleName, "" }, info.syncId_, status); 31453c3577eSopenharmony_ci Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, 31553c3577eSopenharmony_ci status }); 31653c3577eSopenharmony_ci info.SetError(status); 31753c3577eSopenharmony_ci continue; 31853c3577eSopenharmony_ci } 31953c3577eSopenharmony_ci auto query = info.GenerateQuery(database.name, database.GetTableNames()); 32053c3577eSopenharmony_ci SyncParam syncParam = { info.mode_, info.wait_, info.isCompensation_, info.triggerMode_, 32153c3577eSopenharmony_ci it == traceIds.end() ? "" : it->second, cloud.user }; 32253c3577eSopenharmony_ci auto evt = std::make_unique<SyncEvent>(std::move(storeInfo), 32353c3577eSopenharmony_ci SyncEvent::EventInfo{ syncParam, retry, std::move(query), info.async_ }); 32453c3577eSopenharmony_ci EventCenter::GetInstance().PostEvent(std::move(evt)); 32553c3577eSopenharmony_ci isPostEvent = true; 32653c3577eSopenharmony_ci } 32753c3577eSopenharmony_ci } 32853c3577eSopenharmony_ci if (!isPostEvent) { 32953c3577eSopenharmony_ci ZLOGE("schema is invalid, user: %{public}d", cloud.user); 33053c3577eSopenharmony_ci info.SetError(E_ERROR); 33153c3577eSopenharmony_ci } 33253c3577eSopenharmony_ci }; 33353c3577eSopenharmony_ci} 33453c3577eSopenharmony_ci 33553c3577eSopenharmony_ciExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo) 33653c3577eSopenharmony_ci{ 33753c3577eSopenharmony_ci times++; 33853c3577eSopenharmony_ci return [this, times, retry, keep = std::move(ref), info = std::move(syncInfo)]() mutable { 33953c3577eSopenharmony_ci activeInfos_.Erase(info.syncId_); 34053c3577eSopenharmony_ci bool createdByDefaultUser = InitDefaultUser(info.user_); 34153c3577eSopenharmony_ci CloudInfo cloud; 34253c3577eSopenharmony_ci cloud.user = info.user_; 34353c3577eSopenharmony_ci 34453c3577eSopenharmony_ci auto cloudSyncInfos = GetCloudSyncInfo(info, cloud); 34553c3577eSopenharmony_ci if (cloudSyncInfos.empty()) { 34653c3577eSopenharmony_ci ZLOGD("get cloud info failed, user: %{public}d.", cloud.user); 34753c3577eSopenharmony_ci info.SetError(E_CLOUD_DISABLED); 34853c3577eSopenharmony_ci return; 34953c3577eSopenharmony_ci } 35053c3577eSopenharmony_ci auto traceIds = GetPrepareTraceId(info, cloud); 35153c3577eSopenharmony_ci BatchReport(info.user_, traceIds, SyncStage::PREPARE, E_OK); 35253c3577eSopenharmony_ci UpdateStartSyncInfo(cloudSyncInfos); 35353c3577eSopenharmony_ci auto code = IsValid(info, cloud); 35453c3577eSopenharmony_ci if (code != E_OK) { 35553c3577eSopenharmony_ci BatchUpdateFinishState(cloudSyncInfos, code); 35653c3577eSopenharmony_ci BatchReport(info.user_, traceIds, SyncStage::END, code); 35753c3577eSopenharmony_ci return; 35853c3577eSopenharmony_ci } 35953c3577eSopenharmony_ci 36053c3577eSopenharmony_ci auto retryer = GetRetryer(times, info, cloud.user); 36153c3577eSopenharmony_ci auto schemas = GetSchemaMeta(cloud, info.bundleName_); 36253c3577eSopenharmony_ci if (schemas.empty()) { 36353c3577eSopenharmony_ci UpdateSchema(info); 36453c3577eSopenharmony_ci schemas = GetSchemaMeta(cloud, info.bundleName_); 36553c3577eSopenharmony_ci if (schemas.empty()) { 36653c3577eSopenharmony_ci auto it = traceIds.find(info.bundleName_); 36753c3577eSopenharmony_ci retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT, E_CLOUD_DISABLED, it == traceIds.end() ? "" : it->second); 36853c3577eSopenharmony_ci BatchUpdateFinishState(cloudSyncInfos, E_CLOUD_DISABLED); 36953c3577eSopenharmony_ci BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED); 37053c3577eSopenharmony_ci return; 37153c3577eSopenharmony_ci } 37253c3577eSopenharmony_ci } 37353c3577eSopenharmony_ci Defer defer(GetSyncHandler(std::move(retryer)), CloudEvent::CLOUD_SYNC); 37453c3577eSopenharmony_ci if (createdByDefaultUser) { 37553c3577eSopenharmony_ci info.user_ = 0; 37653c3577eSopenharmony_ci } 37753c3577eSopenharmony_ci auto task = GetPostEventTask(schemas, cloud, info, retry, traceIds); 37853c3577eSopenharmony_ci task(); 37953c3577eSopenharmony_ci }; 38053c3577eSopenharmony_ci} 38153c3577eSopenharmony_ci 38253c3577eSopenharmony_cistd::function<void(const Event &)> SyncManager::GetSyncHandler(Retryer retryer) 38353c3577eSopenharmony_ci{ 38453c3577eSopenharmony_ci return [this, retryer](const Event &event) { 38553c3577eSopenharmony_ci auto &evt = static_cast<const SyncEvent &>(event); 38653c3577eSopenharmony_ci auto &storeInfo = evt.GetStoreInfo(); 38753c3577eSopenharmony_ci GenAsync async = evt.GetAsyncDetail(); 38853c3577eSopenharmony_ci auto prepareTraceId = evt.GetPrepareTraceId(); 38953c3577eSopenharmony_ci auto user = evt.GetUser(); 39053c3577eSopenharmony_ci GenDetails details; 39153c3577eSopenharmony_ci auto &detail = details[SyncInfo::DEFAULT_ID]; 39253c3577eSopenharmony_ci detail.progress = GenProgress::SYNC_FINISH; 39353c3577eSopenharmony_ci auto [result, meta] = GetMetaData(storeInfo); 39453c3577eSopenharmony_ci if (!result) { 39553c3577eSopenharmony_ci return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); 39653c3577eSopenharmony_ci } 39753c3577eSopenharmony_ci auto store = GetStore(meta, storeInfo.user); 39853c3577eSopenharmony_ci if (store == nullptr) { 39953c3577eSopenharmony_ci ZLOGE("store null, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(), 40053c3577eSopenharmony_ci prepareTraceId.c_str()); 40153c3577eSopenharmony_ci return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); 40253c3577eSopenharmony_ci } 40353c3577eSopenharmony_ci ZLOGI("database:<%{public}d:%{public}s:%{public}s:%{public}s> sync start", storeInfo.user, 40453c3577eSopenharmony_ci storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str()); 40553c3577eSopenharmony_ci RadarReporter::Report( 40653c3577eSopenharmony_ci { storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, storeInfo.syncId, evt.GetTriggerMode() }, 40753c3577eSopenharmony_ci "GetSyncHandler", BizState::BEGIN); 40853c3577eSopenharmony_ci Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::START, E_OK }); 40953c3577eSopenharmony_ci SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId }; 41053c3577eSopenharmony_ci auto status = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), 41153c3577eSopenharmony_ci evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user) 41253c3577eSopenharmony_ci : GetCallback(evt.GetAsyncDetail(), storeInfo, evt.GetTriggerMode(), prepareTraceId, user), 41353c3577eSopenharmony_ci syncParam); 41453c3577eSopenharmony_ci if (status != E_OK) { 41553c3577eSopenharmony_ci if (async) { 41653c3577eSopenharmony_ci detail.code = status; 41753c3577eSopenharmony_ci async(std::move(details)); 41853c3577eSopenharmony_ci } 41953c3577eSopenharmony_ci UpdateFinishSyncInfo({ GetAccountId(storeInfo.user), storeInfo.bundleName, "" }, storeInfo.syncId, E_ERROR); 42053c3577eSopenharmony_ci if (status == GeneralError::E_NOT_SUPPORT) { 42153c3577eSopenharmony_ci return; 42253c3577eSopenharmony_ci } 42353c3577eSopenharmony_ci int32_t errCode = status + GenStore::DB_ERR_OFFSET; 42453c3577eSopenharmony_ci RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, 42553c3577eSopenharmony_ci evt.GetTriggerMode(), false, errCode }, "GetSyncHandler", BizState::END); 42653c3577eSopenharmony_ci Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, errCode }); 42753c3577eSopenharmony_ci } 42853c3577eSopenharmony_ci }; 42953c3577eSopenharmony_ci} 43053c3577eSopenharmony_ci 43153c3577eSopenharmony_cistd::function<void(const Event &)> SyncManager::GetClientChangeHandler() 43253c3577eSopenharmony_ci{ 43353c3577eSopenharmony_ci return [this](const Event &event) { 43453c3577eSopenharmony_ci auto &evt = static_cast<const SyncEvent &>(event); 43553c3577eSopenharmony_ci auto store = evt.GetStoreInfo(); 43653c3577eSopenharmony_ci SyncInfo syncInfo(store.user, store.bundleName, store.storeName); 43753c3577eSopenharmony_ci syncInfo.SetMode(evt.GetMode()); 43853c3577eSopenharmony_ci syncInfo.SetWait(evt.GetWait()); 43953c3577eSopenharmony_ci syncInfo.SetAsyncDetail(evt.GetAsyncDetail()); 44053c3577eSopenharmony_ci syncInfo.SetQuery(evt.GetQuery()); 44153c3577eSopenharmony_ci syncInfo.SetCompensation(evt.IsCompensation()); 44253c3577eSopenharmony_ci syncInfo.SetTriggerMode(evt.GetTriggerMode()); 44353c3577eSopenharmony_ci auto times = evt.AutoRetry() ? RETRY_TIMES - CLIENT_RETRY_TIMES : RETRY_TIMES; 44453c3577eSopenharmony_ci executor_->Execute(GetSyncTask(times, evt.AutoRetry(), RefCount(), std::move(syncInfo))); 44553c3577eSopenharmony_ci }; 44653c3577eSopenharmony_ci} 44753c3577eSopenharmony_ci 44853c3577eSopenharmony_ciSyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo, int32_t user) 44953c3577eSopenharmony_ci{ 45053c3577eSopenharmony_ci if (times >= RETRY_TIMES) { 45153c3577eSopenharmony_ci return [this, user, info = SyncInfo(syncInfo)](Duration, int32_t code, int32_t dbCode, 45253c3577eSopenharmony_ci const std::string &prepareTraceId) mutable { 45353c3577eSopenharmony_ci if (code == E_OK || code == E_SYNC_TASK_MERGED) { 45453c3577eSopenharmony_ci return true; 45553c3577eSopenharmony_ci } 45653c3577eSopenharmony_ci info.SetError(code); 45753c3577eSopenharmony_ci RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, 45853c3577eSopenharmony_ci false, dbCode }, 45953c3577eSopenharmony_ci "GetRetryer", BizState::END); 46053c3577eSopenharmony_ci Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, 46153c3577eSopenharmony_ci dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); 46253c3577eSopenharmony_ci return true; 46353c3577eSopenharmony_ci }; 46453c3577eSopenharmony_ci } 46553c3577eSopenharmony_ci return [this, times, user, info = SyncInfo(syncInfo)](Duration interval, int32_t code, int32_t dbCode, 46653c3577eSopenharmony_ci const std::string &prepareTraceId) mutable { 46753c3577eSopenharmony_ci if (code == E_OK || code == E_SYNC_TASK_MERGED) { 46853c3577eSopenharmony_ci return true; 46953c3577eSopenharmony_ci } 47053c3577eSopenharmony_ci if (code == E_NO_SPACE_FOR_ASSET || code == E_RECODE_LIMIT_EXCEEDED) { 47153c3577eSopenharmony_ci info.SetError(code); 47253c3577eSopenharmony_ci RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, 47353c3577eSopenharmony_ci false, dbCode }, 47453c3577eSopenharmony_ci "GetRetryer", BizState::END); 47553c3577eSopenharmony_ci Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, 47653c3577eSopenharmony_ci dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); 47753c3577eSopenharmony_ci return true; 47853c3577eSopenharmony_ci } 47953c3577eSopenharmony_ci 48053c3577eSopenharmony_ci activeInfos_.ComputeIfAbsent(info.syncId_, [this, times, interval, &info](uint64_t key) mutable { 48153c3577eSopenharmony_ci auto syncId = GenerateId(info.user_); 48253c3577eSopenharmony_ci auto ref = GenSyncRef(syncId); 48353c3577eSopenharmony_ci actives_.Compute(syncId, [this, times, interval, &ref, &info](const uint64_t &key, TaskId &value) mutable { 48453c3577eSopenharmony_ci value = executor_->Schedule(interval, GetSyncTask(times, true, ref, std::move(info))); 48553c3577eSopenharmony_ci return true; 48653c3577eSopenharmony_ci }); 48753c3577eSopenharmony_ci return syncId; 48853c3577eSopenharmony_ci }); 48953c3577eSopenharmony_ci return true; 49053c3577eSopenharmony_ci }; 49153c3577eSopenharmony_ci} 49253c3577eSopenharmony_ci 49353c3577eSopenharmony_ciuint64_t SyncManager::GenerateId(int32_t user) 49453c3577eSopenharmony_ci{ 49553c3577eSopenharmony_ci uint64_t syncId = static_cast<uint64_t>(user) & 0xFFFFFFFF; 49653c3577eSopenharmony_ci return (syncId << MV_BIT) | (++genId_); 49753c3577eSopenharmony_ci} 49853c3577eSopenharmony_ci 49953c3577eSopenharmony_ciRefCount SyncManager::GenSyncRef(uint64_t syncId) 50053c3577eSopenharmony_ci{ 50153c3577eSopenharmony_ci return RefCount([syncId, this]() { 50253c3577eSopenharmony_ci actives_.Erase(syncId); 50353c3577eSopenharmony_ci }); 50453c3577eSopenharmony_ci} 50553c3577eSopenharmony_ci 50653c3577eSopenharmony_ciint32_t SyncManager::Compare(uint64_t syncId, int32_t user) 50753c3577eSopenharmony_ci{ 50853c3577eSopenharmony_ci uint64_t inner = static_cast<uint64_t>(user) & 0xFFFFFFFF; 50953c3577eSopenharmony_ci return (syncId & USER_MARK) == (inner << MV_BIT); 51053c3577eSopenharmony_ci} 51153c3577eSopenharmony_ci 51253c3577eSopenharmony_civoid SyncManager::UpdateSchema(const SyncManager::SyncInfo &syncInfo) 51353c3577eSopenharmony_ci{ 51453c3577eSopenharmony_ci StoreInfo storeInfo; 51553c3577eSopenharmony_ci storeInfo.user = syncInfo.user_; 51653c3577eSopenharmony_ci storeInfo.bundleName = syncInfo.bundleName_; 51753c3577eSopenharmony_ci EventCenter::GetInstance().PostEvent(std::make_unique<CloudEvent>(CloudEvent::GET_SCHEMA, storeInfo)); 51853c3577eSopenharmony_ci} 51953c3577eSopenharmony_ci 52053c3577eSopenharmony_cistd::map<uint32_t, GeneralStore::BindInfo> SyncManager::GetBindInfos(const StoreMetaData &meta, 52153c3577eSopenharmony_ci const std::vector<int32_t> &users, const Database &schemaDatabase) 52253c3577eSopenharmony_ci{ 52353c3577eSopenharmony_ci auto instance = CloudServer::GetInstance(); 52453c3577eSopenharmony_ci if (instance == nullptr) { 52553c3577eSopenharmony_ci ZLOGD("not support cloud sync"); 52653c3577eSopenharmony_ci return {}; 52753c3577eSopenharmony_ci } 52853c3577eSopenharmony_ci std::map<uint32_t, GeneralStore::BindInfo> bindInfos; 52953c3577eSopenharmony_ci for (auto &activeUser : users) { 53053c3577eSopenharmony_ci if (activeUser == 0) { 53153c3577eSopenharmony_ci continue; 53253c3577eSopenharmony_ci } 53353c3577eSopenharmony_ci auto cloudDB = instance->ConnectCloudDB(meta.bundleName, activeUser, schemaDatabase); 53453c3577eSopenharmony_ci if (cloudDB == nullptr) { 53553c3577eSopenharmony_ci ZLOGE("failed, no cloud DB <%{public}d:0x%{public}x %{public}s<->%{public}s>", meta.tokenId, activeUser, 53653c3577eSopenharmony_ci Anonymous::Change(schemaDatabase.name).c_str(), Anonymous::Change(schemaDatabase.alias).c_str()); 53753c3577eSopenharmony_ci return {}; 53853c3577eSopenharmony_ci } 53953c3577eSopenharmony_ci if (meta.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN && 54053c3577eSopenharmony_ci meta.storeType <= StoreMetaData::StoreType::STORE_KV_END) { 54153c3577eSopenharmony_ci bindInfos.insert_or_assign(activeUser, GeneralStore::BindInfo{ std::move(cloudDB), nullptr }); 54253c3577eSopenharmony_ci continue; 54353c3577eSopenharmony_ci } 54453c3577eSopenharmony_ci auto assetLoader = instance->ConnectAssetLoader(meta.bundleName, activeUser, schemaDatabase); 54553c3577eSopenharmony_ci if (assetLoader == nullptr) { 54653c3577eSopenharmony_ci ZLOGE("failed, no cloud DB <%{public}d:0x%{public}x %{public}s<->%{public}s>", meta.tokenId, activeUser, 54753c3577eSopenharmony_ci Anonymous::Change(schemaDatabase.name).c_str(), Anonymous::Change(schemaDatabase.alias).c_str()); 54853c3577eSopenharmony_ci return {}; 54953c3577eSopenharmony_ci } 55053c3577eSopenharmony_ci bindInfos.insert_or_assign(activeUser, GeneralStore::BindInfo{ std::move(cloudDB), std::move(assetLoader) }); 55153c3577eSopenharmony_ci } 55253c3577eSopenharmony_ci return bindInfos; 55353c3577eSopenharmony_ci} 55453c3577eSopenharmony_ci 55553c3577eSopenharmony_ciAutoCache::Store SyncManager::GetStore(const StoreMetaData &meta, int32_t user, bool mustBind) 55653c3577eSopenharmony_ci{ 55753c3577eSopenharmony_ci if (user != 0 && !Account::GetInstance()->IsVerified(user)) { 55853c3577eSopenharmony_ci ZLOGW("user:%{public}d is locked!", user); 55953c3577eSopenharmony_ci return nullptr; 56053c3577eSopenharmony_ci } 56153c3577eSopenharmony_ci auto instance = CloudServer::GetInstance(); 56253c3577eSopenharmony_ci if (instance == nullptr) { 56353c3577eSopenharmony_ci ZLOGD("not support cloud sync"); 56453c3577eSopenharmony_ci return nullptr; 56553c3577eSopenharmony_ci } 56653c3577eSopenharmony_ci auto store = AutoCache::GetInstance().GetStore(meta, {}); 56753c3577eSopenharmony_ci if (store == nullptr) { 56853c3577eSopenharmony_ci ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); 56953c3577eSopenharmony_ci return nullptr; 57053c3577eSopenharmony_ci } 57153c3577eSopenharmony_ci if (!store->IsBound()) { 57253c3577eSopenharmony_ci std::vector<int32_t> users{}; 57353c3577eSopenharmony_ci CloudInfo info; 57453c3577eSopenharmony_ci if (user == 0) { 57553c3577eSopenharmony_ci AccountDelegate::GetInstance()->QueryForegroundUsers(users); 57653c3577eSopenharmony_ci } else { 57753c3577eSopenharmony_ci users.push_back(user); 57853c3577eSopenharmony_ci } 57953c3577eSopenharmony_ci if (!users.empty()) { 58053c3577eSopenharmony_ci info.user = users[0]; 58153c3577eSopenharmony_ci } 58253c3577eSopenharmony_ci SchemaMeta schemaMeta; 58353c3577eSopenharmony_ci std::string schemaKey = info.GetSchemaKey(meta.bundleName, meta.instanceId); 58453c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { 58553c3577eSopenharmony_ci ZLOGE("failed, no schema bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), 58653c3577eSopenharmony_ci meta.GetStoreAlias().c_str()); 58753c3577eSopenharmony_ci return nullptr; 58853c3577eSopenharmony_ci } 58953c3577eSopenharmony_ci auto dbMeta = schemaMeta.GetDataBase(meta.storeId); 59053c3577eSopenharmony_ci std::map<uint32_t, GeneralStore::BindInfo> bindInfos = GetBindInfos(meta, users, dbMeta); 59153c3577eSopenharmony_ci if (mustBind && bindInfos.size() != users.size()) { 59253c3577eSopenharmony_ci return nullptr; 59353c3577eSopenharmony_ci } 59453c3577eSopenharmony_ci GeneralStore::CloudConfig config; 59553c3577eSopenharmony_ci if (MetaDataManager::GetInstance().LoadMeta(info.GetKey(), info, true)) { 59653c3577eSopenharmony_ci config.maxNumber = info.maxNumber; 59753c3577eSopenharmony_ci config.maxSize = info.maxSize; 59853c3577eSopenharmony_ci } 59953c3577eSopenharmony_ci store->Bind(dbMeta, bindInfos, config); 60053c3577eSopenharmony_ci } 60153c3577eSopenharmony_ci return store; 60253c3577eSopenharmony_ci} 60353c3577eSopenharmony_ci 60453c3577eSopenharmony_civoid SyncManager::Report(const ReportParam &reportParam) 60553c3577eSopenharmony_ci{ 60653c3577eSopenharmony_ci auto cloudReport = CloudReport::GetInstance(); 60753c3577eSopenharmony_ci if (cloudReport == nullptr) { 60853c3577eSopenharmony_ci return; 60953c3577eSopenharmony_ci } 61053c3577eSopenharmony_ci cloudReport->Report(reportParam); 61153c3577eSopenharmony_ci} 61253c3577eSopenharmony_ci 61353c3577eSopenharmony_ciSyncManager::TraceIds SyncManager::GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud) 61453c3577eSopenharmony_ci{ 61553c3577eSopenharmony_ci TraceIds traceIds; 61653c3577eSopenharmony_ci if (!info.prepareTraceId_.empty()) { 61753c3577eSopenharmony_ci traceIds.emplace(info.bundleName_, info.prepareTraceId_); 61853c3577eSopenharmony_ci return traceIds; 61953c3577eSopenharmony_ci } 62053c3577eSopenharmony_ci auto cloudReport = CloudReport::GetInstance(); 62153c3577eSopenharmony_ci if (cloudReport == nullptr) { 62253c3577eSopenharmony_ci return traceIds; 62353c3577eSopenharmony_ci } 62453c3577eSopenharmony_ci if (info.bundleName_.empty()) { 62553c3577eSopenharmony_ci for (const auto &it : cloud.apps) { 62653c3577eSopenharmony_ci traceIds.emplace(it.first, cloudReport->GetPrepareTraceId(info.user_)); 62753c3577eSopenharmony_ci } 62853c3577eSopenharmony_ci } else { 62953c3577eSopenharmony_ci traceIds.emplace(info.bundleName_, cloudReport->GetPrepareTraceId(info.user_)); 63053c3577eSopenharmony_ci } 63153c3577eSopenharmony_ci return traceIds; 63253c3577eSopenharmony_ci} 63353c3577eSopenharmony_ci 63453c3577eSopenharmony_cibool SyncManager::NeedGetCloudInfo(CloudInfo &cloud) 63553c3577eSopenharmony_ci{ 63653c3577eSopenharmony_ci return (!MetaDataManager::GetInstance().LoadMeta(cloud.GetKey(), cloud, true) || !cloud.enableCloud) && 63753c3577eSopenharmony_ci DmAdapter::GetInstance().IsNetworkAvailable() && Account::GetInstance()->IsLoginAccount(); 63853c3577eSopenharmony_ci} 63953c3577eSopenharmony_ci 64053c3577eSopenharmony_cistd::vector<std::tuple<QueryKey, uint64_t>> SyncManager::GetCloudSyncInfo(const SyncInfo &info, CloudInfo &cloud) 64153c3577eSopenharmony_ci{ 64253c3577eSopenharmony_ci std::vector<std::tuple<QueryKey, uint64_t>> cloudSyncInfos; 64353c3577eSopenharmony_ci if (NeedGetCloudInfo(cloud)) { 64453c3577eSopenharmony_ci ZLOGI("get cloud info from server, user: %{public}d.", cloud.user); 64553c3577eSopenharmony_ci auto instance = CloudServer::GetInstance(); 64653c3577eSopenharmony_ci if (instance == nullptr) { 64753c3577eSopenharmony_ci return cloudSyncInfos; 64853c3577eSopenharmony_ci } 64953c3577eSopenharmony_ci cloud = instance->GetServerInfo(cloud.user, false); 65053c3577eSopenharmony_ci if (!cloud.IsValid()) { 65153c3577eSopenharmony_ci ZLOGE("cloud is empty, user: %{public}d", cloud.user); 65253c3577eSopenharmony_ci return cloudSyncInfos; 65353c3577eSopenharmony_ci } 65453c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().SaveMeta(cloud.GetKey(), cloud, true)) { 65553c3577eSopenharmony_ci ZLOGW("save cloud info fail, user: %{public}d", cloud.user); 65653c3577eSopenharmony_ci } 65753c3577eSopenharmony_ci } 65853c3577eSopenharmony_ci if (info.bundleName_.empty()) { 65953c3577eSopenharmony_ci for (const auto &it : cloud.apps) { 66053c3577eSopenharmony_ci QueryKey queryKey{ .accountId = cloud.id, .bundleName = it.first, .storeId = "" }; 66153c3577eSopenharmony_ci cloudSyncInfos.emplace_back(std::make_tuple(queryKey, info.syncId_)); 66253c3577eSopenharmony_ci } 66353c3577eSopenharmony_ci } else { 66453c3577eSopenharmony_ci QueryKey queryKey{ .accountId = cloud.id, .bundleName = info.bundleName_, .storeId = "" }; 66553c3577eSopenharmony_ci cloudSyncInfos.emplace_back(std::make_tuple(queryKey, info.syncId_)); 66653c3577eSopenharmony_ci } 66753c3577eSopenharmony_ci return cloudSyncInfos; 66853c3577eSopenharmony_ci} 66953c3577eSopenharmony_ci 67053c3577eSopenharmony_civoid SyncManager::GetLastResults( 67153c3577eSopenharmony_ci const std::string &storeId, std::map<SyncId, CloudSyncInfo> &infos, QueryLastResults &results) 67253c3577eSopenharmony_ci{ 67353c3577eSopenharmony_ci for (auto &[key, info] : infos) { 67453c3577eSopenharmony_ci if (info.code != -1) { 67553c3577eSopenharmony_ci results.insert(std::pair<std::string, CloudSyncInfo>(storeId, info)); 67653c3577eSopenharmony_ci } 67753c3577eSopenharmony_ci } 67853c3577eSopenharmony_ci} 67953c3577eSopenharmony_ci 68053c3577eSopenharmony_cibool SyncManager::NeedSaveSyncInfo(const QueryKey &queryKey) 68153c3577eSopenharmony_ci{ 68253c3577eSopenharmony_ci if (queryKey.accountId.empty()) { 68353c3577eSopenharmony_ci return false; 68453c3577eSopenharmony_ci } 68553c3577eSopenharmony_ci if (std::find(kvApps_.begin(), kvApps_.end(), queryKey.bundleName) != kvApps_.end()) { 68653c3577eSopenharmony_ci return false; 68753c3577eSopenharmony_ci } 68853c3577eSopenharmony_ci return true; 68953c3577eSopenharmony_ci} 69053c3577eSopenharmony_ci 69153c3577eSopenharmony_ciint32_t SyncManager::QueryLastSyncInfo(const std::vector<QueryKey> &queryKeys, QueryLastResults &results) 69253c3577eSopenharmony_ci{ 69353c3577eSopenharmony_ci for (const auto &queryKey : queryKeys) { 69453c3577eSopenharmony_ci std::string storeId = queryKey.storeId; 69553c3577eSopenharmony_ci QueryKey key{ .accountId = queryKey.accountId, .bundleName = queryKey.bundleName, .storeId = "" }; 69653c3577eSopenharmony_ci lastSyncInfos_.ComputeIfPresent( 69753c3577eSopenharmony_ci key, [&storeId, &results](auto &key, std::map<SyncId, CloudSyncInfo> &vals) { 69853c3577eSopenharmony_ci GetLastResults(storeId, vals, results); 69953c3577eSopenharmony_ci return !vals.empty(); 70053c3577eSopenharmony_ci }); 70153c3577eSopenharmony_ci } 70253c3577eSopenharmony_ci return SUCCESS; 70353c3577eSopenharmony_ci} 70453c3577eSopenharmony_ci 70553c3577eSopenharmony_civoid SyncManager::UpdateStartSyncInfo(const std::vector<std::tuple<QueryKey, uint64_t>> &cloudSyncInfos) 70653c3577eSopenharmony_ci{ 70753c3577eSopenharmony_ci int64_t startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); 70853c3577eSopenharmony_ci for (const auto &[queryKey, syncId] : cloudSyncInfos) { 70953c3577eSopenharmony_ci if (!NeedSaveSyncInfo(queryKey)) { 71053c3577eSopenharmony_ci continue; 71153c3577eSopenharmony_ci } 71253c3577eSopenharmony_ci lastSyncInfos_.Compute(queryKey, [id = syncId, startTime](auto &, std::map<SyncId, CloudSyncInfo> &val) { 71353c3577eSopenharmony_ci val[id] = { .startTime = startTime }; 71453c3577eSopenharmony_ci return !val.empty(); 71553c3577eSopenharmony_ci }); 71653c3577eSopenharmony_ci } 71753c3577eSopenharmony_ci} 71853c3577eSopenharmony_ci 71953c3577eSopenharmony_civoid SyncManager::UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId, int32_t code) 72053c3577eSopenharmony_ci{ 72153c3577eSopenharmony_ci if (!NeedSaveSyncInfo(queryKey)) { 72253c3577eSopenharmony_ci return; 72353c3577eSopenharmony_ci } 72453c3577eSopenharmony_ci lastSyncInfos_.ComputeIfPresent(queryKey, [syncId, code](auto &key, std::map<SyncId, CloudSyncInfo> &val) { 72553c3577eSopenharmony_ci auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); 72653c3577eSopenharmony_ci for (auto iter = val.begin(); iter != val.end();) { 72753c3577eSopenharmony_ci bool isExpired = ((now - iter->second.startTime) >= EXPIRATION_TIME) && iter->second.code == -1; 72853c3577eSopenharmony_ci if ((iter->first != syncId && ((iter->second.code != -1) || isExpired))) { 72953c3577eSopenharmony_ci iter = val.erase(iter); 73053c3577eSopenharmony_ci } else if (iter->first == syncId) { 73153c3577eSopenharmony_ci iter->second.finishTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); 73253c3577eSopenharmony_ci iter->second.code = code; 73353c3577eSopenharmony_ci iter++; 73453c3577eSopenharmony_ci } else { 73553c3577eSopenharmony_ci iter++; 73653c3577eSopenharmony_ci } 73753c3577eSopenharmony_ci } 73853c3577eSopenharmony_ci return true; 73953c3577eSopenharmony_ci }); 74053c3577eSopenharmony_ci} 74153c3577eSopenharmony_ci 74253c3577eSopenharmony_cistd::function<void(const GenDetails &result)> SyncManager::GetCallback(const GenAsync &async, 74353c3577eSopenharmony_ci const StoreInfo &storeInfo, int32_t triggerMode, const std::string &prepareTraceId, int32_t user) 74453c3577eSopenharmony_ci{ 74553c3577eSopenharmony_ci return [this, async, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &result) { 74653c3577eSopenharmony_ci if (async != nullptr) { 74753c3577eSopenharmony_ci async(result); 74853c3577eSopenharmony_ci } 74953c3577eSopenharmony_ci 75053c3577eSopenharmony_ci if (result.empty()) { 75153c3577eSopenharmony_ci ZLOGE("result is empty"); 75253c3577eSopenharmony_ci return; 75353c3577eSopenharmony_ci } 75453c3577eSopenharmony_ci 75553c3577eSopenharmony_ci if (result.begin()->second.progress != GenProgress::SYNC_FINISH) { 75653c3577eSopenharmony_ci return; 75753c3577eSopenharmony_ci } 75853c3577eSopenharmony_ci 75953c3577eSopenharmony_ci int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode; 76053c3577eSopenharmony_ci RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, 76153c3577eSopenharmony_ci result.begin()->second.changeCount, dbCode }, 76253c3577eSopenharmony_ci "GetCallback", BizState::END); 76353c3577eSopenharmony_ci Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode }); 76453c3577eSopenharmony_ci 76553c3577eSopenharmony_ci auto id = GetAccountId(storeInfo.user); 76653c3577eSopenharmony_ci if (id.empty()) { 76753c3577eSopenharmony_ci ZLOGD("account id is empty"); 76853c3577eSopenharmony_ci return; 76953c3577eSopenharmony_ci } 77053c3577eSopenharmony_ci QueryKey queryKey{ 77153c3577eSopenharmony_ci .accountId = id, 77253c3577eSopenharmony_ci .bundleName = storeInfo.bundleName, 77353c3577eSopenharmony_ci .storeId = "" 77453c3577eSopenharmony_ci }; 77553c3577eSopenharmony_ci 77653c3577eSopenharmony_ci int32_t code = result.begin()->second.code; 77753c3577eSopenharmony_ci UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); 77853c3577eSopenharmony_ci }; 77953c3577eSopenharmony_ci} 78053c3577eSopenharmony_ci 78153c3577eSopenharmony_cistd::string SyncManager::GetAccountId(int32_t user) 78253c3577eSopenharmony_ci{ 78353c3577eSopenharmony_ci CloudInfo cloudInfo; 78453c3577eSopenharmony_ci cloudInfo.user = user; 78553c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { 78653c3577eSopenharmony_ci ZLOGE("not exist meta, user:%{public}d.", cloudInfo.user); 78753c3577eSopenharmony_ci return ""; 78853c3577eSopenharmony_ci } 78953c3577eSopenharmony_ci return cloudInfo.id; 79053c3577eSopenharmony_ci} 79153c3577eSopenharmony_ci 79253c3577eSopenharmony_ciExecutorPool::Duration SyncManager::GetInterval(int32_t code) 79353c3577eSopenharmony_ci{ 79453c3577eSopenharmony_ci switch (code) { 79553c3577eSopenharmony_ci case E_LOCKED_BY_OTHERS: 79653c3577eSopenharmony_ci return LOCKED_INTERVAL; 79753c3577eSopenharmony_ci case E_BUSY: 79853c3577eSopenharmony_ci return BUSY_INTERVAL; 79953c3577eSopenharmony_ci default: 80053c3577eSopenharmony_ci return RETRY_INTERVAL; 80153c3577eSopenharmony_ci } 80253c3577eSopenharmony_ci} 80353c3577eSopenharmony_ci 80453c3577eSopenharmony_cistd::vector<SchemaMeta> SyncManager::GetSchemaMeta(const CloudInfo &cloud, const std::string &bundleName) 80553c3577eSopenharmony_ci{ 80653c3577eSopenharmony_ci std::vector<SchemaMeta> schemas; 80753c3577eSopenharmony_ci auto key = cloud.GetSchemaPrefix(bundleName); 80853c3577eSopenharmony_ci MetaDataManager::GetInstance().LoadMeta(key, schemas, true); 80953c3577eSopenharmony_ci return schemas; 81053c3577eSopenharmony_ci} 81153c3577eSopenharmony_ci 81253c3577eSopenharmony_civoid SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, 81353c3577eSopenharmony_ci const std::string &prepareTraceId) 81453c3577eSopenharmony_ci{ 81553c3577eSopenharmony_ci if (async) { 81653c3577eSopenharmony_ci details[SyncInfo::DEFAULT_ID].code = E_ERROR; 81753c3577eSopenharmony_ci async(details); 81853c3577eSopenharmony_ci } 81953c3577eSopenharmony_ci QueryKey queryKey{ GetAccountId(storeInfo.user), storeInfo.bundleName, "" }; 82053c3577eSopenharmony_ci UpdateFinishSyncInfo(queryKey, storeInfo.syncId, E_ERROR); 82153c3577eSopenharmony_ci Report({ storeInfo.user, storeInfo.bundleName, prepareTraceId, SyncStage::END, E_ERROR }); 82253c3577eSopenharmony_ci} 82353c3577eSopenharmony_ci 82453c3577eSopenharmony_cibool SyncManager::InitDefaultUser(int32_t &user) 82553c3577eSopenharmony_ci{ 82653c3577eSopenharmony_ci if (user != 0) { 82753c3577eSopenharmony_ci return false; 82853c3577eSopenharmony_ci } 82953c3577eSopenharmony_ci std::vector<int32_t> users; 83053c3577eSopenharmony_ci AccountDelegate::GetInstance()->QueryUsers(users); 83153c3577eSopenharmony_ci if (!users.empty()) { 83253c3577eSopenharmony_ci user = users[0]; 83353c3577eSopenharmony_ci } 83453c3577eSopenharmony_ci return true; 83553c3577eSopenharmony_ci} 83653c3577eSopenharmony_ci 83753c3577eSopenharmony_cistd::function<void(const DistributedData::GenDetails &result)> SyncManager::RetryCallback(const StoreInfo &storeInfo, 83853c3577eSopenharmony_ci Retryer retryer, int32_t triggerMode, const std::string &prepareTraceId, int32_t user) 83953c3577eSopenharmony_ci{ 84053c3577eSopenharmony_ci return [this, retryer, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &details) { 84153c3577eSopenharmony_ci if (details.empty()) { 84253c3577eSopenharmony_ci ZLOGE("retry, details empty"); 84353c3577eSopenharmony_ci return; 84453c3577eSopenharmony_ci } 84553c3577eSopenharmony_ci int32_t code = details.begin()->second.code; 84653c3577eSopenharmony_ci int32_t dbCode = details.begin()->second.dbCode; 84753c3577eSopenharmony_ci if (details.begin()->second.progress == GenProgress::SYNC_FINISH) { 84853c3577eSopenharmony_ci QueryKey queryKey{ GetAccountId(storeInfo.user), storeInfo.bundleName, "" }; 84953c3577eSopenharmony_ci UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); 85053c3577eSopenharmony_ci if (code == E_OK) { 85153c3577eSopenharmony_ci RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, 85253c3577eSopenharmony_ci triggerMode, details.begin()->second.changeCount }, 85353c3577eSopenharmony_ci "RetryCallback", BizState::END); 85453c3577eSopenharmony_ci Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, 85553c3577eSopenharmony_ci dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); 85653c3577eSopenharmony_ci } 85753c3577eSopenharmony_ci } 85853c3577eSopenharmony_ci retryer(GetInterval(code), code, dbCode, prepareTraceId); 85953c3577eSopenharmony_ci }; 86053c3577eSopenharmony_ci} 86153c3577eSopenharmony_ci 86253c3577eSopenharmony_civoid SyncManager::BatchUpdateFinishState(const std::vector<std::tuple<QueryKey, uint64_t>> &cloudSyncInfos, 86353c3577eSopenharmony_ci int32_t code) 86453c3577eSopenharmony_ci{ 86553c3577eSopenharmony_ci for (const auto &[queryKey, syncId] : cloudSyncInfos) { 86653c3577eSopenharmony_ci UpdateFinishSyncInfo(queryKey, syncId, code); 86753c3577eSopenharmony_ci } 86853c3577eSopenharmony_ci} 86953c3577eSopenharmony_ci 87053c3577eSopenharmony_civoid SyncManager::BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode) 87153c3577eSopenharmony_ci{ 87253c3577eSopenharmony_ci for (const auto &[bundle, id] : traceIds) { 87353c3577eSopenharmony_ci Report({ userId, bundle, id, syncStage, errCode }); 87453c3577eSopenharmony_ci } 87553c3577eSopenharmony_ci} 87653c3577eSopenharmony_ci 87753c3577eSopenharmony_cistd::pair<bool, StoreMetaData> SyncManager::GetMetaData(const StoreInfo &storeInfo) 87853c3577eSopenharmony_ci{ 87953c3577eSopenharmony_ci StoreMetaData meta(storeInfo); 88053c3577eSopenharmony_ci meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; 88153c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { 88253c3577eSopenharmony_ci meta.user = "0"; // check if it is a public store. 88353c3577eSopenharmony_ci StoreMetaDataLocal localMetaData; 88453c3577eSopenharmony_ci if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || 88553c3577eSopenharmony_ci !localMetaData.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { 88653c3577eSopenharmony_ci ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), 88753c3577eSopenharmony_ci meta.GetStoreAlias().c_str()); 88853c3577eSopenharmony_ci return { false, meta }; 88953c3577eSopenharmony_ci } 89053c3577eSopenharmony_ci } 89153c3577eSopenharmony_ci return { true, meta }; 89253c3577eSopenharmony_ci} 89353c3577eSopenharmony_ci} // namespace OHOS::CloudData