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 ¶ms)
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 ¶ms)
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 ¶ms)
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 ¶ms)
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 ¶ms)
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