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 &param)
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