• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 
16 #define LOG_TAG "RdbAssetLoader"
17 #include "rdb_asset_loader.h"
18 
19 #include <variant>
20 
21 #include "error/general_error.h"
22 #include "log_print.h"
23 #include "rdb_cloud.h"
24 #include "store/general_value.h"
25 #include "value_proxy.h"
26 
27 using namespace DistributedDB;
28 using ValueProxy = OHOS::DistributedData::ValueProxy;
29 namespace OHOS::DistributedRdb {
RdbAssetLoader(std::shared_ptr<DistributedData::AssetLoader> cloudAssetLoader,BindAssets bindAssets)30 RdbAssetLoader::RdbAssetLoader(std::shared_ptr<DistributedData::AssetLoader> cloudAssetLoader, BindAssets bindAssets)
31     : assetLoader_(std::move(cloudAssetLoader)), snapshots_(std::move(bindAssets))
32 {
33 }
34 
Download(const std::string & tableName,const std::string & gid,const Type & prefix,std::map<std::string,Assets> & assets)35 DBStatus RdbAssetLoader::Download(const std::string &tableName, const std::string &gid, const Type &prefix,
36     std::map<std::string, Assets> &assets)
37 {
38     DistributedData::VBucket downLoadAssets = ValueProxy::Convert(assets);
39     std::set<std::string> skipAssets;
40     std::set<std::string> deleteAssets;
41     PostEvent(skipAssets, downLoadAssets, DistributedData::AssetEvent::DOWNLOAD, deleteAssets);
42     DistributedDB::Type prefixTemp = prefix;
43     auto error = assetLoader_->Download(tableName, gid, ValueProxy::Convert(std::move(prefixTemp)), downLoadAssets);
44     PostEvent(skipAssets, downLoadAssets, DistributedData::AssetEvent::DOWNLOAD_FINISHED, deleteAssets);
45     assets = ValueProxy::Convert(std::move(downLoadAssets));
46     return skipAssets.empty() ? RdbCloud::ConvertStatus(static_cast<DistributedData::GeneralError>(error))
47                               : CLOUD_RECORD_EXIST_CONFLICT;
48 }
49 
BatchDownload(const std::string & tableName,std::vector<AssetRecord> & downloadAssets)50 void RdbAssetLoader::BatchDownload(const std::string &tableName, std::vector<AssetRecord> &downloadAssets)
51 {
52     std::vector<AssetsRecord> assetsRecords = Convert(std::move(downloadAssets));
53     std::set<std::string> skipAssets;
54     std::set<std::string> deleteAssets;
55     PostEvent(skipAssets, assetsRecords, DistributedData::AssetEvent::DOWNLOAD, deleteAssets);
56     assetLoader_->Download(tableName, assetsRecords);
57     PostEvent(skipAssets, assetsRecords, DistributedData::AssetEvent::DOWNLOAD_FINISHED, deleteAssets);
58     downloadAssets = Convert(std::move(assetsRecords));
59 }
60 
Convert(std::vector<AssetRecord> && downloadAssets)61 std::vector<RdbAssetLoader::AssetsRecord> RdbAssetLoader::Convert(std::vector<AssetRecord> &&downloadAssets)
62 {
63     std::vector<AssetsRecord> assetsRecords;
64     for (auto &assetRecord : downloadAssets) {
65         AssetsRecord assetsRecord;
66         assetsRecord.gid = std::move(assetRecord.gid);
67         DistributedDB::Type prefixTemp = assetRecord.prefix;
68         assetsRecord.prefix = ValueProxy::Convert(std::move(prefixTemp));
69         assetsRecord.assets = ValueProxy::Convert(std::move(assetRecord.assets));
70         assetsRecords.emplace_back(std::move(assetsRecord));
71     }
72     return assetsRecords;
73 }
74 
UpdateStatus(AssetRecord & assetRecord,const VBucket & assets)75 void RdbAssetLoader::UpdateStatus(AssetRecord &assetRecord, const VBucket &assets)
76 {
77     for (const auto &[key, value] : assets) {
78         auto downloadAssets = std::get_if<DistributedData::Assets>(&value);
79         if (downloadAssets == nullptr) {
80             assetRecord.status = DBStatus::CLOUD_ERROR;
81             continue;
82         }
83         for (const auto &asset : *downloadAssets) {
84             if (assetRecord.status != DBStatus::OK) {
85                 return;
86             }
87             assetRecord.status = ConvertStatus(static_cast<AssetStatus>(asset.status));
88         }
89     }
90 }
91 
Convert(std::vector<AssetsRecord> && assetsRecords)92 std::vector<IAssetLoader::AssetRecord> RdbAssetLoader::Convert(std::vector<AssetsRecord> &&assetsRecords)
93 {
94     std::vector<AssetRecord> assetRecords;
95     for (auto &assetsRecord : assetsRecords) {
96         AssetRecord assetRecord{
97             .gid = std::move(assetsRecord.gid),
98         };
99         UpdateStatus(assetRecord, assetsRecord.assets);
100         assetRecord.assets = ValueProxy::Convert(std::move(assetsRecord.assets));
101         assetRecords.emplace_back(std::move(assetRecord));
102     }
103     return assetRecords;
104 }
105 
ConvertStatus(AssetStatus error)106 DBStatus RdbAssetLoader::ConvertStatus(AssetStatus error)
107 {
108     switch (error) {
109         case AssetStatus::STATUS_NORMAL:
110         case AssetStatus::STATUS_DOWNLOADING:
111             return DBStatus::OK;
112         case AssetStatus::STATUS_SKIP_ASSET:
113             return DBStatus::SKIP_ASSET;
114         default:
115             ZLOGE("error:0x%{public}x", error);
116             break;
117     }
118     return DBStatus::CLOUD_ERROR;
119 }
120 
RemoveLocalAssets(const std::vector<Asset> & assets)121 DBStatus RdbAssetLoader::RemoveLocalAssets(const std::vector<Asset> &assets)
122 {
123     DistributedData::VBucket deleteAssets = ValueProxy::Convert(std::map<std::string, Assets>{{ "", assets }});
124     auto error = assetLoader_->RemoveLocalAssets("", "", {}, deleteAssets);
125     return RdbCloud::ConvertStatus(static_cast<DistributedData::GeneralError>(error));
126 }
127 
CancelDownload()128 DBStatus RdbAssetLoader::CancelDownload()
129 {
130     if (assetLoader_ == nullptr) {
131         ZLOGE("assetLoader is nullptr");
132         return DBStatus::DB_ERROR;
133     }
134     auto error = assetLoader_->CancelDownload();
135     return RdbCloud::ConvertStatus(static_cast<DistributedData::GeneralError>(error));
136 }
137 
PostEvent(std::set<std::string> & skipAssets,std::vector<AssetsRecord> & assetsRecords,DistributedData::AssetEvent eventId,std::set<std::string> & deleteAssets)138 void RdbAssetLoader::PostEvent(std::set<std::string> &skipAssets, std::vector<AssetsRecord> &assetsRecords,
139     DistributedData::AssetEvent eventId, std::set<std::string> &deleteAssets)
140 {
141     for (auto &assetsRecord : assetsRecords) {
142         for (auto &asset : assetsRecord.assets) {
143             auto *downLoadAssets = Traits::get_if<DistributedData::Assets>(&asset.second);
144             if (downLoadAssets == nullptr) {
145                 return;
146             }
147             PostEvent(eventId, *downLoadAssets, skipAssets, deleteAssets);
148         }
149     }
150 }
151 
PostEvent(std::set<std::string> & skipAssets,std::map<std::string,DistributedData::Value> & assets,DistributedData::AssetEvent eventId,std::set<std::string> & deleteAssets)152 void RdbAssetLoader::PostEvent(std::set<std::string>& skipAssets, std::map<std::string, DistributedData::Value>& assets,
153     DistributedData::AssetEvent eventId, std::set<std::string>& deleteAssets)
154 {
155     for (auto& asset : assets) {
156         auto* downLoadAssets = Traits::get_if<DistributedData::Assets>(&asset.second);
157         if (downLoadAssets == nullptr) {
158             return;
159         }
160         PostEvent(eventId, *downLoadAssets, skipAssets, deleteAssets);
161     }
162 }
163 
PostEvent(DistributedData::AssetEvent eventId,DistributedData::Assets & assets,std::set<std::string> & skipAssets,std::set<std::string> & deleteAssets)164 void RdbAssetLoader::PostEvent(DistributedData::AssetEvent eventId, DistributedData::Assets& assets,
165     std::set<std::string>& skipAssets, std::set<std::string>& deleteAssets)
166 {
167     for (auto& downLoadAsset : assets) {
168         if (downLoadAsset.status == DistributedData::Asset::STATUS_DELETE) {
169             deleteAssets.insert(downLoadAsset.uri);
170             continue;
171         }
172         if (snapshots_ == nullptr) {
173             continue;
174         }
175         auto it = snapshots_->find(downLoadAsset.uri);
176         if (it == snapshots_->end() || it->second == nullptr) {
177             continue;
178         }
179         auto snapshot = it->second;
180         if (eventId == DistributedData::DOWNLOAD) {
181             snapshot->Download(downLoadAsset);
182             if (snapshot->GetAssetStatus(downLoadAsset) == DistributedData::STATUS_WAIT_DOWNLOAD) {
183                 skipAssets.insert(downLoadAsset.uri);
184             }
185         } else {
186             auto skipPos = skipAssets.find(downLoadAsset.uri);
187             auto deletePos = deleteAssets.find(downLoadAsset.uri);
188             if (skipPos != skipAssets.end() || deletePos != deleteAssets.end()) {
189                 continue;
190             }
191             snapshot->Downloaded(downLoadAsset);
192         }
193     }
194 }
195 } // namespace OHOS::DistributedRdb