• 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 "ObjectAssetMachine"
17 #include "object_asset_machine.h"
18 
19 #include <utility>
20 #include <utils/anonymous.h>
21 
22 #include "cloud/change_event.h"
23 #include "device_manager_adapter.h"
24 #include "eventcenter/event_center.h"
25 #include "log_print.h"
26 #include "metadata/meta_data_manager.h"
27 #include "object_asset_loader.h"
28 #include "snapshot/bind_event.h"
29 #include "store/auto_cache.h"
30 
31 namespace OHOS {
32 namespace DistributedObject {
33 using namespace OHOS::DistributedData;
34 using namespace OHOS::DistributedRdb;
35 using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter;
36 
37 constexpr static const char* SQL_AND = " = ? and ";
38 constexpr static const int32_t AND_SIZE = 5;
39 static int32_t DoTransfer(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
40     const std::pair<std::string, Asset>& newAsset);
41 
42 static int32_t ChangeAssetToNormal(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
43     const std::pair<std::string, Asset>& newAsset);
44 
45 static int32_t CompensateSync(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
46     const std::pair<std::string, Asset>& newAsset);
47 
48 static int32_t CompensateTransferring(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
49     const std::pair<std::string, Asset>& newAsset);
50 
51 static int32_t SaveNewAsset(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
52     const std::pair<std::string, Asset>& newAsset);
53 
54 static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
55     const std::pair<std::string, Asset>& newAsset);
56 
57 static int32_t UpdateStore(ChangedAssetInfo& changedAsset);
58 
59 static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset);
60 static VBuckets GetMigratedData(AutoCache::Store& store, AssetBindInfo& assetBindInfo, const Asset& newAsset);
61 static void MergeAssetData(VBucket& record, const Asset& newAsset, const AssetBindInfo& assetBindInfo);
62 static void MergeAsset(Asset& oldAsset, const Asset& newAsset);
63 static std::string BuildSql(const AssetBindInfo& bindInfo, Values& args);
64 static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset);
65 
66 static const DFAAction AssetDFA[STATUS_BUTT][EVENT_BUTT] = {
67     {
68         // STATUS_STABLE
69         { STATUS_TRANSFERRING, nullptr, (Action)DoTransfer }, // remote_changed
70         { STATUS_NO_CHANGE, nullptr, (Action)Recover },       // transfer_finished
71         { STATUS_UPLOADING, nullptr, nullptr },               // upload
72         { STATUS_NO_CHANGE, nullptr, (Action)Recover },       // upload_finished
73         { STATUS_DOWNLOADING, nullptr, nullptr },             // download
74         { STATUS_NO_CHANGE, nullptr, (Action)Recover },       // upload_finished
75     },
76     {
77         // TRANSFERRING
78         { STATUS_WAIT_TRANSFER, nullptr, (Action)SaveNewAsset },        // remote_changed
79         { STATUS_STABLE, nullptr, nullptr },                            // transfer_finished
80         { STATUS_WAIT_UPLOAD, nullptr, (Action)ChangeAssetToNormal },   // upload
81         { STATUS_NO_CHANGE, nullptr, (Action)Recover },                 // upload_finished
82         { STATUS_WAIT_DOWNLOAD, nullptr, (Action)ChangeAssetToNormal }, // download
83         { STATUS_NO_CHANGE, nullptr, (Action)Recover },                 // upload_finished
84     },
85     {
86         // DOWNLOADING
87         { STATUS_WAIT_TRANSFER, nullptr, (Action)SaveNewAsset }, // remote_changed
88         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // transfer_finished
89         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // upload
90         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // upload_finished
91         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // download
92         { STATUS_STABLE, nullptr, nullptr },                     // download_finished
93     },
94     {
95         // STATUS_UPLOADING
96         { STATUS_WAIT_TRANSFER, nullptr, (Action)SaveNewAsset }, // remote_changed
97         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // transfer_finished
98         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // upload
99         { STATUS_STABLE, nullptr, nullptr },                     // upload_finished
100         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // download
101         { STATUS_NO_CHANGE, nullptr, (Action)Recover },          // download_finished
102     },
103     {
104         // STATUS_WAIT_TRANSFER
105         { STATUS_WAIT_TRANSFER, nullptr, (Action)SaveNewAsset },        // remote_changed
106         { STATUS_STABLE, nullptr, (Action)CompensateTransferring },     // transfer_finished
107         { STATUS_WAIT_UPLOAD, nullptr, (Action)ChangeAssetToNormal },   // upload
108         { STATUS_STABLE, nullptr, (Action)CompensateTransferring },     // upload_finished
109         { STATUS_WAIT_DOWNLOAD, nullptr, (Action)ChangeAssetToNormal }, // download
110         { STATUS_STABLE, nullptr, (Action)CompensateTransferring },     // download_finished
111     },
112     {
113         // STATUS_WAIT_UPLOAD
114         { STATUS_WAIT_TRANSFER, nullptr, (Action)SaveNewAsset },        // remote_changed
115         { STATUS_STABLE, nullptr, (Action)CompensateSync },             // transfer_finished
116         { STATUS_WAIT_UPLOAD, nullptr, (Action)ChangeAssetToNormal },   // upload
117         { STATUS_NO_CHANGE, nullptr, (Action)Recover },                 // upload_finished
118         { STATUS_WAIT_DOWNLOAD, nullptr, (Action)ChangeAssetToNormal }, // download
119         { STATUS_NO_CHANGE, nullptr, (Action)Recover },                 // download_finished
120     },
121     {
122         // STATUS_WAIT_DOWNLOAD
123         { STATUS_WAIT_TRANSFER, nullptr, (Action)SaveNewAsset },         // remote_changed
124         { STATUS_STABLE, nullptr, (Action)CompensateSync },              // transfer_finished
125         { STATUS_WAIT_UPLOAD, nullptr, (Action)ChangeAssetToNormal },    // upload
126         { STATUS_NO_CHANGE, nullptr, (Action)Recover },                  // upload_finished
127         { STATUS_WAIT_DOWNLOAD, nullptr, (Action)STATUS_WAIT_DOWNLOAD }, // download
128         { STATUS_NO_CHANGE, nullptr, (Action)Recover },                  // download_finished
129     }
130 };
131 
DFAPostEvent(AssetEvent eventId,ChangedAssetInfo & changedAssetInfo,Asset & asset,const std::pair<std::string,Asset> & newAsset)132 int32_t ObjectAssetMachine::DFAPostEvent(AssetEvent eventId, ChangedAssetInfo& changedAssetInfo, Asset& asset,
133     const std::pair<std::string, Asset>& newAsset)
134 {
135     if (eventId < 0 || eventId >= EVENT_BUTT) {
136         return GeneralError::E_ERROR;
137     }
138 
139     const DFAAction* action = &AssetDFA[changedAssetInfo.status][eventId];
140     if (action->before != nullptr) {
141         int32_t res = action->before(eventId, changedAssetInfo, asset, newAsset);
142         if (res != GeneralError::E_OK) {
143             return GeneralError::E_ERROR;
144         }
145     }
146     if (action->next != STATUS_NO_CHANGE) {
147         ZLOGI("status before:%{public}d, eventId: %{public}d, status after:%{public}d", changedAssetInfo.status,
148             eventId, action->next);
149         changedAssetInfo.status = static_cast<TransferStatus>(action->next);
150     }
151     if (action->after != nullptr) {
152         int32_t res = action->after(eventId, changedAssetInfo, asset, newAsset);
153         if (res != GeneralError::E_OK) {
154             return GeneralError::E_ERROR;
155         }
156     }
157     return GeneralError::E_OK;
158 }
159 
DoTransfer(int32_t eventId,ChangedAssetInfo & changedAsset,Asset & asset,const std::pair<std::string,Asset> & newAsset)160 static int32_t DoTransfer(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
161     const std::pair<std::string, Asset>& newAsset)
162 {
163     changedAsset.deviceId = newAsset.first;
164     changedAsset.asset = newAsset.second;
165     std::vector<Asset> assets{ changedAsset.asset };
166     ObjectAssetLoader::GetInstance()->TransferAssetsAsync(changedAsset.storeInfo.user,
167         changedAsset.storeInfo.bundleName, changedAsset.deviceId, assets, [&changedAsset](bool success) {
168             if (success) {
169                 auto status = UpdateStore(changedAsset);
170                 if (status != E_OK) {
171                     ZLOGE("UpdateStore error, error:%{public}d, assetName:%{public}s, store:%{public}s, "
172                           "table:%{public}s",
173                         status, changedAsset.asset.name.c_str(),
174                         Anonymous::Change(changedAsset.bindInfo.storeName).c_str(),
175                         changedAsset.bindInfo.tableName.c_str());
176                 }
177             }
178             ObjectAssetMachine::DFAPostEvent(TRANSFER_FINISHED, changedAsset, changedAsset.asset);
179         });
180     return E_OK;
181 }
182 
UpdateStore(ChangedAssetInfo & changedAsset)183 static int32_t UpdateStore(ChangedAssetInfo& changedAsset)
184 {
185     auto store = GetStore(changedAsset);
186     if (store == nullptr) {
187         ZLOGE("store null, storeId:%{public}s", Anonymous::Change(changedAsset.bindInfo.storeName).c_str());
188         return E_ERROR;
189     }
190 
191     VBuckets vBuckets = GetMigratedData(store, changedAsset.bindInfo, changedAsset.asset);
192     if (vBuckets.empty()) {
193         return E_OK;
194     }
195     return store->MergeMigratedData(changedAsset.bindInfo.tableName, std::move(vBuckets));
196 }
197 
GetMigratedData(AutoCache::Store & store,AssetBindInfo & assetBindInfo,const Asset & newAsset)198 static VBuckets GetMigratedData(AutoCache::Store& store, AssetBindInfo& assetBindInfo, const Asset& newAsset)
199 {
200     Values args;
201     VBuckets vBuckets;
202     auto sql = BuildSql(assetBindInfo, args);
203     auto cursor = store->Query(assetBindInfo.tableName, sql, std::move(args));
204     if (cursor == nullptr) {
205         return vBuckets;
206     }
207     int32_t count = cursor->GetCount();
208     if (count != 1) {
209         return vBuckets;
210     }
211     vBuckets.reserve(count);
212     auto err = cursor->MoveToFirst();
213     while (err == E_OK && count > 0) {
214         VBucket entry;
215         err = cursor->GetRow(entry);
216         if (err != E_OK) {
217             return vBuckets;
218         }
219         MergeAssetData(entry, newAsset, assetBindInfo);
220         vBuckets.emplace_back(std::move(entry));
221         err = cursor->MoveToNext();
222         count--;
223     }
224     return vBuckets;
225 }
226 
BuildSql(const AssetBindInfo & bindInfo,Values & args)227 static std::string BuildSql(const AssetBindInfo& bindInfo, Values& args)
228 {
229     std::string sql;
230     sql.append("SELECT ").append(bindInfo.field).append(" FROM ").append(bindInfo.tableName).append(" WHERE ");
231     for (auto const& [key, value] : bindInfo.primaryKey) {
232         sql.append(key).append(SQL_AND);
233         args.emplace_back(value);
234     }
235     sql = sql.substr(0, sql.size() - AND_SIZE);
236     return sql;
237 }
238 
MergeAssetData(VBucket & record,const Asset & newAsset,const AssetBindInfo & assetBindInfo)239 static void MergeAssetData(VBucket& record, const Asset& newAsset, const AssetBindInfo& assetBindInfo)
240 {
241     for (auto const& [key, primary] : assetBindInfo.primaryKey) {
242         record[key] = primary;
243     }
244 
245     auto it = record.find(assetBindInfo.field);
246     if (it == record.end()) {
247         ZLOGD("Not find field:%{public}s in store", assetBindInfo.field.c_str());
248         return;
249     }
250 
251     auto& value = it->second;
252     if (value.index() == TYPE_INDEX<std::monostate>) {
253         Assets assets{ newAsset };
254         value = assets;
255         return;
256     }
257     if (value.index() == TYPE_INDEX<DistributedData::Asset>) {
258         auto* asset = Traits::get_if<DistributedData::Asset>(&value);
259         if (asset->name != newAsset.name) {
260             ZLOGD("Asset not same, old uri: %{public}s, new uri: %{public}s", asset->uri.c_str(), newAsset.uri.c_str());
261             return;
262         }
263     }
264 
265     if (value.index() == TYPE_INDEX<DistributedData::Assets>) {
266         auto* assets = Traits::get_if<DistributedData::Assets>(&value);
267         for (auto& asset : *assets) {
268             if (asset.name == newAsset.name) {
269                 MergeAsset(asset, newAsset);
270                 return;
271             }
272         }
273         assets->emplace_back(newAsset);
274     }
275 }
276 
MergeAsset(Asset & oldAsset,const Asset & newAsset)277 static void MergeAsset(Asset& oldAsset, const Asset& newAsset)
278 {
279     oldAsset.name = newAsset.name;
280     oldAsset.uri = newAsset.uri;
281     oldAsset.modifyTime = newAsset.modifyTime;
282     oldAsset.createTime = newAsset.createTime;
283     oldAsset.size = newAsset.size;
284     oldAsset.hash = newAsset.hash;
285     oldAsset.path = newAsset.path;
286 }
287 
GetStore(ChangedAssetInfo & changedAsset)288 static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset)
289 {
290     StoreMetaData meta;
291     meta.storeId = changedAsset.bindInfo.storeName;
292     meta.bundleName = changedAsset.storeInfo.bundleName;
293     meta.user = std::to_string(changedAsset.storeInfo.user);
294     meta.instanceId = changedAsset.storeInfo.instanceId;
295     meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
296     if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) {
297         ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
298             meta.GetStoreAlias().c_str());
299         return nullptr;
300     }
301     return AutoCache::GetInstance().GetStore(meta, {});
302 }
303 
CompensateTransferring(int32_t eventId,ChangedAssetInfo & changedAsset,Asset & asset,const std::pair<std::string,Asset> & newAsset)304 static int32_t CompensateTransferring(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
305     const std::pair<std::string, Asset>& newAsset)
306 {
307     std::pair<std::string, Asset> newChangedAsset{ changedAsset.deviceId, changedAsset.asset };
308     return ObjectAssetMachine::DFAPostEvent(REMOTE_CHANGED, changedAsset, changedAsset.asset, newChangedAsset);
309 }
310 
CompensateSync(int32_t eventId,ChangedAssetInfo & changedAsset,Asset & asset,const std::pair<std::string,Asset> & newAsset)311 static int32_t CompensateSync(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
312     const std::pair<std::string, Asset>& newAsset)
313 {
314     BindEvent::BindEventInfo bindEventInfo = MakeBindInfo(changedAsset);
315     auto evt = std::make_unique<BindEvent>(BindEvent::COMPENSATE_SYNC, std::move(bindEventInfo));
316     EventCenter::GetInstance().PostEvent(std::move(evt));
317     return E_OK;
318 }
319 
SaveNewAsset(int32_t eventId,ChangedAssetInfo & changedAsset,Asset & asset,const std::pair<std::string,Asset> & newAsset)320 static int32_t SaveNewAsset(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
321     const std::pair<std::string, Asset>& newAsset)
322 {
323     changedAsset.deviceId = newAsset.first;
324     changedAsset.asset = newAsset.second;
325     return E_OK;
326 }
327 
ChangeAssetToNormal(int32_t eventId,ChangedAssetInfo & changedAssetInfo,Asset & asset,const std::pair<std::string,Asset> & newAsset)328 static int32_t ChangeAssetToNormal(int32_t eventId, ChangedAssetInfo& changedAssetInfo, Asset& asset,
329     const std::pair<std::string, Asset>& newAsset)
330 {
331     asset.status = Asset::STATUS_NORMAL;
332     return E_OK;
333 }
334 
Recover(int32_t eventId,ChangedAssetInfo & changedAsset,Asset & asset,const std::pair<std::string,Asset> & newAsset)335 static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset,
336     const std::pair<std::string, Asset>& newAsset)
337 {
338     ZLOGE("An abnormal event has occurred, eventId:%{public}d, status:%{public}d, assetName:%{public}s", eventId,
339         changedAsset.status, changedAsset.asset.name.c_str());
340 
341     BindEvent::BindEventInfo bindEventInfo = MakeBindInfo(changedAsset);
342     changedAsset.status = TransferStatus::STATUS_STABLE;
343     auto evt = std::make_unique<BindEvent>(BindEvent::RECOVER_SYNC, std::move(bindEventInfo));
344     EventCenter::GetInstance().PostEvent(std::move(evt));
345     return E_OK;
346 }
347 
MakeBindInfo(ChangedAssetInfo & changedAsset)348 static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset)
349 {
350     BindEvent::BindEventInfo bindEventInfo;
351     bindEventInfo.bundleName = changedAsset.storeInfo.bundleName;
352     bindEventInfo.user = changedAsset.storeInfo.user;
353     bindEventInfo.tokenId = changedAsset.storeInfo.tokenId;
354     bindEventInfo.instanceId = changedAsset.storeInfo.instanceId;
355     bindEventInfo.storeName = changedAsset.bindInfo.storeName;
356     bindEventInfo.tableName = changedAsset.bindInfo.tableName;
357     bindEventInfo.filed = changedAsset.bindInfo.field;
358     bindEventInfo.primaryKey = changedAsset.bindInfo.primaryKey;
359     bindEventInfo.assetName = changedAsset.bindInfo.assetName;
360     return bindEventInfo;
361 }
362 
ObjectAssetMachine()363 ObjectAssetMachine::ObjectAssetMachine() {}
364 
365 } // namespace DistributedObject
366 } // namespace OHOS
367