1 /*
2 * Copyright (C) 2025 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 #define MLOG_TAG "PhotosDataHandler"
16
17 #include "photos_data_handler.h"
18
19 #include <sstream>
20
21 #include "backup_database_utils.h"
22 #include "backup_file_utils.h"
23 #include "ffrt.h"
24 #include "ffrt_inner.h"
25 #include "media_file_utils.h"
26 #include "upgrade_restore_task_report.h"
27
28 namespace OHOS::Media {
OnStart(int32_t sceneCode,const std::string & taskId,std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb)29 void PhotosDataHandler::OnStart(int32_t sceneCode, const std::string &taskId,
30 std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb)
31 {
32 SetSceneCode(sceneCode).SetTaskId(taskId).SetMediaLibraryRdb(mediaLibraryRdb);
33 }
34
SetSceneCode(int32_t sceneCode)35 PhotosDataHandler &PhotosDataHandler::SetSceneCode(int32_t sceneCode)
36 {
37 sceneCode_ = sceneCode;
38 return *this;
39 }
40
SetTaskId(const std::string & taskId)41 PhotosDataHandler &PhotosDataHandler::SetTaskId(const std::string &taskId)
42 {
43 taskId_ = taskId;
44 return *this;
45 }
46
SetMediaLibraryRdb(std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb)47 PhotosDataHandler &PhotosDataHandler::SetMediaLibraryRdb(std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb)
48 {
49 mediaLibraryRdb_ = mediaLibraryRdb;
50 photosDao_.SetMediaLibraryRdb(mediaLibraryRdb);
51 return *this;
52 }
53
HandleDirtyFiles()54 void PhotosDataHandler::HandleDirtyFiles()
55 {
56 int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
57 int32_t totalNumber = photosDao_.GetDirtyFilesCount();
58 MEDIA_INFO_LOG("totalNumber = %{public}d", totalNumber);
59 ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
60 int64_t startClean = MediaFileUtils::UTCTimeMilliSeconds();
61 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
62 ffrt::submit([this, offset]() { HandleDirtyFilesBatch(offset); }, { &offset }, {},
63 ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
64 }
65 ffrt::wait();
66 int64_t startDelete = MediaFileUtils::UTCTimeMilliSeconds();
67 int32_t deleteCount = PhotosDataHandler::DeleteDirtyFilesInDb();
68 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
69 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
70 .Report("HANDLE_DIRTY_FILES", "",
71 "total dirty count: " + std::to_string(totalNumber) +
72 ", query total cost: " + std::to_string(startClean - startQuery) +
73 "; clean files count: " + std::to_string(dirtyFileCleanNumber_) +
74 ", clean files cost: " + std::to_string(startDelete - startClean) +
75 ", failed clean files count: " + std::to_string(failedDirtyFileCleanNumber_) +
76 "; clean db count: " + std::to_string(deleteCount) +
77 ", delete in db cost: " + std::to_string(end - startDelete));
78 }
79
HandleDirtyFilesBatch(int32_t offset)80 void PhotosDataHandler::HandleDirtyFilesBatch(int32_t offset)
81 {
82 MEDIA_INFO_LOG("start clean dirty files offset: %{public}d", offset);
83 int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
84 std::vector<PhotosDao::PhotosRowData> dirtyFiles = photosDao_.GetDirtyFiles(offset);
85 int64_t startClean = MediaFileUtils::UTCTimeMilliSeconds();
86 int32_t count = CleanDirtyFiles(dirtyFiles);
87 dirtyFileCleanNumber_ += count;
88 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
89 MEDIA_INFO_LOG("query %{public}zu dirty files cost %{public}" PRId64", clean cost %{public}" PRId64,
90 dirtyFiles.size(), startClean - startQuery, end - startClean);
91 }
92
CleanDirtyFiles(const std::vector<PhotosDao::PhotosRowData> & dirtyFiles)93 int32_t PhotosDataHandler::CleanDirtyFiles(const std::vector<PhotosDao::PhotosRowData> &dirtyFiles)
94 {
95 int32_t count = 0;
96 CHECK_AND_RETURN_RET(!dirtyFiles.empty(), count);
97 for (const auto &dirtyFile : dirtyFiles) {
98 // clean cloud path
99 bool deleteFileRet = MediaFileUtils::DeleteFileOrFolder(dirtyFile.data, true);
100 // clean thumbs folder
101 std::string thumbsFolder =
102 BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::CLOUD_THUMB, dirtyFile.data);
103 bool deleteThumbsRet = MediaFileUtils::DeleteFileOrFolder(thumbsFolder, false);
104 if (!deleteFileRet || !deleteThumbsRet) {
105 std::lock_guard<mutex> lock(cleanFailedFilesMutex_);
106 MEDIA_ERR_LOG("Clean file failed, path: %{public}s, ret: %{public}d, errno: %{public}d",
107 BackupFileUtils::GarbleFilePath(dirtyFile.data, sceneCode_).c_str(),
108 static_cast<int32_t>(deleteFileRet), static_cast<int32_t>(deleteThumbsRet), errno);
109 cleanFailedFiles_.push_back(to_string(dirtyFile.fileId));
110 failedDirtyFileCleanNumber_++;
111 continue;
112 }
113 count++;
114 }
115 return count;
116 }
117
DeleteDirtyFilesInDb()118 int32_t PhotosDataHandler::DeleteDirtyFilesInDb()
119 {
120 // clean database
121 NativeRdb::AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
122 predicates.EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
123 predicates.NotIn(MediaColumn::MEDIA_ID, cleanFailedFiles_);
124 int32_t changedRows = 0;
125 int32_t deleteDbRet = BackupDatabaseUtils::Delete(predicates, changedRows, mediaLibraryRdb_);
126 MEDIA_INFO_LOG("changedRows: %{public}d, deleteRet: %{public}d", changedRows, deleteDbRet);
127 return changedRows;
128 }
129 } // namespace OHOS::Media
130