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
16 #define MLOG_TAG "MediaLibraryCloneRestoreHighlight"
17
18 #include "clone_restore_highlight.h"
19
20 #include "backup_file_utils.h"
21 #include "medialibrary_data_manager_utils.h"
22 #include "media_file_utils.h"
23 #include "upgrade_restore_task_report.h"
24
25 namespace OHOS::Media {
26 const int32_t PAGE_SIZE = 200;
27 const std::vector<std::string> HIGHLIGHT_RATIO_WORD_ART = { "1_1", "3_2", "3_4", "microcard", "medium_card",
28 "big_card", "screen_0_ver", "screen_0_hor" };
29 const std::vector<std::string> HIGHLIGHT_COVER_NAME = { "foreground", "background" };
30 const std::string MUSIC_DIR_DST_PATH = "/storage/media/local/files/highlight/music";
31 const std::string GARBLE_DST_PATH = "/storage/media/local/files";
32 const int32_t HIGHLIGHT_STATUS_NOT_PRODUCE = -1;
33 const int32_t HIGHLIGHT_STATUS_DELETE = -4;
34 const std::string RESTORE_STATUS_SUCCESS = "1";
35
36 const std::unordered_map<std::string, std::unordered_set<std::string>> ALBUM_COLUMNS_MAP = {
37 { "AnalysisAlbum",
38 {
39 "album_id",
40 "album_type",
41 "album_subtype",
42 "album_name",
43 "cover_uri",
44 "count",
45 "date_modified",
46 "rank",
47 "tag_id",
48 "user_operation",
49 "group_tag",
50 "user_display_level",
51 "is_me",
52 "is_removed",
53 "rename_operation",
54 "is_local",
55 "is_cover_satisfied",
56 "relationship"
57 }
58 },
59 { "AnalysisPhotoMap",
60 {
61 "map_album",
62 "map_asset",
63 "order_position"
64 }
65 },
66 { "tab_highlight_album",
67 {
68 "id",
69 "album_id",
70 "ai_album_id",
71 "sub_title",
72 "cluster_type",
73 "cluster_sub_type",
74 "cluster_condition",
75 "min_date_added",
76 "max_date_added",
77 "generate_time",
78 "highlight_version",
79 "remarks",
80 "highlight_status",
81 "insert_pic_count",
82 "remove_pic_count",
83 "share_screenshot_count",
84 "share_cover_count",
85 "rename_count",
86 "change_cover_count",
87 "render_viewed_times",
88 "render_viewed_duration",
89 "art_layout_viewed_times",
90 "art_layout_viewed_duration",
91 "music_edit_count",
92 "filter_edit_count",
93 "is_muted",
94 "is_favorite",
95 "theme",
96 "pin_time",
97 "use_subtitle",
98 "highlight_location"
99 }
100 },
101 { "tab_highlight_cover_info",
102 {
103 "album_id",
104 "ratio",
105 "background",
106 "foreground",
107 "wordart",
108 "is_covered",
109 "color",
110 "radius",
111 "saturation",
112 "brightness",
113 "background_color_type",
114 "shadow_level",
115 "title_scale_x",
116 "title_scale_y",
117 "title_rect_width",
118 "title_rect_height",
119 "background_scale_x",
120 "background_scale_y",
121 "background_rect_width",
122 "background_rect_height",
123 "is_chosen",
124 "layout_index",
125 "cover_algo_version",
126 "cover_service_version",
127 "cover_key",
128 "status"
129 }
130 },
131 { "tab_highlight_play_info",
132 {
133 "album_id",
134 "music",
135 "filter",
136 "play_info",
137 "is_chosen",
138 "play_info_version",
139 "play_info_id",
140 "highlighting_algo_version",
141 "camera_movement_algo_version",
142 "transition_algo_version",
143 "play_service_version",
144 "status"
145 }
146 }
147 };
148
149 template<typename Key, typename Value>
GetValueFromMap(const std::unordered_map<Key,Value> & map,const Key & key,const Value & defaultValue=Value ())150 Value GetValueFromMap(const std::unordered_map<Key, Value> &map, const Key &key, const Value &defaultValue = Value())
151 {
152 auto it = map.find(key);
153 CHECK_AND_RETURN_RET(it != map.end(), defaultValue);
154 return it->second;
155 }
156
Init(const InitInfo & info)157 void CloneRestoreHighlight::Init(const InitInfo &info)
158 {
159 sceneCode_ = info.sceneCode;
160 taskId_ = info.taskId;
161 mediaLibraryRdb_ = info.mediaLibraryRdb;
162 mediaRdb_ = info.mediaRdb;
163
164 std::string highlightSourcePath = info.backupRestoreDir + "/storage/media/local/files/highlight/";
165 isHighlightDirExist_ = MediaFileUtils::IsDirectory(highlightSourcePath);
166 MEDIA_INFO_LOG("/highlight/ source dir %{public}s.", isHighlightDirExist_ ? "exist" : "don't exist");
167 coverPath_ = highlightSourcePath + "cover/";
168 musicDir_ = highlightSourcePath + "music";
169 garblePath_ = info.backupRestoreDir + GARBLE_DST_PATH;
170
171 photoInfoMap_ = info.photoInfoMap;
172 }
173
Restore()174 void CloneRestoreHighlight::Restore()
175 {
176 int64_t startPreprocess = MediaFileUtils::UTCTimeMilliSeconds();
177 Preprocess();
178 int64_t startRestoreAlbums = MediaFileUtils::UTCTimeMilliSeconds();
179 RestoreAlbums();
180 int64_t startRestoreMaps = MediaFileUtils::UTCTimeMilliSeconds();
181 RestoreMaps();
182 int64_t startUpdateAlbums = MediaFileUtils::UTCTimeMilliSeconds();
183 UpdateAlbums();
184 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
185 restoreTimeCost_ += end - startPreprocess;
186 MEDIA_INFO_LOG("TimeCost: Preprocess: %{public}" PRId64 ",RestoreAlbums: %{public}" PRId64
187 ", RestoreMaps: %{public}" PRId64 ", UpdateAlbums: %{public}" PRId64, startRestoreAlbums - startPreprocess,
188 startRestoreMaps - startRestoreAlbums, startUpdateAlbums - startRestoreMaps, end - startUpdateAlbums);
189 }
190
Preprocess()191 void CloneRestoreHighlight::Preprocess()
192 {
193 CHECK_AND_RETURN_LOG(mediaRdb_ != nullptr && mediaLibraryRdb_ != nullptr, "rdbStore is nullptr.");
194 const std::vector<std::string> SQLS = {
195 "ALTER TABLE AnalysisAlbum ADD COLUMN need_restore_highlight INTEGER DEFAULT 0 ",
196 "UPDATE AnalysisAlbum SET need_restore_highlight = 1 "
197 " WHERE album_id IN (SELECT album_id FROM tab_highlight_album WHERE highlight_status > 0 "
198 " UNION SELECT ai_album_id FROM tab_highlight_album WHERE highlight_status > 0) ",
199 "CREATE INDEX idx_need_restore_highlight ON AnalysisAlbum(need_restore_highlight) "
200 " WHERE need_restore_highlight = 1 ",
201 };
202 for (const auto &sql : SQLS) {
203 int32_t errCode = BackupDatabaseUtils::ExecuteSQL(mediaRdb_, sql);
204 if (errCode != NativeRdb::E_OK) {
205 MEDIA_ERR_LOG("Execute %{public}s failed, errCode: %{public}d", sql.c_str(), errCode);
206 ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, std::to_string(errCode),
207 "clone restore highlight preprocess failed");
208 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
209 return;
210 }
211 }
212 isCloneHighlight_ = true;
213 }
214
RestoreAlbums()215 void CloneRestoreHighlight::RestoreAlbums()
216 {
217 CHECK_AND_RETURN_LOG(isCloneHighlight_, "clone highlight flag is false.");
218 MEDIA_INFO_LOG("restore highlight album start.");
219 isMapOrder_ = IsMapColumnOrderExist();
220 GetAnalysisAlbumInfos();
221 InsertIntoAnalysisAlbum();
222 GetHighlightAlbumInfos();
223 InsertIntoHighlightAlbum();
224 MoveHighlightCovers();
225 MoveHighlightMusic(musicDir_, MUSIC_DIR_DST_PATH);
226 GetHighlightCoverInfos();
227 InsertIntoHighlightCoverInfo();
228 GetHighlightPlayInfos();
229 InsertIntoHighlightPlayInfo();
230 }
231
RestoreMaps()232 void CloneRestoreHighlight::RestoreMaps()
233 {
234 CHECK_AND_RETURN_LOG(isCloneHighlight_, "clone highlight flag is false.");
235 MEDIA_INFO_LOG("restore highlight map start.");
236 int32_t totalNumber = GetTotalNumberOfMaps();
237 MEDIA_INFO_LOG("totalNumber: %{public}d", totalNumber);
238 for (int32_t offset = 0; offset < totalNumber; offset += PAGE_SIZE) {
239 RestoreMapsBatch();
240 }
241 }
242
GetTotalNumberOfMaps()243 int32_t CloneRestoreHighlight::GetTotalNumberOfMaps()
244 {
245 const std::string QUERY_SQL = "SELECT count(1) AS count FROM AnalysisPhotoMap AS map "
246 " INNER JOIN AnalysisAlbum AS a ON map.map_album = a.album_id "
247 " WHERE a.album_subtype IN (4104, 4105) AND a.need_restore_highlight = 1 ";
248 return BackupDatabaseUtils::QueryInt(mediaRdb_, QUERY_SQL, "count");
249 }
250
RestoreMapsBatch()251 void CloneRestoreHighlight::RestoreMapsBatch()
252 {
253 std::vector<NativeRdb::ValuesBucket> values;
254 int64_t startUpdateTime = MediaFileUtils::UTCTimeMilliSeconds();
255 UpdateMapInsertValues(values);
256 int64_t startInsertTime = MediaFileUtils::UTCTimeMilliSeconds();
257 InsertAnalysisPhotoMap(values);
258 int64_t endTime = MediaFileUtils::UTCTimeMilliSeconds();
259 MEDIA_INFO_LOG("TimeCost: UpdateMapInsertValues: %{public}" PRId64 ", InsertAnalysisPhotoMap: %{public}" PRId64,
260 startInsertTime - startUpdateTime, endTime - startInsertTime);
261 }
262
UpdateAlbums()263 void CloneRestoreHighlight::UpdateAlbums()
264 {
265 CHECK_AND_RETURN_LOG(isCloneHighlight_, "clone highlight flag is false.");
266 MEDIA_INFO_LOG("update highlight album start.");
267 const std::string UPDATE_ALBUM_SQL = "UPDATE AnalysisAlbum SET "
268 "cover_uri = ?, "
269 "count = (SELECT count(1) FROM AnalysisPhotoMap AS apm WHERE apm.map_album = AnalysisAlbum.album_id) "
270 "WHERE album_id = ?";
271 for (const auto &info : analysisInfos_) {
272 bool cond = (!info.oldCoverUri.has_value() || !info.albumIdNew.has_value());
273 CHECK_AND_CONTINUE(!cond);
274 BackupDatabaseUtils::ExecuteSQL(mediaLibraryRdb_, UPDATE_ALBUM_SQL, { info.coverUri,
275 info.albumIdNew.value() });
276 }
277
278 const std::string UPDATE_COVER_KEY_SQL = "UPDATE tab_highlight_cover_info SET cover_key = ? "
279 "WHERE album_id = ? AND ratio = ?";
280 for (const auto &coverInfo : coverInfos_) {
281 bool cond = (!coverInfo.ratio.has_value() || !coverInfo.highlightIdNew.has_value());
282 CHECK_AND_CONTINUE(!cond);
283 auto it = std::find_if(analysisInfos_.begin(), analysisInfos_.end(),
284 [coverInfo](const AnalysisAlbumInfo& info) { return info.highlightIdNew == coverInfo.highlightIdNew; });
285 cond = (it == analysisInfos_.end() || !it->albumName.has_value());
286 CHECK_AND_CONTINUE(!cond);
287 std::string coverUri = it->albumName.value() + "_" + coverInfo.ratio.value() + "_" + it->coverUri;
288 BackupDatabaseUtils::ExecuteSQL(mediaLibraryRdb_, UPDATE_COVER_KEY_SQL, { coverUri,
289 coverInfo.highlightIdNew.value(), coverInfo.ratio.value()});
290 }
291 }
292
GetNewHighlightAlbumId(int32_t oldId)293 int32_t CloneRestoreHighlight::GetNewHighlightAlbumId(int32_t oldId)
294 {
295 int32_t newId = -1;
296 auto it = std::find_if(highlightInfos_.begin(), highlightInfos_.end(),
297 [oldId](const HighlightAlbumInfo& info) { return info.highlightIdOld == oldId; });
298 bool cond = (it != highlightInfos_.end() && it->highlightIdNew.has_value());
299 CHECK_AND_EXECUTE(!cond, newId = it->highlightIdNew.value());
300 return newId;
301 }
302
GetNewHighlightPhotoId(int32_t oldId)303 int32_t CloneRestoreHighlight::GetNewHighlightPhotoId(int32_t oldId)
304 {
305 auto it = photoInfoMap_.find(oldId);
306 if (it == photoInfoMap_.end()) {
307 return 0;
308 }
309 return it->second.fileIdNew;
310 }
311
GetNewHighlightPhotoUri(int32_t oldId)312 std::string CloneRestoreHighlight::GetNewHighlightPhotoUri(int32_t oldId)
313 {
314 auto it = photoInfoMap_.find(oldId);
315 if (it == photoInfoMap_.end()) {
316 return "";
317 }
318 PhotoInfo photoInfo = it->second;
319 return MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
320 std::to_string(photoInfo.fileIdNew), MediaFileUtils::GetExtraUri(photoInfo.displayName, photoInfo.cloudPath));
321 }
322
IsCloneHighlight()323 bool CloneRestoreHighlight::IsCloneHighlight()
324 {
325 return isCloneHighlight_;
326 }
327
GetDefaultPlayInfo()328 std::string CloneRestoreHighlight::GetDefaultPlayInfo()
329 {
330 nlohmann::json playInfo;
331 playInfo["beatsInfo"] = nlohmann::json::array();
332 playInfo["effectline"] = nlohmann::json::object();
333 playInfo["effectline"]["effectline"] = nlohmann::json::array();
334 playInfo["timeline"] = nlohmann::json::array();
335 return playInfo.dump();
336 }
337
UpdateHighlightStatus(const std::vector<int32_t> & highlightIds)338 void CloneRestoreHighlight::UpdateHighlightStatus(const std::vector<int32_t> &highlightIds)
339 {
340 std::unordered_map<int32_t, std::vector<NativeRdb::ValueObject>> highlightStatusMap;
341 for (auto highlightId : highlightIds) {
342 auto it = std::find_if(highlightInfos_.begin(), highlightInfos_.end(),
343 [highlightId](const HighlightAlbumInfo &highlightInfo) {
344 return highlightInfo.highlightIdNew.has_value() && highlightInfo.highlightIdNew.value() == highlightId &&
345 highlightInfo.highlightStatus.has_value() && highlightInfo.highlightStatus.value() > 0;
346 });
347 CHECK_AND_CONTINUE(it != highlightInfos_.end());
348 UpdateHighlightStatusMap(it->highlightStatus.value(), highlightId, highlightStatusMap);
349 }
350 UpdateHighlightStatusInDatabase(highlightStatusMap);
351 }
352
UpdateHighlightStatusMap(int32_t highlightStatus,int32_t highlightId,std::unordered_map<int32_t,std::vector<NativeRdb::ValueObject>> & highlightStatusMap)353 void CloneRestoreHighlight::UpdateHighlightStatusMap(int32_t highlightStatus, int32_t highlightId,
354 std::unordered_map<int32_t, std::vector<NativeRdb::ValueObject>> &highlightStatusMap)
355 {
356 std::vector<NativeRdb::ValueObject> &highlightIds = highlightStatusMap[highlightStatus];
357 highlightIds.emplace_back(highlightId);
358 }
359
UpdateHighlightStatusInDatabase(const std::unordered_map<int32_t,std::vector<NativeRdb::ValueObject>> & highlightStatusMap)360 void CloneRestoreHighlight::UpdateHighlightStatusInDatabase(
361 const std::unordered_map<int32_t, std::vector<NativeRdb::ValueObject>> &highlightStatusMap)
362 {
363 CHECK_AND_RETURN(!highlightStatusMap.empty());
364 for (const auto &[highlightStatus, highlightIds] : highlightStatusMap) {
365 int32_t changedRows = -1;
366 std::unique_ptr<NativeRdb::AbsRdbPredicates> updatePredicates =
367 make_unique<NativeRdb::AbsRdbPredicates>("tab_highlight_album");
368 updatePredicates->In("id", highlightIds);
369 NativeRdb::ValuesBucket rdbValues;
370 rdbValues.PutInt("highlight_status", highlightStatus);
371 int32_t errCode = BackupDatabaseUtils::Update(mediaLibraryRdb_, changedRows, rdbValues, updatePredicates);
372 std::stringstream updateReport;
373 updateReport << "highlightStatus: " << highlightStatus << ", to be pushed: " << highlightIds.size() <<
374 ", update: " << changedRows;
375 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
376 .Report("CLONE_RESTORE_HIGHLIGHT_STATUS", std::to_string(errCode), updateReport.str());
377 }
378 }
379
GetMaxAlbumId(const std::string & tableName,const std::string & idName)380 int32_t CloneRestoreHighlight::GetMaxAlbumId(const std::string &tableName, const std::string &idName)
381 {
382 int32_t maxAlbumId = 1;
383 const std::string QUERY_SQL = "SELECT MAX(" + idName + ") " + idName + " FROM " + tableName;
384 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, QUERY_SQL);
385 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, -1, "query resultSql is null.");
386 if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
387 auto albumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, idName);
388 CHECK_AND_EXECUTE(!albumId.has_value(), maxAlbumId = albumId.value() + 1);
389 }
390 resultSet->Close();
391 return maxAlbumId;
392 }
393
IsMapColumnOrderExist()394 bool CloneRestoreHighlight::IsMapColumnOrderExist()
395 {
396 bool result = false;
397 std::unordered_set<std::string> intersection = GetCommonColumns("AnalysisPhotoMap");
398 CHECK_AND_EXECUTE(intersection.count("order_position") <= 0, result = true);
399 return result;
400 }
401
GetAnalysisAlbumInfos()402 void CloneRestoreHighlight::GetAnalysisAlbumInfos()
403 {
404 int32_t albumIdNow = GetMaxAlbumId("AnalysisAlbum", "album_id");
405 maxIdOfAlbum_ = albumIdNow;
406 int32_t rowCount = 0;
407 int32_t offset = 0;
408 do {
409 const std::string QUERY_SQL = "SELECT * FROM AnalysisAlbum "
410 " WHERE album_subtype IN (4104, 4105) AND need_restore_highlight = 1 "
411 " LIMIT " + std::to_string(offset) + ", " + std::to_string(PAGE_SIZE);
412 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, QUERY_SQL);
413 CHECK_AND_BREAK_INFO_LOG(resultSet != nullptr, "query resultSql is null.");
414 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
415 AnalysisAlbumInfo info;
416 GetAnalysisRowInfo(info, resultSet);
417 info.albumIdNew = std::make_optional<int32_t>(albumIdNow++);
418 analysisInfos_.emplace_back(info);
419 }
420 resultSet->GetRowCount(rowCount);
421 offset += PAGE_SIZE;
422 resultSet->Close();
423 } while (rowCount == PAGE_SIZE);
424 MEDIA_INFO_LOG("query AnalysisAlbum nums: %{public}zu", analysisInfos_.size());
425 }
426
GetAnalysisRowInfo(AnalysisAlbumInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)427 void CloneRestoreHighlight::GetAnalysisRowInfo(AnalysisAlbumInfo &info, std::shared_ptr<NativeRdb::ResultSet> resultSet)
428 {
429 if (intersectionMap_.find("AnalysisAlbum") == intersectionMap_.end()) {
430 intersectionMap_.insert(std::make_pair("AnalysisAlbum", GetCommonColumns("AnalysisAlbum")));
431 }
432 std::unordered_set<std::string>& intersection = intersectionMap_["AnalysisAlbum"];
433 GetIfInIntersection("album_id", info.albumIdOld, intersection, resultSet);
434 GetIfInIntersection("album_type", info.albumType, intersection, resultSet);
435 GetIfInIntersection("album_subtype", info.albumSubtype, intersection, resultSet);
436 GetIfInIntersection("album_name", info.albumName, intersection, resultSet);
437 GetIfInIntersection("cover_uri", info.oldCoverUri, intersection, resultSet);
438 GetIfInIntersection("date_modified", info.dateModified, intersection, resultSet);
439 GetIfInIntersection("rank", info.rank, intersection, resultSet);
440 GetIfInIntersection("tag_id", info.tagId, intersection, resultSet);
441 GetIfInIntersection("user_operation", info.userOperation, intersection, resultSet);
442 GetIfInIntersection("group_tag", info.groupTag, intersection, resultSet);
443 GetIfInIntersection("user_display_level", info.userDisplayLevel, intersection, resultSet);
444 GetIfInIntersection("is_me", info.isMe, intersection, resultSet);
445 GetIfInIntersection("is_removed", info.isRemoved, intersection, resultSet);
446 GetIfInIntersection("rename_operation", info.renameOperation, intersection, resultSet);
447 GetIfInIntersection("is_local", info.isLocal, intersection, resultSet);
448 GetIfInIntersection("is_cover_satisfied", info.isCoverSatisfied, intersection, resultSet);
449 GetIfInIntersection("relationship", info.relationship, intersection, resultSet);
450 UpdateAlbumCoverUri(info);
451 }
452
UpdateAlbumCoverUri(AnalysisAlbumInfo & info)453 void CloneRestoreHighlight::UpdateAlbumCoverUri(AnalysisAlbumInfo &info)
454 {
455 std::string fileIdOldStr = MediaFileUtils::GetIdFromUri(info.oldCoverUri.value_or(""));
456 CHECK_AND_RETURN(!fileIdOldStr.empty() && MediaLibraryDataManagerUtils::IsNumber(fileIdOldStr));
457 int32_t fileIdOld = std::atoi(fileIdOldStr.c_str());
458 info.coverUri = GetNewHighlightPhotoUri(fileIdOld);
459 MEDIA_INFO_LOG("oldCoverUri: %{public}s, newCoverUri: %{public}s.",
460 BackupFileUtils::GarbleFilePath(info.oldCoverUri.value_or(""), DEFAULT_RESTORE_ID).c_str(),
461 BackupFileUtils::GarbleFilePath(info.coverUri, DEFAULT_RESTORE_ID).c_str());
462 }
463
InsertIntoAnalysisAlbum()464 void CloneRestoreHighlight::InsertIntoAnalysisAlbum()
465 {
466 size_t offset = 0;
467 do {
468 std::vector<NativeRdb::ValuesBucket> values;
469 for (size_t index = 0; index < PAGE_SIZE && index + offset < analysisInfos_.size(); index++) {
470 NativeRdb::ValuesBucket value;
471 GetAnalysisInsertValue(value, analysisInfos_[index + offset]);
472 values.emplace_back(value);
473 }
474 int64_t rowNum = 0;
475 int32_t errCode = BatchInsertWithRetry("AnalysisAlbum", values, rowNum);
476 if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
477 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
478 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
479 "insert into AnalysisAlbum fail, num:" + std::to_string(failNums));
480 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
481 albumFailedCnt_ += failNums;
482 }
483 albumSuccessCnt_ += rowNum;
484 offset += PAGE_SIZE;
485 } while (offset < analysisInfos_.size());
486 }
487
GetAnalysisInsertValue(NativeRdb::ValuesBucket & value,const AnalysisAlbumInfo & info)488 void CloneRestoreHighlight::GetAnalysisInsertValue(NativeRdb::ValuesBucket &value, const AnalysisAlbumInfo &info)
489 {
490 std::unordered_set<std::string>& intersection = intersectionMap_["AnalysisAlbum"];
491 PutIfInIntersection(value, "album_id", info.albumIdNew, intersection);
492 PutIfInIntersection(value, "album_type", info.albumType, intersection);
493 PutIfInIntersection(value, "album_subtype", info.albumSubtype, intersection);
494 PutIfInIntersection(value, "album_name", info.albumName, intersection);
495 PutIfInIntersection(value, "date_modified", info.dateModified, intersection);
496 PutIfInIntersection(value, "rank", info.rank, intersection);
497 PutIfInIntersection(value, "tag_id", info.tagId, intersection);
498 PutIfInIntersection(value, "user_operation", info.userOperation, intersection);
499 PutIfInIntersection(value, "group_tag", info.groupTag, intersection);
500 PutIfInIntersection(value, "user_display_level", info.userDisplayLevel, intersection);
501 PutIfInIntersection(value, "is_me", info.isMe, intersection);
502 PutIfInIntersection(value, "is_removed", info.isRemoved, intersection);
503 PutIfInIntersection(value, "rename_operation", info.renameOperation, intersection);
504 PutIfInIntersection(value, "is_local", info.isLocal, intersection);
505 PutIfInIntersection(value, "is_cover_satisfied", info.isCoverSatisfied, intersection);
506 PutIfInIntersection(value, "relationship", info.relationship, intersection);
507 }
508
UpdateMapInsertValues(std::vector<NativeRdb::ValuesBucket> & values)509 void CloneRestoreHighlight::UpdateMapInsertValues(std::vector<NativeRdb::ValuesBucket> &values)
510 {
511 const std::string QUERY_SQL = "SELECT map.rowid, map.* FROM AnalysisPhotoMap AS map "
512 " INNER JOIN AnalysisAlbum AS a ON map.map_album = a.album_id "
513 " WHERE a.album_subtype IN (4104, 4105) AND a.need_restore_highlight = 1 "
514 " AND map.rowid > ? ORDER BY map.rowid LIMIT ? ";
515 std::vector<NativeRdb::ValueObject> params = { lastIdOfMap_, PAGE_SIZE };
516 auto resultSet = BackupDatabaseUtils::QuerySql(mediaRdb_, QUERY_SQL, params);
517 CHECK_AND_RETURN_LOG(resultSet != nullptr, "query AnalysisPhotoMap err!");
518 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
519 UpdateMapInsertValuesByAlbumId(values, resultSet);
520 }
521 resultSet->Close();
522 }
523
UpdateMapInsertValuesByAlbumId(std::vector<NativeRdb::ValuesBucket> & values,std::shared_ptr<NativeRdb::ResultSet> resultSet)524 void CloneRestoreHighlight::UpdateMapInsertValuesByAlbumId(std::vector<NativeRdb::ValuesBucket> &values,
525 std::shared_ptr<NativeRdb::ResultSet> resultSet)
526 {
527 lastIdOfMap_ = GetInt32Val("rowid", resultSet);
528
529 std::optional<int32_t> oldFileId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "map_asset");
530 bool exceptCond = oldFileId.has_value() && photoInfoMap_.count(oldFileId.value()) > 0;
531 CHECK_AND_RETURN_LOG(exceptCond, "the query oldFileId is invalid!");
532 PhotoInfo photoInfo = photoInfoMap_.at(oldFileId.value());
533
534 std::optional<int32_t> oldAlbumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "map_album");
535 CHECK_AND_RETURN_LOG(oldAlbumId.has_value(), "the query oldAlbumId is invalid!");
536 auto it = std::find_if(analysisInfos_.begin(), analysisInfos_.end(),
537 [oldAlbumId](const AnalysisAlbumInfo& info) {
538 return info.albumIdOld.has_value() && info.albumIdOld.value() == oldAlbumId.value();
539 });
540 CHECK_AND_RETURN_LOG(it != analysisInfos_.end() && it->albumIdNew.has_value(),
541 "not find the needed album info, oldAlbumId: %{public}d", oldAlbumId.value());
542
543 std::optional<int32_t> order = std::nullopt;
544 CHECK_AND_EXECUTE(!isMapOrder_,
545 order = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "order_position"));
546 values.emplace_back(GetMapInsertValue(it->albumIdNew.value(), photoInfo.fileIdNew, order));
547 std::lock_guard<mutex> lock(counterMutex_);
548 std::string reportAlbumName = std::to_string(it->albumIdNew.value());
549 CHECK_AND_EXECUTE(!it->albumName.has_value(), reportAlbumName += "_" + it->albumName.value());
550 CHECK_AND_EXECUTE(albumPhotoCounter_.count(reportAlbumName) != 0,
551 albumPhotoCounter_[reportAlbumName] = 0);
552 albumPhotoCounter_[reportAlbumName]++;
553 }
554
InsertAnalysisPhotoMap(std::vector<NativeRdb::ValuesBucket> & values)555 void CloneRestoreHighlight::InsertAnalysisPhotoMap(std::vector<NativeRdb::ValuesBucket> &values)
556 {
557 int64_t rowNum = 0;
558 int32_t errCode = BatchInsertWithRetry("AnalysisPhotoMap", values, rowNum);
559 if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
560 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
561 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
562 "insert into AnalysisPhotoMap fail, num:" + std::to_string(failNums));
563 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
564 mapFailedCnt_ += failNums;
565 }
566 mapSuccessCnt_ += rowNum;
567 }
568
GetMapInsertValue(int32_t albumId,int32_t fileId,std::optional<int32_t> & order)569 NativeRdb::ValuesBucket CloneRestoreHighlight::GetMapInsertValue(int32_t albumId, int32_t fileId,
570 std::optional<int32_t> &order)
571 {
572 NativeRdb::ValuesBucket value;
573 value.PutInt("map_album", albumId);
574 value.PutInt("map_asset", fileId);
575 CHECK_AND_EXECUTE(!order.has_value(), value.PutInt("order_position", order.value()));
576 return value;
577 }
578
BatchInsertWithRetry(const std::string & tableName,const std::vector<NativeRdb::ValuesBucket> & values,int64_t & rowNum)579 int32_t CloneRestoreHighlight::BatchInsertWithRetry(const std::string &tableName,
580 const std::vector<NativeRdb::ValuesBucket> &values, int64_t &rowNum)
581 {
582 CHECK_AND_RETURN_RET(!values.empty(), 0);
583 int32_t errCode = E_ERR;
584 TransactionOperations trans{ __func__ };
585 trans.SetBackupRdbStore(mediaLibraryRdb_);
586 std::function<int(void)> func = [&]()->int {
587 errCode = trans.BatchInsert(rowNum, tableName, values);
588 CHECK_AND_PRINT_LOG(errCode == E_OK,
589 "InsertSql failed, errCode: %{public}d, rowNum: %{public}" PRId64, errCode, rowNum);
590 return errCode;
591 };
592 errCode = trans.RetryTrans(func, true);
593 CHECK_AND_PRINT_LOG(errCode == E_OK, "BatchInsertWithRetry: tans finish fail!, ret:%{public}d", errCode);
594 return errCode;
595 }
596
GetHighlightAlbumInfos()597 void CloneRestoreHighlight::GetHighlightAlbumInfos()
598 {
599 int32_t idNow = GetMaxAlbumId("tab_highlight_album", "id");
600 maxIdOfHighlight_ = idNow;
601 int32_t rowCount = 0;
602 int32_t offset = 0;
603 do {
604 const std::string QUERY_SQL = "SELECT * FROM tab_highlight_album WHERE highlight_status > 0 "
605 " LIMIT " + std::to_string(offset) + ", " + std::to_string(PAGE_SIZE);
606 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, QUERY_SQL);
607 CHECK_AND_BREAK_INFO_LOG(resultSet != nullptr, "query resultSql is null.");
608
609 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
610 HighlightAlbumInfo info;
611 info.highlightIdNew = std::make_optional<int32_t>(idNow++);
612 GetHighlightRowInfo(info, resultSet);
613 GetHighlightNewAlbumId(info);
614 HighlightDeduplicate(info);
615 highlightInfos_.emplace_back(info);
616 }
617 resultSet->GetRowCount(rowCount);
618 offset += PAGE_SIZE;
619 resultSet->Close();
620 } while (rowCount == PAGE_SIZE);
621 MEDIA_INFO_LOG("query tab_highlight_album nums: %{public}zu", highlightInfos_.size());
622 }
623
GetHighlightRowInfo(HighlightAlbumInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)624 void CloneRestoreHighlight::GetHighlightRowInfo(HighlightAlbumInfo &info,
625 std::shared_ptr<NativeRdb::ResultSet> resultSet)
626 {
627 if (intersectionMap_.find("tab_highlight_album") == intersectionMap_.end()) {
628 intersectionMap_.insert(std::make_pair("tab_highlight_album", GetCommonColumns("tab_highlight_album")));
629 }
630 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_album"];
631 GetIfInIntersection("id", info.highlightIdOld, intersection, resultSet);
632 GetIfInIntersection("album_id", info.albumIdOld, intersection, resultSet);
633 GetIfInIntersection("ai_album_id", info.aiAlbumIdOld, intersection, resultSet);
634 GetIfInIntersection("sub_title", info.subTitle, intersection, resultSet);
635 GetIfInIntersection("cluster_type", info.clusterType, intersection, resultSet);
636 GetIfInIntersection("cluster_sub_type", info.clusterSubType, intersection, resultSet);
637 GetIfInIntersection("cluster_condition", info.clusterCondition, intersection, resultSet);
638 GetIfInIntersection("min_date_added", info.minDateAdded, intersection, resultSet);
639 GetIfInIntersection("max_date_added", info.maxDateAdded, intersection, resultSet);
640 GetIfInIntersection("generate_time", info.generateTime, intersection, resultSet);
641 GetIfInIntersection("highlight_version", info.highlightVersion, intersection, resultSet);
642 GetIfInIntersection("remarks", info.remarks, intersection, resultSet);
643 GetIfInIntersection("highlight_status", info.highlightStatus, intersection, resultSet);
644 GetIfInIntersection("insert_pic_count", info.insertPicCount, intersection, resultSet);
645 GetIfInIntersection("remove_pic_count", info.removePicCount, intersection, resultSet);
646 GetIfInIntersection("share_screenshot_count", info.shareScreenshotCount, intersection, resultSet);
647 GetIfInIntersection("share_cover_count", info.shareCoverCount, intersection, resultSet);
648 GetIfInIntersection("rename_count", info.renameCount, intersection, resultSet);
649 GetIfInIntersection("change_cover_count", info.changeCoverCount, intersection, resultSet);
650 GetIfInIntersection("render_viewed_times", info.renderViewedTimes, intersection, resultSet);
651 GetIfInIntersection("render_viewed_duration", info.renderViewedDuration, intersection, resultSet);
652 GetIfInIntersection("art_layout_viewed_times", info.artLayoutViewedTimes, intersection, resultSet);
653 GetIfInIntersection("art_layout_viewed_duration", info.artLayoutViewedDuration, intersection, resultSet);
654 GetIfInIntersection("music_edit_count", info.musicEditCount, intersection, resultSet);
655 GetIfInIntersection("filter_edit_count", info.filterEditCount, intersection, resultSet);
656 GetIfInIntersection("is_muted", info.isMuted, intersection, resultSet);
657 GetIfInIntersection("is_favorite", info.isFavorite, intersection, resultSet);
658 GetIfInIntersection("theme", info.theme, intersection, resultSet);
659 GetIfInIntersection("pin_time", info.pinTime, intersection, resultSet);
660 GetIfInIntersection("use_subtitle", info.useSubtitle, intersection, resultSet);
661 GetIfInIntersection("highlight_location", info.highlightLocation, intersection, resultSet);
662 }
663
GetHighlightNewAlbumId(HighlightAlbumInfo & info)664 void CloneRestoreHighlight::GetHighlightNewAlbumId(HighlightAlbumInfo &info)
665 {
666 info.albumIdNew = info.albumIdOld;
667 info.aiAlbumIdNew = info.aiAlbumIdOld;
668
669 if (info.albumIdOld.has_value()) {
670 auto it = std::find_if(analysisInfos_.begin(), analysisInfos_.end(),
671 [info](const AnalysisAlbumInfo &analysisInfo) {
672 return analysisInfo.albumIdOld.has_value() &&
673 analysisInfo.albumIdOld.value() == info.albumIdOld.value();
674 });
675 if (it != analysisInfos_.end()) {
676 info.albumIdNew = it->albumIdNew;
677 it->highlightIdOld = info.highlightIdOld;
678 it->highlightIdNew = info.highlightIdNew;
679 }
680 }
681
682 if (info.aiAlbumIdOld.has_value()) {
683 auto it = std::find_if(analysisInfos_.begin(), analysisInfos_.end(),
684 [info](const AnalysisAlbumInfo &analysisInfo) {
685 return analysisInfo.albumIdOld.has_value() &&
686 analysisInfo.albumIdOld.value() == info.aiAlbumIdOld.value();
687 });
688 if (it != analysisInfos_.end()) {
689 info.aiAlbumIdNew = it->albumIdNew;
690 it->highlightIdOld = info.highlightIdOld;
691 it->highlightIdNew = info.highlightIdNew;
692 }
693 }
694 }
695
InsertIntoHighlightAlbum()696 void CloneRestoreHighlight::InsertIntoHighlightAlbum()
697 {
698 size_t offset = 0;
699 do {
700 std::vector<NativeRdb::ValuesBucket> values;
701 for (size_t index = 0; index < PAGE_SIZE && index + offset < highlightInfos_.size(); index++) {
702 bool cond = (!highlightInfos_[index + offset].clusterType.has_value() ||
703 !highlightInfos_[index + offset].clusterSubType.has_value() ||
704 !highlightInfos_[index + offset].clusterCondition.has_value() ||
705 !highlightInfos_[index + offset].highlightVersion.has_value());
706 CHECK_AND_CONTINUE(!cond);
707
708 NativeRdb::ValuesBucket value;
709 GetHighlightInsertValue(value, highlightInfos_[index + offset]);
710 PutTempHighlightStatus(value, highlightInfos_[index + offset]);
711 values.emplace_back(value);
712 }
713 int64_t rowNum = 0;
714 int32_t errCode = BatchInsertWithRetry("tab_highlight_album", values, rowNum);
715 if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
716 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
717 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
718 "insert into tab_highlight_album fail, num:" + std::to_string(failNums));
719 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
720 highlightFailedCnt_ += failNums;
721 }
722 highlightSuccessCnt_ += rowNum;
723 offset += PAGE_SIZE;
724 } while (offset < highlightInfos_.size());
725 }
726
GetHighlightInsertValue(NativeRdb::ValuesBucket & value,const HighlightAlbumInfo & info)727 void CloneRestoreHighlight::GetHighlightInsertValue(NativeRdb::ValuesBucket &value, const HighlightAlbumInfo &info)
728 {
729 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_album"];
730 PutIfInIntersection(value, "id", info.highlightIdNew, intersection);
731 PutIfInIntersection(value, "album_id", info.albumIdNew, intersection);
732 PutIfInIntersection(value, "ai_album_id", info.aiAlbumIdNew, intersection);
733 PutIfInIntersection(value, "sub_title", info.subTitle, intersection);
734 PutIfInIntersection(value, "min_date_added", info.minDateAdded, intersection);
735 PutIfInIntersection(value, "max_date_added", info.maxDateAdded, intersection);
736 PutIfInIntersection(value, "generate_time", info.generateTime, intersection);
737 PutIfInIntersection(value, "cluster_type", info.clusterType, intersection);
738 PutIfInIntersection(value, "cluster_sub_type", info.clusterSubType, intersection);
739 PutIfInIntersection(value, "cluster_condition", info.clusterCondition, intersection);
740 PutIfInIntersection(value, "remarks", info.remarks, intersection);
741 PutIfInIntersection(value, "highlight_version", info.highlightVersion, intersection);
742 PutIfInIntersection(value, "insert_pic_count", info.insertPicCount, intersection);
743 PutIfInIntersection(value, "remove_pic_count", info.removePicCount, intersection);
744 PutIfInIntersection(value, "share_screenshot_count", info.shareScreenshotCount, intersection);
745 PutIfInIntersection(value, "share_cover_count", info.shareCoverCount, intersection);
746 PutIfInIntersection(value, "rename_count", info.renameCount, intersection);
747 PutIfInIntersection(value, "change_cover_count", info.changeCoverCount, intersection);
748 PutIfInIntersection(value, "render_viewed_times", info.renderViewedTimes, intersection);
749 PutIfInIntersection(value, "render_viewed_duration", info.renderViewedDuration, intersection);
750 PutIfInIntersection(value, "art_layout_viewed_times", info.artLayoutViewedTimes, intersection);
751 PutIfInIntersection(value, "art_layout_viewed_duration", info.artLayoutViewedDuration, intersection);
752 PutIfInIntersection(value, "music_edit_count", info.musicEditCount, intersection);
753 PutIfInIntersection(value, "filter_edit_count", info.filterEditCount, intersection);
754 PutIfInIntersection(value, "is_muted", info.isMuted, intersection);
755 PutIfInIntersection(value, "is_favorite", info.isFavorite, intersection);
756 PutIfInIntersection(value, "theme", info.theme, intersection);
757 PutIfInIntersection(value, "pin_time", info.pinTime, intersection);
758 PutIfInIntersection(value, "use_subtitle", info.useSubtitle, intersection);
759 PutIfInIntersection(value, "highlight_location", info.highlightLocation, intersection);
760 }
761
PutTempHighlightStatus(NativeRdb::ValuesBucket & value,const HighlightAlbumInfo & info)762 void CloneRestoreHighlight::PutTempHighlightStatus(NativeRdb::ValuesBucket &value, const HighlightAlbumInfo &info)
763 {
764 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_album"];
765 std::optional<int32_t> status = info.highlightStatus;
766 CHECK_AND_EXECUTE(info.highlightStatus.value_or(HIGHLIGHT_STATUS_NOT_PRODUCE) <= 0,
767 status = std::make_optional<int32_t>(HIGHLIGHT_STATUS_NOT_PRODUCE));
768 PutIfInIntersection(value, "highlight_status", status, intersection);
769 }
770
MoveHighlightCovers()771 void CloneRestoreHighlight::MoveHighlightCovers()
772 {
773 std::unordered_set<int32_t> hasMovedAlbums;
774 for (const auto &info : analysisInfos_) {
775 bool cond = (!info.albumIdNew.has_value() || !info.oldCoverUri.has_value() ||
776 !info.highlightIdOld.has_value() || !info.highlightIdNew.has_value());
777 CHECK_AND_CONTINUE(!cond);
778 CHECK_AND_CONTINUE(hasMovedAlbums.count(info.highlightIdOld.value()) <= 0);
779 hasMovedAlbums.insert(info.highlightIdOld.value());
780 std::string srcDir = coverPath_ + std::to_string(info.highlightIdOld.value()) + "/";
781 MoveHighlightWordart(info, srcDir);
782 MoveHighlightGround(info, srcDir);
783 }
784 }
785
MoveHighlightWordart(const AnalysisAlbumInfo & info,const std::string & srcDir)786 void CloneRestoreHighlight::MoveHighlightWordart(const AnalysisAlbumInfo &info, const std::string &srcDir)
787 {
788 for (const auto &ratio : HIGHLIGHT_RATIO_WORD_ART) {
789 std::string srcPath = srcDir + ratio + "/wordart.png";
790 CHECK_AND_CONTINUE(MediaFileUtils::IsFileExists(srcPath));
791 std::string dstDir = "/storage/media/local/files/highlight/cover/" +
792 std::to_string(info.highlightIdNew.value()) + "/" + ratio;
793 CHECK_AND_CONTINUE_ERR_LOG(MediaFileUtils::CreateDirectory(dstDir), "create %{public}s failed",
794 BackupFileUtils::GarbleFilePath(dstDir, sceneCode_, GARBLE_DST_PATH).c_str());
795
796 std::string dstPath = dstDir + "/wordart.png";
797 int32_t errCode = BackupFileUtils::MoveFile(srcPath.c_str(), dstPath.c_str(), sceneCode_);
798 CHECK_AND_PRINT_LOG(errCode == E_OK, "move file failed, srcPath:%{public}s,"
799 " dstPath:%{public}s, errCode:%{public}d",
800 BackupFileUtils::GarbleFilePath(srcPath, sceneCode_, garblePath_).c_str(),
801 BackupFileUtils::GarbleFilePath(dstPath, sceneCode_, GARBLE_DST_PATH).c_str(), errCode);
802 }
803 }
804
MoveHighlightGround(const AnalysisAlbumInfo & info,const std::string & srcDir)805 void CloneRestoreHighlight::MoveHighlightGround(const AnalysisAlbumInfo &info, const std::string &srcDir)
806 {
807 for (const auto &fileName : HIGHLIGHT_COVER_NAME) {
808 std::string groundPath = srcDir + "/full/" + fileName + ".png";
809 std::string groundDstDir = "/storage/media/local/files/highlight/cover/" +
810 std::to_string(info.highlightIdNew.value()) + "/full";
811 CHECK_AND_CONTINUE(MediaFileUtils::IsFileExists(groundPath));
812 CHECK_AND_CONTINUE_ERR_LOG(MediaFileUtils::CreateDirectory(groundDstDir), "create %{public}s failed",
813 BackupFileUtils::GarbleFilePath(groundDstDir, sceneCode_, GARBLE_DST_PATH).c_str());
814
815 std::string groundDstPath = groundDstDir + "/" + fileName + ".png";
816 int32_t errCode = BackupFileUtils::MoveFile(groundPath.c_str(), groundDstPath.c_str(), sceneCode_);
817 CHECK_AND_PRINT_LOG(errCode == E_OK,
818 "move file failed, srcPath:%{public}s, dstPath:%{public}s, errCode:%{public}d",
819 BackupFileUtils::GarbleFilePath(groundPath, sceneCode_, garblePath_).c_str(),
820 BackupFileUtils::GarbleFilePath(groundDstPath, sceneCode_, GARBLE_DST_PATH).c_str(), errCode);
821 }
822 }
823
MoveHighlightMusic(const std::string & srcDir,const std::string & dstDir)824 int32_t CloneRestoreHighlight::MoveHighlightMusic(const std::string &srcDir, const std::string &dstDir)
825 {
826 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dstDir), E_FAIL, "create dstDir %{public}s failed",
827 BackupFileUtils::GarbleFilePath(dstDir, sceneCode_, GARBLE_DST_PATH).c_str());
828 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(srcDir), E_OK, "%{public}s doesn't exist, skip.",
829 BackupFileUtils::GarbleFilePath(srcDir, sceneCode_, garblePath_).c_str());
830 for (const auto &dirEntry : std::filesystem::directory_iterator{ srcDir }) {
831 std::string srcFilePath = dirEntry.path();
832 if (MediaFileUtils::IsDirectory(srcFilePath)) {
833 size_t index = srcFilePath.rfind("/");
834 CHECK_AND_CONTINUE(index != std::string::npos);
835 std::string subDir = srcFilePath.substr(index);
836 MoveHighlightMusic(srcFilePath, dstDir + subDir);
837 } else {
838 std::string tmpFilePath = srcFilePath;
839 std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
840 CHECK_AND_CONTINUE_INFO_LOG(!MediaFileUtils::IsFileExists(dstFilePath),
841 "dst file already exists, srcPath:%{public}s, dstPath:%{public}s",
842 BackupFileUtils::GarbleFilePath(srcFilePath, sceneCode_, garblePath_).c_str(),
843 BackupFileUtils::GarbleFilePath(dstFilePath, sceneCode_, GARBLE_DST_PATH).c_str());
844 int32_t errCode = BackupFileUtils::MoveFile(srcFilePath.c_str(), dstFilePath.c_str(), sceneCode_);
845 CHECK_AND_PRINT_LOG(errCode == E_OK,
846 "move file failed, srcPath:%{public}s, dstPath:%{public}s, errCode:%{public}d",
847 BackupFileUtils::GarbleFilePath(srcFilePath, sceneCode_, garblePath_).c_str(),
848 BackupFileUtils::GarbleFilePath(dstFilePath, sceneCode_, GARBLE_DST_PATH).c_str(), errCode);
849 }
850 }
851 return E_OK;
852 }
853
GetHighlightCoverInfos()854 void CloneRestoreHighlight::GetHighlightCoverInfos()
855 {
856 int32_t rowCount = 0;
857 int32_t offset = 0;
858 do {
859 const std::string QUERY_SQL = "SELECT tab_highlight_cover_info.* FROM tab_highlight_cover_info "
860 " INNER JOIN tab_highlight_album AS h ON tab_highlight_cover_info.album_id = h.id "
861 " WHERE h.highlight_status > 0 "
862 " LIMIT " + std::to_string(offset) + ", " + std::to_string(PAGE_SIZE);
863 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, QUERY_SQL);
864 CHECK_AND_BREAK_INFO_LOG(resultSet != nullptr, "query resultSql is null.");
865
866 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
867 auto albumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "album_id");
868 CHECK_AND_CONTINUE(albumId.has_value());
869 auto itAlbum = std::find_if(highlightInfos_.begin(), highlightInfos_.end(),
870 [albumId](const HighlightAlbumInfo& hiInfo) {
871 return hiInfo.highlightIdOld.has_value() && hiInfo.highlightIdOld == albumId;
872 });
873 CHECK_AND_CONTINUE_ERR_LOG(itAlbum != highlightInfos_.end(), "can not find coverinfo in highlight");
874 HighlightCoverInfo info;
875 info.highlightIdNew = itAlbum->highlightIdNew;
876 GetCoverRowInfo(info, resultSet);
877 GetCoverGroundSourceInfo(info, resultSet);
878 coverInfos_.emplace_back(info);
879 }
880 resultSet->GetRowCount(rowCount);
881 offset += PAGE_SIZE;
882 resultSet->Close();
883 } while (rowCount == PAGE_SIZE);
884 MEDIA_INFO_LOG("query tab_highlight_cover_info nums: %{public}zu", coverInfos_.size());
885 }
886
GetCoverRowInfo(HighlightCoverInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)887 void CloneRestoreHighlight::GetCoverRowInfo(HighlightCoverInfo &info,
888 std::shared_ptr<NativeRdb::ResultSet> resultSet)
889 {
890 if (intersectionMap_.find("tab_highlight_cover_info") == intersectionMap_.end()) {
891 intersectionMap_.insert(
892 std::make_pair("tab_highlight_cover_info", GetCommonColumns("tab_highlight_cover_info")));
893 }
894 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_cover_info"];
895 GetIfInIntersection("ratio", info.ratio, intersection, resultSet);
896 GetIfInIntersection("is_covered", info.isCovered, intersection, resultSet);
897 GetIfInIntersection("color", info.color, intersection, resultSet);
898 GetIfInIntersection("radius", info.radius, intersection, resultSet);
899 GetIfInIntersection("saturation", info.saturation, intersection, resultSet);
900 GetIfInIntersection("brightness", info.brightness, intersection, resultSet);
901 GetIfInIntersection("background_color_type", info.backgroundColorType, intersection, resultSet);
902 GetIfInIntersection("shadow_level", info.shadowLevel, intersection, resultSet);
903 GetIfInIntersection("title_scale_x", info.scaleX, intersection, resultSet);
904 GetIfInIntersection("title_scale_y", info.scaleY, intersection, resultSet);
905 GetIfInIntersection("title_rect_width", info.rectWidth, intersection, resultSet);
906 GetIfInIntersection("title_rect_height", info.rectHeight, intersection, resultSet);
907 GetIfInIntersection("background_scale_x", info.bgrScaleX, intersection, resultSet);
908 GetIfInIntersection("background_scale_y", info.bgrScaleY, intersection, resultSet);
909 GetIfInIntersection("background_rect_width", info.bgrRectWidth, intersection, resultSet);
910 GetIfInIntersection("background_rect_height", info.bgrRectHeight, intersection, resultSet);
911 GetIfInIntersection("layout_index", info.layoutIndex, intersection, resultSet);
912 GetIfInIntersection("cover_algo_version", info.coverAlgoVer, intersection, resultSet);
913 GetIfInIntersection("cover_service_version", info.coverServiceVer, intersection, resultSet);
914 GetIfInIntersection("status", info.status, intersection, resultSet);
915 }
916
GetCoverGroundSourceInfo(HighlightCoverInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)917 void CloneRestoreHighlight::GetCoverGroundSourceInfo(HighlightCoverInfo &info,
918 std::shared_ptr<NativeRdb::ResultSet> resultSet)
919 {
920 bool cond = (!info.highlightIdNew.has_value() || !info.ratio.has_value());
921 CHECK_AND_RETURN(!cond);
922 std::string wordartPath = "/storage/media/local/files/highlight/cover/" +
923 std::to_string(info.highlightIdNew.value()) + "/" + info.ratio.value() + "/wordart.png";
924 CHECK_AND_EXECUTE(!MediaFileUtils::IsFileExists(wordartPath),
925 info.wordart = "file://media/highlight/cover/" + std::to_string(info.highlightIdNew.value()) +
926 "/" + info.ratio.value() + "/wordart.png?oper=highlight");
927
928 for (const auto &fileName : HIGHLIGHT_COVER_NAME) {
929 std::string groundPath = "/storage/media/local/files/highlight/cover/" +
930 std::to_string(info.highlightIdNew.value()) + "/full/" + fileName + ".png";
931 if (BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, fileName).has_value()
932 && MediaFileUtils::IsFileExists(groundPath)) {
933 if (fileName == HIGHLIGHT_COVER_NAME[0]) {
934 info.foreground = "file://media/highlight/cover/" +
935 std::to_string(info.highlightIdNew.value()) + "/full/" + fileName + ".png?oper=highlight";
936 } else {
937 info.background = "file://media/highlight/cover/" +
938 std::to_string(info.highlightIdNew.value()) + "/full/" + fileName + ".png?oper=highlight";
939 }
940 }
941 }
942 }
943
InsertIntoHighlightCoverInfo()944 void CloneRestoreHighlight::InsertIntoHighlightCoverInfo()
945 {
946 size_t offset = 0;
947 do {
948 std::vector<NativeRdb::ValuesBucket> values;
949 for (size_t index = 0; index < PAGE_SIZE && index + offset < coverInfos_.size(); index++) {
950 CHECK_AND_CONTINUE(coverInfos_[index + offset].highlightIdNew.has_value());
951 NativeRdb::ValuesBucket value;
952 GetCoverInsertValue(value, coverInfos_[index + offset]);
953 values.emplace_back(value);
954 }
955
956 int64_t rowNum = 0;
957 int32_t errCode = BatchInsertWithRetry("tab_highlight_cover_info", values, rowNum);
958 if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
959 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
960 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
961 "insert into tab_highlight_cover_info fail, num:" + std::to_string(failNums));
962 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
963 coverInfoFailedCnt_ += failNums;
964 }
965 coverInfoSuccessCnt_ += rowNum;
966 offset += PAGE_SIZE;
967 } while (offset < coverInfos_.size());
968 }
969
GetCoverInsertValue(NativeRdb::ValuesBucket & value,const HighlightCoverInfo & info)970 void CloneRestoreHighlight::GetCoverInsertValue(NativeRdb::ValuesBucket &value, const HighlightCoverInfo &info)
971 {
972 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_cover_info"];
973 PutIfInIntersection(value, "album_id", info.highlightIdNew, intersection);
974 PutIfInIntersection(value, "ratio", info.ratio, intersection);
975 PutIfInIntersection(value, "background", info.background, intersection);
976 PutIfInIntersection(value, "foreground", info.foreground, intersection);
977 PutIfInIntersection(value, "wordart", info.wordart, intersection);
978 PutIfInIntersection(value, "is_covered", info.isCovered, intersection);
979 PutIfInIntersection(value, "color", info.color, intersection);
980 PutIfInIntersection(value, "radius", info.radius, intersection);
981 PutIfInIntersection(value, "saturation", info.saturation, intersection);
982 PutIfInIntersection(value, "brightness", info.brightness, intersection);
983 PutIfInIntersection(value, "background_color_type", info.backgroundColorType, intersection);
984 PutIfInIntersection(value, "shadow_level", info.shadowLevel, intersection);
985 PutIfInIntersection(value, "title_scale_x", info.scaleX, intersection);
986 PutIfInIntersection(value, "title_scale_y", info.scaleY, intersection);
987 PutIfInIntersection(value, "title_rect_width", info.rectWidth, intersection);
988 PutIfInIntersection(value, "title_rect_height", info.rectHeight, intersection);
989 PutIfInIntersection(value, "background_scale_x", info.bgrScaleX, intersection);
990 PutIfInIntersection(value, "background_scale_y", info.bgrScaleY, intersection);
991 PutIfInIntersection(value, "background_rect_width", info.bgrRectWidth, intersection);
992 PutIfInIntersection(value, "background_rect_height", info.bgrRectHeight, intersection);
993 PutIfInIntersection(value, "layout_index", info.layoutIndex, intersection);
994 PutIfInIntersection(value, "cover_algo_version", info.coverAlgoVer, intersection);
995 PutIfInIntersection(value, "cover_service_version", info.coverServiceVer, intersection);
996 PutIfInIntersection(value, "status", info.status, intersection);
997 }
998
GetHighlightPlayInfos()999 void CloneRestoreHighlight::GetHighlightPlayInfos()
1000 {
1001 int32_t rowCount = 0;
1002 int32_t offset = 0;
1003 do {
1004 const std::string QUERY_SQL = "SELECT tab_highlight_play_info.* FROM tab_highlight_play_info "
1005 " INNER JOIN tab_highlight_album AS h ON tab_highlight_play_info.album_id = h.id "
1006 " WHERE h.highlight_status > 0 "
1007 " LIMIT " + std::to_string(offset) + ", " + std::to_string(PAGE_SIZE);
1008 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, QUERY_SQL);
1009 CHECK_AND_BREAK_INFO_LOG(resultSet != nullptr, "query resultSql is null.");
1010 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1011 auto albumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "album_id");
1012 CHECK_AND_CONTINUE(albumId.has_value());
1013 auto itAlbum = std::find_if(highlightInfos_.begin(), highlightInfos_.end(),
1014 [albumId](const HighlightAlbumInfo& hiInfo) {
1015 return hiInfo.highlightIdOld.has_value() && hiInfo.highlightIdOld == albumId;
1016 });
1017 CHECK_AND_CONTINUE_ERR_LOG(itAlbum != highlightInfos_.end(),
1018 "can not find playinfo in highlight, albumId: %{public}d", albumId.value());
1019 HighlightPlayInfo info;
1020 info.highlightIdNew = itAlbum->highlightIdNew;
1021 GetPlayRowInfo(info, resultSet);
1022 playInfos_.emplace_back(info);
1023 }
1024 resultSet->GetRowCount(rowCount);
1025 offset += PAGE_SIZE;
1026 resultSet->Close();
1027 } while (rowCount == PAGE_SIZE);
1028 MEDIA_INFO_LOG("query tab_highlight_play_info nums: %{public}zu", playInfos_.size());
1029 }
1030
GetPlayRowInfo(HighlightPlayInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)1031 void CloneRestoreHighlight::GetPlayRowInfo(HighlightPlayInfo &info,
1032 std::shared_ptr<NativeRdb::ResultSet> resultSet)
1033 {
1034 if (intersectionMap_.find("tab_highlight_play_info") == intersectionMap_.end()) {
1035 intersectionMap_.insert(
1036 std::make_pair("tab_highlight_play_info", GetCommonColumns("tab_highlight_play_info")));
1037 }
1038 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_play_info"];
1039 GetIfInIntersection("play_info_id", info.playId, intersection, resultSet);
1040 GetIfInIntersection("music", info.music, intersection, resultSet);
1041 GetIfInIntersection("filter", info.filter, intersection, resultSet);
1042 GetIfInIntersection("is_chosen", info.isChosen, intersection, resultSet);
1043 GetIfInIntersection("play_info_version", info.pInfoVer, intersection, resultSet);
1044 GetIfInIntersection("highlighting_algo_version", info.hAlgoVer, intersection, resultSet);
1045 GetIfInIntersection("camera_movement_algo_version", info.cameraAlgoVer, intersection, resultSet);
1046 GetIfInIntersection("transition_algo_version", info.transAlgoVer, intersection, resultSet);
1047 GetIfInIntersection("play_service_version", info.playServiceVer, intersection, resultSet);
1048 GetIfInIntersection("status", info.status, intersection, resultSet);
1049 }
1050
InsertIntoHighlightPlayInfo()1051 void CloneRestoreHighlight::InsertIntoHighlightPlayInfo()
1052 {
1053 size_t offset = 0;
1054 do {
1055 std::vector<NativeRdb::ValuesBucket> values;
1056 for (size_t index = 0; index < PAGE_SIZE && index + offset < playInfos_.size(); index++) {
1057 CHECK_AND_CONTINUE(playInfos_[index + offset].highlightIdNew.has_value());
1058 NativeRdb::ValuesBucket value;
1059 GetPlayInsertValue(value, playInfos_[index + offset]);
1060 value.PutString("play_info", GetDefaultPlayInfo());
1061 values.emplace_back(value);
1062 }
1063
1064 int64_t rowNum = 0;
1065 int32_t errCode = BatchInsertWithRetry("tab_highlight_play_info", values, rowNum);
1066 if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
1067 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
1068 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
1069 "insert into tab_highlight_play_info fail, num:" + std::to_string(failNums));
1070 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
1071 playInfoFailedCnt_ += failNums;
1072 }
1073 playInfoSuccessCnt_ += rowNum;
1074 offset += PAGE_SIZE;
1075 } while (offset < playInfos_.size());
1076 }
1077
GetPlayInsertValue(NativeRdb::ValuesBucket & value,const HighlightPlayInfo & info)1078 void CloneRestoreHighlight::GetPlayInsertValue(NativeRdb::ValuesBucket &value, const HighlightPlayInfo &info)
1079 {
1080 std::unordered_set<std::string>& intersection = intersectionMap_["tab_highlight_play_info"];
1081 PutIfInIntersection(value, "album_id", info.highlightIdNew, intersection);
1082 PutIfInIntersection(value, "play_info_id", info.playId, intersection);
1083 PutIfInIntersection(value, "music", info.music, intersection);
1084 PutIfInIntersection(value, "filter", info.filter, intersection);
1085 PutIfInIntersection(value, "is_chosen", info.isChosen, intersection);
1086 PutIfInIntersection(value, "play_info_version", info.pInfoVer, intersection);
1087 PutIfInIntersection(value, "highlighting_algo_version", info.hAlgoVer, intersection);
1088 PutIfInIntersection(value, "camera_movement_algo_version", info.cameraAlgoVer, intersection);
1089 PutIfInIntersection(value, "transition_algo_version", info.transAlgoVer, intersection);
1090 PutIfInIntersection(value, "play_service_version", info.playServiceVer, intersection);
1091 PutIfInIntersection(value, "status", info.status, intersection);
1092 }
1093
GetCommonColumns(const std::string & tableName)1094 std::unordered_set<std::string> CloneRestoreHighlight::GetCommonColumns(const std::string &tableName)
1095 {
1096 std::unordered_map<std::string, std::string> srcColumnInfoMap =
1097 BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_, tableName);
1098 std::unordered_map<std::string, std::string> dstColumnInfoMap =
1099 BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_, tableName);
1100 std::unordered_set<std::string> result;
1101 auto comparedColumns = GetValueFromMap(ALBUM_COLUMNS_MAP, tableName);
1102 for (auto it = dstColumnInfoMap.begin(); it != dstColumnInfoMap.end(); ++it) {
1103 bool cond = (srcColumnInfoMap.find(it->first) != srcColumnInfoMap.end() &&
1104 comparedColumns.count(it->first) > 0);
1105 CHECK_AND_EXECUTE(!cond, result.insert(it->first));
1106 }
1107 return result;
1108 }
1109
ReportCloneRestoreHighlightTask()1110 void CloneRestoreHighlight::ReportCloneRestoreHighlightTask()
1111 {
1112 ReportRestoreTaskOfTotal();
1113 ReportRestoreTaskOfAlbumStats();
1114 ReportRestoreTaskOfAlbumInfo();
1115 }
1116
ReportRestoreTaskOfTotal()1117 void CloneRestoreHighlight::ReportRestoreTaskOfTotal()
1118 {
1119 std::stringstream totalReport;
1120 totalReport << "isHighlightDirExist: " << isHighlightDirExist_ << ", timeCost: " << restoreTimeCost_ <<
1121 "; ALBUM: max_id: " << maxIdOfAlbum_ << ", success: " << albumSuccessCnt_ <<
1122 ", duplicate: " << albumDuplicateCnt_ << ", failed: " << albumFailedCnt_ <<
1123 "; HIGHLIGHT: max_id: " << maxIdOfHighlight_ << ", success: " << highlightSuccessCnt_ <<
1124 ", duplicate: " << highlightDuplicateCnt_ << ", failed: " << highlightFailedCnt_ <<
1125 "; MAP: success: " << mapSuccessCnt_ << ", failed: " << mapFailedCnt_ <<
1126 "; COVER_INFO: success: " << coverInfoSuccessCnt_ << ", failed: " << coverInfoFailedCnt_ <<
1127 "; PLAY_INFO: success: " << playInfoSuccessCnt_ << ", failed: " << playInfoFailedCnt_;
1128 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
1129 .Report("CLONE_RESTORE_HIGHLIGHT_TOTAL", RESTORE_STATUS_SUCCESS, totalReport.str());
1130 }
1131
ReportRestoreTaskOfAlbumStats()1132 void CloneRestoreHighlight::ReportRestoreTaskOfAlbumStats()
1133 {
1134 int32_t maxCnt = 0;
1135 int32_t totalCnt = 0;
1136 for (const auto &counter : albumPhotoCounter_) {
1137 maxCnt = maxCnt > counter.second ? maxCnt : counter.second;
1138 totalCnt += counter.second;
1139 }
1140 double meanCnt = albumPhotoCounter_.size() == 0 ? 0 : (double) totalCnt / albumPhotoCounter_.size();
1141 std::stringstream albumStatsReport;
1142 albumStatsReport << "num: " << albumPhotoCounter_.size() << ", max: " << maxCnt << ", mean: " << meanCnt
1143 << ", total: " << totalCnt;
1144 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
1145 .Report("CLONE_RESTORE_HIGHLIGHT_ALBUM_STATS", RESTORE_STATUS_SUCCESS, albumStatsReport.str());
1146 }
1147
ReportRestoreTaskOfAlbumInfo()1148 void CloneRestoreHighlight::ReportRestoreTaskOfAlbumInfo()
1149 {
1150 for (const auto &counter : albumPhotoCounter_) {
1151 std::stringstream albumInfoReport;
1152 albumInfoReport << "albumName: " << counter.first << ", photo count: " << counter.second;
1153 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
1154 .ReportInAudit("CLONE_RESTORE_HIGHLIGHT_ALBUM_INFO", RESTORE_STATUS_SUCCESS, albumInfoReport.str());
1155 }
1156 }
1157
HighlightDeduplicate(const HighlightAlbumInfo & info)1158 void CloneRestoreHighlight::HighlightDeduplicate(const HighlightAlbumInfo &info)
1159 {
1160 std::string duplicateAlbumName = "";
1161 std::unordered_set<int32_t> duplicateAnalysisAlbumIdSet;
1162 std::vector<NativeRdb::ValueObject> changeIds =
1163 GetHighlightDuplicateIds(info, duplicateAlbumName, duplicateAnalysisAlbumIdSet);
1164 UpdateHighlightDuplicateRows(changeIds, duplicateAlbumName);
1165 DeleteAnalysisDuplicateRows(duplicateAnalysisAlbumIdSet, duplicateAlbumName);
1166 }
1167
GetHighlightDuplicateIds(const HighlightAlbumInfo & info,std::string & duplicateAlbumName,std::unordered_set<int32_t> & duplicateAnalysisAlbumIdSet)1168 std::vector<NativeRdb::ValueObject> CloneRestoreHighlight::GetHighlightDuplicateIds(const HighlightAlbumInfo &info,
1169 std::string &duplicateAlbumName, std::unordered_set<int32_t> &duplicateAnalysisAlbumIdSet)
1170 {
1171 std::vector<NativeRdb::ValueObject> changeIds = {};
1172 CHECK_AND_RETURN_RET((info.clusterType.has_value() && info.clusterSubType.has_value() &&
1173 info.clusterCondition.has_value() && info.highlightVersion.has_value() && info.albumIdOld.has_value()),
1174 changeIds);
1175 CHECK_AND_RETURN_RET((!info.highlightStatus.has_value() || info.highlightStatus.value() > 0), changeIds);
1176
1177 auto it = std::find_if(analysisInfos_.begin(), analysisInfos_.end(),
1178 [info](const AnalysisAlbumInfo &analysisInfo) {
1179 return analysisInfo.albumIdOld.has_value() &&
1180 analysisInfo.albumIdOld.value() == info.albumIdOld.value();
1181 });
1182 CHECK_AND_RETURN_RET((it != analysisInfos_.end() && it->albumName.has_value()), changeIds);
1183 duplicateAlbumName = it->albumName.value();
1184
1185 const std::string QUERY_SQL = "SELECT t.id, t.album_id, t.ai_album_id "
1186 "FROM tab_highlight_album AS t INNER JOIN AnalysisAlbum AS a "
1187 "ON t.album_id = a.album_id WHERE t.cluster_type = ? AND t.cluster_sub_type = ? AND t.cluster_condition = ? "
1188 "AND a.album_name = ? AND t.highlight_status <> ?";
1189 std::vector<NativeRdb::ValueObject> params = {
1190 info.clusterType.value(), info.clusterSubType.value(), info.clusterCondition.value(), duplicateAlbumName,
1191 HIGHLIGHT_STATUS_DELETE
1192 };
1193 auto resultSet = BackupDatabaseUtils::QuerySql(mediaLibraryRdb_, QUERY_SQL, params);
1194
1195 CHECK_AND_RETURN_RET((resultSet != nullptr), changeIds);
1196
1197 if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1198 resultSet->Close();
1199 return changeIds;
1200 }
1201
1202 do {
1203 std::optional<int32_t> highlightId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "id");
1204 std::optional<int32_t> albumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "album_id");
1205 std::optional<int32_t> aiAlbumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "ai_album_id");
1206 CHECK_AND_CONTINUE(highlightId.has_value());
1207 changeIds.emplace_back(highlightId.value());
1208 CHECK_AND_EXECUTE(!albumId.has_value(), duplicateAnalysisAlbumIdSet.insert(albumId.value()));
1209 CHECK_AND_EXECUTE(!aiAlbumId.has_value(), duplicateAnalysisAlbumIdSet.insert(aiAlbumId.value()));
1210 } while (resultSet->GoToNextRow() == NativeRdb::E_OK);
1211 resultSet->Close();
1212 return changeIds;
1213 }
1214
UpdateHighlightDuplicateRows(const std::vector<NativeRdb::ValueObject> & changeIds,const std::string & duplicateAlbumName)1215 void CloneRestoreHighlight::UpdateHighlightDuplicateRows(const std::vector<NativeRdb::ValueObject> &changeIds,
1216 const std::string &duplicateAlbumName)
1217 {
1218 CHECK_AND_RETURN(!changeIds.empty());
1219 int32_t changedRows = 0;
1220 std::unique_ptr<NativeRdb::AbsRdbPredicates> updatePredicates =
1221 make_unique<NativeRdb::AbsRdbPredicates>("tab_highlight_album");
1222 updatePredicates->In("id", changeIds);
1223 NativeRdb::ValuesBucket rdbValues;
1224 rdbValues.PutInt("highlight_status", HIGHLIGHT_STATUS_DELETE);
1225 BackupDatabaseUtils::Update(mediaLibraryRdb_, changedRows, rdbValues, updatePredicates);
1226 MEDIA_INFO_LOG("deduplicate highlight album, duplicate album name: %{public}s, duplicate nums: %{public}zu, "
1227 "update nums: %{public}d", duplicateAlbumName.c_str(), changeIds.size(), changedRows);
1228 highlightDuplicateCnt_ += changedRows;
1229 }
1230
DeleteAnalysisDuplicateRows(const std::unordered_set<int32_t> & duplicateAnalysisAlbumIdSet,const std::string & duplicateAlbumName)1231 void CloneRestoreHighlight::DeleteAnalysisDuplicateRows(const std::unordered_set<int32_t> &duplicateAnalysisAlbumIdSet,
1232 const std::string &duplicateAlbumName)
1233 {
1234 CHECK_AND_RETURN(!duplicateAnalysisAlbumIdSet.empty());
1235 int32_t deleteRows = 0;
1236 std::vector<NativeRdb::ValueObject> duplicateAnalysisAlbumIds(duplicateAnalysisAlbumIdSet.begin(),
1237 duplicateAnalysisAlbumIdSet.end());
1238 NativeRdb::AbsRdbPredicates deletePredicates("AnalysisAlbum");
1239 deletePredicates.In("album_id", duplicateAnalysisAlbumIds);
1240 BackupDatabaseUtils::Delete(deletePredicates, deleteRows, mediaLibraryRdb_);
1241 MEDIA_INFO_LOG("delete duplicate analysis album, duplicate album name: %{public}s, duplicate nums: %{public}zu, "
1242 "delete nums: %{public}d", duplicateAlbumName.c_str(), duplicateAnalysisAlbumIds.size(), deleteRows);
1243 albumDuplicateCnt_ += deleteRows;
1244 }
1245
UpdateRestoreTimeCost(int64_t timeCost)1246 void CloneRestoreHighlight::UpdateRestoreTimeCost(int64_t timeCost)
1247 {
1248 restoreTimeCost_ += timeCost;
1249 }
1250 } // namespace OHOS::Media