• 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 #include "album_data_handler.h"
17 
18 #include "medialibrary_db_const.h"
19 #include "medialibrary_type_const.h"
20 
21 #include "data_sync_const.h"
22 #include "data_sync_notifier.h"
23 #include "dfs_error.h"
24 #include "gallery_album_const.h"
25 #include "utils_log.h"
26 
27 namespace OHOS {
28 namespace FileManagement {
29 namespace CloudSync {
30 using namespace std;
31 using namespace NativeRdb;
32 using namespace DriveKit;
33 using namespace Media;
34 using PAC = Media::PhotoAlbumColumns;
35 using ChangeType = OHOS::AAFwk::ChangeInfo::ChangeType;
36 
AlbumDataHandler(int32_t userId,const std::string & bundleName,std::shared_ptr<RdbStore> rdb)37 AlbumDataHandler::AlbumDataHandler(int32_t userId, const std::string &bundleName, std::shared_ptr<RdbStore> rdb)
38     : RdbDataHandler(userId, bundleName, PAC::TABLE, rdb)
39 {
40 }
41 
GetFetchCondition(FetchCondition & cond)42 void AlbumDataHandler::GetFetchCondition(FetchCondition &cond)
43 {
44     cond.limitRes = LIMIT_SIZE;
45     cond.recordType = recordType_;
46     cond.desiredKeys = desiredKeys_;
47     cond.fullKeys = desiredKeys_;
48 }
49 
50 
QueryLocalMatch(const std::string & recordId)51 tuple<shared_ptr<ResultSet>, int> AlbumDataHandler::QueryLocalMatch(const std::string &recordId)
52 {
53     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PAC::TABLE);
54     predicates.EqualTo(PAC::ALBUM_CLOUD_ID, recordId);
55     auto resultSet = Query(predicates, ALBUM_LOCAL_QUERY_COLUMNS);
56     if (resultSet == nullptr) {
57         LOGE("get nullptr query result");
58         return {nullptr, 0};
59     }
60     int rowCount = 0;
61     int ret = resultSet->GetRowCount(rowCount);
62     if (ret != 0) {
63         LOGE("result set get row count err %{public}d", ret);
64         return {nullptr, 0};
65     }
66     return { move(resultSet), rowCount };
67 }
68 
InsertCloudAlbum(DKRecord & record)69 int32_t AlbumDataHandler::InsertCloudAlbum(DKRecord &record)
70 {
71     LOGI("insert of record %s", record.GetRecordId().c_str());
72 
73     ValuesBucket values;
74     int32_t ret = createConvertor_.RecordToValueBucket(record, values);
75     if (ret != E_OK) {
76         LOGE("record to value bucket failed, ret = %{public}d", ret);
77         return ret;
78     }
79     values.PutInt(PAC::ALBUM_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
80     values.PutString(PAC::ALBUM_CLOUD_ID, record.GetRecordId());
81 
82     /* update if a album with the same name exists? */
83     int64_t rowId;
84     ret = Insert(rowId, values);
85     if (ret != E_OK) {
86         LOGE("Insert pull record failed, rdb ret = %{public}d", ret);
87         return E_RDB;
88     }
89     return E_OK;
90 }
91 
DeleteCloudAlbum(DKRecord & record)92 int32_t AlbumDataHandler::DeleteCloudAlbum(DKRecord &record)
93 {
94     int32_t deletedRows;
95     int ret = Delete(deletedRows, PAC::ALBUM_CLOUD_ID + " = ?", { record.GetRecordId() });
96     if (ret != E_OK) {
97         LOGE("delete in rdb failed, ret: %{public}d", ret);
98         return E_INVAL_ARG;
99     }
100     return E_OK;
101 }
102 
UpdateCloudAlbum(DKRecord & record)103 int32_t AlbumDataHandler::UpdateCloudAlbum(DKRecord &record)
104 {
105     int32_t changedRows;
106     ValuesBucket values;
107     int32_t ret = createConvertor_.RecordToValueBucket(record, values);
108     if (ret != E_OK) {
109         LOGE("record to value bucket failed, ret = %{public}d", ret);
110         return ret;
111     }
112     values.PutInt(PAC::ALBUM_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
113 
114     ret = Update(changedRows, values, PAC::ALBUM_CLOUD_ID + " = ?", { record.GetRecordId() });
115     if (ret != E_OK) {
116         LOGE("rdb update failed, err = %{public}d", ret);
117         return E_RDB;
118     }
119     return E_OK;
120 }
121 
GetLocalMatchDirty(NativeRdb::ResultSet & resultSet)122 static int32_t GetLocalMatchDirty(NativeRdb::ResultSet &resultSet)
123 {
124     int32_t dirty;
125     int32_t ret = DataConvertor::GetInt(PAC::ALBUM_DIRTY, dirty, resultSet);
126     if (ret != E_OK) {
127         LOGE("fail to get album dirty value");
128         /* assume dirty so that no follow-up actions */
129         return static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY);
130     }
131     return dirty;
132 }
133 
HandleLocalDirty(int32_t dirty,const DriveKit::DKRecord & record)134 int32_t AlbumDataHandler::HandleLocalDirty(int32_t dirty, const DriveKit::DKRecord &record)
135 {
136     /* new -> dirty: keep local info and update cloud's */
137     if (dirty == static_cast<int32_t>(Media::DirtyType::TYPE_NEW)) {
138         int32_t changedRows;
139         ValuesBucket values;
140         values.PutInt(PAC::ALBUM_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY));
141         int32_t ret = Update(changedRows, values, PAC::ALBUM_NAME + " = ?", { record.GetRecordId() });
142         if (ret != E_OK) {
143             LOGE("rdb update failed, err = %{public}d", ret);
144             return E_RDB;
145         }
146         return E_OK;
147     }
148     return E_OK;
149 }
150 
OnFetchRecords(shared_ptr<vector<DKRecord>> & records,OnFetchParams & params)151 int32_t AlbumDataHandler::OnFetchRecords(shared_ptr<vector<DKRecord>> &records,
152                                          OnFetchParams &params)
153 {
154     LOGI("on fetch %{public}zu records", records->size());
155     int32_t ret = E_OK;
156     for (auto &record : *records) {
157         auto [resultSet, rowCount] = QueryLocalMatch(record.GetRecordId());
158         if (resultSet == nullptr) {
159             LOGE("get nullptr query result");
160             continue;
161         }
162         /* need to handle album cover uri */
163         if (rowCount == 0) {
164             if (!record.GetIsDelete()) {
165                 /* insert */
166                 ret = InsertCloudAlbum(record);
167             }
168         } else if (rowCount == 1) {
169             resultSet->GoToNextRow();
170             int32_t dirty = GetLocalMatchDirty(*resultSet);
171             if (dirty != static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED)) {
172                 /* local dirty */
173                 ret = HandleLocalDirty(dirty, record);
174             } else if (record.GetIsDelete()) {
175                 /* delete */
176                 ret = DeleteCloudAlbum(record);
177             } else {
178                 /* update */
179                 ret = UpdateCloudAlbum(record);
180             }
181         } else {
182             /* invalid cases */
183             LOGE("recordId %s rowCount %{public}d", record.GetRecordId().c_str(), rowCount);
184         }
185 
186         /* check ret */
187         if (ret != E_OK) {
188             LOGE("recordId %s error %{public}d", record.GetRecordId().c_str(), ret);
189             if (ret == E_STOP) {
190                 return E_STOP;
191             }
192             continue;
193         } else {
194             /* notify */
195             (void)DataSyncNotifier::GetInstance().TryNotify(DataSyncConst::ALBUM_URI_PREFIX,
196                 ChangeType::UPDATE, DataSyncConst::INVALID_ID);
197         }
198     }
199     (void)DataSyncNotifier::GetInstance().FinalNotify();
200     return E_OK;
201 }
202 
GetRetryRecords(std::vector<DriveKit::DKRecordId> & records)203 int32_t AlbumDataHandler::GetRetryRecords(std::vector<DriveKit::DKRecordId> &records)
204 {
205     return E_OK;
206 }
207 
Clean(const int action)208 int32_t AlbumDataHandler::Clean(const int action)
209 {
210     return E_OK;
211 }
212 
GetCreatedRecords(vector<DKRecord> & records)213 int32_t AlbumDataHandler::GetCreatedRecords(vector<DKRecord> &records)
214 {
215     /* build predicates */
216     auto createPredicates = NativeRdb::AbsRdbPredicates(PAC::TABLE);
217     createPredicates.EqualTo(PAC::ALBUM_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_NEW)));
218     /* skip system albums */
219     createPredicates.And()->EqualTo(PAC::ALBUM_SUBTYPE, to_string(Media::PhotoAlbumSubType::USER_GENERIC));
220     if (!createFailSet_.empty()) {
221         createPredicates.And()->NotIn(PAC::ALBUM_NAME, createFailSet_);
222     }
223     createPredicates.Limit(LIMIT_SIZE);
224 
225     /* query */
226     auto results = Query(createPredicates, GALLERY_ALBUM_COLUMNS);
227     if (results == nullptr) {
228         LOGE("get nullptr created result");
229         return E_RDB;
230     }
231 
232     /* results to records */
233     int ret = createConvertor_.ResultSetToRecords(move(results), records);
234     if (ret != 0) {
235         LOGE("result set to records err %{public}d", ret);
236         return ret;
237     }
238 
239     return E_OK;
240 }
241 
GetDeletedRecords(vector<DKRecord> & records)242 int32_t AlbumDataHandler::GetDeletedRecords(vector<DKRecord> &records)
243 {
244     /* build predicates */
245     auto createPredicates = NativeRdb::AbsRdbPredicates(PAC::TABLE);
246     createPredicates.EqualTo(PAC::ALBUM_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_DELETED)));
247     /* skip system albums */
248     createPredicates.And()->EqualTo(PAC::ALBUM_SUBTYPE, to_string(Media::PhotoAlbumSubType::USER_GENERIC));
249     if (!modifyFailSet_.empty()) {
250         createPredicates.And()->NotIn(PAC::ALBUM_NAME, modifyFailSet_);
251     }
252     createPredicates.Limit(LIMIT_SIZE);
253 
254     /* query */
255     auto results = Query(createPredicates, GALLERY_ALBUM_COLUMNS);
256     if (results == nullptr) {
257         LOGE("get nullptr created result");
258         return E_RDB;
259     }
260 
261     /* results to records */
262     int ret = deleteConvertor_.ResultSetToRecords(move(results), records);
263     if (ret != 0) {
264         LOGE("result set to records err %{public}d", ret);
265         return ret;
266     }
267 
268     return E_OK;
269 }
270 
GetMetaModifiedRecords(vector<DKRecord> & records)271 int32_t AlbumDataHandler::GetMetaModifiedRecords(vector<DKRecord> &records)
272 {
273     /* build predicates */
274     auto createPredicates = NativeRdb::AbsRdbPredicates(PAC::TABLE);
275     createPredicates.EqualTo(PAC::ALBUM_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY)));
276     /* skip system albums */
277     createPredicates.And()->EqualTo(PAC::ALBUM_SUBTYPE, to_string(Media::PhotoAlbumSubType::USER_GENERIC));
278     if (!modifyFailSet_.empty()) {
279         createPredicates.And()->NotIn(PAC::ALBUM_NAME, modifyFailSet_);
280     }
281     createPredicates.Limit(LIMIT_SIZE);
282 
283     /* query */
284     auto results = Query(createPredicates, GALLERY_ALBUM_COLUMNS);
285     if (results == nullptr) {
286         LOGE("get nullptr created result");
287         return E_RDB;
288     }
289 
290     /* results to records */
291     int ret = modifyConvertor_.ResultSetToRecords(move(results), records);
292     if (ret != 0) {
293         LOGE("result set to records err %{public}d", ret);
294         return ret;
295     }
296 
297     return E_OK;
298 }
299 
OnCreateRecords(const map<DKRecordId,DKRecordOperResult> & map)300 int32_t AlbumDataHandler::OnCreateRecords(const map<DKRecordId, DKRecordOperResult> &map)
301 {
302     int32_t ret = E_OK;
303     for (auto &entry : map) {
304         int32_t err;
305         const DKRecordOperResult &result = entry.second;
306         if (result.IsSuccess()) {
307             err = OnCreateSuccess(entry);
308         } else {
309             err = OnCreateFail(entry);
310         }
311         if (err == E_STOP) {
312             ret = E_STOP;
313         }
314     }
315     return ret;
316 }
317 
OnDeleteRecords(const map<DKRecordId,DKRecordOperResult> & map)318 int32_t AlbumDataHandler::OnDeleteRecords(const map<DKRecordId, DKRecordOperResult> &map)
319 {
320     int32_t ret = E_OK;
321     for (auto &entry : map) {
322         int32_t err;
323         const DKRecordOperResult &result = entry.second;
324         if (result.IsSuccess()) {
325             err = OnDeleteSuccess(entry);
326         } else {
327             err = OnCreateFail(entry);
328         }
329         if (err == E_STOP) {
330             ret = E_STOP;
331         }
332     }
333     return ret;
334 }
335 
OnModifyMdirtyRecords(const map<DKRecordId,DKRecordOperResult> & map)336 int32_t AlbumDataHandler::OnModifyMdirtyRecords(const map<DKRecordId, DKRecordOperResult> &map)
337 {
338     int32_t ret = E_OK;
339     for (auto &entry : map) {
340         int32_t err;
341         const DKRecordOperResult &result = entry.second;
342         if (result.IsSuccess()) {
343             err = OnUploadSuccess(entry);
344         } else {
345             err = OnCreateFail(entry);
346         }
347         if (err == E_STOP) {
348             ret = E_STOP;
349         }
350     }
351     return ret;
352 }
353 
GetAlbumNameFromRecord(const DriveKit::DKRecordOperResult & result)354 static inline string GetAlbumNameFromRecord(const DriveKit::DKRecordOperResult &result)
355 {
356     auto record = result.GetDKRecord();
357     DKRecordData data;
358     record.GetRecordData(data);
359     return data[ALBUM_NAME];
360 }
361 
OnCreateSuccess(const pair<DriveKit::DKRecordId,DriveKit::DKRecordOperResult> & entry)362 int32_t AlbumDataHandler::OnCreateSuccess(const pair<DriveKit::DKRecordId,
363     DriveKit::DKRecordOperResult> &entry)
364 {
365     ValuesBucket valuesBucket;
366     int32_t changedRows;
367     string whereClause = PAC::ALBUM_NAME + " = ?";
368     vector<string> whereArgs = { GetAlbumNameFromRecord(entry.second) };
369     valuesBucket.PutInt(PAC::ALBUM_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
370     valuesBucket.PutString(PAC::ALBUM_CLOUD_ID, entry.first);
371     int32_t ret = Update(changedRows, valuesBucket, whereClause, whereArgs);
372     if (ret != 0) {
373         LOGE("update local records err %{public}d", ret);
374         return ret;
375     }
376     return E_OK;
377 }
378 
OnUploadSuccess(const pair<DriveKit::DKRecordId,DriveKit::DKRecordOperResult> & entry)379 int32_t AlbumDataHandler::OnUploadSuccess(const pair<DriveKit::DKRecordId,
380     DriveKit::DKRecordOperResult> &entry)
381 {
382     ValuesBucket valuesBucket;
383     int32_t changedRows;
384     string whereClause = PAC::ALBUM_CLOUD_ID + " = ?";
385     vector<string> whereArgs = { entry.first };
386     valuesBucket.PutInt(PAC::ALBUM_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
387     int32_t ret = Update(changedRows, valuesBucket, whereClause, whereArgs);
388     if (ret != 0) {
389         LOGE("update local records err %{public}d", ret);
390         return ret;
391     }
392     return E_OK;
393 }
394 
OnDeleteSuccess(const pair<DriveKit::DKRecordId,DriveKit::DKRecordOperResult> & entry)395 int32_t AlbumDataHandler::OnDeleteSuccess(const pair<DriveKit::DKRecordId,
396     DriveKit::DKRecordOperResult> &entry)
397 {
398     int32_t deletedRows;
399     string whereClause = PAC::ALBUM_CLOUD_ID + " = ?";
400     vector<string> whereArgs = { entry.first };
401     int32_t ret = Delete(deletedRows, whereClause, whereArgs);
402     if (ret != 0) {
403         LOGE("delete local records err %{public}d", ret);
404         return ret;
405     }
406     return E_OK;
407 }
408 
OnCreateFail(const pair<DriveKit::DKRecordId,DriveKit::DKRecordOperResult> & entry)409 int32_t AlbumDataHandler::OnCreateFail(const pair<DriveKit::DKRecordId,
410     DriveKit::DKRecordOperResult> &entry)
411 {
412     createFailSet_.push_back(entry.first);
413     return E_OK;
414 }
415 
OnDeleteFail(const pair<DriveKit::DKRecordId,DriveKit::DKRecordOperResult> & entry)416 int32_t AlbumDataHandler::OnDeleteFail(const pair<DriveKit::DKRecordId,
417     DriveKit::DKRecordOperResult> &entry)
418 {
419     modifyFailSet_.push_back(entry.first);
420     return E_OK;
421 }
422 
OnModifyFail(const pair<DriveKit::DKRecordId,DriveKit::DKRecordOperResult> & entry)423 int32_t AlbumDataHandler::OnModifyFail(const pair<DriveKit::DKRecordId,
424     DriveKit::DKRecordOperResult> &entry)
425 {
426     modifyFailSet_.push_back(entry.first);
427     return E_OK;
428 }
429 
Reset()430 void AlbumDataHandler::Reset()
431 {
432     modifyFailSet_.clear();
433     createFailSet_.clear();
434 }
435 
SetChecking()436 void AlbumDataHandler::SetChecking()
437 {
438     ClearCursor();
439 }
440 } // namespace CloudSync
441 } // namespace FileManagement
442 } // namespace OHOS
443