• 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 "file_data_handler.h"
17 
18 #include <cstring>
19 #include <filesystem>
20 #include <tuple>
21 #include <set>
22 
23 #include <dirent.h>
24 #include <sys/ioctl.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <utime.h>
28 
29 #include "thumbnail_const.h"
30 #include "data_sync_const.h"
31 #include "dfs_error.h"
32 #include "directory_ex.h"
33 #include "dk_assets_downloader.h"
34 #include "dk_error.h"
35 #include "utils_log.h"
36 #include "gallery_album_const.h"
37 #include "gallery_file_const.h"
38 #include "meta_file.h"
39 
40 namespace OHOS {
41 namespace FileManagement {
42 namespace CloudSync {
43 using namespace std;
44 using namespace NativeRdb;
45 using namespace DriveKit;
46 using namespace Media;
47 using ChangeType = OHOS::AAFwk::ChangeInfo::ChangeType;
48 using PAC = Media::PhotoAlbumColumns;
49 using PM = Media::PhotoMap;
50 using PC = Media::PhotoColumn;
51 
52 constexpr int DEFAULT_DOWNLOAD_THUMB_LIMIT = 500;
FileDataHandler(int32_t userId,const string & bundleName,std::shared_ptr<RdbStore> rdb)53 FileDataHandler::FileDataHandler(int32_t userId, const string &bundleName, std::shared_ptr<RdbStore> rdb)
54     : RdbDataHandler(userId, bundleName, TABLE_NAME, rdb), userId_(userId), bundleName_(bundleName)
55 {
56     cloudPrefImpl_.GetInt(DOWNLOAD_THUMB_LIMIT, downloadThumbLimit_);
57     if (downloadThumbLimit_ <= 0) {
58         downloadThumbLimit_ = DEFAULT_DOWNLOAD_THUMB_LIMIT;
59         cloudPrefImpl_.SetInt(DOWNLOAD_THUMB_LIMIT, downloadThumbLimit_);
60     }
61 }
62 
GetFetchCondition(FetchCondition & cond)63 void FileDataHandler::GetFetchCondition(FetchCondition &cond)
64 {
65     cond.limitRes = LIMIT_SIZE;
66     cond.recordType = recordType_;
67     if (isChecking_) {
68         cond.desiredKeys = checkedKeys_;
69     } else {
70         cond.desiredKeys = desiredKeys_;
71     }
72     cond.fullKeys = desiredKeys_;
73 }
74 
GetRetryRecords(std::vector<DriveKit::DKRecordId> & records)75 int32_t FileDataHandler::GetRetryRecords(std::vector<DriveKit::DKRecordId> &records)
76 {
77     NativeRdb::AbsRdbPredicates retryPredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
78     retryPredicates.SetWhereClause(PhotoColumn::PHOTO_DIRTY + " = ? AND " + PhotoColumn::MEDIA_DATE_TRASHED + " = ?");
79     retryPredicates.SetWhereArgs({to_string(static_cast<int32_t>(DirtyType::TYPE_RETRY)), "0"});
80     retryPredicates.Limit(LIMIT_SIZE);
81 
82     auto results = Query(retryPredicates, {PhotoColumn::PHOTO_CLOUD_ID});
83     if (results == nullptr) {
84         LOGE("get nullptr modified result");
85         return E_RDB;
86     }
87 
88     while (results->GoToNextRow() == 0) {
89         string record;
90         int ret = DataConvertor::GetString(PhotoColumn::PHOTO_CLOUD_ID, record, *results);
91         if (ret == E_OK) {
92             records.emplace_back(record);
93         }
94     }
95 
96     return E_OK;
97 }
98 
AppendToDownload(NativeRdb::ResultSet & local,const std::string & fieldKey,std::vector<DKDownloadAsset> & assetsToDownload)99 void FileDataHandler::AppendToDownload(NativeRdb::ResultSet &local,
100                                        const std::string &fieldKey,
101                                        std::vector<DKDownloadAsset> &assetsToDownload)
102 {
103     DKDownloadAsset downloadAsset;
104     downloadAsset.recordType = recordType_;
105     downloadAsset.fieldKey = fieldKey;
106     string filePath;
107     int ret = DataConvertor::GetString(PhotoColumn::MEDIA_FILE_PATH, filePath, local);
108     if (ret != E_OK) {
109         LOGE("Get file path failed");
110         return;
111     }
112     string recordId;
113     ret = DataConvertor::GetString(PhotoColumn::PHOTO_CLOUD_ID, recordId, local);
114     if (ret != E_OK) {
115         LOGE("cannot get cloud_id fron result set");
116         return;
117     }
118     downloadAsset.recordId = recordId;
119 
120     const string &suffix = (fieldKey == "lcd") ? LCD_SUFFIX : THUMB_SUFFIX;
121     downloadAsset.downLoadPath = createConvertor_.GetThumbPath(filePath, suffix);
122     downloadAsset.asset.assetName = MetaFile::GetFileName(downloadAsset.downLoadPath);
123     downloadAsset.downLoadPath = MetaFile::GetParentDir(downloadAsset.downLoadPath);
124     ForceCreateDirectory(downloadAsset.downLoadPath);
125     assetsToDownload.push_back(downloadAsset);
126 }
127 
GetAssetsToDownload(vector<DriveKit::DKDownloadAsset> & outAssetsToDownload)128 int32_t FileDataHandler::GetAssetsToDownload(vector<DriveKit::DKDownloadAsset> &outAssetsToDownload)
129 {
130     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
131     predicates.EqualTo(Media::PhotoColumn::PHOTO_SYNC_STATUS,
132                        to_string(static_cast<int32_t>(SyncStatusType::TYPE_DOWNLOAD)));
133     auto results = Query(predicates, MEDIA_CLOUD_SYNC_COLUMNS);
134     if (results == nullptr) {
135         LOGE("get nullptr TYPE_DOWNLOAD result");
136         return E_RDB;
137     }
138 
139     while (results->GoToNextRow() == 0) {
140         AppendToDownload(*results, "lcd", outAssetsToDownload);
141         AppendToDownload(*results, "thumbnail", outAssetsToDownload);
142     }
143     return E_OK;
144 }
145 
146 const std::vector<std::string> PULL_QUERY_COLUMNS = {
147     PhotoColumn::MEDIA_FILE_PATH,
148     PhotoColumn::MEDIA_SIZE,
149     PhotoColumn::MEDIA_DATE_MODIFIED,
150     PhotoColumn::PHOTO_DIRTY,
151     PhotoColumn::MEDIA_DATE_TRASHED,
152     PhotoColumn::PHOTO_POSITION,
153     PhotoColumn::PHOTO_CLOUD_ID,
154     PhotoColumn::PHOTO_CLOUD_VERSION,
155     MediaColumn::MEDIA_ID,
156     PhotoColumn::MEDIA_RELATIVE_PATH,
157     PhotoColumn::MEDIA_DATE_ADDED,
158 };
159 
QueryLocalByCloudId(const string & recordId)160 tuple<shared_ptr<NativeRdb::ResultSet>, int> FileDataHandler::QueryLocalByCloudId(const string &recordId)
161 {
162     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
163     predicates.EqualTo(PhotoColumn::PHOTO_CLOUD_ID, recordId);
164     auto resultSet = Query(predicates, PULL_QUERY_COLUMNS);
165     if (resultSet == nullptr) {
166         LOGE("get nullptr created result");
167         return {nullptr, 0};
168     }
169     int rowCount = 0;
170     int ret = resultSet->GetRowCount(rowCount);
171     if (ret != 0 || rowCount < 0) {
172         LOGE("result set get row count err %{public}d, rowCount %{public}d", ret, rowCount);
173         return {nullptr, rowCount};
174     }
175     return {std::move(resultSet), rowCount};
176 }
177 
178 const std::vector<std::string> CLEAN_QUERY_COLUMNS = {
179     PhotoColumn::MEDIA_FILE_PATH,
180     PhotoColumn::PHOTO_DIRTY,
181     PhotoColumn::MEDIA_DATE_TRASHED,
182     PhotoColumn::PHOTO_POSITION,
183     PhotoColumn::PHOTO_CLOUD_ID,
184 };
185 
186 
GetFileId(NativeRdb::ResultSet & local)187 static int32_t GetFileId(NativeRdb::ResultSet &local)
188 {
189     int32_t fileId;
190     int ret = DataConvertor::GetInt(MediaColumn::MEDIA_ID, fileId, local);
191     if (ret != E_OK) {
192         LOGE("Get file id failed");
193         return 0; // 0:invalid file id, not exits in db
194     }
195     return fileId;
196 }
197 
OnFetchRecords(shared_ptr<vector<DKRecord>> & records,OnFetchParams & params)198 int32_t FileDataHandler::OnFetchRecords(shared_ptr<vector<DKRecord>> &records, OnFetchParams &params)
199 {
200     LOGI("on fetch %{public}zu records", records->size());
201     int32_t ret = E_OK;
202     for (auto &record : *records) {
203         auto [resultSet, rowCount] = QueryLocalByCloudId(record.GetRecordId());
204         if (resultSet == nullptr || rowCount < 0) {
205             return E_RDB;
206         }
207         int32_t fileId = 0;
208         ChangeType changeType = ChangeType::INVAILD;
209         if ((rowCount == 0) && !record.GetIsDelete()) {
210             CompensateFilePath(record);
211             ret = PullRecordInsert(record, params);
212             InsertAssetToPhotoMap(record, params);
213         } else if (rowCount == 1) {
214             resultSet->GoToNextRow();
215             if (record.GetIsDelete()) {
216                 ret = PullRecordDelete(record, *resultSet);
217                 fileId = GetFileId(*resultSet);
218                 changeType = ChangeType::DELETE;
219             } else {
220                 ret = PullRecordUpdate(record, *resultSet, params);
221                 fileId = GetFileId(*resultSet);
222                 changeType = ChangeType::UPDATE;
223                 UpdateAssetInPhotoMap(record, fileId);
224             }
225         }
226         if (ret != E_OK) {
227             LOGE("recordId %s error %{public}d", record.GetRecordId().c_str(), ret);
228             if (ret == E_RDB) {
229                 break;
230             }
231             ret = E_OK;
232         }
233         string notifyUri = DataSyncConst::PHOTO_URI_PREFIX + to_string(fileId);
234         DataSyncNotifier::GetInstance().TryNotify(notifyUri, changeType, to_string(fileId));
235     }
236     LOGI("before BatchInsert size len %{public}zu, map size %{public}zu", params.insertFiles.size(),
237          params.recordAlbumMaps.size());
238     if (!params.insertFiles.empty() || !params.recordAlbumMaps.empty()) {
239         int64_t rowId;
240         ret = BatchInsert(rowId, TABLE_NAME, params.insertFiles);
241         if (ret != E_OK) {
242             LOGE("batch insert failed return %{public}d", ret);
243             ret = E_RDB;
244             params.assetsToDownload.clear();
245         } else {
246             BatchInsertAssetMaps(params);
247             DataSyncNotifier::GetInstance().TryNotify(DataSyncConst::PHOTO_URI_PREFIX, ChangeType::INSERT,
248                                                       DataSyncConst::INVALID_ID);
249         }
250     }
251     LOGI("after BatchInsert ret %{public}d", ret);
252     DataSyncNotifier::GetInstance().FinalNotify();
253     MetaFileMgr::GetInstance().ClearAll();
254     return ret;
255 }
256 
CompensateFilePath(DriveKit::DKRecord & record)257 int32_t FileDataHandler::CompensateFilePath(DriveKit::DKRecord &record)
258 {
259     DKRecordData data;
260     record.GetRecordData(data);
261     if (data.find(FILE_ATTRIBUTES) == data.end() || data.find(FILE_SIZE) == data.end()) {
262         LOGE("record data cannot find attributes or size");
263         return E_INVAL_ARG;
264     }
265     DriveKit::DKRecordFieldMap attributes;
266     data[FILE_ATTRIBUTES].GetRecordMap(attributes);
267     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end()) {
268         LOGE("record data cannot find some attributes, may came from old devices");
269         string fullPath;
270         int ret = CalculateFilePath(record, fullPath);
271         if (ret != E_OK) {
272             return ret;
273         }
274         attributes[PhotoColumn::MEDIA_FILE_PATH] = DriveKit::DKRecordField(fullPath);
275         data[FILE_ATTRIBUTES] = DriveKit::DKRecordField(attributes);
276         record.SetRecordData(data);
277     }
278     return E_OK;
279 }
280 
GetDentryPathName(const string & fullPath,string & outPath,string & outFilename)281 static int GetDentryPathName(const string &fullPath, string &outPath, string &outFilename)
282 {
283     const string sandboxPrefix = "/storage/cloud";
284     size_t pos = fullPath.find_first_of(sandboxPrefix);
285     size_t lpos = fullPath.find_last_of("/");
286     if (pos != 0 || pos == string::npos || lpos == string::npos) {
287         LOGE("invalid path %{private}s", fullPath.c_str());
288         return E_INVAL_ARG;
289     }
290 
291     outPath = fullPath.substr(sandboxPrefix.length(), lpos - sandboxPrefix.length());
292     outPath = (outPath == "") ? "/" : outPath;
293     outFilename = fullPath.substr(lpos + 1);
294     return E_OK;
295 }
296 
DentryInsert(int userId,const DKRecord & record)297 static int32_t DentryInsert(int userId, const DKRecord &record)
298 {
299     DKRecordData data;
300     record.GetRecordData(data);
301     if (data.find(FILE_ATTRIBUTES) == data.end() || data.find(FILE_SIZE) == data.end()) {
302         LOGE("record data cannot find attributes or size");
303         return E_INVAL_ARG;
304     }
305     DriveKit::DKRecordFieldMap attibutes;
306     data[FILE_ATTRIBUTES].GetRecordMap(attibutes);
307     if (attibutes.find(PhotoColumn::MEDIA_FILE_PATH) == attibutes.end()) {
308         LOGE("record data cannot find some attributes");
309         return E_OK;
310     }
311 
312     string fullPath;
313     string relativePath;
314     string fileName;
315     if (attibutes[PhotoColumn::MEDIA_FILE_PATH].GetString(fullPath) != DKLocalErrorCode::NO_ERROR) {
316         LOGE("bad file_path in props");
317         return E_INVAL_ARG;
318     }
319     if (GetDentryPathName(fullPath, relativePath, fileName) != E_OK) {
320         LOGE("split to dentry path failed, path:%s", fullPath.c_str());
321         return E_INVAL_ARG;
322     }
323 
324     int64_t isize;
325     if (DataConvertor::GetLongComp(data[PhotoColumn::MEDIA_SIZE], isize) != E_OK) {
326         LOGE("bad size in props");
327         return E_INVAL_ARG;
328     }
329     int64_t mtime = static_cast<int64_t>(record.GetEditedTime()) / MILLISECOND_TO_SECOND;
330     string rawRecordId = record.GetRecordId();
331     string cloudId = MetaFileMgr::RecordIdToCloudId(rawRecordId);
332     auto mFile = MetaFileMgr::GetInstance().GetMetaFile(userId, relativePath);
333     MetaBase mBaseLookup(fileName);
334     MetaBase mBase(fileName, cloudId);
335     mBase.size = static_cast<uint64_t>(isize);
336     mBase.mtime = static_cast<uint64_t>(mtime);
337     if (mFile->DoLookup(mBaseLookup) == E_OK) {
338         LOGE("dentry exist when insert, do update instead");
339         return mFile->DoUpdate(mBase);
340     }
341     return mFile->DoCreate(mBase);
342 }
343 
DentryInsertThumb(const string & fullPath,const string & recordId,uint64_t size,uint64_t mtime,const string & type)344 int FileDataHandler::DentryInsertThumb(const string &fullPath,
345                                        const string &recordId,
346                                        uint64_t size,
347                                        uint64_t mtime,
348                                        const string &type)
349 {
350     string thumbnailPath = createConvertor_.GetThumbPathInCloud(fullPath, type);
351     string relativePath;
352     string fileName;
353     if (GetDentryPathName(thumbnailPath, relativePath, fileName) != E_OK) {
354         LOGE("split to dentry path failed, path:%s", thumbnailPath.c_str());
355         return E_INVAL_ARG;
356     }
357 
358     string cloudId = MetaFileMgr::RecordIdToCloudId(recordId);
359     auto mFile = MetaFileMgr::GetInstance().GetMetaFile(userId_, relativePath);
360     MetaBase mBaseLookup(fileName);
361     MetaBase mBase(fileName, cloudId);
362     mBase.size = size;
363     mBase.mtime = mtime;
364     mBase.fileType = (type == THUMB_SUFFIX) ? FILE_TYPE_THUMBNAIL : FILE_TYPE_LCD;
365     if (mFile->DoLookup(mBaseLookup) == E_OK) {
366         LOGI("dentry exist when insert, do update instead");
367         return mFile->DoUpdate(mBase);
368     }
369     return mFile->DoCreate(mBase);
370 }
371 
DentryRemoveThumb(const string & downloadPath)372 int FileDataHandler::DentryRemoveThumb(const string &downloadPath)
373 {
374     string thumbnailPath = createConvertor_.GetLocalPathToCloud(downloadPath);
375     string relativePath;
376     string fileName;
377     if (GetDentryPathName(thumbnailPath, relativePath, fileName) != E_OK) {
378         LOGE("split to dentry path failed, path:%s", thumbnailPath.c_str());
379         return E_INVAL_ARG;
380     }
381 
382     auto mFile = MetaFileMgr::GetInstance().GetMetaFile(userId_, relativePath);
383     MetaBase mBase(fileName, "");
384     return mFile->DoRemove(mBase);
385 }
386 
AddCloudThumbs(const DKRecord & record)387 int FileDataHandler::AddCloudThumbs(const DKRecord &record)
388 {
389     LOGI("thumbs of %s add to cloud_view", record.GetRecordId().c_str());
390     constexpr int64_t THUMB_SIZE = 2 * 1024 * 1024; // thumbnail and lcd size show as 2MB
391 
392     DKRecordData data;
393     record.GetRecordData(data);
394     if (data.find(FILE_ATTRIBUTES) == data.end()) {
395         LOGE("record data cannot find attributes");
396         return E_INVAL_ARG;
397     }
398     DriveKit::DKRecordFieldMap attributes;
399     data[FILE_ATTRIBUTES].GetRecordMap(attributes);
400 
401     string fullPath;
402     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end() ||
403         attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(fullPath) != DKLocalErrorCode::NO_ERROR) {
404         LOGE("bad file path in record");
405         return E_INVAL_ARG;
406     }
407     int64_t mtime = static_cast<int64_t>(record.GetCreateTime()) / MILLISECOND_TO_SECOND;
408     int ret = DentryInsertThumb(fullPath, record.GetRecordId(), THUMB_SIZE, mtime, THUMB_SUFFIX);
409     if (ret != E_OK) {
410         LOGE("dentry insert of thumb failed ret %{public}d", ret);
411         return ret;
412     }
413     ret = DentryInsertThumb(fullPath, record.GetRecordId(), THUMB_SIZE, mtime, LCD_SUFFIX);
414     if (ret != E_OK) {
415         LOGE("dentry insert of lcd failed ret %{public}d", ret);
416         return ret;
417     }
418     return E_OK;
419 }
420 
ConflictRenameThumb(NativeRdb::ResultSet & resultSet,string fullPath,string & tmpPath,string & newPath)421 string FileDataHandler::ConflictRenameThumb(NativeRdb::ResultSet &resultSet,
422                                             string fullPath,
423                                             string &tmpPath,
424                                             string &newPath)
425 {
426     /* thumb new path */
427     tmpPath = cleanConvertor_.GetThumbPath(fullPath, THUMB_SUFFIX);
428     if (tmpPath == "") {
429         LOGE("err tmp Path for GetThumbPath");
430         return "";
431     }
432     size_t tmpfound = tmpPath.find_last_of('/');
433     if (tmpfound == string::npos) {
434         LOGE("err tmp Path found");
435         return "";
436     }
437     tmpPath.resize(tmpfound);
438     size_t found = tmpPath.find_last_of('.');
439     if (found == string::npos) {
440         LOGE("err thumb Path found");
441         return "";
442     }
443     newPath = tmpPath.substr(0, found) + CON_SUFFIX + tmpPath.substr(found);
444     /* new name */
445     size_t namefound = newPath.find_last_of('/');
446     if (namefound == string::npos) {
447         LOGE("err name Path found");
448         return "";
449     }
450     string newName = newPath.substr(namefound + 1);
451     return newName;
452 }
453 
ConflictRenamePath(NativeRdb::ResultSet & resultSet,string & fullPath,string & rdbPath,string & localPath,string & newLocalPath)454 int32_t FileDataHandler::ConflictRenamePath(NativeRdb::ResultSet &resultSet,
455                                             string &fullPath,
456                                             string &rdbPath,
457                                             string &localPath,
458                                             string &newLocalPath)
459 {
460     /* sandbox new path */
461     size_t rdbfound = fullPath.find_last_of('.');
462     if (rdbfound == string::npos) {
463         LOGE("err rdb Path found");
464         return E_INVAL_ARG;
465     }
466     rdbPath = fullPath.substr(0, rdbfound) + CON_SUFFIX + fullPath.substr(rdbfound);
467     /* local new path */
468     localPath = cleanConvertor_.GetHmdfsLocalPath(fullPath);
469     if (localPath == "") {
470         LOGE("err local Path for GetHmdfsLocalPath");
471         return E_INVAL_ARG;
472     }
473     size_t localfound = localPath.find_last_of('.');
474     if (localfound == string::npos) {
475         LOGE("err local Path found");
476         return E_INVAL_ARG;
477     }
478     newLocalPath = localPath.substr(0, localfound) + CON_SUFFIX + localPath.substr(localfound);
479     return E_OK;
480 }
481 
ConflictRename(NativeRdb::ResultSet & resultSet,string & fullPath,string & relativePath)482 int32_t FileDataHandler::ConflictRename(NativeRdb::ResultSet &resultSet, string &fullPath, string &relativePath)
483 {
484     string rdbPath, newvirPath, tmpPath, newPath, localPath, newLocalPath;
485     int ret = ConflictRenamePath(resultSet, fullPath, rdbPath, tmpPath, newPath);
486     if (ret != E_OK) {
487         LOGE("ConflictRenamePath failed, ret=%{public}d", ret);
488         return E_INVAL_ARG;
489     }
490     /* thumb new path and new name */
491     string newName = ConflictRenameThumb(resultSet, fullPath, localPath, newLocalPath);
492     if (newName == "") {
493         LOGE("err Rename Thumb path");
494         return E_INVAL_ARG;
495     }
496     int updateRows;
497     ValuesBucket values;
498     values.PutString(PhotoColumn::MEDIA_FILE_PATH, rdbPath);
499     values.PutString(PhotoColumn::MEDIA_NAME, newName);
500     if (!relativePath.empty()) {
501         newvirPath = relativePath + newName;
502         values.PutString(PhotoColumn::MEDIA_VIRTURL_PATH, newvirPath);
503     }
504     string whereClause = PhotoColumn::MEDIA_FILE_PATH + " = ?";
505     ret = Update(updateRows, values, whereClause, {fullPath});
506     if (ret != E_OK) {
507         LOGE("update retry flag failed, ret=%{public}d", ret);
508         return E_RDB;
509     }
510     ret = rename(tmpPath.c_str(), newPath.c_str());
511     if (ret != 0) {
512         LOGE("err rename localPath to newLocalPath, ret = %{public}d", ret);
513         return E_INVAL_ARG;
514     }
515     ret = rename(localPath.c_str(), newLocalPath.c_str());
516     if (ret != 0) {
517         LOGE("err rename tmpPath to newPath, ret = %{public}d", ret);
518         return E_INVAL_ARG;
519     }
520     return E_OK;
521 }
522 
ConflictDataMerge(const DKRecord & record,string & fullPath)523 int32_t FileDataHandler::ConflictDataMerge(const DKRecord &record, string &fullPath)
524 {
525     int updateRows;
526     ValuesBucket values;
527     values.PutString(PhotoColumn::PHOTO_CLOUD_ID, record.GetRecordId());
528     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_SYNCED));
529     values.PutInt(PhotoColumn::PHOTO_POSITION, POSITION_BOTH);
530 
531     string whereClause = PhotoColumn::MEDIA_FILE_PATH + " = ?";
532     int32_t ret = Update(updateRows, values, whereClause, {fullPath});
533     if (ret != E_OK) {
534         LOGE("update retry flag failed, ret=%{public}d", ret);
535         return E_RDB;
536     }
537     return E_OK;
538 }
539 
ConflictHandler(NativeRdb::ResultSet & resultSet,int64_t isize,int64_t crTime,bool & modifyPathflag)540 int32_t FileDataHandler::ConflictHandler(NativeRdb::ResultSet &resultSet,
541                                          int64_t isize,
542                                          int64_t crTime,
543                                          bool &modifyPathflag)
544 {
545     string localId;
546     int ret = DataConvertor::GetString(PhotoColumn::PHOTO_CLOUD_ID, localId, resultSet);
547     if (ret != E_OK) {
548         LOGE("Get cloud id failed");
549         return E_INVAL_ARG;
550     }
551     if (ret == E_OK && !localId.empty()) {
552         LOGI("clould id not NULL %{public}s", localId.c_str());
553         modifyPathflag = true;
554     }
555     int64_t localIsize = 0;
556     ret = DataConvertor::GetLong(PhotoColumn::MEDIA_SIZE, localIsize, resultSet);
557     if (ret != E_OK) {
558         LOGE("Get local isize failed");
559         return E_INVAL_ARG;
560     }
561     int64_t localCrtime = 0;
562     ret = DataConvertor::GetLong(PhotoColumn::MEDIA_DATE_ADDED, localCrtime, resultSet);
563     if (ret != E_OK) {
564         LOGE("Get local ctime failed");
565         return E_INVAL_ARG;
566     }
567     if (localIsize == isize && localCrtime == crTime) {
568         LOGI("Possible duplicate files");
569     } else {
570         modifyPathflag = true;
571     }
572     return E_OK;
573 }
574 
ConflictMerge(NativeRdb::ResultSet & resultSet,const DKRecord & record,string & fullPath,string & relativePath)575 int32_t FileDataHandler::ConflictMerge(NativeRdb::ResultSet &resultSet,
576                                        const DKRecord &record,
577                                        string &fullPath,
578                                        string &relativePath)
579 {
580     LOGI("Different files with the same name");
581     /* Modify path */
582     int ret = ConflictRename(resultSet, fullPath, relativePath);
583     if (ret != E_OK) {
584         LOGE("Conflict dataMerge rename fail");
585         return ret;
586     }
587     return E_OK;
588 }
589 
ConflictDownload(const DKRecord & record,string & fullPath,bool & comflag)590 int32_t FileDataHandler::ConflictDownload(const DKRecord &record,
591                                           string &fullPath,
592                                           bool &comflag)
593 {
594     LOGI("Unification of the same document");
595     /* update database */
596     int ret = ConflictDataMerge(record, fullPath);
597     if (ret != E_OK) {
598         LOGE("Conflict dataMerge fail");
599         return ret;
600     }
601     comflag = true;
602     return E_OK;
603 }
604 
GetConflictData(DKRecord & record,string & fullPath,int64_t & isize,int64_t & crTime,string & relativePath)605 int32_t FileDataHandler::GetConflictData(DKRecord &record,
606                                          string &fullPath,
607                                          int64_t &isize,
608                                          int64_t &crTime,
609                                          string &relativePath)
610 {
611     DKRecordData data;
612     record.GetRecordData(data);
613     if (data.find(FILE_ATTRIBUTES) == data.end() || data.find(FILE_SIZE) == data.end()) {
614         LOGE("record data cannot find attributes or size");
615         return E_INVAL_ARG;
616     }
617     DriveKit::DKRecordFieldMap attributes;
618     data[FILE_ATTRIBUTES].GetRecordMap(attributes);
619     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end()) {
620         LOGE("record data cannot find some attributes, may came from old devices");
621         return E_INVAL_ARG;
622     }
623     if (attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(fullPath) != DKLocalErrorCode::NO_ERROR) {
624         LOGE("bad file_path in attributes");
625         return E_INVAL_ARG;
626     }
627     if (attributes[PhotoColumn::MEDIA_RELATIVE_PATH].GetString(relativePath) != DKLocalErrorCode::NO_ERROR) {
628         LOGE("bad virtual_Path in attributes");
629         return E_INVAL_ARG;
630     }
631     if (DataConvertor::GetLongComp(data[PhotoColumn::MEDIA_SIZE], isize) != E_OK) {
632         LOGE("bad size in data");
633         return E_INVAL_ARG;
634     }
635     crTime = static_cast<int64_t>(record.GetCreateTime()) / MILLISECOND_TO_SECOND;
636     return E_OK;
637 }
638 
CalculateFilePath(DKRecord & record,string & filePath)639 int32_t FileDataHandler::CalculateFilePath(DKRecord &record, string &filePath)
640 {
641     // method reference from medialibrary
642     int32_t mediaType;
643     int32_t ret = GetMediaType(record, mediaType);
644     if (ret != E_OK) {
645         return E_INVAL_ARG;
646     }
647     int32_t uniqueId = GetAssetUniqueId(mediaType);
648     int32_t errCode = CreateAssetPathById(record, uniqueId, mediaType, filePath);
649     return errCode;
650 }
651 
GetMediaType(DKRecord & record,int32_t & mediaType)652 int32_t FileDataHandler::GetMediaType(DKRecord &record, int32_t &mediaType)
653 {
654     DKRecordData data;
655     record.GetRecordData(data);
656     if (data.find(FILE_FILETYPE) == data.end()) {
657         LOGE("record data cannot find properties");
658         return E_INVAL_ARG;
659     }
660     int32_t fileType;
661     if (data[FILE_FILETYPE].GetInt(fileType) != DKLocalErrorCode::NO_ERROR) {
662         LOGE("record data cannot find fileType");
663         return E_INVAL_ARG;
664     }
665     mediaType = fileType == FILE_TYPE_VIDEO ? MediaType::MEDIA_TYPE_VIDEO : MediaType::MEDIA_TYPE_IMAGE;
666     return E_OK;
667 }
668 
GetAssetUniqueId(int32_t & type)669 int32_t FileDataHandler::GetAssetUniqueId(int32_t &type)
670 {
671     string typeString;
672     switch (type) {
673         case MediaType::MEDIA_TYPE_IMAGE:
674             typeString += IMAGE_ASSET_TYPE;
675             break;
676         case MediaType::MEDIA_TYPE_VIDEO:
677             typeString += VIDEO_ASSET_TYPE;
678             break;
679         default:
680             LOGE("This type %{public}d can not get unique id", type);
681             return MediaType::MEDIA_TYPE_FILE;
682     }
683 
684     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(ASSET_UNIQUE_NUMBER_TABLE);
685     predicates.SetWhereClause(ASSET_MEDIA_TYPE + " = ?");
686     predicates.SetWhereArgs({typeString});
687     auto resultSet = Query(predicates, {UNIQUE_NUMBER});
688     int32_t uniqueId = 0;
689     if (resultSet->GoToNextRow() == 0) {
690         DataConvertor::GetInt(UNIQUE_NUMBER, uniqueId, *resultSet);
691     }
692     ++uniqueId;
693 
694     int updateRows;
695     ValuesBucket values;
696     values.PutInt(UNIQUE_NUMBER, uniqueId);
697     string whereClause = ASSET_MEDIA_TYPE + " = ?";
698     Update(updateRows, ASSET_UNIQUE_NUMBER_TABLE, values, whereClause, {typeString});
699     return uniqueId;
700 }
701 
CreateAssetPathById(DKRecord & record,int32_t & uniqueId,int32_t & mediaType,string & filePath)702 int32_t FileDataHandler::CreateAssetPathById(DKRecord &record, int32_t &uniqueId,
703     int32_t &mediaType, string &filePath)
704 {
705     string mediaDirPath = "Photo/";
706     int32_t bucketNum = 0;
707     int32_t errCode = CreateAssetBucket(uniqueId, bucketNum);
708     if (errCode != E_OK) {
709         return errCode;
710     }
711 
712     string realName;
713     errCode = CreateAssetRealName(uniqueId, mediaType, GetFileExtension(record), realName);
714     if (errCode != E_OK) {
715         return errCode;
716     }
717     string dirPath = ROOT_MEDIA_DIR + mediaDirPath + to_string(bucketNum);
718     filePath = dirPath + "/" + realName;
719     return E_OK;
720 }
721 
CreateAssetBucket(int32_t & uniqueId,int32_t & bucketNum)722 int32_t FileDataHandler::CreateAssetBucket(int32_t &uniqueId, int32_t &bucketNum)
723 {
724     if (uniqueId < 0) {
725         LOGE("input uniqueId [%{private}d] is invalid", uniqueId);
726         return E_INVAL_ARG;
727     }
728     int start = ASSET_DIR_START_NUM;
729     int divider = ASSET_DIR_START_NUM;
730     while (uniqueId > start * ASSET_IN_BUCKET_NUM_MAX) {
731         divider = start;
732         start <<= 1;
733     }
734 
735     int fileIdRemainder = uniqueId % divider;
736     if (fileIdRemainder == 0) {
737         bucketNum = start + fileIdRemainder;
738     } else {
739         bucketNum = (start - divider) + fileIdRemainder;
740     }
741     return E_OK;
742 }
743 
CreateAssetRealName(int32_t & fileId,int32_t & mediaType,const string & extension,string & name)744 int32_t FileDataHandler::CreateAssetRealName(int32_t &fileId, int32_t &mediaType,
745     const string &extension, string &name)
746 {
747     string fileNumStr = to_string(fileId);
748     if (fileId <= ASSET_MAX_COMPLEMENT_ID) {
749         size_t fileIdLen = fileNumStr.length();
750         fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
751     }
752 
753     string mediaTypeStr;
754     switch (mediaType) {
755         case MediaType::MEDIA_TYPE_IMAGE:
756             mediaTypeStr = DEFAULT_IMAGE_NAME;
757             break;
758         case MediaType::MEDIA_TYPE_VIDEO:
759             mediaTypeStr = DEFAULT_VIDEO_NAME;
760             break;
761         default:
762             LOGE("This mediatype %{public}d can not get real name", mediaType);
763             return E_INVAL_ARG;
764     }
765 
766     name = mediaTypeStr + to_string(UTCTimeSeconds()) + "_" + fileNumStr + "." + extension;
767     return E_OK;
768 }
769 
PullRecordConflict(DKRecord & record,bool & comflag)770 int32_t FileDataHandler::PullRecordConflict(DKRecord &record, bool &comflag)
771 {
772     LOGI("judgment downlode conflict");
773     string fullPath, relativePath;
774     int64_t isize, crTime;
775     bool modifyPathflag = false;
776     int32_t ret = GetConflictData(record, fullPath, isize, crTime, relativePath);
777     if (ret != E_OK) {
778         LOGE("Getdata fail");
779         return ret;
780     }
781     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
782     predicates.SetWhereClause(PhotoColumn::MEDIA_FILE_PATH + " = ?");
783     predicates.SetWhereArgs({fullPath});
784     predicates.Limit(LIMIT_SIZE);
785     auto resultSet = Query(predicates, PULL_QUERY_COLUMNS);
786     if (resultSet == nullptr) {
787         LOGE("get nullptr created result");
788         return E_RDB;
789     }
790     int32_t rowCount = 0;
791     ret = resultSet->GetRowCount(rowCount);
792     if (ret != 0) {
793         LOGE("result set get row count err %{public}d", ret);
794         return E_RDB;
795     }
796     if (rowCount == 0) {
797         LOGI("Normal download process");
798         return E_OK;
799     }
800     if (rowCount == 1) {
801         resultSet->GoToNextRow();
802         ret = ConflictHandler(*resultSet, isize, crTime, modifyPathflag);
803         if (ret != E_OK) {
804             return ret;
805         }
806         if (modifyPathflag) {
807             ret = ConflictMerge(*resultSet, record, fullPath, relativePath);
808         } else {
809             ret = ConflictDownload(record, fullPath, comflag);
810         }
811         if (comflag) {
812             UpdateAssetInPhotoMap(record, GetFileId(*resultSet));
813         }
814     } else {
815         LOGE("unknown error: PullRecordConflict(),same path rowCount = %{public}d", rowCount);
816         ret = E_RDB;
817     }
818     return ret;
819 }
820 
GetFileExtension(DKRecord & record)821 string FileDataHandler::GetFileExtension(DKRecord &record)
822 {
823     DKRecordData data;
824     record.GetRecordData(data);
825     if (data.find(FILE_FILE_NAME) == data.end()) {
826         LOGE("record data cannot find properties");
827         return "";
828     }
829     string displayName;
830     if (data[FILE_FILE_NAME].GetString(displayName) != DKLocalErrorCode::NO_ERROR) {
831         LOGE("record data cannot find fileType");
832         return "";
833     }
834     string extension;
835     if (!displayName.empty()) {
836         string::size_type pos = displayName.find_last_of('.');
837         if (pos == string::npos) {
838             return "";
839         }
840         extension = displayName.substr(pos + 1);
841     }
842     return extension;
843 }
844 
IfContainsFullField(const DriveKit::DKRecord & record)845 static bool IfContainsFullField(const DriveKit::DKRecord &record)
846 {
847     DriveKit::DKRecordData data;
848     record.GetRecordData(data);
849     if (data.find(FILE_ATTRIBUTES) != data.end()) {
850         DriveKit::DKRecordFieldMap attributes;
851         data[FILE_ATTRIBUTES].GetRecordMap(attributes);
852         return !(attributes.find(PhotoColumn::MEDIA_TITLE) == attributes.end());
853     }
854     return false;
855 }
856 
PullRecordInsert(DKRecord & record,OnFetchParams & params)857 int32_t FileDataHandler::PullRecordInsert(DKRecord &record, OnFetchParams &params)
858 {
859     LOGI("insert of record %{public}s", record.GetRecordId().c_str());
860 
861     /* check local file conflict */
862     bool comflag = false;
863     int ret = PullRecordConflict(record, comflag);
864     if (comflag) {
865         LOGI("Conflict:same document no Insert");
866         return E_OK;
867     } else if (ret != E_OK) {
868         LOGE("MateFile Conflict failed %{public}d", ret);
869     }
870     ret = DentryInsert(userId_, record);
871     if (ret != E_OK) {
872         LOGE("MetaFile Create failed %{public}d", ret);
873         return ret;
874     }
875 
876     ValuesBucket values;
877     ret = createConvertor_.RecordToValueBucket(record, values);
878     if (ret != E_OK) {
879         LOGE("record to valuebucket failed, ret=%{public}d", ret);
880         return ret;
881     }
882     if (!IfContainsFullField(record)) {
883         values.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY));
884     } else {
885         values.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
886     }
887     values.PutInt(Media::PhotoColumn::PHOTO_POSITION, POSITION_CLOUD);
888     values.PutLong(Media::PhotoColumn::PHOTO_CLOUD_VERSION, record.GetVersion());
889     values.PutString(Media::PhotoColumn::PHOTO_CLOUD_ID, record.GetRecordId());
890     bool downloadThumb = (!startCursor_.empty() || (++params.totalPullCount <= downloadThumbLimit_));
891     values.PutInt(
892         Media::PhotoColumn::PHOTO_SYNC_STATUS,
893         static_cast<int32_t>(downloadThumb? SyncStatusType::TYPE_DOWNLOAD : SyncStatusType::TYPE_VISIBLE));
894     params.insertFiles.push_back(values);
895     AddCloudThumbs(record);
896     if (downloadThumb) {
897         AppendToDownload(record, "lcd", params.assetsToDownload);
898         AppendToDownload(record, "thumbnail", params.assetsToDownload);
899     }
900     return E_OK;
901 }
902 
OnDownloadThumb(const map<DKDownloadAsset,DKDownloadResult> & resultMap)903 int32_t FileDataHandler::OnDownloadThumb(const map<DKDownloadAsset, DKDownloadResult> &resultMap)
904 {
905     for (const auto &it : resultMap) {
906         if (it.second.IsSuccess()) {
907             continue;
908         }
909         if (it.first.fieldKey == "thumbnail") {
910             LOGE("record %s %{public}s download failed, localErr: %{public}d, serverErr: %{public}d",
911                  it.first.recordId.c_str(), it.first.fieldKey.c_str(),
912                  static_cast<int>(it.second.GetDKError().dkErrorCode), it.second.GetDKError().serverErrorCode);
913             LOGI("update sync_status to visible of record %s", it.first.recordId.c_str());
914             int updateRows;
915             ValuesBucket values;
916             values.PutInt(Media::PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
917 
918             string whereClause = Media::PhotoColumn::PHOTO_CLOUD_ID + " = ?";
919             int32_t ret = Update(updateRows, values, whereClause, {it.first.recordId});
920             if (ret != E_OK) {
921                 LOGE("update retry flag failed, ret=%{public}d", ret);
922             }
923             DataSyncNotifier::GetInstance().TryNotify(DataSyncConst::PHOTO_URI_PREFIX, ChangeType::INSERT,
924                                                       to_string(updateRows));
925         }
926     }
927     return E_OK;
928 }
929 
OnDownloadThumb(const DKDownloadAsset & asset)930 int32_t FileDataHandler::OnDownloadThumb(const DKDownloadAsset &asset)
931 {
932     if (asset.fieldKey == "thumbnail") {
933         LOGI("update sync_status to visible of record %s", asset.recordId.c_str());
934         int updateRows;
935         ValuesBucket values;
936         values.PutInt(Media::PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
937 
938         string whereClause = Media::PhotoColumn::PHOTO_CLOUD_ID + " = ?";
939         int32_t ret = Update(updateRows, values, whereClause, {asset.recordId});
940         if (ret != E_OK) {
941             LOGE("update retry flag failed, ret=%{public}d", ret);
942         }
943         DataSyncNotifier::GetInstance().TryNotify(DataSyncConst::PHOTO_URI_PREFIX, ChangeType::INSERT,
944                                                   to_string(updateRows));
945         DataSyncNotifier::GetInstance().FinalNotify();
946     }
947 
948     DentryRemoveThumb(asset.downLoadPath + "/" + asset.asset.assetName);
949     return E_OK;
950 }
951 
IsLocalDirty(NativeRdb::ResultSet & local)952 static bool IsLocalDirty(NativeRdb::ResultSet &local)
953 {
954     int dirty;
955     int ret = DataConvertor::GetInt(PhotoColumn::PHOTO_DIRTY, dirty, local);
956     if (ret != E_OK) {
957         LOGE("Get dirty int failed");
958         return false;
959     }
960     return (dirty == static_cast<int32_t>(DirtyType::TYPE_MDIRTY)) ||
961            (dirty == static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) ||
962            (dirty == static_cast<int32_t>(DirtyType::TYPE_DELETED));
963 }
964 
965 constexpr unsigned HMDFS_IOC = 0xf2;
966 constexpr unsigned WRITEOPEN_CMD = 0x02;
967 #define HMDFS_IOC_GET_WRITEOPEN_CNT _IOR(HMDFS_IOC, WRITEOPEN_CMD, uint32_t)
968 
GetFilePath(NativeRdb::ResultSet & local)969 static string GetFilePath(NativeRdb::ResultSet &local)
970 {
971     string filePath;
972     int ret = DataConvertor::GetString(PhotoColumn::MEDIA_FILE_PATH, filePath, local);
973     if (ret != E_OK) {
974         LOGE("Get file path failed");
975         return "";
976     }
977     return filePath;
978 }
979 
GetLocalPath(int userId,const string & filePath)980 static string GetLocalPath(int userId, const string &filePath)
981 {
982     const string sandboxPrefix = "/storage/cloud";
983     const string dfsPrefix = "/mnt/hmdfs/";
984     const string dfsSuffix = "/account/cloud_merge_view";
985     size_t pos = filePath.find_first_of(sandboxPrefix);
986     if (pos != 0 || pos == string::npos) {
987         LOGE("invalid path %{private}s", filePath.c_str());
988         return "";
989     }
990 
991     string dfsPath = dfsPrefix + to_string(userId) + dfsSuffix + filePath.substr(sandboxPrefix.length());
992     return dfsPath;
993 }
994 
LocalWriteOpen(const string & dfsPath)995 static bool LocalWriteOpen(const string &dfsPath)
996 {
997     unique_ptr<char[]> absPath = make_unique<char[]>(PATH_MAX + 1);
998     if (realpath(dfsPath.c_str(), absPath.get()) == nullptr) {
999         return false;
1000     }
1001     string realPath = absPath.get();
1002     int fd = open(realPath.c_str(), O_RDONLY);
1003     if (fd < 0) {
1004         LOGE("open failed, errno:%{public}d", errno);
1005         return false;
1006     }
1007     uint32_t writeOpenCnt = 0;
1008     int ret = ioctl(fd, HMDFS_IOC_GET_WRITEOPEN_CNT, &writeOpenCnt);
1009     if (ret < 0) {
1010         LOGE("ioctl failed, errno:%{public}d", errno);
1011         return false;
1012     }
1013 
1014     close(fd);
1015     return writeOpenCnt != 0;
1016 }
1017 
SetRetry(const string & recordId)1018 int FileDataHandler::SetRetry(const string &recordId)
1019 {
1020     LOGI("set retry of record %s", recordId.c_str());
1021     int updateRows;
1022     ValuesBucket values;
1023     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_RETRY));
1024 
1025     string whereClause = PhotoColumn::PHOTO_CLOUD_ID + " = ?";
1026     int32_t ret = Update(updateRows, values, whereClause, {recordId});
1027     if (ret != E_OK) {
1028         LOGE("update retry flag failed, ret=%{public}d", ret);
1029         return E_RDB;
1030     }
1031     return E_OK;
1032 }
1033 
FileIsLocal(NativeRdb::ResultSet & local)1034 static bool FileIsLocal(NativeRdb::ResultSet &local)
1035 {
1036     int position = 0;
1037     int ret = DataConvertor::GetInt(PhotoColumn::PHOTO_POSITION, position, local);
1038     if (ret != E_OK) {
1039         LOGE("Get local position failed");
1040         return false;
1041     }
1042 
1043     return !!(static_cast<uint32_t>(position) & 1);
1044 }
1045 
IsMtimeChanged(const DKRecord & record,NativeRdb::ResultSet & local,bool & changed)1046 static int IsMtimeChanged(const DKRecord &record, NativeRdb::ResultSet &local, bool &changed)
1047 {
1048     // get local mtime
1049     int64_t localCrtime = 0;
1050     int ret = DataConvertor::GetLong(PhotoColumn::MEDIA_DATE_ADDED, localCrtime, local);
1051     if (ret != E_OK) {
1052         LOGE("Get local ctime failed");
1053         return E_INVAL_ARG;
1054     }
1055 
1056     // get record mtime
1057     int64_t crTime = static_cast<int64_t>(record.GetCreateTime()) / MILLISECOND_TO_SECOND;
1058     LOGI("cloudMtime %{public}llu, localMtime %{public}llu",
1059          static_cast<unsigned long long>(crTime), static_cast<unsigned long long>(localCrtime));
1060     changed = !(crTime == localCrtime);
1061     return E_OK;
1062 }
1063 
PullRecordUpdate(DKRecord & record,NativeRdb::ResultSet & local,OnFetchParams & params)1064 int32_t FileDataHandler::PullRecordUpdate(DKRecord &record, NativeRdb::ResultSet &local, OnFetchParams &params)
1065 {
1066     LOGI("update of record %s", record.GetRecordId().c_str());
1067     if (IsLocalDirty(local)) {
1068         LOGI("local record dirty, ignore cloud update");
1069         return E_OK;
1070     }
1071     bool mtimeChanged = false;
1072     if (IsMtimeChanged(record, local, mtimeChanged) != E_OK) {
1073         return E_INVAL_ARG;
1074     }
1075 
1076     int ret = E_OK;
1077     if (FileIsLocal(local)) {
1078         string filePath = GetFilePath(local);
1079         string localPath = GetLocalPath(userId_, filePath);
1080         if (LocalWriteOpen(localPath)) {
1081             return SetRetry(record.GetRecordId());
1082         }
1083 
1084         if (mtimeChanged) {
1085             LOGI("cloud file DATA changed, %s", record.GetRecordId().c_str());
1086             ret = unlink(localPath.c_str());
1087             if (ret != 0) {
1088                 LOGE("unlink local failed, errno %{public}d", errno);
1089             }
1090             DentryInsert(userId_, record);
1091         }
1092     }
1093 
1094     LOGI("cloud file META changed, %s", record.GetRecordId().c_str());
1095     /* update rdb */
1096     ValuesBucket values;
1097     createConvertor_.RecordToValueBucket(record, values);
1098     values.PutLong(Media::PhotoColumn::PHOTO_CLOUD_VERSION, record.GetVersion());
1099     int32_t changedRows;
1100     string whereClause = PhotoColumn::PHOTO_CLOUD_ID + " = ?";
1101     ret = Update(changedRows, values, whereClause, {record.GetRecordId()});
1102     if (ret != E_OK) {
1103         LOGE("rdb update failed, err=%{public}d", ret);
1104         return E_RDB;
1105     }
1106     if (mtimeChanged && (ThumbsAtLocal(record) || (AddCloudThumbs(record) != E_OK))) {
1107         AppendToDownload(record, "lcd", params.assetsToDownload);
1108         AppendToDownload(record, "thumbnail", params.assetsToDownload);
1109     }
1110 
1111     LOGI("update of record success");
1112     return E_OK;
1113 }
1114 
GetCheckRecords(vector<DriveKit::DKRecordId> & checkRecords,const shared_ptr<std::vector<DriveKit::DKRecord>> & records)1115 int32_t FileDataHandler::GetCheckRecords(vector<DriveKit::DKRecordId> &checkRecords,
1116     const shared_ptr<std::vector<DriveKit::DKRecord>> &records)
1117 {
1118     for (const auto &record : *records) {
1119         auto [resultSet, rowCount] = QueryLocalByCloudId(record.GetRecordId());
1120         if (resultSet == nullptr || rowCount < 0) {
1121             return E_RDB;
1122         }
1123 
1124         if ((rowCount == 0) && !record.GetIsDelete()) {
1125             checkRecords.push_back(record.GetRecordId());
1126         } else if (rowCount == 1) {
1127             resultSet->GoToNextRow();
1128             int64_t version = 0;
1129             DataConvertor::GetLong(PhotoColumn::PHOTO_CLOUD_VERSION, version, *resultSet);
1130             if (record.GetVersion() != static_cast<unsigned long>(version) &&
1131                 (!IsLocalDirty(*resultSet) || record.GetIsDelete())) {
1132                 checkRecords.push_back(record.GetRecordId());
1133             }
1134         } else {
1135             LOGE("recordId %s has multiple file in db!", record.GetRecordId().c_str());
1136         }
1137     }
1138 
1139     return E_OK;
1140 }
1141 
ThumbsAtLocal(const DKRecord & record)1142 bool FileDataHandler::ThumbsAtLocal(const DKRecord &record)
1143 {
1144     DKRecordData datas;
1145     record.GetRecordData(datas);
1146     if (datas.find(FILE_ATTRIBUTES) == datas.end()) {
1147         LOGE("record data cannot find attributes");
1148         return false;
1149     }
1150     DriveKit::DKRecordFieldMap attributes;
1151     datas[FILE_ATTRIBUTES].GetRecordMap(attributes);
1152 
1153     string fullPath;
1154     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end() ||
1155         attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(fullPath) != DKLocalErrorCode::NO_ERROR) {
1156         LOGE("bad file path in record");
1157         return false;
1158     }
1159 
1160     string thumbLocalPath = createConvertor_.GetThumbPath(fullPath, THUMB_SUFFIX);
1161     return access(thumbLocalPath.c_str(), F_OK) == 0;
1162 }
1163 
FileIsRecycled(NativeRdb::ResultSet & local)1164 static bool FileIsRecycled(NativeRdb::ResultSet &local)
1165 {
1166     int64_t localDateTrashed = 0;
1167     int ret = DataConvertor::GetLong(PhotoColumn::MEDIA_DATE_TRASHED, localDateTrashed, local);
1168     if (ret != E_OK) {
1169         LOGE("Get local recycled failed");
1170         return false;
1171     }
1172 
1173     return localDateTrashed > 0;
1174 }
1175 
1176 // if cloud delete but local exist, we would do recycle instead of delete
RecycleFile(const string & recordId)1177 int FileDataHandler::RecycleFile(const string &recordId)
1178 {
1179     LOGI("recycle of record %s", recordId.c_str());
1180 
1181     ValuesBucket values;
1182     values.PutNull(PhotoColumn::PHOTO_CLOUD_ID);
1183     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
1184     values.PutInt(PhotoColumn::PHOTO_POSITION, POSITION_LOCAL);
1185     values.PutLong(PhotoColumn::MEDIA_DATE_TRASHED, UTCTimeSeconds());
1186     values.PutLong(Media::PhotoColumn::PHOTO_CLOUD_VERSION, 0);
1187     int32_t changedRows;
1188     string whereClause = PhotoColumn::PHOTO_CLOUD_ID + " = ?";
1189     int ret = Update(changedRows, values, whereClause, {recordId});
1190     if (ret != E_OK) {
1191         LOGE("rdb update failed, err=%{public}d", ret);
1192         return E_RDB;
1193     }
1194     return E_OK;
1195 }
1196 
RemoveThmParentPath(const string & filePath)1197 void FileDataHandler::RemoveThmParentPath(const string &filePath)
1198 {
1199     string thmbFile = cleanConvertor_.GetThumbPath(filePath, THUMB_SUFFIX);
1200     filesystem::path thmbFilePath(thmbFile.c_str());
1201     filesystem::path thmbFileParentPath = thmbFilePath.parent_path();
1202     LOGD("filePath: %s, thmbFile: %s, thmbFileParentDir: %s", filePath.c_str(), thmbFile.c_str(),
1203          thmbFileParentPath.string().c_str());
1204     ForceRemoveDirectory(thmbFileParentPath.string());
1205 }
1206 
PullRecordDelete(DKRecord & record,NativeRdb::ResultSet & local)1207 int32_t FileDataHandler::PullRecordDelete(DKRecord &record, NativeRdb::ResultSet &local)
1208 {
1209     LOGI("delete of record %s", record.GetRecordId().c_str());
1210     string filePath = GetFilePath(local);
1211     string localPath = GetLocalPath(userId_, filePath);
1212 
1213     bool isLocal = FileIsLocal(local);
1214     if (FileIsRecycled(local) || !isLocal) {
1215         if (isLocal) {
1216             LOGI("force delete instead");
1217             int ret = unlink(localPath.c_str());
1218             if (ret != 0) {
1219                 LOGE("unlink local failed, errno %{public}d", errno);
1220             }
1221         } else { // delete dentry
1222             string relativePath;
1223             string fileName;
1224             if (GetDentryPathName(filePath, relativePath, fileName) != E_OK) {
1225                 LOGE("split to dentry path failed, path:%s", filePath.c_str());
1226                 return E_INVAL_ARG;
1227             }
1228             auto mFile = MetaFileMgr::GetInstance().GetMetaFile(userId_, relativePath);
1229             MetaBase mBase(fileName);
1230             int ret = mFile->DoRemove(mBase);
1231             if (ret != E_OK) {
1232                 LOGE("remove dentry failed, ret:%{public}d", ret);
1233             }
1234         }
1235         // delete THM
1236         RemoveThmParentPath(filePath);
1237         // delete rdb
1238         int32_t deletedRows;
1239         int ret = Delete(deletedRows, Media::PhotoColumn::PHOTO_CLOUD_ID + " = ?", {record.GetRecordId()});
1240         if (ret != E_OK) {
1241             LOGE("delete in rdb failed, ret:%{public}d", ret);
1242             return E_INVAL_ARG;
1243         }
1244         DeleteAssetInPhotoMap(GetFileId(local));
1245         return E_OK;
1246     }
1247 
1248     if (IsLocalDirty(local)) {
1249         LOGI("local record dirty, ignore cloud delete");
1250         return ClearCloudInfo(record.GetRecordId());
1251     }
1252 
1253     if (LocalWriteOpen(localPath)) {
1254         return SetRetry(record.GetRecordId());
1255     }
1256     return RecycleFile(record.GetRecordId());
1257 }
1258 
OnDownloadSuccess(const DriveKit::DKDownloadAsset & asset)1259 int32_t FileDataHandler::OnDownloadSuccess(const DriveKit::DKDownloadAsset &asset)
1260 {
1261     string downloadPath = asset.downLoadPath + "/" + asset.asset.assetName;
1262     string filePath = localConvertor_.GetSandboxPath(downloadPath);
1263 
1264     int ret = E_OK;
1265 
1266     // delete dentry
1267     string relativePath;
1268     string fileName;
1269     if (GetDentryPathName(filePath, relativePath, fileName) != E_OK) {
1270         LOGE("split to dentry path failed, path:%s", filePath.c_str());
1271         return E_INVAL_ARG;
1272     }
1273     auto mFile = MetaFileMgr::GetInstance().GetMetaFile(userId_, relativePath);
1274     MetaBase mBase(fileName);
1275     ret = mFile->DoRemove(mBase);
1276     if (ret != E_OK) {
1277         LOGE("remove dentry failed, ret:%{public}d", ret);
1278     }
1279 
1280     auto [resultSet, rowCount] = QueryLocalByCloudId(asset.recordId);
1281     if (resultSet == nullptr || rowCount != 1) {
1282         LOGE("QueryLocalByCloudId failed rowCount %{public}d", rowCount);
1283         return E_INVAL_ARG;
1284     }
1285     resultSet->GoToNextRow();
1286     int64_t localMtime = 0;
1287     ret = DataConvertor::GetLong(PhotoColumn::MEDIA_DATE_MODIFIED, localMtime, *resultSet);
1288     if (ret == E_OK) {
1289         struct utimbuf ubuf {
1290             .actime = localMtime, .modtime = localMtime
1291         };
1292         LOGI("update downloaded file mtime %{public}llu", static_cast<unsigned long long>(localMtime));
1293         if (utime(downloadPath.c_str(), &ubuf) < 0) {
1294             LOGE("utime failed return %{public}d ", errno);
1295         }
1296     }
1297 
1298     // update rdb
1299     ValuesBucket valuesBucket;
1300     valuesBucket.PutInt(Media::PhotoColumn::PHOTO_POSITION, POSITION_BOTH);
1301 
1302     int32_t changedRows;
1303     string whereClause = Media::PhotoColumn::MEDIA_FILE_PATH + " = ?";
1304     vector<string> whereArgs = {filePath};
1305     ret = Update(changedRows, valuesBucket, whereClause, whereArgs);
1306     if (ret != 0) {
1307         LOGE("on download file from cloud err %{public}d", ret);
1308     }
1309     return ret;
1310 }
1311 
AppendToDownload(const DKRecord & record,const std::string & fieldKey,std::vector<DKDownloadAsset> & assetsToDownload)1312 void FileDataHandler::AppendToDownload(const DKRecord &record,
1313                                        const std::string &fieldKey,
1314                                        std::vector<DKDownloadAsset> &assetsToDownload)
1315 {
1316     DKDownloadAsset downloadAsset;
1317     downloadAsset.recordType = record.GetRecordType();
1318     downloadAsset.recordId = record.GetRecordId();
1319     downloadAsset.fieldKey = fieldKey;
1320     DKRecordData data;
1321     record.GetRecordData(data);
1322     if (data.find(FILE_ATTRIBUTES) == data.end()) {
1323         LOGE("record data cannot find attributes");
1324         return;
1325     }
1326     DKRecordFieldMap attributes;
1327     data[FILE_ATTRIBUTES].GetRecordMap(attributes);
1328 
1329     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end()) {
1330         LOGE("record prop cannot find file path");
1331         return;
1332     }
1333     string path;
1334     attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(path);
1335     if (fieldKey != "content") {
1336         const string &suffix = fieldKey == "lcd" ? LCD_SUFFIX : THUMB_SUFFIX;
1337         downloadAsset.downLoadPath = createConvertor_.GetThumbPath(path, suffix);
1338     } else {
1339         downloadAsset.downLoadPath = createConvertor_.GetLowerTmpPath(path);
1340     }
1341     downloadAsset.asset.assetName = MetaFile::GetFileName(downloadAsset.downLoadPath);
1342     downloadAsset.downLoadPath = MetaFile::GetParentDir(downloadAsset.downLoadPath);
1343     ForceCreateDirectory(downloadAsset.downLoadPath);
1344     assetsToDownload.push_back(downloadAsset);
1345 }
1346 
UpdateAssetInPhotoMap(const DKRecord & record,int32_t fileId)1347 int32_t FileDataHandler::UpdateAssetInPhotoMap(const DKRecord &record, int32_t fileId)
1348 {
1349     NativeRdb::AbsRdbPredicates updatePredicates = NativeRdb::AbsRdbPredicates(PhotoMap::TABLE);
1350     updatePredicates.EqualTo(PhotoMap::ASSET_ID, to_string(fileId));
1351     auto resultSet = Query(updatePredicates, CLEAN_QUERY_COLUMNS);
1352 
1353     DKRecordData data;
1354     record.GetRecordData(data);
1355     if (data.find(FILE_LOGIC_ALBUM_IDS) == data.end()) {
1356         LOGE("record data cannot find properties");
1357         return E_INVAL_ARG;
1358     }
1359     DKRecordFieldList list;
1360     if (data[FILE_LOGIC_ALBUM_IDS].GetRecordList(list) != DKLocalErrorCode::NO_ERROR) {
1361         LOGE("cannot get album ids from record");
1362         return E_INVAL_ARG;
1363     }
1364 
1365     set<int> cloudMapIds;
1366     for (const auto &it : list) {
1367         DKReference ref;
1368         if (it.GetReference(ref) != DKLocalErrorCode::NO_ERROR) {
1369             LOGE("id list member not a reference");
1370             continue;
1371         }
1372         int albumId = GetAlbumIdFromCloudId(ref.recordId);
1373         if (albumId < 0) {
1374             LOGE("cannot get album id from album name %{public}s, ignore", ref.recordId.c_str());
1375             continue;
1376         }
1377         LOGI("record get albumId %{public}d", albumId);
1378         cloudMapIds.insert(albumId);
1379         QueryAndInsertMap(albumId, fileId);
1380     }
1381 
1382     QueryAndDeleteMap(fileId, cloudMapIds);
1383     return E_OK;
1384 }
1385 
InsertAssetToPhotoMap(const DKRecord & record,OnFetchParams & params)1386 int32_t FileDataHandler::InsertAssetToPhotoMap(const DKRecord &record, OnFetchParams &params)
1387 {
1388     DKRecordData data;
1389     record.GetRecordData(data);
1390     if (data.find(FILE_LOGIC_ALBUM_IDS) == data.end()) {
1391         LOGE("record data cannot find properties");
1392         return E_INVAL_ARG;
1393     }
1394     DKRecordFieldList list;
1395     if (data[FILE_LOGIC_ALBUM_IDS].GetRecordList(list) != DKLocalErrorCode::NO_ERROR) {
1396         LOGE("cannot get album ids from record");
1397         return E_INVAL_ARG;
1398     }
1399 
1400     set<int> cloudMapIds;
1401     for (const auto &it : list) {
1402         DKReference ref;
1403         if (it.GetReference(ref) != DKLocalErrorCode::NO_ERROR) {
1404             LOGE("id list member not a reference");
1405             continue;
1406         }
1407         int albumId = GetAlbumIdFromCloudId(ref.recordId);
1408         if (albumId < 0) {
1409             LOGE("cannot get album id from album name %{public}s, ignore", ref.recordId.c_str());
1410             continue;
1411         }
1412         LOGI("record get albumId %{public}d", albumId);
1413         cloudMapIds.insert(albumId);
1414     }
1415 
1416     params.recordAlbumMaps[record.GetRecordId()] = cloudMapIds;
1417     return E_OK;
1418 }
1419 
BatchInsertAssetMaps(OnFetchParams & params)1420 int32_t FileDataHandler::BatchInsertAssetMaps(OnFetchParams &params)
1421 {
1422     for (const auto &it : params.recordAlbumMaps) {
1423         auto [resultSet, rowCount] = QueryLocalByCloudId(it.first);
1424         if (resultSet == nullptr || rowCount < 0) {
1425             continue;
1426         }
1427         resultSet->GoToNextRow();
1428         int fileId = 0;
1429         int ret = DataConvertor::GetInt(MediaColumn::MEDIA_ID, fileId, *resultSet);
1430         if (ret != E_OK) {
1431             LOGE("Get media id failed");
1432             continue;
1433         }
1434 
1435         for (auto albumId : it.second) {
1436             int64_t rowId;
1437             ValuesBucket values;
1438             values.PutInt(PhotoMap::ALBUM_ID, albumId);
1439             values.PutInt(PhotoMap::ASSET_ID, fileId);
1440             values.PutInt(PhotoMap::DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_SYNCED));
1441             ret = Insert(rowId, PhotoMap::TABLE, values);
1442             if (ret != E_OK) {
1443                 LOGE("fail to insert albumId %{public}d - fileId %{public}d mapping, ret %{public}d", albumId, fileId,
1444                      ret);
1445                 continue;
1446             }
1447             LOGI("albumId %{public}d - fileId %{public}d add mapping success", albumId, fileId);
1448         }
1449     }
1450     return E_OK;
1451 }
1452 
GetAlbumIdFromCloudId(const std::string & cloudId)1453 int32_t FileDataHandler::GetAlbumIdFromCloudId(const std::string &cloudId)
1454 {
1455     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoAlbumColumns::TABLE);
1456     predicates.EqualTo(PhotoAlbumColumns::ALBUM_CLOUD_ID, cloudId);
1457     auto resultSet = Query(predicates, {PhotoAlbumColumns::ALBUM_ID});
1458     int rowCount = 0;
1459     int ret = -1;
1460     if (resultSet) {
1461         ret = resultSet->GetRowCount(rowCount);
1462     }
1463     if (resultSet == nullptr || ret != E_OK || rowCount < 0) {
1464         LOGE("get nullptr result or rowcount %{public}d", rowCount);
1465         return -1;
1466     }
1467     if (resultSet->GoToNextRow() == 0) {
1468         int albumId;
1469         ret = DataConvertor::GetInt(PhotoAlbumColumns::ALBUM_ID, albumId, *resultSet);
1470         if (ret == E_OK) {
1471             return albumId;
1472         }
1473     }
1474     LOGE("fail to get ALBUM_ID value");
1475     return -1;
1476 }
1477 
QueryAndInsertMap(int32_t albumId,int32_t fileId)1478 void FileDataHandler::QueryAndInsertMap(int32_t albumId, int32_t fileId)
1479 {
1480     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoMap::TABLE);
1481     predicates.EqualTo(PhotoMap::ALBUM_ID, to_string(albumId))->And()->EqualTo(PhotoMap::ASSET_ID, to_string(fileId));
1482     auto resultSet = Query(predicates, {});
1483     int rowCount = 0;
1484     int ret = -1;
1485     if (resultSet) {
1486         ret = resultSet->GetRowCount(rowCount);
1487     }
1488     if (resultSet == nullptr || ret != E_OK || rowCount < 0) {
1489         LOGE("get nullptr result or rowcount %{public}d", rowCount);
1490         return;
1491     }
1492     if (rowCount > 0) {
1493         LOGI("albumId %{public}d - fileId %{public}d already mapped", albumId, fileId);
1494         return;
1495     }
1496 
1497     int64_t rowId;
1498     ValuesBucket values;
1499     values.PutInt(PhotoMap::ALBUM_ID, albumId);
1500     values.PutInt(PhotoMap::ASSET_ID, fileId);
1501     values.PutInt(PhotoMap::DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_SYNCED));
1502     ret = Insert(rowId, PhotoMap::TABLE, values);
1503     if (ret != E_OK) {
1504         LOGE("fail to insert albumId %{public}d - fileId %{public}d mapping, ret %{public}d", albumId, fileId, ret);
1505         return;
1506     }
1507     LOGI("albumId %{public}d - fileId %{public}d add mapping success", albumId, fileId);
1508 }
1509 
QueryAndDeleteMap(int32_t fileId,const set<int> & cloudMapIds)1510 void FileDataHandler::QueryAndDeleteMap(int32_t fileId, const set<int> &cloudMapIds)
1511 {
1512     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoMap::TABLE);
1513     predicates.EqualTo(PhotoMap::ASSET_ID, to_string(fileId));
1514 
1515     auto resultSet = Query(predicates, {});
1516     int rowCount = 0;
1517     int ret = -1;
1518     if (resultSet) {
1519         ret = resultSet->GetRowCount(rowCount);
1520     }
1521     if (resultSet == nullptr || ret != E_OK || rowCount < 0) {
1522         LOGE("get nullptr result or rowcount %{public}d", rowCount);
1523         return;
1524     }
1525     while (resultSet->GoToNextRow() == 0) {
1526         int albumId;
1527         ret = DataConvertor::GetInt(PhotoMap::ALBUM_ID, albumId, *resultSet);
1528         if (ret != E_OK) {
1529             LOGE("fail to get ALBUM_ID value");
1530             continue;
1531         }
1532         int localDirty  = 0;
1533         ret = DataConvertor::GetInt(PhotoMap::DIRTY, localDirty, *resultSet);
1534         if (ret != E_OK) {
1535             LOGE("fail to get Dirty value");
1536             continue;
1537         }
1538 
1539         if (localDirty != static_cast<int32_t>(DirtyTypes::TYPE_SYNCED)) {
1540             LOGI("mapping albumId %{public}d - fileId %{public}d local dirty %{public}d, skip",
1541                 albumId, fileId, localDirty);
1542             continue;
1543         }
1544         if (cloudMapIds.find(albumId) == cloudMapIds.end()) {
1545             LOGE("delete mapping albumId %{public}d - fileId %{public}d", albumId, fileId);
1546             int deletedRows;
1547             ret = Delete(deletedRows, PhotoMap::TABLE, PhotoMap::ASSET_ID + " = ? AND " + PhotoMap::ALBUM_ID + " = ?",
1548                          {to_string(fileId), to_string(albumId)});
1549             if (ret != E_OK) {
1550                 LOGE("delete mapping failed %{public}d", ret);
1551                 continue;
1552             }
1553         }
1554     }
1555 }
1556 
DeleteAssetInPhotoMap(int32_t fileId)1557 int32_t FileDataHandler::DeleteAssetInPhotoMap(int32_t fileId)
1558 {
1559     if (fileId <= 0) {
1560         return E_INVAL_ARG;
1561     }
1562 
1563     int32_t deletedRows;
1564     int ret = Delete(deletedRows, PhotoMap::TABLE, PhotoMap::ASSET_ID + " = ?", {to_string(fileId)});
1565     if (ret != E_OK) {
1566         LOGE("delete in rdb failed, ret: %{public}d", ret);
1567         return E_RDB;
1568     }
1569     return E_OK;
1570 }
1571 
DeleteDentryFile(void)1572 int32_t FileDataHandler::DeleteDentryFile(void)
1573 {
1574     std::string cacheDir =
1575         "/data/service/el2/" + std::to_string(userId_) + "/hmdfs/cache/account_cache/dentry_cache/cloud/";
1576     LOGD("cacheDir: %s", cacheDir.c_str());
1577     ForceRemoveDirectory(cacheDir);
1578 
1579     return E_OK;
1580 }
1581 
ClearCloudInfo(const string & cloudId)1582 int32_t FileDataHandler::ClearCloudInfo(const string &cloudId)
1583 {
1584     ValuesBucket values;
1585     values.PutNull(PhotoColumn::PHOTO_CLOUD_ID);
1586     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
1587     values.PutInt(PhotoColumn::PHOTO_POSITION, POSITION_LOCAL);
1588     values.PutLong(PhotoColumn::PHOTO_CLOUD_VERSION, 0);
1589     int32_t updateRows = 0;
1590     std::string whereClause = PhotoColumn::PHOTO_CLOUD_ID + " = ?";
1591     int ret = Update(updateRows, values, whereClause, {cloudId});
1592     if (ret != E_OK) {
1593         LOGE("Update in rdb failed, ret:%{public}d", ret);
1594     }
1595     return ret;
1596 }
1597 
CleanPureCloudRecord(NativeRdb::ResultSet & local,const int action,const std::string & filePath)1598 int32_t FileDataHandler::CleanPureCloudRecord(NativeRdb::ResultSet &local, const int action,
1599                                               const std::string &filePath)
1600 {
1601     int res = E_OK;
1602     RemoveThmParentPath(filePath);
1603     int32_t deleteRows = 0;
1604     string whereClause = PhotoColumn::PHOTO_CLOUD_ID + " = ?";
1605     string cloudId;
1606     res = DataConvertor::GetString(PhotoColumn::PHOTO_CLOUD_ID, cloudId, local);
1607     if (res != E_OK) {
1608         LOGE("Get cloud_id fail");
1609         return res;
1610     }
1611     res = Delete(deleteRows, whereClause, {cloudId});
1612     LOGD("RDB Delete result: %d, deleteRows is: %d", res, deleteRows);
1613     if (res != 0) {
1614         LOGE("Clean delete in rdb failed, res:%{public}d", res);
1615         return E_RDB;
1616     }
1617     DeleteAssetInPhotoMap(deleteRows);
1618     return E_OK;
1619 }
1620 
DeleteAsset(const string & assetPath)1621 static int32_t DeleteAsset(const string &assetPath)
1622 {
1623     int ret = E_OK;
1624     if (access(assetPath.c_str(), F_OK) == 0) {
1625         LOGD("assetPath exist");
1626         ret = remove(assetPath.c_str());
1627         if (ret != 0) {
1628             LOGE("Clean remove assetPath failed, errno %{public}d", errno);
1629             return errno;
1630         }
1631     }
1632     return ret;
1633 }
1634 
CleanNotDirtyData(const string & thmbDir,const string & assetPath,const string & cloudId)1635 int32_t FileDataHandler::CleanNotDirtyData(const string &thmbDir, const string &assetPath, const string &cloudId)
1636 {
1637     int ret = E_OK;
1638     ForceRemoveDirectory(thmbDir);
1639     ret = DeleteAsset(assetPath);
1640     if (ret != E_OK) {
1641         LOGE("Clean remove assetPath failed, errno %{public}d", ret);
1642         return ret;
1643     }
1644     int32_t deleteRows = 0;
1645     std::string whereClause = Media::PhotoColumn::PHOTO_CLOUD_ID + " = ?";
1646     ret = Delete(deleteRows, whereClause, {cloudId});
1647     LOGD("RDB Delete result: %d, deleteRows is: %d", ret, deleteRows);
1648     if (ret != 0) {
1649         LOGE("Clean delete in rdb failed, ret:%{public}d", ret);
1650         return ret;
1651     }
1652     DeleteAssetInPhotoMap(deleteRows);
1653     return ret;
1654 }
1655 
CleanNotPureCloudRecord(NativeRdb::ResultSet & local,const int action,const std::string & filePath)1656 int32_t FileDataHandler::CleanNotPureCloudRecord(NativeRdb::ResultSet &local, const int action,
1657                                                  const std::string &filePath)
1658 {
1659     string cloudId;
1660     int res = DataConvertor::GetString(PhotoColumn::PHOTO_CLOUD_ID, cloudId, local);
1661     if (res != E_OK) {
1662         LOGE("Get cloud_id fail");
1663         return res;
1664     }
1665     string lowerPath = cleanConvertor_.GetLowerPath(filePath);
1666     string thmbFile = cleanConvertor_.GetThumbPath(filePath, THUMB_SUFFIX);
1667     filesystem::path thmbFilePath(thmbFile.c_str());
1668     filesystem::path thmbFileParentPath = thmbFilePath.parent_path();
1669     LOGD("filePath: %s, thmbFile: %s, thmbFileParentPath: %s, lowerPath: %s", filePath.c_str(),
1670          thmbFile.c_str(), thmbFileParentPath.string().c_str(), lowerPath.c_str());
1671     int32_t ret = E_OK;
1672     if (action == FileDataHandler::Action::CLEAR_DATA) {
1673         if (IsLocalDirty(local)) {
1674             LOGD("data is dirty, action:clear");
1675             ret = ClearCloudInfo(cloudId);
1676             if (ret != E_OK) {
1677                 LOGE("Clean Update in rdb failed, ret:%{public}d", ret);
1678                 return ret;
1679             }
1680         } else {
1681             LOGD("data is not dirty, action:clear.");
1682             ret = CleanNotDirtyData(thmbFileParentPath.string(), lowerPath, cloudId);
1683             if (ret != 0) {
1684                 LOGE("Clean dirty data failed.");
1685                 return ret;
1686             }
1687         }
1688     } else {
1689         LOGD("action:retain");
1690         ret = ClearCloudInfo(cloudId);
1691         if (ret != E_OK) {
1692             LOGE("Clean Update in rdb failed, ret:%{public}d", ret);
1693             return ret;
1694         }
1695     }
1696     return E_OK;
1697 }
1698 
CleanCloudRecord(NativeRdb::ResultSet & local,const int action,const std::string & filePath)1699 int32_t FileDataHandler::CleanCloudRecord(NativeRdb::ResultSet &local, const int action,
1700                                           const std::string &filePath)
1701 {
1702     int res = E_OK;
1703     if (!FileIsLocal(local)) {
1704         LOGD("File is pure cloud data");
1705         res = CleanPureCloudRecord(local, action, filePath);
1706         if (res != E_OK) {
1707             LOGE("Clean pure cloud record failed, res:%{public}d", res);
1708             return res;
1709         }
1710     } else {
1711         LOGD("File is not pure cloud data");
1712         res = CleanNotPureCloudRecord(local, action, filePath);
1713         if (res != E_OK) {
1714             LOGE("Clean no pure cloud record failed, res:%{public}d", res);
1715             return res;
1716         }
1717     }
1718     return res;
1719 }
1720 
Clean(const int action)1721 int32_t FileDataHandler::Clean(const int action)
1722 {
1723     LOGD("Enter function FileDataHandler::Clean");
1724     int res = E_OK;
1725     NativeRdb::AbsRdbPredicates cleanPredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
1726     cleanPredicates.IsNotNull(PhotoColumn::PHOTO_CLOUD_ID);
1727     cleanPredicates.Limit(LIMIT_SIZE);
1728     while (1) {
1729         auto resultSet = Query(cleanPredicates, CLEAN_QUERY_COLUMNS);
1730         if (resultSet == nullptr) {
1731             LOGE("get nullptr result");
1732             return E_RDB;
1733         }
1734         int count = 0;
1735         res = resultSet->GetRowCount(count);
1736         if (res != E_OK || count == 0) {
1737             LOGE("get row count error or row count is 0, res: %{public}d", res);
1738             break;
1739         }
1740         NativeRdb::ResultSet *resultSetPtr = resultSet.get();
1741 
1742         while (resultSet->GoToNextRow() == 0) {
1743             string filePath;
1744             res = DataConvertor::GetString(PhotoColumn::MEDIA_FILE_PATH, filePath, *resultSetPtr);
1745             if (res != E_OK) {
1746                 LOGE("Get path wrong");
1747                 return E_INVAL_ARG;
1748             }
1749             res = CleanCloudRecord(*resultSetPtr, action, filePath);
1750             if (res != E_OK) {
1751                 LOGE("Clean cloud record failed, res:%{public}d", res);
1752                 return res;
1753             }
1754         }
1755     }
1756     res = DeleteDentryFile();
1757     if (res != E_OK) {
1758         LOGE("Clean remove dentry failed, res:%{public}d", res);
1759         return res;
1760     }
1761 
1762     DataSyncNotifier::GetInstance().TryNotify(DataSyncConst::PHOTO_URI_PREFIX, ChangeType::INSERT,
1763                                               DataSyncConst::INVALID_ID);
1764     DataSyncNotifier::GetInstance().FinalNotify();
1765 
1766     return E_OK;
1767 }
1768 
GetCreatedRecords(vector<DKRecord> & records)1769 int32_t FileDataHandler::GetCreatedRecords(vector<DKRecord> &records)
1770 {
1771     /* build predicates */
1772     NativeRdb::AbsRdbPredicates createPredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
1773     createPredicates
1774         .EqualTo(Media::PhotoColumn::PHOTO_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_NEW)))
1775         ->And()
1776         ->EqualTo(Media::PhotoColumn::MEDIA_DATE_TRASHED, "0")
1777         ->BeginWrap()
1778         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_IMAGE))
1779         ->Or()
1780         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_VIDEO))
1781         ->EndWrap();
1782     if (!createFailSet_.empty()) {
1783         createPredicates.And()->NotIn(Media::PhotoColumn::MEDIA_FILE_PATH, createFailSet_);
1784     }
1785 
1786     /* small-size first */
1787     createPredicates.OrderByAsc(Media::PhotoColumn::MEDIA_SIZE);
1788     createPredicates.Limit(LIMIT_SIZE);
1789 
1790     /* query */
1791     auto results = Query(createPredicates, MEDIA_CLOUD_SYNC_COLUMNS);
1792     if (results == nullptr) {
1793         LOGE("get nullptr created result");
1794         return E_RDB;
1795     }
1796 
1797     /* results to records */
1798     int ret = createConvertor_.ResultSetToRecords(move(results), records);
1799     if (ret != 0) {
1800         LOGE("result set to records err %{public}d", ret);
1801         return ret;
1802     }
1803 
1804     /* bind album */
1805     ret = BindAlbums(records);
1806     if (ret != E_OK) {
1807         LOGE("bind albums err %{public}d", ret);
1808         return ret;
1809     }
1810 
1811     /* erase local info */
1812     ret = EraseLocalInfo(records);
1813     if (ret != 0) {
1814         LOGE("erase local info err %{public}d", ret);
1815         return ret;
1816     }
1817 
1818     return E_OK;
1819 }
1820 
GetDeletedRecords(vector<DKRecord> & records)1821 int32_t FileDataHandler::GetDeletedRecords(vector<DKRecord> &records)
1822 {
1823     /* build predicates */
1824     NativeRdb::AbsRdbPredicates deletePredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
1825     deletePredicates
1826         .EqualTo(Media::PhotoColumn::PHOTO_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_DELETED)))
1827         ->BeginWrap()
1828         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_IMAGE))
1829         ->Or()
1830         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_VIDEO))
1831         ->EndWrap();
1832     if (!modifyFailSet_.empty()) {
1833         deletePredicates.And()->NotIn(Media::PhotoColumn::PHOTO_CLOUD_ID, modifyFailSet_);
1834     }
1835     deletePredicates.Limit(LIMIT_SIZE);
1836 
1837     /* query */
1838     auto results = Query(deletePredicates, MEDIA_CLOUD_SYNC_COLUMNS);
1839     if (results == nullptr) {
1840         LOGE("get nullptr deleted result");
1841         return E_RDB;
1842     }
1843 
1844     /* results to records */
1845     int ret = deleteConvertor_.ResultSetToRecords(move(results), records);
1846     if (ret != 0) {
1847         LOGE("result set to records err %{public}d", ret);
1848         return ret;
1849     }
1850 
1851     return E_OK;
1852 }
1853 
GetMetaModifiedRecords(vector<DKRecord> & records)1854 int32_t FileDataHandler::GetMetaModifiedRecords(vector<DKRecord> &records)
1855 {
1856     /* build predicates */
1857     NativeRdb::AbsRdbPredicates updatePredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
1858     updatePredicates
1859         .EqualTo(Media::PhotoColumn::PHOTO_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY)))
1860         ->BeginWrap()
1861         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_IMAGE))
1862         ->Or()
1863         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_VIDEO))
1864         ->EndWrap();
1865     if (!modifyFailSet_.empty()) {
1866         updatePredicates.And()->NotIn(Media::PhotoColumn::PHOTO_CLOUD_ID, modifyFailSet_);
1867     }
1868     updatePredicates.Limit(LIMIT_SIZE);
1869 
1870     /* query */
1871     auto results = Query(updatePredicates, MEDIA_CLOUD_SYNC_COLUMNS);
1872     if (results == nullptr) {
1873         LOGE("get nullptr modified result");
1874         return E_RDB;
1875     }
1876 
1877     /* results to records */
1878     int ret = mdirtyConvertor_.ResultSetToRecords(move(results), records);
1879     if (ret != 0) {
1880         LOGE("result set to records err %{public}d", ret);
1881         return ret;
1882     }
1883 
1884     /* album map change */
1885     ret = BindAlbumChanges(records);
1886     if (ret != E_OK) {
1887         LOGE("update album map change err %{public}d", ret);
1888         return ret;
1889     }
1890 
1891     /* erase local info */
1892     ret = EraseLocalInfo(records);
1893     if (ret != 0) {
1894         LOGE("erase local info err %{public}d", ret);
1895         return ret;
1896     }
1897 
1898     return E_OK;
1899 }
1900 
GetFileIdFromRecord(DKRecord & record,int32_t & fileId)1901 static inline int32_t GetFileIdFromRecord(DKRecord &record, int32_t &fileId)
1902 {
1903     DKRecordData data;
1904     record.GetRecordData(data);
1905     if (data.find(FILE_ATTRIBUTES) == data.end()) {
1906         LOGE("file attributes is no exit");
1907         return E_INVAL_ARG;
1908     }
1909     DriveKit::DKRecordFieldMap attributes = data[FILE_ATTRIBUTES];
1910     if (attributes.find(Media::MediaColumn::MEDIA_ID) == attributes.end()) {
1911         LOGE("media id is no exit");
1912         return E_INVAL_ARG;
1913     }
1914     fileId = attributes[Media::MediaColumn::MEDIA_ID];
1915     return E_OK;
1916 }
1917 
InsertAlbumIds(DKRecord & record,vector<string> & cloudIds)1918 static inline void InsertAlbumIds(DKRecord &record, vector<string> &cloudIds)
1919 {
1920     DKRecordData data;
1921     DKRecordFieldList list;
1922     record.StealRecordData(data);
1923     for (auto &id : cloudIds) {
1924         list.push_back(DKRecordField(DKReference{ id, "album" }));
1925     }
1926     data[FILE_LOGIC_ALBUM_IDS] = DKRecordField(list);
1927     record.SetRecordData(data);
1928 }
1929 
InsertAlbumIdChanges(DKRecord & record,vector<string> & add,vector<string> & rm)1930 static inline void InsertAlbumIdChanges(DKRecord &record, vector<string> &add, vector<string> &rm)
1931 {
1932     DKRecordData data;
1933     record.StealRecordData(data);
1934     /* add */
1935     DKRecordFieldList addList;
1936     for (auto &id : add) {
1937         addList.push_back(DKRecordField(DKReference{ id, "album" }));
1938     }
1939     data[FILE_ADD_LOGIC_ALBUM_IDS] = DKRecordField(addList);
1940     /* remove */
1941     DKRecordFieldList rmList;
1942     for (auto &id : rm) {
1943         rmList.push_back(DKRecordField(DKReference{ id, "album" }));
1944     }
1945     data[FILE_RM_LOGIC_ALBUM_IDS] = DKRecordField(rmList);
1946     record.SetRecordData(data);
1947 }
1948 
1949 /* need optimization: IN or JOIN */
GetAlbumCloudIds(vector<int32_t> & localIds,vector<string> & cloudIds)1950 int32_t FileDataHandler::GetAlbumCloudIds(vector<int32_t> &localIds, vector<string> &cloudIds)
1951 {
1952     for (auto localId : localIds) {
1953         NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PAC::TABLE);
1954         predicates.EqualTo(PAC::ALBUM_ID, to_string(localId));
1955         /* query map */
1956         auto results = Query(predicates, {});
1957         if (results == nullptr) {
1958             LOGE("get nullptr result");
1959             return E_RDB;
1960         }
1961         if (results->GoToNextRow() != NativeRdb::E_OK) {
1962             LOGE("failed to go to next row");
1963             return E_RDB;
1964         }
1965         string cloudId;
1966         int32_t ret = createConvertor_.GetString(PAC::ALBUM_CLOUD_ID, cloudId, *results);
1967         if (ret != E_OK) {
1968             return ret;
1969         }
1970         if (!cloudId.empty()) {
1971             cloudIds.push_back(cloudId);
1972         }
1973     }
1974     return E_OK;
1975 }
1976 
GetAlbumIdsFromResultSet(const shared_ptr<NativeRdb::ResultSet> resultSet,vector<int32_t> & ids)1977 int32_t FileDataHandler::GetAlbumIdsFromResultSet(const shared_ptr<NativeRdb::ResultSet> resultSet,
1978     vector<int32_t> &ids)
1979 {
1980     while (resultSet->GoToNextRow() == 0) {
1981         int32_t id;
1982         int32_t ret = createConvertor_.GetInt(PM::ALBUM_ID, id, *resultSet);
1983         if (ret != E_OK) {
1984             return ret;
1985         }
1986         ids.push_back(id);
1987     }
1988     return E_OK;
1989 }
1990 
BindAlbums(std::vector<DriveKit::DKRecord> & records)1991 int32_t FileDataHandler::BindAlbums(std::vector<DriveKit::DKRecord> &records)
1992 {
1993     for (auto &record : records) {
1994         NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PM::TABLE);
1995         /* map exceed limit? */
1996         int32_t fileId;
1997         int32_t ret = GetFileIdFromRecord(record, fileId);
1998         if (ret != E_OK) {
1999             LOGE("get file id from record err %{public}d", ret);
2000             return ret;
2001         }
2002         predicates.EqualTo(PM::ASSET_ID, to_string(fileId));
2003         /* query map */
2004         auto results = Query(predicates, {});
2005         if (results == nullptr) {
2006             LOGE("get nullptr result");
2007             return E_RDB;
2008         }
2009         vector<int32_t> albumIds;
2010         ret = GetAlbumIdsFromResultSet(results, albumIds);
2011         if (ret != E_OK) {
2012             LOGE("get album ids from result set err %{public}d", ret);
2013             return ret;
2014         }
2015         /* query album */
2016         vector<string> cloudIds;
2017         ret = GetAlbumCloudIds(albumIds, cloudIds);
2018         if (ret != E_OK) {
2019             LOGE("get album cloud id err %{public}d", ret);
2020             return ret;
2021         }
2022         /* insert album ids */
2023         InsertAlbumIds(record, cloudIds);
2024     }
2025     return E_OK;
2026 }
2027 
GetAlbumIdsFromResultSet(const shared_ptr<NativeRdb::ResultSet> resultSet,vector<int32_t> & add,vector<int32_t> & rm)2028 int32_t FileDataHandler::GetAlbumIdsFromResultSet(const shared_ptr<NativeRdb::ResultSet> resultSet,
2029     vector<int32_t> &add, vector<int32_t> &rm)
2030 {
2031     while (resultSet->GoToNextRow() == 0) {
2032         int32_t id;
2033         int32_t ret = createConvertor_.GetInt(PM::ALBUM_ID, id, *resultSet);
2034         if (ret != E_OK) {
2035             return ret;
2036         }
2037         int32_t state;
2038         ret = createConvertor_.GetInt(PM::DIRTY, state, *resultSet);
2039         if (ret != E_OK) {
2040             return ret;
2041         }
2042         if (state == static_cast<int32_t>(Media::DirtyType::TYPE_NEW)) {
2043             add.push_back(id);
2044         } else if (state == static_cast<int32_t>(Media::DirtyType::TYPE_DELETED)) {
2045             rm.push_back(id);
2046         }
2047     }
2048     return E_OK;
2049 }
2050 
BindAlbumChanges(std::vector<DriveKit::DKRecord> & records)2051 int32_t FileDataHandler::BindAlbumChanges(std::vector<DriveKit::DKRecord> &records)
2052 {
2053     for (auto &record : records) {
2054         NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PM::TABLE);
2055         /* map exceed limit? */
2056         int32_t fileId;
2057         int32_t ret = GetFileIdFromRecord(record, fileId);
2058         if (ret != E_OK) {
2059             LOGE("get file id from record err %{public}d", ret);
2060             return ret;
2061         }
2062         predicates.EqualTo(PM::ASSET_ID, to_string(fileId))
2063             ->And()
2064             ->NotEqualTo(PM::DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED)));
2065         /* query map */
2066         auto results = Query(predicates, {});
2067         if (results == nullptr) {
2068             LOGE("get nullptr result");
2069             return E_RDB;
2070         }
2071         /* new or delete */
2072         vector<int32_t> add, remove;
2073         ret = GetAlbumIdsFromResultSet(results, add, remove);
2074         if (ret != E_OK) {
2075             LOGE("get album ids from result set err %{public}d", ret);
2076             return ret;
2077         }
2078         /* query album */
2079         vector<string> addCloud, removeCloud;
2080         ret = GetAlbumCloudIds(add, addCloud);
2081         if (ret != E_OK) {
2082             LOGE("get album cloud id err %{public}d", ret);
2083             return ret;
2084         }
2085         ret = GetAlbumCloudIds(remove, removeCloud);
2086         if (ret != E_OK) {
2087             LOGE("get album cloud id err %{public}d", ret);
2088             return ret;
2089         }
2090         /* update */
2091         InsertAlbumIdChanges(record, addCloud, removeCloud);
2092     }
2093     return E_OK;
2094 }
2095 
GetDownloadAsset(std::string cloudId,vector<DriveKit::DKDownloadAsset> & outAssetsToDownload)2096 int32_t FileDataHandler::GetDownloadAsset(std::string cloudId, vector<DriveKit::DKDownloadAsset> &outAssetsToDownload)
2097 {
2098     vector<DKRecord> records;
2099     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
2100     predicates.SetWhereClause(Media::PhotoColumn::MEDIA_FILE_PATH + " = ?");
2101     predicates.SetWhereArgs({cloudId});
2102     predicates.Limit(LIMIT_SIZE);
2103     auto resultSet = Query(predicates, MEDIA_CLOUD_SYNC_COLUMNS);
2104     if (resultSet == nullptr) {
2105         LOGE("get nullptr created result");
2106         return E_RDB;
2107     }
2108     int32_t rowCount = 0;
2109     int32_t ret = resultSet->GetRowCount(rowCount);
2110     if (ret != 0) {
2111         LOGE("result set get row count err %{public}d", ret);
2112         return E_RDB;
2113     }
2114 
2115     ret = localConvertor_.ResultSetToRecords(move(resultSet), records);
2116     if (ret != 0) {
2117         LOGE("result set to records err %{public}d", ret);
2118         return ret;
2119     }
2120     for (const auto &record : records) {
2121         AppendToDownload(record, "content", outAssetsToDownload);
2122     }
2123 
2124     return E_OK;
2125 }
2126 
GetFileModifiedRecords(vector<DKRecord> & records)2127 int32_t FileDataHandler::GetFileModifiedRecords(vector<DKRecord> &records)
2128 {
2129     /* build predicates */
2130     NativeRdb::AbsRdbPredicates updatePredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
2131     updatePredicates
2132         .EqualTo(Media::PhotoColumn::PHOTO_DIRTY, to_string(static_cast<int32_t>(Media::DirtyType::TYPE_FDIRTY)))
2133         ->And()
2134         ->EqualTo(Media::PhotoColumn::MEDIA_DATE_TRASHED, "0")
2135         ->BeginWrap()
2136         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_IMAGE))
2137         ->Or()
2138         ->EqualTo(Media::PhotoColumn::MEDIA_TYPE, to_string(Media::MEDIA_TYPE_VIDEO))
2139         ->EndWrap();
2140     if (!modifyFailSet_.empty()) {
2141         updatePredicates.And()->NotIn(Media::PhotoColumn::PHOTO_CLOUD_ID, modifyFailSet_);
2142     }
2143     updatePredicates.Limit(LIMIT_SIZE);
2144 
2145     /* query */
2146     auto results = Query(updatePredicates, MEDIA_CLOUD_SYNC_COLUMNS);
2147     if (results == nullptr) {
2148         LOGE("get nullptr modified result");
2149         return E_RDB;
2150     }
2151 
2152     /* results to records */
2153     int ret = fdirtyConvertor_.ResultSetToRecords(move(results), records);
2154     if (ret != E_OK) {
2155         LOGE("result set to records err %{public}d", ret);
2156         return ret;
2157     }
2158 
2159     /* album map change */
2160     ret = BindAlbumChanges(records);
2161     if (ret != E_OK) {
2162         LOGE("update album map change err %{public}d", ret);
2163         return ret;
2164     }
2165 
2166     /* erase local info */
2167     ret = EraseLocalInfo(records);
2168     if (ret != E_OK) {
2169         LOGE("erase local info err %{public}d", ret);
2170         return ret;
2171     }
2172 
2173     return E_OK;
2174 }
2175 
EraseLocalInfo(vector<DriveKit::DKRecord> & records)2176 int32_t FileDataHandler::EraseLocalInfo(vector<DriveKit::DKRecord> &records)
2177 {
2178     for (auto &record : records) {
2179         DKRecordData data;
2180         record.GetRecordData(data);
2181         DKRecordFieldMap attributes;
2182         data[FILE_ATTRIBUTES].GetRecordMap(attributes);
2183         attributes.erase(Media::MediaColumn::MEDIA_ID);
2184         attributes.erase(Media::PhotoColumn::PHOTO_CLOUD_ID);
2185         data[FILE_ATTRIBUTES] = DKRecordField(attributes);
2186         record.SetRecordData(data);
2187     }
2188     return E_OK;
2189 }
2190 
GetFilePathFromRecord(const DKRecord & record)2191 static string GetFilePathFromRecord(const DKRecord &record)
2192 {
2193     DKRecordData data;
2194     record.GetRecordData(data);
2195     if (data.find(FILE_ATTRIBUTES) == data.end()) {
2196         LOGE("record data cannot find attributes");
2197         return "";
2198     }
2199     DriveKit::DKRecordFieldMap attributes = data[FILE_ATTRIBUTES];
2200     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end()) {
2201         LOGE("record data cannot find file path");
2202         return "";
2203     }
2204     string path;
2205     if (attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(path) != DKLocalErrorCode::NO_ERROR) {
2206         LOGE("bad file_path in props");
2207         return "";
2208     }
2209     return path;
2210 }
2211 
OnCreateRecords(const map<DKRecordId,DKRecordOperResult> & map)2212 int32_t FileDataHandler::OnCreateRecords(const map<DKRecordId, DKRecordOperResult> &map)
2213 {
2214     std::map<std::string, std::pair<std::int64_t, std::int64_t>> localMap;
2215     GetLocalTimeMap(map, localMap, Media::PhotoColumn::MEDIA_FILE_PATH);
2216 
2217     int32_t ret = E_OK;
2218     for (auto &entry : map) {
2219         int32_t err;
2220         const DKRecordOperResult &result = entry.second;
2221         if (result.IsSuccess()) {
2222             err = OnCreateRecordSuccess(entry, localMap);
2223         } else {
2224             err = OnRecordFailed(entry);
2225         }
2226         if (err != E_OK) {
2227             string filePath = GetFilePathFromRecord(entry.second.GetDKRecord());
2228             if (!filePath.empty()) {
2229                 createFailSet_.push_back(filePath);
2230             }
2231             LOGE("create record fail: file path %{private}s", filePath.c_str());
2232         }
2233         if ((err == E_STOP) || (err == E_CLOUD_STORAGE_FULL) || (err == E_SYNC_FAILED_NETWORK_NOT_AVAILABLE)) {
2234             ret = err;
2235         }
2236     }
2237     (void)DataSyncNotifier::GetInstance().FinalNotify();
2238     return ret;
2239 }
2240 
OnDeleteRecords(const map<DKRecordId,DKRecordOperResult> & map)2241 int32_t FileDataHandler::OnDeleteRecords(const map<DKRecordId, DKRecordOperResult> &map)
2242 {
2243     int32_t ret = E_OK;
2244     for (auto &entry : map) {
2245         const DKRecordOperResult &result = entry.second;
2246         int32_t err;
2247         if (result.IsSuccess()) {
2248             err = OnDeleteRecordSuccess(entry);
2249         } else {
2250             err = OnRecordFailed(entry);
2251         }
2252         if (err != E_OK) {
2253             modifyFailSet_.push_back(entry.first);
2254             LOGE("delete record fail: cloud id: %{private}s", entry.first.c_str());
2255         }
2256         if ((err == E_STOP) || (err == E_CLOUD_STORAGE_FULL) || (err == E_SYNC_FAILED_NETWORK_NOT_AVAILABLE)) {
2257             ret = err;
2258         }
2259     }
2260     return ret;
2261 }
2262 
OnModifyMdirtyRecords(const map<DKRecordId,DKRecordOperResult> & map)2263 int32_t FileDataHandler::OnModifyMdirtyRecords(const map<DKRecordId, DKRecordOperResult> &map)
2264 {
2265     std::map<std::string, std::pair<std::int64_t, std::int64_t>> localMap;
2266     GetLocalTimeMap(map, localMap, Media::PhotoColumn::PHOTO_CLOUD_ID);
2267 
2268     int32_t ret = E_OK;
2269     for (auto &entry : map) {
2270         int32_t err;
2271         const DKRecordOperResult &result = entry.second;
2272         if (result.IsSuccess()) {
2273             err = OnModifyRecordSuccess(entry, localMap);
2274         } else {
2275             err = OnRecordFailed(entry);
2276         }
2277         if (err != E_OK) {
2278             modifyFailSet_.push_back(entry.first);
2279             LOGE("modify mdirty record fail: cloud id: %{private}s", entry.first.c_str());
2280         }
2281         if ((err == E_STOP) || (err == E_CLOUD_STORAGE_FULL) || (err == E_SYNC_FAILED_NETWORK_NOT_AVAILABLE)) {
2282             ret = err;
2283         }
2284     }
2285     return ret;
2286 }
2287 
OnModifyFdirtyRecords(const map<DKRecordId,DKRecordOperResult> & map)2288 int32_t FileDataHandler::OnModifyFdirtyRecords(const map<DKRecordId, DKRecordOperResult> &map)
2289 {
2290     std::map<std::string, std::pair<std::int64_t, std::int64_t>> localMap;
2291     GetLocalTimeMap(map, localMap, Media::PhotoColumn::PHOTO_CLOUD_ID);
2292 
2293     int32_t ret = E_OK;
2294     for (auto &entry : map) {
2295         int32_t err;
2296         const DKRecordOperResult &result = entry.second;
2297         if (result.IsSuccess()) {
2298             err = OnModifyRecordSuccess(entry, localMap);
2299         } else {
2300             err = OnRecordFailed(entry);
2301         }
2302         if (err != E_OK) {
2303             modifyFailSet_.push_back(entry.first);
2304             LOGE("modify fdirty record fail: cloud id: %{public}s", entry.first.c_str());
2305         }
2306         if ((err == E_STOP) || (err == E_CLOUD_STORAGE_FULL) || (err == E_SYNC_FAILED_NETWORK_NOT_AVAILABLE)) {
2307             ret = err;
2308         }
2309     }
2310     return ret;
2311 }
2312 
Reset()2313 void FileDataHandler::Reset()
2314 {
2315     modifyFailSet_.clear();
2316     createFailSet_.clear();
2317 }
2318 
OnCreateRecordSuccess(const std::pair<DKRecordId,DKRecordOperResult> & entry,const std::map<std::string,std::pair<std::int64_t,std::int64_t>> & localMap)2319 int32_t FileDataHandler::OnCreateRecordSuccess(
2320     const std::pair<DKRecordId, DKRecordOperResult> &entry,
2321     const std::map<std::string, std::pair<std::int64_t, std::int64_t>> &localMap)
2322 {
2323     auto record = entry.second.GetDKRecord();
2324 
2325     DKRecordData data;
2326     record.GetRecordData(data);
2327     if (data.find(FILE_ATTRIBUTES) == data.end()) {
2328         LOGE("record data cannot find attributes");
2329         return E_INVAL_ARG;
2330     }
2331     DriveKit::DKRecordFieldMap attributes = data[FILE_ATTRIBUTES];
2332     if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end()) {
2333         LOGE("record data cannot find file path");
2334         return E_INVAL_ARG;
2335     }
2336 
2337     string path;
2338     if (attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(path) != DKLocalErrorCode::NO_ERROR) {
2339         LOGE("bad file_path in props");
2340         return E_INVAL_ARG;
2341     }
2342 
2343     ValuesBucket valuesBucket;
2344     valuesBucket.PutString(Media::PhotoColumn::PHOTO_CLOUD_ID, entry.first);
2345     valuesBucket.PutInt(Media::PhotoColumn::PHOTO_POSITION, POSITION_BOTH);
2346     valuesBucket.PutLong(Media::PhotoColumn::PHOTO_CLOUD_VERSION, record.GetVersion());
2347     int32_t changedRows;
2348     string whereClause = Media::PhotoColumn::MEDIA_FILE_PATH + " = ?";
2349     vector<string> whereArgs = {path};
2350 
2351     /* compare mtime and metatime */
2352     if (IfTimeChanged(record, localMap, path, Media::PhotoColumn::MEDIA_DATE_MODIFIED)) {
2353         valuesBucket.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_FDIRTY));
2354     } else if (IfTimeChanged(record, localMap, path, PhotoColumn::PHOTO_META_DATE_MODIFIED)) {
2355         valuesBucket.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY));
2356     } else {
2357         valuesBucket.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
2358     }
2359 
2360     /* update file */
2361     int32_t ret = Update(changedRows, valuesBucket, whereClause, whereArgs);
2362     if (ret != 0) {
2363         LOGE("on create records update synced err %{public}d", ret);
2364         return ret;
2365     }
2366 
2367     /* notify */
2368     int32_t fileId;
2369     if (data[FILE_LOCAL_ID].GetInt(fileId) == DKLocalErrorCode::NO_ERROR) {
2370         (void)DataSyncNotifier::GetInstance().TryNotify(DataSyncConst::PHOTO_URI_PREFIX + to_string(fileId),
2371             ChangeType::UPDATE, to_string(fileId));
2372     }
2373 
2374     /* update album map */
2375     ret = UpdateLocalAlbumMap(entry.first);
2376     if (ret != E_OK) {
2377         LOGE("update local album map err %{public}d", ret);
2378         return ret;
2379     }
2380 
2381     return E_OK;
2382 }
2383 
OnDeleteRecordSuccess(const std::pair<DKRecordId,DKRecordOperResult> & entry)2384 int32_t FileDataHandler::OnDeleteRecordSuccess(const std::pair<DKRecordId, DKRecordOperResult> &entry)
2385 {
2386     string cloudId = entry.first;
2387     /* delete local */
2388     int32_t deletedRows;
2389     string whereClause = Media::PhotoColumn::PHOTO_CLOUD_ID + " = ?";
2390     int32_t ret = Delete(deletedRows, whereClause, {cloudId});
2391     if (ret != 0) {
2392         LOGE("on delete records update err %{public}d", ret);
2393         return ret;
2394     }
2395     DeleteAssetInPhotoMap(deletedRows);
2396     return E_OK;
2397 }
2398 
OnModifyRecordSuccess(const std::pair<DKRecordId,DKRecordOperResult> & entry,const std::map<std::string,std::pair<std::int64_t,std::int64_t>> & localMap)2399 int32_t FileDataHandler::OnModifyRecordSuccess(
2400     const std::pair<DKRecordId, DKRecordOperResult> &entry,
2401     const std::map<std::string, std::pair<std::int64_t, std::int64_t>> &localMap)
2402 {
2403     auto record = entry.second.GetDKRecord();
2404     DKRecordData data;
2405     record.GetRecordData(data);
2406     string cloudId = entry.first;
2407 
2408     /* compare mtime */
2409     if (IfTimeChanged(record, localMap, cloudId, Media::PhotoColumn::MEDIA_DATE_MODIFIED)) {
2410         LOGI("mtime changed, need to update fdirty");
2411         return E_OK;
2412     }
2413     /* record to value bucket */
2414     ValuesBucket valuesBucket;
2415     valuesBucket.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED));
2416 
2417     int32_t changedRows;
2418     string whereClause = Media::PhotoColumn::PHOTO_CLOUD_ID + " = ?";
2419     valuesBucket.PutLong(Media::PhotoColumn::PHOTO_CLOUD_VERSION, record.GetVersion());
2420     int32_t ret = Update(changedRows, valuesBucket, whereClause, {cloudId});
2421     if (ret != 0) {
2422         LOGE("on modify records update synced err %{public}d", ret);
2423         return ret;
2424     }
2425 
2426     /* compare metatime */
2427     if (IfTimeChanged(record, localMap, cloudId, PhotoColumn::PHOTO_META_DATE_MODIFIED)) {
2428         LOGI("metatime changed, need to update mdirty");
2429         valuesBucket.PutInt(Media::PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(Media::DirtyType::TYPE_MDIRTY));
2430         ret = Update(changedRows, valuesBucket, whereClause, {cloudId});
2431         if (ret != 0) {
2432             LOGE("on modify records update mdirty err %{public}d", ret);
2433             return ret;
2434         }
2435     }
2436 
2437     /* update album map */
2438     ret = UpdateLocalAlbumMap(entry.first);
2439     if (ret != E_OK) {
2440         LOGE("update local album map err %{public}d", ret);
2441         return ret;
2442     }
2443 
2444     return E_OK;
2445 }
2446 
UpdateLocalAlbumMap(const string & cloudId)2447 int32_t FileDataHandler::UpdateLocalAlbumMap(const string &cloudId)
2448 {
2449     /* update new */
2450     string newSql = "UPDATE " + PM::TABLE + " SET " + PM::DIRTY + " = " +
2451         to_string(static_cast<int32_t>(Media::DirtyType::TYPE_SYNCED)) + " WHERE " + PM::ASSET_ID +
2452         " IN (SELECT " + PC::MEDIA_ID + " FROM " + PC::PHOTOS_TABLE + " WHERE " +
2453         PC::PHOTO_CLOUD_ID + " = '" + cloudId + "')";
2454     int32_t ret = ExecuteSql(newSql);
2455     if (ret != NativeRdb::E_OK) {
2456         LOGE("Update local album map err %{public}d", ret);
2457         return ret;
2458     }
2459     /* update deleted */
2460     string deleteSql = "DELETE FROM " + PM::TABLE + " WHERE " + PM::DIRTY + " = " +
2461         to_string(static_cast<int32_t>(Media::DirtyType::TYPE_DELETED)) + " AND " + PM::ASSET_ID +
2462         " IN (SELECT " + PC::MEDIA_ID + " FROM " + PC::PHOTOS_TABLE + " WHERE " +
2463         PC::PHOTO_CLOUD_ID + " = '" + cloudId + "')";
2464     ret = ExecuteSql(deleteSql);
2465     if (ret != NativeRdb::E_OK) {
2466         LOGE("delete local album map err %{public}d", ret);
2467         return ret;
2468     }
2469     return ret;
2470 }
2471 
IfTimeChanged(const DriveKit::DKRecord & record,const std::map<std::string,std::pair<std::int64_t,std::int64_t>> & localMap,const std::string & path,const std::string & type)2472 bool FileDataHandler::IfTimeChanged(
2473     const DriveKit::DKRecord &record,
2474     const std::map<std::string, std::pair<std::int64_t, std::int64_t>> &localMap,
2475     const std::string &path,
2476     const std::string &type)
2477 {
2478     int64_t cloudtime = 0;
2479     int64_t localtime = 0;
2480     auto it = localMap.find(path);
2481     if (it == localMap.end()) {
2482         return true;
2483     }
2484     /* get mtime or metatime */
2485     if (type == Media::PhotoColumn::MEDIA_DATE_MODIFIED) {
2486         localtime = it->second.first;
2487         cloudtime = static_cast<int64_t>(record.GetEditedTime()) / MILLISECOND_TO_SECOND;
2488     } else {
2489         localtime = it->second.second;
2490         DKRecordData data;
2491         record.GetRecordData(data);
2492         if (data.find(FILE_ATTRIBUTES) == data.end()) {
2493             LOGE("record data cannot find attributes");
2494             return false;
2495         }
2496         DriveKit::DKRecordFieldMap attributes;
2497         data[FILE_ATTRIBUTES].GetRecordMap(attributes);
2498         if (attributes[PhotoColumn::PHOTO_META_DATE_MODIFIED].GetLong(cloudtime) != DKLocalErrorCode::NO_ERROR) {
2499             LOGE("obtain PHOTO_META_DATE_MODIFIED error");
2500             return false;
2501         }
2502     }
2503     if (localtime == cloudtime) {
2504         return false;
2505     }
2506     return true;
2507 }
2508 
GetLocalTimeMap(const std::map<DKRecordId,DKRecordOperResult> & map,std::map<std::string,std::pair<std::int64_t,std::int64_t>> & cloudMap,const std::string & type)2509 void FileDataHandler::GetLocalTimeMap(const std::map<DKRecordId, DKRecordOperResult> &map,
2510                                       std::map<std::string, std::pair<std::int64_t, std::int64_t>> &cloudMap,
2511                                       const std::string &type)
2512 {
2513     std::vector<std::string> path;
2514     for (auto &entry : map) {
2515         if (type == Media::PhotoColumn::PHOTO_CLOUD_ID) {
2516             path.push_back(entry.first);
2517         } else {
2518             auto record = entry.second.GetDKRecord();
2519             DKRecordData data;
2520             record.GetRecordData(data);
2521             if (data.find(FILE_ATTRIBUTES) == data.end()) {
2522                 LOGE("record data cannot find attributes");
2523                 return;
2524             }
2525             DriveKit::DKRecordFieldMap attributes = data[FILE_ATTRIBUTES];
2526             if (attributes.find(PhotoColumn::MEDIA_FILE_PATH) == attributes.end()) {
2527                 LOGE("record data cannot find some attributes");
2528                 return;
2529             }
2530             string curPath;
2531             if (attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(curPath) != DKLocalErrorCode::NO_ERROR) {
2532                 LOGE("bad file_path in props");
2533                 return;
2534             }
2535             path.push_back(curPath);
2536         }
2537     }
2538     NativeRdb::AbsRdbPredicates createPredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME);
2539     createPredicates.And()->In(type, path);
2540     auto resultSet = Query(createPredicates, MEDIA_CLOUD_SYNC_COLUMNS);
2541     if (resultSet == nullptr) {
2542         return;
2543     }
2544 
2545     OnResultSetConvertToMap(move(resultSet), cloudMap, type);
2546 }
2547 
OnResultSetConvertToMap(const shared_ptr<NativeRdb::ResultSet> resultSet,std::map<std::string,std::pair<std::int64_t,std::int64_t>> & cloudMap,const std::string & type)2548 void FileDataHandler::OnResultSetConvertToMap(const shared_ptr<NativeRdb::ResultSet> resultSet,
2549                                               std::map<std::string, std::pair<std::int64_t, std::int64_t>> &cloudMap,
2550                                               const std::string &type)
2551 {
2552     int32_t idIndex = -1;
2553     int32_t mtimeIndex = -1;
2554     int32_t metatimeIndex = -1;
2555     resultSet->GetColumnIndex(type, idIndex);
2556     resultSet->GetColumnIndex(Media::PhotoColumn::MEDIA_DATE_MODIFIED, mtimeIndex);
2557     resultSet->GetColumnIndex(PhotoColumn::PHOTO_META_DATE_MODIFIED, metatimeIndex);
2558 
2559     /* iterate all rows compare mtime metatime */
2560     while (resultSet->GoToNextRow() == 0) {
2561         string idValue;
2562         int64_t mtime;
2563         int64_t metatime;
2564         if (resultSet->GetString(idIndex, idValue) == 0 && resultSet->GetLong(mtimeIndex, mtime) == 0 &&
2565             resultSet->GetLong(metatimeIndex, metatime) == 0) {
2566             cloudMap.insert(std::make_pair(idValue, std::make_pair(mtime, metatime)));
2567         }
2568     }
2569 }
2570 
OnRecordFailed(const std::pair<DKRecordId,DKRecordOperResult> & entry)2571 int32_t FileDataHandler::OnRecordFailed(const std::pair<DKRecordId, DKRecordOperResult> &entry)
2572 {
2573     const DKRecordOperResult &result = entry.second;
2574     int32_t serverErrorCode = INT32_MAX;
2575     serverErrorCode = result.GetDKError().serverErrorCode;
2576     LOGE("serverErrorCode %{public}d", serverErrorCode);
2577     if (result.GetDKError().errorDetails.size() == 0) {
2578         LOGE("errorDetails is empty");
2579         return E_INVAL_ARG;
2580     }
2581     string errorDetailcode = "";
2582     errorDetailcode = result.GetDKError().errorDetails[0].errorCode;
2583     if (static_cast<DKServerErrorCode>(serverErrorCode) == DKServerErrorCode::ACCESS_DENIED &&
2584         errorDetailcode == SPACE_NOT_ENOUGH) {
2585         return HandleCloudSpaceNotEnough();
2586     } else if (static_cast<DKServerErrorCode>(serverErrorCode) == DKServerErrorCode::AUTHENTICATION_FAILED &&
2587                errorDetailcode == AT_FAILED) {
2588         return HandleATFailed();
2589     } else if (static_cast<DKServerErrorCode>(serverErrorCode) == DKServerErrorCode::ACCESS_DENIED &&
2590                errorDetailcode == NAME_CONFLICT) {
2591         return HandleNameConflict();
2592     } else if (static_cast<DKServerErrorCode>(serverErrorCode) == DKServerErrorCode::ATOMIC_ERROR &&
2593                errorDetailcode == INVALID_FILE) {
2594         return HandleNameInvalid();
2595     } else if (static_cast<DKServerErrorCode>(serverErrorCode) == DKServerErrorCode::NETWORK_ERROR) {
2596         LOGE("errorDetailcode = %{public}s", errorDetailcode.c_str());
2597         return HandleNetworkErr();
2598     } else {
2599         LOGE(" unknown error code record failed, serverErrorCode = %{public}d, errorDetailcode = %{public}s",
2600              serverErrorCode, errorDetailcode.c_str());
2601         return E_STOP;
2602     }
2603     return E_OK;
2604 }
2605 
HandleCloudSpaceNotEnough()2606 int32_t FileDataHandler::HandleCloudSpaceNotEnough()
2607 {
2608     LOGE("Cloud Space Not Enough");
2609     /* Stop sync */
2610     return E_CLOUD_STORAGE_FULL;
2611 }
2612 
HandleATFailed()2613 int32_t FileDataHandler::HandleATFailed()
2614 {
2615     LOGE("AT Failed");
2616     return E_DATA;
2617 }
2618 
HandleNameConflict()2619 int32_t FileDataHandler::HandleNameConflict()
2620 {
2621     LOGE("Name Conflict");
2622     return E_DATA;
2623 }
2624 
HandleNameInvalid()2625 int32_t FileDataHandler::HandleNameInvalid()
2626 {
2627     LOGE("Name Invalid");
2628     return E_DATA;
2629 }
2630 
HandleNetworkErr()2631 int32_t FileDataHandler::HandleNetworkErr()
2632 {
2633     LOGE("Network Error");
2634     return E_SYNC_FAILED_NETWORK_NOT_AVAILABLE;
2635 }
2636 
UTCTimeSeconds()2637 int64_t FileDataHandler::UTCTimeSeconds()
2638 {
2639     struct timespec ts;
2640     ts.tv_sec = 0;
2641     ts.tv_nsec = 0;
2642     clock_gettime(CLOCK_REALTIME, &ts);
2643     return static_cast<int64_t>(ts.tv_sec);
2644 }
2645 } // namespace CloudSync
2646 } // namespace FileManagement
2647 } // namespace OHOS
2648