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 #define MLOG_TAG "MediaLibraryCloneRestore"
17
18 #include "clone_restore.h"
19 #include "backup_const_column.h"
20
21 #include "application_context.h"
22 #include "backup_dfx_utils.h"
23 #include "backup_file_utils.h"
24 #include "backup_log_utils.h"
25 #include "cloud_sync_utils.h"
26 #include "database_report.h"
27 #include "ffrt.h"
28 #include "ffrt_inner.h"
29 #include "media_column.h"
30 #include "media_file_utils.h"
31 #include "media_library_db_upgrade.h"
32 #include "media_log.h"
33 #include "medialibrary_data_manager.h"
34 #include "medialibrary_errno.h"
35 #include "medialibrary_notify.h"
36 #include "medialibrary_photo_operations.h"
37 #include "medialibrary_type_const.h"
38 #include "ohos_account_kits.h"
39 #include "photos_dao.h"
40 #include "rdb_store.h"
41 #include "result_set_utils.h"
42 #include "upgrade_restore_task_report.h"
43 #include "userfile_manager_types.h"
44 #include "ohos_account_kits.h"
45
46 #ifdef CLOUD_SYNC_MANAGER
47 #include "cloud_sync_manager.h"
48 #endif
49
50 using namespace std;
51 namespace OHOS {
52 namespace Media {
53 const int32_t CLONE_QUERY_COUNT = 200;
54 const string MEDIA_DB_PATH = "/data/storage/el2/database/rdb/media_library.db";
55 const std::string THM_SAVE_WITHOUT_ROTATE_PATH = "/THM_EX";
56 constexpr int64_t SECONDS_LEVEL_LIMIT = 1e10;
57 const int32_t ORIETATION_ZERO = 0;
58 const int32_t MIGRATE_CLOUD_THM_TYPE = 0;
59 const int32_t MIGRATE_CLOUD_LCD_TYPE = 1;
60 const int32_t MIGRATE_CLOUD_ASTC_TYPE = 2;
61 const unordered_map<string, unordered_set<string>> NEEDED_COLUMNS_MAP = {
62 { PhotoColumn::PHOTOS_TABLE,
63 {
64 MediaColumn::MEDIA_ID,
65 MediaColumn::MEDIA_FILE_PATH,
66 MediaColumn::MEDIA_SIZE,
67 MediaColumn::MEDIA_TYPE,
68 MediaColumn::MEDIA_NAME,
69 MediaColumn::MEDIA_DATE_ADDED,
70 MediaColumn::MEDIA_DATE_MODIFIED,
71 PhotoColumn::PHOTO_ORIENTATION,
72 PhotoColumn::PHOTO_SUBTYPE,
73 MediaColumn::MEDIA_DATE_TRASHED,
74 MediaColumn::MEDIA_HIDDEN,
75 }},
76 { PhotoAlbumColumns::TABLE,
77 {
78 PhotoAlbumColumns::ALBUM_ID,
79 PhotoAlbumColumns::ALBUM_TYPE,
80 PhotoAlbumColumns::ALBUM_SUBTYPE,
81 PhotoAlbumColumns::ALBUM_NAME,
82 PhotoAlbumColumns::ALBUM_BUNDLE_NAME,
83 }},
84 { PhotoMap::TABLE,
85 {
86 PhotoMap::ALBUM_ID,
87 PhotoMap::ASSET_ID,
88 }},
89 { ANALYSIS_ALBUM_TABLE,
90 {
91 PhotoAlbumColumns::ALBUM_ID,
92 PhotoAlbumColumns::ALBUM_TYPE,
93 PhotoAlbumColumns::ALBUM_SUBTYPE,
94 PhotoAlbumColumns::ALBUM_NAME,
95 }},
96 { ANALYSIS_PHOTO_MAP_TABLE,
97 {
98 PhotoMap::ALBUM_ID,
99 PhotoMap::ASSET_ID,
100 }},
101 { AudioColumn::AUDIOS_TABLE,
102 {
103 MediaColumn::MEDIA_ID,
104 MediaColumn::MEDIA_FILE_PATH,
105 MediaColumn::MEDIA_SIZE,
106 MediaColumn::MEDIA_TYPE,
107 MediaColumn::MEDIA_NAME,
108 MediaColumn::MEDIA_DATE_ADDED,
109 MediaColumn::MEDIA_DATE_MODIFIED,
110 }},
111 };
112 const unordered_map<string, unordered_set<string>> NEEDED_COLUMNS_EXCEPTION_MAP = {
113 { PhotoAlbumColumns::TABLE,
114 {
115 PhotoAlbumColumns::ALBUM_BUNDLE_NAME,
116 }},
117 };
118 const unordered_map<string, unordered_set<string>> EXCLUDED_COLUMNS_MAP = {
119 { PhotoColumn::PHOTOS_TABLE,
120 {
121 PhotoColumn::PHOTO_CLOUD_ID, PhotoColumn::PHOTO_DIRTY, PhotoColumn::PHOTO_META_DATE_MODIFIED,
122 PhotoColumn::PHOTO_SYNC_STATUS, PhotoColumn::PHOTO_CLOUD_VERSION, PhotoColumn::PHOTO_POSITION,
123 PhotoColumn::PHOTO_THUMB_STATUS, PhotoColumn::PHOTO_CLEAN_FLAG, // cloud related
124 PhotoColumn::PHOTO_THUMBNAIL_READY, PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, // thumbnail related
125 PhotoColumn::PHOTO_LCD_VISIT_TIME, // lcd related
126 PhotoColumn::PHOTO_CE_AVAILABLE, PhotoColumn::PHOTO_CE_STATUS_CODE, // cloud enhancement
127 PhotoColumn::PHOTO_THUMBNAIL_VISIBLE,
128 PhotoColumn::PHOTO_METADATA_FLAGS, // meta recovery related
129 }},
130 { PhotoAlbumColumns::TABLE,
131 {
132 PhotoAlbumColumns::ALBUM_COVER_URI, PhotoAlbumColumns::ALBUM_COUNT, PhotoAlbumColumns::CONTAINS_HIDDEN,
133 PhotoAlbumColumns::HIDDEN_COUNT, PhotoAlbumColumns::HIDDEN_COVER, PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
134 PhotoAlbumColumns::ALBUM_VIDEO_COUNT, // updated by album udpate
135 PhotoAlbumColumns::ALBUM_DIRTY, PhotoAlbumColumns::ALBUM_CLOUD_ID, // cloud related
136 PhotoAlbumColumns::ALBUM_ORDER, // created by trigger
137 }},
138 { ANALYSIS_ALBUM_TABLE,
139 {
140 PhotoAlbumColumns::ALBUM_COVER_URI,
141 PhotoAlbumColumns::ALBUM_COUNT,
142 }},
143 };
144 const unordered_map<string, unordered_map<string, string>> TABLE_QUERY_WHERE_CLAUSE_MAP = {
145 { PhotoColumn::PHOTOS_TABLE,
146 {
147 { PhotoColumn::PHOTO_POSITION, PhotoColumn::PHOTO_POSITION + " IN (1, 3) "},
148 { PhotoColumn::PHOTO_SYNC_STATUS, PhotoColumn::PHOTO_SYNC_STATUS + " = " +
149 to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) },
150 { PhotoColumn::PHOTO_CLEAN_FLAG, PhotoColumn::PHOTO_CLEAN_FLAG + " = " +
151 to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) },
152 { MediaColumn::MEDIA_TIME_PENDING, MediaColumn::MEDIA_TIME_PENDING + " = 0" },
153 { PhotoColumn::PHOTO_IS_TEMP, PhotoColumn::PHOTO_IS_TEMP + " = 0" },
154 }},
155 { PhotoAlbumColumns::TABLE,
156 {
157 { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
158 { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_TYPE + " != " +
159 to_string(PhotoAlbumType::SYSTEM)},
160 }},
161 { ANALYSIS_ALBUM_TABLE,
162 {
163 { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
164 { PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumColumns::ALBUM_SUBTYPE + " IN (" +
165 to_string(PhotoAlbumSubType::SHOOTING_MODE) + ", " +
166 to_string(PhotoAlbumSubType::GEOGRAPHY_CITY) + ", " +
167 to_string(PhotoAlbumSubType::CLASSIFY) + ")" },
168 }},
169 };
170 const unordered_map<string, unordered_map<string, string>> TABLE_QUERY_WHERE_CLAUSE_MAP_WITH_CLOUD = {
171 { PhotoColumn::PHOTOS_TABLE,
172 {
173 { PhotoColumn::PHOTO_POSITION, PhotoColumn::PHOTO_POSITION + " IN (1, 2, 3) "},
174 { PhotoColumn::PHOTO_SYNC_STATUS, PhotoColumn::PHOTO_SYNC_STATUS + " = " +
175 to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) },
176 { PhotoColumn::PHOTO_CLEAN_FLAG, PhotoColumn::PHOTO_CLEAN_FLAG + " = " +
177 to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) },
178 { MediaColumn::MEDIA_TIME_PENDING, MediaColumn::MEDIA_TIME_PENDING + " = 0" },
179 { PhotoColumn::PHOTO_IS_TEMP, PhotoColumn::PHOTO_IS_TEMP + " = 0" },
180 }},
181 { PhotoAlbumColumns::TABLE,
182 {
183 { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
184 { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_TYPE + " != " +
185 to_string(PhotoAlbumType::SYSTEM)},
186 }},
187 { ANALYSIS_ALBUM_TABLE,
188 {
189 { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
190 { PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumColumns::ALBUM_SUBTYPE + " IN (" +
191 to_string(PhotoAlbumSubType::SHOOTING_MODE) + ", " +
192 to_string(PhotoAlbumSubType::GEOGRAPHY_CITY) + ", " +
193 to_string(PhotoAlbumSubType::CLASSIFY) + ")" },
194 }},
195 };
196 const vector<string> CLONE_ALBUMS = { PhotoAlbumColumns::TABLE, ANALYSIS_ALBUM_TABLE };
197 const unordered_map<string, string> CLONE_ALBUM_MAP = {
198 { PhotoAlbumColumns::TABLE, PhotoMap::TABLE },
199 { ANALYSIS_ALBUM_TABLE, ANALYSIS_PHOTO_MAP_TABLE },
200 };
201 const unordered_map<string, ResultSetDataType> COLUMN_TYPE_MAP = {
202 { "INT", ResultSetDataType::TYPE_INT32 },
203 { "INTEGER", ResultSetDataType::TYPE_INT32 },
204 { "BIGINT", ResultSetDataType::TYPE_INT64 },
205 { "DOUBLE", ResultSetDataType::TYPE_DOUBLE },
206 { "TEXT", ResultSetDataType::TYPE_STRING },
207 };
208 const unordered_map<string, string> ALBUM_URI_PREFIX_MAP = {
209 { PhotoAlbumColumns::TABLE, PhotoAlbumColumns::ALBUM_URI_PREFIX },
210 { ANALYSIS_ALBUM_TABLE, PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX },
211 };
212
213 template<typename Key, typename Value>
GetValueFromMap(const unordered_map<Key,Value> & map,const Key & key,const Value & defaultValue=Value ())214 Value GetValueFromMap(const unordered_map<Key, Value> &map, const Key &key, const Value &defaultValue = Value())
215 {
216 auto it = map.find(key);
217 CHECK_AND_RETURN_RET(it != map.end(), defaultValue);
218 return it->second;
219 }
220
CloneRestore()221 CloneRestore::CloneRestore()
222 {
223 sceneCode_ = CLONE_RESTORE_ID;
224 ffrt_disable_worker_escape();
225 MEDIA_INFO_LOG("Set ffrt_disable_worker_escape");
226 }
227
StartRestore(const string & backupRestoreDir,const string & upgradePath)228 void CloneRestore::StartRestore(const string &backupRestoreDir, const string &upgradePath)
229 {
230 MEDIA_INFO_LOG("Start clone restore");
231 SetParameterForClone();
232 GetAccountValid();
233 isSyncSwitchOn_ = CloudSyncUtils::IsCloudSyncSwitchOn();
234 #ifdef CLOUD_SYNC_MANAGER
235 FileManagement::CloudSync::CloudSyncManager::GetInstance().StopSync("com.ohos.medialibrary.medialibrarydata");
236 #endif
237 backupRestoreDir_ = backupRestoreDir;
238 garbagePath_ = backupRestoreDir_ + "/storage/media/local/files";
239 int32_t errorCode = Init(backupRestoreDir, upgradePath, true);
240 if (errorCode == E_OK) {
241 RestoreGallery();
242 RestoreMusic();
243 UpdateDatabase();
244 (void)NativeRdb::RdbHelper::DeleteRdbStore(dbPath_);
245 } else {
246 SetErrorCode(RestoreError::INIT_FAILED);
247 ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, errorCode);
248 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
249 }
250 HandleRestData();
251 StopParameterForClone(CLONE_RESTORE_ID);
252 CloseAllKvStore();
253 MEDIA_INFO_LOG("End clone restore");
254 }
255
InitThumbnailStatus()256 void CloneRestore::InitThumbnailStatus()
257 {
258 std::string cloneThumbnailDir = backupRestoreDir_ + RESTORE_FILES_LOCAL_DIR + ".thumbs";
259 if (!MediaFileUtils::IsFileExists(cloneThumbnailDir)) {
260 MEDIA_WARN_LOG("Uncloned thumbnail dir, no need to clone thumbnail");
261 return;
262 }
263 hasCloneThumbnailDir_ = true;
264 isInitKvstoreSuccess_ = InitAllKvStore();
265 }
266
Init(const string & backupRestoreDir,const string & upgradePath,bool isUpgrade)267 int32_t CloneRestore::Init(const string &backupRestoreDir, const string &upgradePath, bool isUpgrade)
268 {
269 dbPath_ = backupRestoreDir_ + MEDIA_DB_PATH;
270 filePath_ = backupRestoreDir_ + "/storage/media/local/files";
271 if (!MediaFileUtils::IsFileExists(dbPath_)) {
272 MEDIA_ERR_LOG("Media db is not exist.");
273 return E_FAIL;
274 }
275 if (isUpgrade && BaseRestore::Init() != E_OK) {
276 return E_FAIL;
277 }
278
279 auto context = AbilityRuntime::Context::GetApplicationContext();
280 CHECK_AND_RETURN_RET_LOG(context != nullptr, E_FAIL, "Failed to get context");
281 int32_t err = BackupDatabaseUtils::InitDb(mediaRdb_, MEDIA_DATA_ABILITY_DB_NAME, dbPath_, BUNDLE_NAME, true,
282 context->GetArea());
283 CHECK_AND_RETURN_RET_LOG(mediaRdb_ != nullptr, E_FAIL, "Init remote medialibrary rdb fail, err = %{public}d", err);
284
285 BackupDatabaseUtils::CheckDbIntegrity(mediaRdb_, sceneCode_, "OLD_MEDIA_LIBRARY");
286 InitThumbnailStatus();
287 this->photoAlbumClone_.OnStart(this->mediaRdb_, this->mediaLibraryRdb_);
288 this->photosClone_.OnStart(this->mediaLibraryRdb_, this->mediaRdb_);
289 cloneRestoreClassify_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->mediaRdb_);
290 cloneRestoreGeo_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->mediaRdb_);
291 cloneRestoreGeoDictionary_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->mediaRdb_);
292 cloneRestoreHighlight_.Init(this->sceneCode_, this->taskId_, mediaLibraryRdb_, mediaRdb_, backupRestoreDir);
293 cloneRestoreCVAnalysis_.Init(this->sceneCode_, this->taskId_, mediaLibraryRdb_, mediaRdb_, backupRestoreDir);
294 MEDIA_INFO_LOG("Init db succ.");
295 return E_OK;
296 }
297
RestorePhoto()298 void CloneRestore::RestorePhoto()
299 {
300 MEDIA_INFO_LOG("Start clone restore: photos");
301 CHECK_AND_RETURN_LOG(IsReadyForRestore(PhotoColumn::PHOTOS_TABLE),
302 "Column status is not ready for restore photo, quit");
303 unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_,
304 PhotoColumn::PHOTOS_TABLE);
305 unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
306 PhotoColumn::PHOTOS_TABLE);
307 if (!PrepareCommonColumnInfoMap(PhotoColumn::PHOTOS_TABLE, srcColumnInfoMap, dstColumnInfoMap)) {
308 MEDIA_ERR_LOG("Prepare common column info failed");
309 return;
310 }
311 // The begining of the restore process
312 // Start clone restore
313 this->photosClone_.LoadPhotoAlbums();
314 // Scenario 1, clone photos from PhotoAlbum, PhotoMap and Photos.
315 int totalNumberInPhotoMap = this->photosClone_.GetPhotosRowCountInPhotoMap();
316 MEDIA_INFO_LOG("GetPhotosRowCountInPhotoMap, totalNumber = %{public}d", totalNumberInPhotoMap);
317 totalNumber_ += static_cast<uint64_t>(totalNumberInPhotoMap);
318 MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
319 ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
320 for (int32_t offset = 0; offset < totalNumberInPhotoMap; offset += CLONE_QUERY_COUNT) {
321 ffrt::submit([this, offset]() { RestorePhotoBatch(offset, 1); }, {&offset}, {},
322 ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
323 }
324 ffrt::wait();
325 size_t vectorLen = photosFailedOffsets.size();
326 needReportFailed_ = true;
327 for (size_t offset = 0; offset < vectorLen; offset++) {
328 RestorePhotoBatch(offset, 1);
329 }
330 needReportFailed_ = false;
331 // Scenario 2, clone photos from Photos only.
332 int32_t totalNumber = this->photosClone_.GetPhotosRowCountNotInPhotoMap();
333 MEDIA_INFO_LOG("QueryTotalNumberNot, totalNumber = %{public}d", totalNumber);
334 totalNumber_ += static_cast<uint64_t>(totalNumber);
335 MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
336 for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
337 ffrt::submit([this, offset]() { RestorePhotoBatch(offset); }, { &offset }, {},
338 ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
339 }
340 ffrt::wait();
341 vectorLen = photosFailedOffsets.size();
342 needReportFailed_ = true;
343 for (size_t offset = 0; offset < vectorLen; offset++) {
344 RestorePhotoBatch(offset);
345 }
346 this->photosClone_.OnStop(otherTotalNumber_, otherProcessStatus_);
347 }
348
GetAccountValid()349 void CloneRestore::GetAccountValid()
350 {
351 string oldId = "";
352 string newId = "";
353 nlohmann::json jsonArr = nlohmann::json::parse(restoreInfo_, nullptr, false);
354 if (jsonArr.is_discarded()) {
355 MEDIA_ERR_LOG("cloud account parse failed");
356 return;
357 }
358 for (const auto& item : jsonArr) {
359 if (!item.contains("type") || !item.contains("detail") || item["type"] != "singleAccountId") {
360 continue;
361 }
362 oldId = item["detail"];
363 MEDIA_INFO_LOG("the old is %{public}s", oldId.c_str());
364 break;
365 }
366 std::pair<bool, OHOS::AccountSA::OhosAccountInfo> ret =
367 OHOS::AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
368 if (ret.first) {
369 OHOS::AccountSA::OhosAccountInfo& resultInfo = ret.second;
370 newId = resultInfo.uid_;
371 } else {
372 MEDIA_ERR_LOG("new account logins failed");
373 return;
374 }
375 MEDIA_INFO_LOG("clone the old id is %{public}s, new id is %{public}s",
376 BackupFileUtils::GarbleFilePath(oldId, sceneCode_).c_str(),
377 BackupFileUtils::GarbleFilePath(newId, sceneCode_).c_str());
378 isAccountValid_ = (oldId != "" && oldId == newId);
379 }
380
RestorePhotoForCloud()381 void CloneRestore::RestorePhotoForCloud()
382 {
383 MEDIA_INFO_LOG("singleClone start clone restore: photos");
384 CHECK_AND_RETURN_LOG(IsReadyForRestore(PhotoColumn::PHOTOS_TABLE),
385 "singleClone column status is not ready for restore photo, quit");
386 unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_,
387 PhotoColumn::PHOTOS_TABLE);
388 unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
389 PhotoColumn::PHOTOS_TABLE);
390 CHECK_AND_RETURN_LOG(PrepareCommonColumnInfoMap(PhotoColumn::PHOTOS_TABLE, srcColumnInfoMap, dstColumnInfoMap),
391 "singleClone Prepare common column info failed");
392
393 this->photosClone_.LoadPhotoAlbums();
394 int totalNumberInPhotoMap = this->photosClone_.GetCloudPhotosRowCountInPhotoMap();
395 MEDIA_INFO_LOG("singleClone getPhotosRowCountInPhotoMap, totalNumber = %{public}d", totalNumberInPhotoMap);
396 totalNumber_ += static_cast<uint64_t>(totalNumberInPhotoMap);
397 MEDIA_INFO_LOG("singleClone onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
398 ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
399 for (int32_t offset = 0; offset < totalNumberInPhotoMap; offset += CLONE_QUERY_COUNT) {
400 ffrt::submit([this, offset]() { RestoreBatchForCloud(offset, 1); }, {&offset}, {},
401 ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
402 }
403 ffrt::wait();
404 size_t vectorLen = photosFailedOffsets.size();
405 needReportFailed_ = true;
406 for (size_t offset = 0; offset < vectorLen; offset++) {
407 RestoreBatchForCloud(offset, 1);
408 }
409 photosFailedOffsets.clear();
410 needReportFailed_ = false;
411 int32_t totalNumber = this->photosClone_.GetCloudPhotosRowCountNotInPhotoMap();
412 MEDIA_INFO_LOG("singleClone queryTotalNumberNot, totalNumber = %{public}d", totalNumber);
413 totalNumber_ += static_cast<uint64_t>(totalNumber);
414 MEDIA_INFO_LOG("singleClone onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
415 for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
416 ffrt::submit([this, offset]() { RestoreBatchForCloud(offset); }, { &offset }, {},
417 ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
418 }
419 ffrt::wait();
420 vectorLen = photosFailedOffsets.size();
421 needReportFailed_ = true;
422 for (size_t offset = 0; offset < vectorLen; offset++) {
423 RestoreBatchForCloud(offset);
424 }
425 this->photosClone_.OnStop(otherTotalNumber_, otherProcessStatus_);
426
427 BackupDatabaseUtils::UpdateFaceAnalysisTblStatus(mediaLibraryRdb_);
428 BackupDatabaseUtils::UpdateAnalysisPhotoMapStatus(mediaLibraryRdb_);
429 ReportPortraitCloneStat(sceneCode_);
430 }
431
RestoreAlbum()432 void CloneRestore::RestoreAlbum()
433 {
434 MEDIA_INFO_LOG("Start clone restore: albums");
435 for (const auto &tableName : CLONE_ALBUMS) {
436 if (!IsReadyForRestore(tableName)) {
437 MEDIA_ERR_LOG("Column status of %{public}s is not ready for restore album, quit",
438 BackupDatabaseUtils::GarbleInfoName(tableName).c_str());
439 continue;
440 }
441 unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_, tableName);
442 unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
443 tableName);
444 if (!PrepareCommonColumnInfoMap(tableName, srcColumnInfoMap, dstColumnInfoMap)) {
445 MEDIA_ERR_LOG("Prepare common column info failed");
446 continue;
447 }
448 GetAlbumExtraQueryWhereClause(tableName);
449 int32_t totalNumber = QueryTotalNumber(tableName);
450 MEDIA_INFO_LOG(
451 "QueryAlbumTotalNumber, tableName=%{public}s, totalNumber=%{public}d", tableName.c_str(), totalNumber);
452 for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
453 vector<AlbumInfo> albumInfos = QueryAlbumInfos(tableName, offset);
454 this->photoAlbumClone_.TRACE_LOG(tableName, albumInfos);
455 InsertAlbum(albumInfos, tableName);
456 }
457 }
458
459 RestoreFromGalleryPortraitAlbum();
460 RestorePortraitClusteringInfo();
461 cloneRestoreGeo_.RestoreGeoKnowledgeInfos();
462 cloneRestoreGeoDictionary_.RestoreAlbums();
463 RestoreHighlightAlbums();
464 }
465
GetHighlightCloudMediaCnt()466 int32_t CloneRestore::GetHighlightCloudMediaCnt()
467 {
468 const std::string QUERY_SQL = "SELECT COUNT(1) AS count FROM AnalysisAlbum AS a "
469 "INNER JOIN AnalysisPhotoMap AS m ON a.album_id = m.map_album "
470 "INNER JOIN Photos AS p ON p.file_id = m.map_asset "
471 "WHERE a.album_subtype IN (4104, 4105) AND p.position = 2";
472 std::shared_ptr<NativeRdb::ResultSet> resultSet = BackupDatabaseUtils::QuerySql(this->mediaRdb_, QUERY_SQL, {});
473 bool cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
474 CHECK_AND_RETURN_RET_LOG(!cond, -1, "query count of highlight cloud media failed.");
475
476 int32_t cnt = GetInt32Val("count", resultSet);
477 MEDIA_INFO_LOG("GetHighlightCloudMediaCnt is %{public}d", cnt);
478 resultSet->Close();
479 return cnt;
480 }
481
RestoreHighlightAlbums()482 void CloneRestore::RestoreHighlightAlbums()
483 {
484 int32_t highlightCloudMediaCnt = GetHighlightCloudMediaCnt();
485 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_)
486 .Report("Highlight Restore", "",
487 "sceneCode_: " + std::to_string(this->sceneCode_) +
488 ", highlightCloudMediaCnt: " + std::to_string(highlightCloudMediaCnt) +
489 ", isAccountValid_: " + std::to_string(isAccountValid_) +
490 ", isSyncSwitchOpen: " + std::to_string(isSyncSwitchOn_));
491 if (highlightCloudMediaCnt == 0 || IsCloudRestoreSatisfied()) {
492 cloneRestoreHighlight_.RestoreAlbums();
493 }
494 }
495
MoveMigrateFile(std::vector<FileInfo> & fileInfos,int64_t & fileMoveCount,int64_t & videoFileMoveCount)496 void CloneRestore::MoveMigrateFile(std::vector<FileInfo> &fileInfos, int64_t &fileMoveCount,
497 int64_t &videoFileMoveCount)
498 {
499 vector<std::string> moveFailedData;
500 for (size_t i = 0; i < fileInfos.size(); i++) {
501 if (!MediaFileUtils::IsFileExists(fileInfos[i].filePath) || fileInfos[i].cloudPath.empty() ||
502 !fileInfos[i].needMove) {
503 continue;
504 }
505 int32_t errCode = MoveAsset(fileInfos[i]);
506 if (errCode != E_OK) {
507 fileInfos[i].needUpdate = false;
508 fileInfos[i].needVisible = false;
509 MEDIA_ERR_LOG("MoveFile failed, filePath = %{public}s, error:%{public}s",
510 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, CLONE_RESTORE_ID, garbagePath_).c_str(),
511 strerror(errno));
512 UpdateFailedFiles(fileInfos[i].fileType, fileInfos[i], RestoreError::MOVE_FAILED);
513 ErrorInfo errorInfo(RestoreError::MOVE_FAILED, 1, std::to_string(errCode),
514 BackupLogUtils::FileInfoToString(sceneCode_, fileInfos[i]));
515 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
516 moveFailedData.push_back(fileInfos[i].cloudPath);
517 continue;
518 }
519 fileMoveCount++;
520 videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
521 }
522 DeleteMoveFailedData(moveFailedData);
523 SetVisiblePhoto(fileInfos);
524 migrateFileNumber_ += fileMoveCount;
525 migrateVideoFileNumber_ += videoFileMoveCount;
526 }
527
UpdateThumbnailStatusToFailed(std::shared_ptr<NativeRdb::RdbStore> & rdbStore,std::string id,bool isThumbnailStatusNeedUpdate,bool isLcdStatusNeedUpdate)528 static void UpdateThumbnailStatusToFailed(std::shared_ptr<NativeRdb::RdbStore> &rdbStore, std::string id,
529 bool isThumbnailStatusNeedUpdate, bool isLcdStatusNeedUpdate)
530 {
531 bool cond = (rdbStore == nullptr || id.empty());
532 CHECK_AND_RETURN_LOG(!cond, "singleClone rdb is nullptr or id is empty");
533
534 NativeRdb::ValuesBucket values;
535 int changedRows;
536 if (isThumbnailStatusNeedUpdate) {
537 values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, RESTORE_THUMBNAIL_READY_NO_THUMBNAIL);
538 values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
539 }
540 if (isLcdStatusNeedUpdate) {
541 values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, RESTORE_LCD_VISIT_TIME_NO_LCD);
542 }
543 int32_t err = rdbStore->Update(changedRows, PhotoColumn::PHOTOS_TABLE,
544 values, MEDIA_DATA_DB_ID + " = ?", vector<string> { id });
545 CHECK_AND_PRINT_LOG(err == NativeRdb::E_OK, "singleClone rdbStore Update failed! %{public}d", err);
546 }
547
GetCloudPhotoFileExistFlag(const FileInfo & fileInfo,CloudPhotoFileExistFlag & resultExistFlag)548 void CloneRestore::GetCloudPhotoFileExistFlag(const FileInfo &fileInfo, CloudPhotoFileExistFlag &resultExistFlag)
549 {
550 std::string dirPath = GetThumbnailLocalPath(fileInfo.cloudPath);
551 CHECK_AND_RETURN_LOG(MediaFileUtils::IsFileExists(dirPath),
552 "GetCloudPhotoFileExistFlag %{public}s not exist!", fileInfo.cloudPath.c_str());
553
554 std::string lcdPath = dirPath + "/LCD.jpg";
555 resultExistFlag.isLcdExist = MediaFileUtils::IsFileExists(lcdPath) ? true : false;
556 std::string thmPath = dirPath + "/THM.jpg";
557 resultExistFlag.isThmExist = MediaFileUtils::IsFileExists(thmPath) ? true : false;
558 std::string astcPath = dirPath + "/THM_ASTC.astc";
559 resultExistFlag.isDayAstcExist = MediaFileUtils::IsFileExists(astcPath) ? true : false;
560
561 if (fileInfo.orientation != 0) {
562 std::string exLcdPath = dirPath + "/THM_EX/LCD.jpg";
563 resultExistFlag.isExLcdExist = MediaFileUtils::IsFileExists(exLcdPath) ? true : false;
564 std::string exThmPath = dirPath + "/THM_EX/THM.jpg";
565 resultExistFlag.isExThmExist = MediaFileUtils::IsFileExists(exThmPath) ? true : false;
566 }
567 MEDIA_DEBUG_LOG("%{public}s, isexist lcd:%{public}d, thm:%{public}d, astc:%{public}d,"
568 "yearastc:%{public}d, exlcd:%{public}d, exthm:%{public}d",
569 dirPath.c_str(), resultExistFlag.isLcdExist, resultExistFlag.isThmExist,
570 resultExistFlag.isDayAstcExist, resultExistFlag.isYearAstcExist,
571 resultExistFlag.isExLcdExist, resultExistFlag.isExThmExist);
572 }
573
CloudPhotoFilesVerify(const std::vector<FileInfo> & fileInfos,std::vector<FileInfo> & LCDNotFound,std::vector<FileInfo> & THMNotFound,unordered_map<string,CloudPhotoFileExistFlag> & resultExistMap)574 void CloneRestore::CloudPhotoFilesVerify(const std::vector<FileInfo> &fileInfos, std::vector<FileInfo> &LCDNotFound,
575 std::vector<FileInfo> &THMNotFound, unordered_map<string, CloudPhotoFileExistFlag> &resultExistMap)
576 {
577 for (size_t i = 0; i < fileInfos.size(); i++) {
578 CloudPhotoFileExistFlag fileExistFlag;
579 unordered_map<string, CloudPhotoFileExistFlag>::iterator iter = resultExistMap.find(fileInfos[i].cloudPath);
580 if (iter != resultExistMap.end()) {
581 fileExistFlag = iter->second;
582 }
583 GetCloudPhotoFileExistFlag(fileInfos[i], fileExistFlag);
584 resultExistMap[fileInfos[i].cloudPath] = fileExistFlag;
585 if (fileInfos[i].orientation != 0) {
586 if (!fileExistFlag.isExLcdExist) {
587 LCDNotFound.push_back(fileInfos[i]);
588 }
589 if (!fileExistFlag.isExThmExist) {
590 THMNotFound.push_back(fileInfos[i]);
591 }
592 } else {
593 if (!fileExistFlag.isLcdExist) {
594 LCDNotFound.push_back(fileInfos[i]);
595 }
596 if (!fileExistFlag.isThmExist) {
597 THMNotFound.push_back(fileInfos[i]);
598 }
599 }
600 }
601 }
602
MoveMigrateCloudFile(std::vector<FileInfo> & fileInfos,int32_t & fileMoveCount,int32_t & videoFileMoveCount,int32_t sceneCode)603 void CloneRestore::MoveMigrateCloudFile(std::vector<FileInfo> &fileInfos, int32_t &fileMoveCount,
604 int32_t &videoFileMoveCount, int32_t sceneCode)
605 {
606 MEDIA_INFO_LOG("singleClone MoveMigrateCloudFile start");
607 unordered_map<string, CloudPhotoFileExistFlag> resultExistMap;
608 for (size_t i = 0; i < fileInfos.size(); i++) {
609 if (!fileInfos[i].needMove) {
610 continue;
611 }
612 MoveCloudThumbnailDir(fileInfos[i]);
613 if (!isInitKvstoreSuccess_) {
614 MEDIA_ERR_LOG("singleClone isInitKvstoreSuccess_ false, id:%{public}d, path:%{public}s",
615 fileInfos[i].fileIdNew, MediaFileUtils::DesensitizePath(fileInfos[i].cloudPath).c_str());
616 continue;
617 }
618 if (fileInfos[i].thumbnailReady < RESTORE_THUMBNAIL_READY_SUCCESS) {
619 MEDIA_ERR_LOG("singleClone Astc does not exist, id:%{public}d, path:%{public}s",
620 fileInfos[i].fileIdNew, MediaFileUtils::DesensitizePath(fileInfos[i].cloudPath).c_str());
621 continue;
622 }
623 if (MoveAstc(fileInfos[i]) != E_OK) {
624 UpdateThumbnailStatusToFailed(mediaLibraryRdb_, to_string(fileInfos[i].fileIdNew), true, false);
625 MEDIA_ERR_LOG("Move astc failed, id:%{public}d, path:%{public}s",
626 fileInfos[i].fileIdNew, MediaFileUtils::DesensitizePath(fileInfos[i].cloudPath).c_str());
627 }
628 CloudPhotoFileExistFlag tmpFlag;
629 tmpFlag.isYearAstcExist = true;
630 resultExistMap[fileInfos[i].cloudPath] = tmpFlag;
631 videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
632 }
633 std::vector<FileInfo> LCDNotFound;
634 std::vector<FileInfo> THMNotFound;
635 CloudPhotoFilesVerify(fileInfos, LCDNotFound, THMNotFound, resultExistMap);
636 MEDIA_INFO_LOG("singleClone LCDNotFound:%{public}zu, THMNotFound:%{public}zu",
637 LCDNotFound.size(), THMNotFound.size());
638 std::vector<std::string> dentryFailedLCD;
639 std::vector<std::string> dentryFailedThumb;
640 if (BatchCreateDentryFile(LCDNotFound, dentryFailedLCD, DENTRY_INFO_LCD) == E_OK) {
641 HandleFailData(fileInfos, dentryFailedLCD, DENTRY_INFO_LCD);
642 }
643 if (BatchCreateDentryFile(THMNotFound, dentryFailedThumb, DENTRY_INFO_THM) == E_OK) {
644 HandleFailData(fileInfos, dentryFailedThumb, DENTRY_INFO_THM);
645 }
646 BatchUpdateFileInfoData(fileInfos, resultExistMap);
647 fileMoveCount = SetVisiblePhoto(fileInfos);
648 successCloudMetaNumber_ += fileMoveCount;
649 migrateFileNumber_ += fileMoveCount;
650 migrateVideoFileNumber_ += videoFileMoveCount;
651 MEDIA_INFO_LOG("singleClone MoveMigrateCloudFile end");
652 }
653
InsertPhoto(vector<FileInfo> & fileInfos)654 int CloneRestore::InsertPhoto(vector<FileInfo> &fileInfos)
655 {
656 CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, E_OK, "mediaLibraryRdb_ is null");
657 CHECK_AND_RETURN_RET_LOG(!fileInfos.empty(), E_OK, "fileInfos are empty");
658 int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
659 vector<NativeRdb::ValuesBucket> values = GetInsertValues(CLONE_RESTORE_ID, fileInfos, SourceType::PHOTOS);
660 int64_t startInsertPhoto = MediaFileUtils::UTCTimeMilliSeconds();
661 int64_t photoRowNum = 0;
662 int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, photoRowNum);
663 if (errCode != E_OK) {
664 if (needReportFailed_) {
665 UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
666 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(fileInfos.size()), errCode);
667 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
668 }
669 return errCode;
670 }
671 migrateDatabaseNumber_ += photoRowNum;
672
673 int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
674 InsertPhotoRelated(fileInfos);
675
676 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
677 int64_t fileMoveCount = 0;
678 int64_t videoFileMoveCount = 0;
679 MoveMigrateFile(fileInfos, fileMoveCount, videoFileMoveCount);
680 int64_t startUpdate = MediaFileUtils::UTCTimeMilliSeconds();
681 UpdatePhotosByFileInfoMap(mediaLibraryRdb_, fileInfos);
682 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
683 MEDIA_INFO_LOG("generate cost %{public}ld, insert %{public}ld assets cost %{public}ld, insert photo related cost "
684 "%{public}ld, and move %{public}ld files (%{public}ld + %{public}ld) cost %{public}ld. update cost %{public}ld",
685 (long)(startInsertPhoto - startGenerate), (long)photoRowNum, (long)(startInsertRelated - startInsertPhoto),
686 (long)(startMove - startInsertRelated), (long)fileMoveCount, (long)(fileMoveCount - videoFileMoveCount),
687 (long)videoFileMoveCount, (long)(startUpdate - startMove), (long)(end - startUpdate));
688 return E_OK;
689 }
690
GetInsertValues(int32_t sceneCode,vector<FileInfo> & fileInfos,int32_t sourceType)691 vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(int32_t sceneCode, vector<FileInfo> &fileInfos,
692 int32_t sourceType)
693 {
694 vector<NativeRdb::ValuesBucket> values;
695 for (size_t i = 0; i < fileInfos.size(); i++) {
696 int32_t errCode = BackupFileUtils::IsFileValid(fileInfos[i].filePath, CLONE_RESTORE_ID);
697 if (errCode != E_OK) {
698 ErrorInfo errorInfo(RestoreError::FILE_INVALID, 1, std::to_string(errCode),
699 BackupLogUtils::FileInfoToString(sceneCode, fileInfos[i]));
700 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
701 continue;
702 }
703 if (!PrepareCloudPath(PhotoColumn::PHOTOS_TABLE, fileInfos[i])) {
704 continue;
705 }
706 if (fileInfos[i].isNew) {
707 NativeRdb::ValuesBucket value = GetInsertValue(fileInfos[i], fileInfos[i].cloudPath, sourceType);
708 values.emplace_back(value);
709 }
710 }
711 return values;
712 }
713
GetCloudInsertValues(int32_t sceneCode,vector<FileInfo> & fileInfos,int32_t sourceType)714 vector<NativeRdb::ValuesBucket> CloneRestore::GetCloudInsertValues(int32_t sceneCode, vector<FileInfo> &fileInfos,
715 int32_t sourceType)
716 {
717 MEDIA_INFO_LOG("singleClone GetCloudInsertValues: %{public}zu", fileInfos.size());
718 vector<NativeRdb::ValuesBucket> values;
719 for (size_t i = 0; i < fileInfos.size(); i++) {
720 if (!PrepareCloudPath(PhotoColumn::PHOTOS_TABLE, fileInfos[i])) {
721 continue;
722 }
723 NativeRdb::ValuesBucket value = GetCloudInsertValue(fileInfos[i], fileInfos[i].cloudPath, sourceType);
724 fileInfos[i].isNew = true;
725 values.emplace_back(value);
726 }
727 return values;
728 }
729
HandleRestData(void)730 void CloneRestore::HandleRestData(void)
731 {
732 MEDIA_INFO_LOG("Start to handle rest data in native.");
733 }
734
QueryFileInfos(int32_t offset,int32_t isRelatedToPhotoMap)735 vector<FileInfo> CloneRestore::QueryFileInfos(int32_t offset, int32_t isRelatedToPhotoMap)
736 {
737 vector<FileInfo> result;
738 result.reserve(CLONE_QUERY_COUNT);
739 std::shared_ptr<NativeRdb::ResultSet> resultSet;
740 if (isRelatedToPhotoMap == 1) {
741 resultSet = this->photosClone_.GetPhotosInPhotoMap(offset, CLONE_QUERY_COUNT);
742 } else {
743 resultSet = this->photosClone_.GetPhotosNotInPhotoMap(offset, CLONE_QUERY_COUNT);
744 }
745 if (resultSet == nullptr) {
746 MEDIA_ERR_LOG("Query resultSql is null.");
747 return result;
748 }
749 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
750 FileInfo fileInfo;
751 fileInfo.isRelatedToPhotoMap = isRelatedToPhotoMap;
752 if (ParseResultSet(resultSet, fileInfo)) {
753 result.emplace_back(fileInfo);
754 }
755 }
756 return result;
757 }
758
QueryCloudFileInfos(int32_t offset,int32_t isRelatedToPhotoMap)759 vector<FileInfo> CloneRestore::QueryCloudFileInfos(int32_t offset, int32_t isRelatedToPhotoMap)
760 {
761 MEDIA_INFO_LOG("singleClone QueryCloudFileInfos");
762 vector<FileInfo> result;
763 result.reserve(CLONE_QUERY_COUNT);
764 std::shared_ptr<NativeRdb::ResultSet> resultSet;
765 if (isRelatedToPhotoMap == 1) {
766 resultSet = this->photosClone_.GetCloudPhotosInPhotoMap(offset, CLONE_QUERY_COUNT);
767 } else {
768 resultSet = this->photosClone_.GetCloudPhotosNotInPhotoMap(offset, CLONE_QUERY_COUNT);
769 }
770 if (resultSet == nullptr) {
771 MEDIA_ERR_LOG("singleClone Query resultSql is null.");
772 return result;
773 }
774 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
775 FileInfo fileInfo;
776 fileInfo.isRelatedToPhotoMap = isRelatedToPhotoMap;
777 if (ParseResultSet(resultSet, fileInfo)) {
778 result.emplace_back(fileInfo);
779 }
780 }
781 return result;
782 }
783
ParseResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo,string dbName)784 bool CloneRestore::ParseResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &fileInfo,
785 string dbName)
786 {
787 return ParseResultSet(PhotoColumn::PHOTOS_TABLE, resultSet, fileInfo);
788 }
789
QueryTotalNumber(const string & tableName)790 int32_t CloneRestore::QueryTotalNumber(const string &tableName)
791 {
792 CHECK_AND_RETURN_RET(tableName != PhotoAlbumColumns::TABLE,
793 this->photoAlbumClone_.GetPhotoAlbumCountInOriginalDb());
794 CHECK_AND_RETURN_RET(tableName != PhotoColumn::PHOTOS_TABLE,
795 this->photosClone_.GetPhotosRowCountNotInPhotoMap());
796 string querySql = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + tableName;
797 string whereClause = GetQueryWhereClauseByTable(tableName);
798 querySql += whereClause.empty() ? "" : " WHERE " + whereClause;
799 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
800 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
801 return 0;
802 }
803 int32_t result = GetInt32Val(MEDIA_COLUMN_COUNT_1, resultSet);
804 return result;
805 }
806
QueryAlbumInfos(const string & tableName,int32_t offset)807 vector<AlbumInfo> CloneRestore::QueryAlbumInfos(const string &tableName, int32_t offset)
808 {
809 vector<AlbumInfo> result;
810 result.reserve(CLONE_QUERY_COUNT);
811 std::shared_ptr<NativeRdb::ResultSet> resultSet = nullptr;
812 if (tableName == PhotoAlbumColumns::TABLE) {
813 resultSet = this->photoAlbumClone_.GetPhotoAlbumInOriginalDb(offset, CLONE_QUERY_COUNT);
814 } else {
815 string querySql = "SELECT * FROM " + tableName;
816 string whereClause = GetQueryWhereClauseByTable(tableName);
817 querySql += whereClause.empty() ? "" : " WHERE " + whereClause;
818 querySql += " LIMIT " + to_string(offset) + ", " + to_string(CLONE_QUERY_COUNT);
819 resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
820 }
821 if (resultSet == nullptr) {
822 MEDIA_ERR_LOG("Query resultSql is null.");
823 return result;
824 }
825 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
826 AlbumInfo albumInfo;
827 if (ParseAlbumResultSet(tableName, resultSet, albumInfo)) {
828 result.emplace_back(albumInfo);
829 }
830 }
831 return result;
832 }
833
ParseAlbumResultSet(const string & tableName,const shared_ptr<NativeRdb::ResultSet> & resultSet,AlbumInfo & albumInfo)834 bool CloneRestore::ParseAlbumResultSet(const string &tableName, const shared_ptr<NativeRdb::ResultSet> &resultSet,
835 AlbumInfo &albumInfo)
836 {
837 albumInfo.albumIdOld = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
838 albumInfo.albumName = GetStringVal(PhotoAlbumColumns::ALBUM_NAME, resultSet);
839 albumInfo.albumType = static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet));
840 albumInfo.albumSubType = static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet));
841 albumInfo.lPath = GetStringVal(PhotoAlbumColumns::ALBUM_LPATH, resultSet);
842 albumInfo.albumBundleName = GetStringVal(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, resultSet);
843 albumInfo.dateModified = GetInt64Val(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, resultSet);
844
845 auto commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
846 for (auto it = commonColumnInfoMap.begin(); it != commonColumnInfoMap.end(); ++it) {
847 string columnName = it->first;
848 string columnType = it->second;
849 GetValFromResultSet(resultSet, albumInfo.valMap, columnName, columnType);
850 }
851 return true;
852 }
853
AnalyzeSource()854 void CloneRestore::AnalyzeSource()
855 {
856 MEDIA_INFO_LOG("analyze source later");
857 }
858
MovePicture(FileInfo & fileInfo)859 int32_t CloneRestore::MovePicture(FileInfo &fileInfo)
860 {
861 bool deleteOriginalFile = fileInfo.isRelatedToPhotoMap == 1 ? false : true;
862 string localPath = BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL,
863 fileInfo.cloudPath);
864 int32_t opRet = E_FAIL;
865 if (deleteOriginalFile) {
866 opRet = this->MoveFile(fileInfo.filePath, localPath);
867 } else {
868 opRet = this->CopyFile(fileInfo.filePath, localPath);
869 }
870 CHECK_AND_RETURN_RET_LOG(opRet == E_OK, E_FAIL,
871 "Move photo file failed, filePath = %{public}s, deleteOriginalFile = %{public}d",
872 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str(),
873 deleteOriginalFile);
874 return E_OK;
875 }
876
MoveMovingPhotoVideo(FileInfo & fileInfo)877 int32_t CloneRestore::MoveMovingPhotoVideo(FileInfo &fileInfo)
878 {
879 CHECK_AND_RETURN_RET(fileInfo.subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO), E_OK);
880 bool deleteOriginalFile = fileInfo.isRelatedToPhotoMap == 1 ? false : true;
881 std::string localPath = BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL,
882 fileInfo.cloudPath);
883 std::string srcLocalVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(fileInfo.filePath);
884 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(srcLocalVideoPath), E_OK,
885 "video of moving photo does not exist: %{private}s", srcLocalVideoPath.c_str());
886 std::string localVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(localPath);
887 int32_t opVideoRet = E_FAIL;
888 if (deleteOriginalFile) {
889 opVideoRet = this->MoveFile(srcLocalVideoPath, localVideoPath);
890 } else {
891 opVideoRet = this->CopyFile(srcLocalVideoPath, localVideoPath);
892 }
893 CHECK_AND_RETURN_RET_LOG(opVideoRet == E_OK, E_FAIL, "Move video of moving photo failed");
894 BackupFileUtils::ModifyFile(localVideoPath, fileInfo.dateModified / MSEC_TO_SEC);
895 return E_OK;
896 }
897
MoveEditedData(FileInfo & fileInfo)898 int32_t CloneRestore::MoveEditedData(FileInfo &fileInfo)
899 {
900 bool deleteOriginalFile = fileInfo.isRelatedToPhotoMap == 1 ? false : true;
901 string localPath =
902 BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL, fileInfo.cloudPath);
903 string srcEditDataPath = this->backupRestoreDir_ +
904 BackupFileUtils::GetFullPathByPrefixType(PrefixType::LOCAL_EDIT_DATA, fileInfo.relativePath);
905 string dstEditDataPath = BackupFileUtils::GetReplacedPathByPrefixType(
906 PrefixType::CLOUD, PrefixType::LOCAL_EDIT_DATA, fileInfo.cloudPath);
907 bool cond = (this->IsFilePathExist(srcEditDataPath) &&
908 this->MoveDirectory(srcEditDataPath, dstEditDataPath, deleteOriginalFile) != E_OK);
909 CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "Move editData file failed");
910 return E_OK;
911 }
912
GetThumbnailLocalPath(const string path)913 std::string CloneRestore::GetThumbnailLocalPath(const string path)
914 {
915 size_t cloudDirLength = RESTORE_FILES_CLOUD_DIR.length();
916 if (path.length() <= cloudDirLength || path.substr(0, cloudDirLength).compare(RESTORE_FILES_CLOUD_DIR) != 0) {
917 return "";
918 }
919
920 std::string suffixStr = path.substr(cloudDirLength);
921 return RESTORE_FILES_LOCAL_DIR + ".thumbs/" + suffixStr;
922 }
923
MoveAstc(FileInfo & fileInfo)924 int32_t CloneRestore::MoveAstc(FileInfo &fileInfo)
925 {
926 bool cond = (oldMonthKvStorePtr_ == nullptr || oldYearKvStorePtr_ == nullptr ||
927 newMonthKvStorePtr_ == nullptr || newYearKvStorePtr_ == nullptr);
928 CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "Kvstore is nullptr");
929 if (fileInfo.fileIdOld <= 0 || fileInfo.fileIdNew <= 0) {
930 MEDIA_ERR_LOG("Old fileId:%{public}d or new fileId:%{public}d is invalid",
931 fileInfo.fileIdOld, fileInfo.fileIdNew);
932 return E_FAIL;
933 }
934
935 string oldKey;
936 string newKey;
937 if (!MediaFileUtils::GenerateKvStoreKey(to_string(fileInfo.fileIdOld), fileInfo.oldAstcDateKey, oldKey) ||
938 !MediaFileUtils::GenerateKvStoreKey(to_string(fileInfo.fileIdNew), fileInfo.newAstcDateKey, newKey)) {
939 return E_FAIL;
940 }
941
942 std::vector<uint8_t> monthValue;
943 std::vector<uint8_t> yearValue;
944 if (oldMonthKvStorePtr_->Query(oldKey, monthValue) != E_OK ||
945 newMonthKvStorePtr_->Insert(newKey, monthValue) != E_OK) {
946 MEDIA_ERR_LOG("MonthValue move failed, fileID %{public}s", newKey.c_str());
947 return E_FAIL;
948 }
949 if (oldYearKvStorePtr_->Query(oldKey, yearValue) != E_OK ||
950 newYearKvStorePtr_->Insert(newKey, yearValue) != E_OK) {
951 MEDIA_ERR_LOG("YearValue move failed, fileID %{public}s", newKey.c_str());
952 return E_FAIL;
953 }
954 if (fileInfo.isRelatedToPhotoMap != 1) {
955 oldMonthKvStorePtr_->Delete(oldKey);
956 oldYearKvStorePtr_->Delete(oldKey);
957 }
958 return E_OK;
959 }
960
MoveThumbnailDir(FileInfo & fileInfo)961 int32_t CloneRestore::MoveThumbnailDir(FileInfo &fileInfo)
962 {
963 string thumbnailOldDir = backupRestoreDir_ + RESTORE_FILES_LOCAL_DIR + ".thumbs" + fileInfo.relativePath;
964 string thumbnailNewDir = GetThumbnailLocalPath(fileInfo.cloudPath);
965 if (fileInfo.relativePath.empty() || thumbnailNewDir.empty()) {
966 MEDIA_ERR_LOG("Old path:%{public}s or new path:%{public}s is invalid",
967 fileInfo.relativePath.c_str(), MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
968 return E_FAIL;
969 }
970 if (!MediaFileUtils::IsDirectory(thumbnailOldDir)) {
971 MEDIA_ERR_LOG("Old dir is not a direcrory or does not exist, errno:%{public}d, dir:%{public}s",
972 errno, MediaFileUtils::DesensitizePath(thumbnailOldDir).c_str());
973 return E_FAIL;
974 }
975 CHECK_AND_RETURN_RET_LOG(BackupFileUtils::PreparePath(thumbnailNewDir) == E_OK, E_FAIL,
976 "Prepare thumbnail dir path failed");
977 bool cond = (MediaFileUtils::IsFileExists(thumbnailNewDir) && !MediaFileUtils::DeleteDir(thumbnailNewDir));
978 CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "Delete thumbnail new dir failed, errno:%{public}d", errno);
979
980 int32_t opRet = E_FAIL;
981 if (fileInfo.isRelatedToPhotoMap != 1) {
982 opRet = MediaFileUtils::ModifyAsset(thumbnailOldDir, thumbnailNewDir);
983 } else {
984 opRet = MediaFileUtils::CopyDirectory(thumbnailOldDir, thumbnailNewDir);
985 }
986 if (opRet != E_OK) {
987 CHECK_AND_RETURN_RET(MediaFileUtils::IsFileExists(thumbnailNewDir), opRet);
988 MEDIA_WARN_LOG("MoveThumbnailDir failed but thumbnailNewDir exists");
989 CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteDir(thumbnailNewDir),
990 "Delete existential thumbnailNewDir failed, errno:%{public}d", errno);
991 return opRet;
992 }
993 return E_OK;
994 }
995
MoveCloudThumbnailDir(FileInfo & fileInfo)996 int32_t CloneRestore::MoveCloudThumbnailDir(FileInfo &fileInfo)
997 {
998 string thumbnailOldDir = backupRestoreDir_ + RESTORE_FILES_LOCAL_DIR + ".thumbs" + fileInfo.relativePath;
999 string thumbnailNewDir = GetThumbnailLocalPath(fileInfo.cloudPath);
1000 bool cond = (fileInfo.relativePath.empty() || thumbnailNewDir.empty());
1001 CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "singleCloud Old path:%{public}s or new path:%{public}s is invalid",
1002 fileInfo.relativePath.c_str(), MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1003
1004 if (!MediaFileUtils::IsDirectory(thumbnailOldDir)) {
1005 MEDIA_ERR_LOG("singleCloud Old dir is not a direcrory or does not exist, errno:%{public}d, dir:%{public}s",
1006 errno, MediaFileUtils::DesensitizePath(thumbnailOldDir).c_str());
1007 return E_FAIL;
1008 }
1009
1010 CHECK_AND_RETURN_RET_LOG(BackupFileUtils::PreparePath(thumbnailNewDir) == E_OK, E_FAIL,
1011 "singleCloud Prepare thumbnail dir path failed");
1012 cond = (MediaFileUtils::IsFileExists(thumbnailNewDir) && !MediaFileUtils::DeleteDir(thumbnailNewDir));
1013 CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "singleCloud Delete thumbnail new dir failed, errno:%{public}d", errno);
1014
1015 int32_t opRet = E_FAIL;
1016 if (fileInfo.isRelatedToPhotoMap != 1) {
1017 opRet = MediaFileUtils::ModifyAsset(thumbnailOldDir, thumbnailNewDir);
1018 } else {
1019 opRet = MediaFileUtils::CopyDirectory(thumbnailOldDir, thumbnailNewDir);
1020 }
1021 if (opRet != E_OK) {
1022 CHECK_AND_RETURN_RET(MediaFileUtils::IsFileExists(thumbnailNewDir), opRet);
1023 MEDIA_WARN_LOG("singleCloud MoveThumbnailDir failed but thumbnailNewDir exists");
1024 return opRet;
1025 }
1026 return E_OK;
1027 }
1028
1029 /**
1030 * The processing logic of the MoveThumbnail function must match the logic of the GetThumbnailInsertValue function.
1031 * If the status indicates that the thumbnail does not exist, the thumbnail does not need to be cloned and
1032 * the status of the thumbnail needs to be set to the initial status in the GetThumbnailInsertValue function.
1033 * If the status indicates that the thumbnail exists but the thumbnail fails to be transferred,
1034 * the thumbnail status needs to be set to the initial status.
1035 */
MoveThumbnail(FileInfo & fileInfo)1036 int32_t CloneRestore::MoveThumbnail(FileInfo &fileInfo)
1037 {
1038 if (!hasCloneThumbnailDir_) {
1039 return E_NO_SUCH_FILE;
1040 }
1041 if (fileInfo.thumbnailReady < RESTORE_THUMBNAIL_READY_SUCCESS &&
1042 fileInfo.lcdVisitTime < RESTORE_LCD_VISIT_TIME_SUCCESS) {
1043 MEDIA_INFO_LOG("Thumbnail dose not exist, id:%{public}d, path:%{public}s",
1044 fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1045 return E_NO_SUCH_FILE;
1046 }
1047 if (MoveThumbnailDir(fileInfo) != E_OK) {
1048 UpdateThumbnailStatusToFailed(mediaLibraryRdb_, to_string(fileInfo.fileIdNew), true, true);
1049 MEDIA_ERR_LOG("Move thumbnail failed, id:%{public}d, path:%{public}s",
1050 fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1051 return E_FAIL;
1052 }
1053
1054 CHECK_AND_RETURN_RET(isInitKvstoreSuccess_, E_NO_SUCH_FILE);
1055 CHECK_AND_RETURN_RET_LOG(fileInfo.thumbnailReady >= RESTORE_THUMBNAIL_READY_SUCCESS, E_NO_SUCH_FILE,
1056 "Astc does not exist, id:%{public}d, path:%{public}s",
1057 fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1058 if (MoveAstc(fileInfo) != E_OK) {
1059 UpdateThumbnailStatusToFailed(mediaLibraryRdb_, to_string(fileInfo.fileIdNew), true, false);
1060 MEDIA_ERR_LOG("Move astc failed, id:%{public}d, path:%{public}s",
1061 fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1062 return E_FAIL;
1063 }
1064
1065 MediaLibraryPhotoOperations::StoreThumbnailSize(to_string(fileInfo.fileIdNew), fileInfo.cloudPath);
1066 return E_OK;
1067 }
1068
MoveAsset(FileInfo & fileInfo)1069 int32_t CloneRestore::MoveAsset(FileInfo &fileInfo)
1070 {
1071 // Picture files.
1072 int32_t optRet = this->MovePicture(fileInfo);
1073 CHECK_AND_RETURN_RET(optRet == E_OK, E_FAIL);
1074 // Video files of moving photo.
1075 optRet = this->MoveMovingPhotoVideo(fileInfo);
1076 CHECK_AND_RETURN_RET(optRet == E_OK, E_FAIL);
1077 // Edit Data.
1078 optRet = this->MoveEditedData(fileInfo);
1079 CHECK_AND_RETURN_RET(optRet == E_OK, E_FAIL);
1080 // Thumbnail of photos.
1081 this->MoveThumbnail(fileInfo);
1082 return E_OK;
1083 }
1084
IsFilePathExist(const string & filePath) const1085 bool CloneRestore::IsFilePathExist(const string &filePath) const
1086 {
1087 if (!MediaFileUtils::IsFileExists(filePath)) {
1088 MEDIA_DEBUG_LOG("%{private}s doesn't exist", filePath.c_str());
1089 return false;
1090 }
1091 bool cond = (MediaFileUtils::IsDirectory(filePath) && MediaFileUtils::IsDirEmpty(filePath));
1092 CHECK_AND_RETURN_RET_LOG(!cond, false, "%{private}s is an empty directory", filePath.c_str());
1093 return true;
1094 }
1095
GetThumbnailInsertValue(const FileInfo & fileInfo,NativeRdb::ValuesBucket & values)1096 void CloneRestore::GetThumbnailInsertValue(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values)
1097 {
1098 if (!hasCloneThumbnailDir_) {
1099 // If there is no thumbnail directory, all statuses of thumbnail are set to the initial status.
1100 values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, RESTORE_LCD_VISIT_TIME_NO_LCD);
1101 values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, RESTORE_THUMBNAIL_READY_NO_THUMBNAIL);
1102 values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
1103 return;
1104 }
1105
1106 // The LCD status is same as the origin status.
1107 values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, fileInfo.lcdVisitTime);
1108 if (!isInitKvstoreSuccess_ || fileInfo.thumbnailReady < RESTORE_THUMBNAIL_READY_SUCCESS) {
1109 // The kvdb does not exist or the THM status indicates that there is no THM.
1110 // Therefore, the THM status needs to be set to the initial status.
1111 values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, RESTORE_THUMBNAIL_READY_NO_THUMBNAIL);
1112 values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
1113 return;
1114 }
1115 values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, fileInfo.thumbnailReady);
1116 values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_TRUE);
1117 }
1118
GetCloudThumbnailInsertValue(const FileInfo & fileInfo,NativeRdb::ValuesBucket & values)1119 void CloneRestore::GetCloudThumbnailInsertValue(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values)
1120 {
1121 values.PutInt(PhotoColumn::PHOTO_POSITION, fileInfo.position);
1122 values.PutString(PhotoColumn::PHOTO_CLOUD_ID, fileInfo.cloudId);
1123 values.PutInt(PhotoColumn::PHOTO_CLOUD_VERSION, fileInfo.cloudVersion);
1124 values.PutInt(PhotoColumn::PHOTO_DIRTY, 0);
1125 values.PutInt(PhotoColumn::PHOTO_CLEAN_FLAG, 0);
1126 values.PutInt(PhotoColumn::PHOTO_THUMB_STATUS, RESTORE_THUMBNAIL_STATUS_NOT_ALL);
1127 values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
1128 values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, 0);
1129 values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
1130 values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, 0);
1131 }
1132
GetInsertValue(const FileInfo & fileInfo,const string & newPath,int32_t sourceType)1133 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const FileInfo &fileInfo, const string &newPath,
1134 int32_t sourceType)
1135 {
1136 NativeRdb::ValuesBucket values;
1137 values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
1138 values.PutLong(MediaColumn::MEDIA_SIZE, fileInfo.fileSize);
1139 values.PutInt(MediaColumn::MEDIA_TYPE, fileInfo.fileType);
1140 values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
1141 values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(fileInfo.displayName));
1142 values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateAdded);
1143 values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, fileInfo.dateModified);
1144 values.PutInt(PhotoColumn::PHOTO_ORIENTATION, fileInfo.orientation); // photos need orientation
1145 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileInfo.subtype);
1146 // use owner_album_id to mark the album id which the photo is in.
1147 values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, fileInfo.ownerAlbumId);
1148 // Only SOURCE album has package_name and owner_package.
1149 values.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileInfo.packageName);
1150 values.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileInfo.bundleName);
1151 if (fileInfo.packageName.empty() && fileInfo.bundleName.empty()) {
1152 // package_name and owner_package are empty, clear owner_appid
1153 values.PutString(MediaColumn::MEDIA_OWNER_APPID, "");
1154 }
1155 values.PutInt(PhotoColumn::PHOTO_QUALITY, fileInfo.photoQuality);
1156 values.PutInt(PhotoColumn::STAGE_VIDEO_TASK_STATUS, static_cast<int32_t>(StageVideoTaskStatus::NO_NEED_TO_STAGE));
1157 values.PutLong(MediaColumn::MEDIA_DATE_TRASHED, fileInfo.recycledTime);
1158 values.PutInt(MediaColumn::MEDIA_HIDDEN, fileInfo.hidden);
1159 values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, fileInfo.sourcePath);
1160 values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
1161 GetThumbnailInsertValue(fileInfo, values);
1162
1163 unordered_map<string, string> commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_,
1164 PhotoColumn::PHOTOS_TABLE);
1165 for (auto it = fileInfo.valMap.begin(); it != fileInfo.valMap.end(); ++it) {
1166 string columnName = it->first;
1167 auto columnVal = it->second;
1168 if (columnName == PhotoColumn::PHOTO_EDIT_TIME) {
1169 PrepareEditTimeVal(values, get<int64_t>(columnVal), fileInfo, commonColumnInfoMap);
1170 continue;
1171 }
1172 if (columnName == PhotoColumn::MEDIA_DATE_TAKEN) {
1173 if (get<int64_t>(columnVal) > SECONDS_LEVEL_LIMIT) {
1174 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, get<int64_t>(columnVal));
1175 } else {
1176 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, get<int64_t>(columnVal) * MSEC_TO_SEC);
1177 }
1178 continue;
1179 }
1180 PrepareCommonColumnVal(values, columnName, columnVal, commonColumnInfoMap);
1181 }
1182 return values;
1183 }
1184
GetCloudInsertValue(const FileInfo & fileInfo,const string & newPath,int32_t sourceType)1185 NativeRdb::ValuesBucket CloneRestore::GetCloudInsertValue(const FileInfo &fileInfo, const string &newPath,
1186 int32_t sourceType)
1187 {
1188 NativeRdb::ValuesBucket values;
1189 values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
1190 values.PutLong(MediaColumn::MEDIA_SIZE, fileInfo.fileSize);
1191 values.PutInt(MediaColumn::MEDIA_TYPE, fileInfo.fileType);
1192 values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
1193 values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateAdded);
1194 values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, fileInfo.dateModified);
1195 values.PutInt(PhotoColumn::PHOTO_ORIENTATION, fileInfo.orientation); // photos need orientation
1196 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileInfo.subtype);
1197 // use owner_album_id to mark the album id which the photo is in.
1198 values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, fileInfo.ownerAlbumId);
1199 // Only SOURCE album has package_name and owner_package.
1200 values.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileInfo.packageName);
1201 values.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileInfo.bundleName);
1202 if (fileInfo.packageName.empty() && fileInfo.bundleName.empty()) {
1203 // package_name and owner_package are empty, clear owner_appid
1204 values.PutString(MediaColumn::MEDIA_OWNER_APPID, "");
1205 }
1206 values.PutInt(PhotoColumn::PHOTO_QUALITY, fileInfo.photoQuality);
1207 values.PutLong(MediaColumn::MEDIA_DATE_TRASHED, fileInfo.recycledTime);
1208 values.PutInt(MediaColumn::MEDIA_HIDDEN, fileInfo.hidden);
1209 values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, fileInfo.sourcePath);
1210 values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
1211 GetCloudThumbnailInsertValue(fileInfo, values);
1212
1213 unordered_map<string, string> commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_,
1214 PhotoColumn::PHOTOS_TABLE);
1215 for (auto it = fileInfo.valMap.begin(); it != fileInfo.valMap.end(); ++it) {
1216 string columnName = it->first;
1217 auto columnVal = it->second;
1218 if (columnName == PhotoColumn::PHOTO_EDIT_TIME) {
1219 PrepareEditTimeVal(values, get<int64_t>(columnVal), fileInfo, commonColumnInfoMap);
1220 continue;
1221 }
1222 if (columnName == PhotoColumn::MEDIA_DATE_TAKEN) {
1223 if (get<int64_t>(columnVal) > SECONDS_LEVEL_LIMIT) {
1224 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, get<int64_t>(columnVal));
1225 } else {
1226 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, get<int64_t>(columnVal) * MSEC_TO_SEC);
1227 }
1228 continue;
1229 }
1230 PrepareCommonColumnVal(values, columnName, columnVal, commonColumnInfoMap);
1231 }
1232 return values;
1233 }
1234
PrepareCommonColumnInfoMap(const string & tableName,const unordered_map<string,string> & srcColumnInfoMap,const unordered_map<string,string> & dstColumnInfoMap)1235 bool CloneRestore::PrepareCommonColumnInfoMap(const string &tableName,
1236 const unordered_map<string, string> &srcColumnInfoMap, const unordered_map<string, string> &dstColumnInfoMap)
1237 {
1238 auto neededColumns = GetValueFromMap(NEEDED_COLUMNS_MAP, tableName);
1239 auto neededColumnsException = GetValueFromMap(NEEDED_COLUMNS_EXCEPTION_MAP, tableName);
1240 auto excludedColumns = GetValueFromMap(EXCLUDED_COLUMNS_MAP, tableName);
1241 auto &commonColumnInfoMap = tableCommonColumnInfoMap_[tableName];
1242 CHECK_AND_RETURN_RET_LOG(HasColumns(dstColumnInfoMap, neededColumns), false, "Destination lack needed columns");
1243 for (auto it = dstColumnInfoMap.begin(); it != dstColumnInfoMap.end(); ++it) {
1244 if (!HasSameColumn(srcColumnInfoMap, it->first, it->second) || excludedColumns.count(it->first) > 0) {
1245 continue;
1246 }
1247 if (neededColumns.count(it->first) > 0 && (neededColumnsException.empty() ||
1248 neededColumnsException.count(it->first) == 0)) {
1249 continue;
1250 }
1251 commonColumnInfoMap[it->first] = it->second;
1252 }
1253 MEDIA_INFO_LOG("Table %{public}s has %{public}zu common columns",
1254 BackupDatabaseUtils::GarbleInfoName(tableName).c_str(), commonColumnInfoMap.size());
1255 return true;
1256 }
1257
HasSameColumn(const unordered_map<string,string> & columnInfoMap,const string & columnName,const string & columnType)1258 bool CloneRestore::HasSameColumn(const unordered_map<string, string> &columnInfoMap, const string &columnName,
1259 const string &columnType)
1260 {
1261 auto it = columnInfoMap.find(columnName);
1262 return it != columnInfoMap.end() && it->second == columnType;
1263 }
1264
GetValFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,unordered_map<string,variant<int32_t,int64_t,double,string>> & valMap,const string & columnName,const string & columnType)1265 void CloneRestore::GetValFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
1266 unordered_map<string, variant<int32_t, int64_t, double, string>> &valMap, const string &columnName,
1267 const string &columnType)
1268 {
1269 int32_t columnIndex = 0;
1270 int32_t errCode = resultSet->GetColumnIndex(columnName, columnIndex);
1271 CHECK_AND_RETURN_LOG(errCode == 0, "Get column index errCode: %{public}d", errCode);
1272 bool isNull = false;
1273 errCode = resultSet->IsColumnNull(columnIndex, isNull);
1274 if (errCode || isNull) {
1275 return;
1276 }
1277 ResultSetDataType dataType = GetValueFromMap(COLUMN_TYPE_MAP, columnType, ResultSetDataType::TYPE_NULL);
1278 switch (dataType) {
1279 case ResultSetDataType::TYPE_INT32: {
1280 int32_t int32Val;
1281 if (resultSet->GetInt(columnIndex, int32Val) == E_OK) {
1282 valMap[columnName] = int32Val;
1283 }
1284 break;
1285 }
1286 case ResultSetDataType::TYPE_INT64: {
1287 int64_t int64Val;
1288 if (resultSet->GetLong(columnIndex, int64Val) == E_OK) {
1289 valMap[columnName] = int64Val;
1290 }
1291 break;
1292 }
1293 case ResultSetDataType::TYPE_DOUBLE: {
1294 double doubleVal;
1295 if (resultSet->GetDouble(columnIndex, doubleVal) == E_OK) {
1296 valMap[columnName] = doubleVal;
1297 }
1298 break;
1299 }
1300 case ResultSetDataType::TYPE_STRING: {
1301 string stringVal;
1302 if (resultSet->GetString(columnIndex, stringVal) == E_OK) {
1303 valMap[columnName] = stringVal;
1304 }
1305 break;
1306 }
1307 default:
1308 MEDIA_ERR_LOG("No such column type: %{public}s", columnType.c_str());
1309 }
1310 }
1311
PrepareCommonColumnVal(NativeRdb::ValuesBucket & values,const string & columnName,const variant<int32_t,int64_t,double,string> & columnVal,const unordered_map<string,string> & commonColumnInfoMap) const1312 void CloneRestore::PrepareCommonColumnVal(NativeRdb::ValuesBucket &values, const string &columnName,
1313 const variant<int32_t, int64_t, double, string> &columnVal,
1314 const unordered_map<string, string> &commonColumnInfoMap) const
1315 {
1316 string columnType = GetValueFromMap(commonColumnInfoMap, columnName);
1317 CHECK_AND_RETURN_LOG(!columnType.empty(), "No such column %{public}s", columnName.c_str());
1318 ResultSetDataType dataType = GetValueFromMap(COLUMN_TYPE_MAP, columnType, ResultSetDataType::TYPE_NULL);
1319 switch (dataType) {
1320 case ResultSetDataType::TYPE_INT32: {
1321 values.PutInt(columnName, get<int32_t>(columnVal));
1322 break;
1323 }
1324 case ResultSetDataType::TYPE_INT64: {
1325 values.PutLong(columnName, get<int64_t>(columnVal));
1326 break;
1327 }
1328 case ResultSetDataType::TYPE_DOUBLE: {
1329 values.PutDouble(columnName, get<double>(columnVal));
1330 break;
1331 }
1332 case ResultSetDataType::TYPE_STRING: {
1333 values.PutString(columnName, get<string>(columnVal));
1334 break;
1335 }
1336 default:
1337 MEDIA_ERR_LOG("No such column type: %{public}s", columnType.c_str());
1338 }
1339 }
1340
GetQueryWhereClause(const string & tableName,const unordered_map<string,string> & columnInfoMap)1341 void CloneRestore::GetQueryWhereClause(const string &tableName, const unordered_map<string, string> &columnInfoMap)
1342 {
1343 unordered_map<string, string> queryWhereClauseMap;
1344 if (IsCloudRestoreSatisfied()) {
1345 queryWhereClauseMap = GetValueFromMap(TABLE_QUERY_WHERE_CLAUSE_MAP_WITH_CLOUD, tableName);
1346 } else {
1347 queryWhereClauseMap = GetValueFromMap(TABLE_QUERY_WHERE_CLAUSE_MAP, tableName);
1348 }
1349
1350 if (queryWhereClauseMap.empty()) {
1351 return;
1352 }
1353 string &queryWhereClause = tableQueryWhereClauseMap_[tableName];
1354 queryWhereClause.clear();
1355 for (auto it = queryWhereClauseMap.begin(); it != queryWhereClauseMap.end(); ++it) {
1356 if (columnInfoMap.count(it->first) == 0) {
1357 continue;
1358 }
1359 if (!queryWhereClause.empty()) {
1360 queryWhereClause += " AND ";
1361 }
1362 queryWhereClause += it->second + " ";
1363 }
1364 }
1365
GetAlbumExtraQueryWhereClause(const string & tableName)1366 void CloneRestore::GetAlbumExtraQueryWhereClause(const string &tableName)
1367 {
1368 string mapTableName = GetValueFromMap(CLONE_ALBUM_MAP, tableName);
1369 CHECK_AND_RETURN_LOG(!mapTableName.empty(), "Get map of table %{public}s failed",
1370 BackupDatabaseUtils::GarbleInfoName(tableName).c_str());
1371 string albumQueryWhereClause = "EXISTS (SELECT " + PhotoMap::ASSET_ID + " FROM " + mapTableName + " WHERE " +
1372 PhotoMap::ALBUM_ID + " = " + PhotoAlbumColumns::ALBUM_ID + " AND EXISTS (SELECT " + MediaColumn::MEDIA_ID +
1373 " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_ID + " = " + PhotoMap::ASSET_ID;
1374 string photoQueryWhereClause = GetValueFromMap(tableQueryWhereClauseMap_, PhotoColumn::PHOTOS_TABLE);
1375 if (!photoQueryWhereClause.empty()) {
1376 albumQueryWhereClause += " AND " + photoQueryWhereClause;
1377 }
1378 albumQueryWhereClause += "))";
1379 tableExtraQueryWhereClauseMap_[tableName] = albumQueryWhereClause;
1380 }
1381
GetInsertValue(const AlbumInfo & albumInfo,const string & tableName) const1382 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const AlbumInfo &albumInfo, const string &tableName) const
1383 {
1384 NativeRdb::ValuesBucket values;
1385 values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, static_cast<int32_t>(albumInfo.albumType));
1386 values.PutInt(PhotoAlbumColumns::ALBUM_SUBTYPE, static_cast<int32_t>(albumInfo.albumSubType));
1387 values.PutString(PhotoAlbumColumns::ALBUM_NAME, albumInfo.albumName);
1388
1389 if (tableName == PhotoAlbumColumns::TABLE) {
1390 values.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED,
1391 (albumInfo.dateModified ? albumInfo.dateModified : MediaFileUtils::UTCTimeMilliSeconds()));
1392 }
1393
1394 unordered_map<string, string> commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
1395 for (auto it = albumInfo.valMap.begin(); it != albumInfo.valMap.end(); ++it) {
1396 string columnName = it->first;
1397 auto columnVal = it->second;
1398 PrepareCommonColumnVal(values, columnName, columnVal, commonColumnInfoMap);
1399 }
1400 return values;
1401 }
1402
BatchQueryPhoto(vector<FileInfo> & fileInfos)1403 void CloneRestore::BatchQueryPhoto(vector<FileInfo> &fileInfos)
1404 {
1405 string selection;
1406 unordered_map<string, size_t> fileIndexMap;
1407 for (size_t index = 0; index < fileInfos.size(); index++) {
1408 if (fileInfos[index].cloudPath.empty()) {
1409 continue;
1410 }
1411 BackupDatabaseUtils::UpdateSelection(selection, fileInfos[index].cloudPath, true);
1412 fileIndexMap[fileInfos[index].cloudPath] = index;
1413 }
1414 string querySql = "SELECT " + MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + ", " +
1415 MediaColumn::MEDIA_DATE_TAKEN + " FROM " + PhotoColumn::PHOTOS_TABLE +
1416 " WHERE " + MediaColumn::MEDIA_FILE_PATH + " IN (" + selection + ")";
1417 querySql += " LIMIT " + to_string(fileIndexMap.size());
1418 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1419 CHECK_AND_RETURN_LOG(resultSet != nullptr, "Query resultSql is null.");
1420 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1421 int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
1422 string cloudPath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
1423 string dateTaken = GetStringVal(MediaColumn::MEDIA_DATE_TAKEN, resultSet);
1424 if (fileId <= 0) {
1425 MEDIA_ERR_LOG("Get fileId invalid: %{public}d", fileId);
1426 continue;
1427 }
1428 if (fileIndexMap.count(cloudPath) == 0) {
1429 continue;
1430 }
1431 size_t index = fileIndexMap.at(cloudPath);
1432 fileInfos[index].fileIdNew = fileId;
1433 fileInfos[index].newAstcDateKey = dateTaken;
1434 }
1435 BackupDatabaseUtils::UpdateAssociateFileId(mediaLibraryRdb_, fileInfos);
1436 }
1437
BatchNotifyPhoto(const vector<FileInfo> & fileInfos)1438 void CloneRestore::BatchNotifyPhoto(const vector<FileInfo> &fileInfos)
1439 {
1440 auto watch = MediaLibraryNotify::GetInstance();
1441 CHECK_AND_RETURN_LOG(watch != nullptr, "Get MediaLibraryNotify instance failed");
1442 for (const auto &fileInfo : fileInfos) {
1443 if (!fileInfo.needMove || fileInfo.cloudPath.empty()) {
1444 continue;
1445 }
1446 string extraUri = MediaFileUtils::GetExtraUri(fileInfo.displayName, fileInfo.cloudPath);
1447 string notifyUri = MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
1448 to_string(fileInfo.fileIdNew), extraUri);
1449 watch->Notify(notifyUri, NotifyType::NOTIFY_ADD);
1450 }
1451 }
1452
InsertAlbum(vector<AlbumInfo> & albumInfos,const string & tableName)1453 void CloneRestore::InsertAlbum(vector<AlbumInfo> &albumInfos, const string &tableName)
1454 {
1455 CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
1456 CHECK_AND_RETURN_LOG(!albumInfos.empty(), "albumInfos are empty");
1457 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
1458 vector<NativeRdb::ValuesBucket> values = GetInsertValues(albumInfos, tableName);
1459 int64_t rowNum = 0;
1460 int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
1461 CHECK_AND_RETURN_LOG(errCode == E_OK, "Batc insert failed");
1462 migrateDatabaseAlbumNumber_ += rowNum;
1463
1464 int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1465 BatchQueryAlbum(albumInfos, tableName);
1466 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1467 MEDIA_INFO_LOG("insert %{public}ld albums cost %{public}ld, query cost %{public}ld.", (long)rowNum,
1468 (long)(startQuery - startInsert), (long)(end - startQuery));
1469 }
1470
GetInsertValues(vector<AlbumInfo> & albumInfos,const string & tableName)1471 vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(vector<AlbumInfo> &albumInfos,
1472 const string &tableName)
1473 {
1474 vector<NativeRdb::ValuesBucket> values;
1475 for (size_t i = 0; i < albumInfos.size(); i++) {
1476 if (HasSameAlbum(albumInfos[i], tableName)) {
1477 MEDIA_WARN_LOG("Album (%{public}d, %{public}d, %{public}d, %{public}s) already exists.",
1478 albumInfos[i].albumIdOld, static_cast<int32_t>(albumInfos[i].albumType),
1479 static_cast<int32_t>(albumInfos[i].albumSubType), albumInfos[i].albumName.c_str());
1480 continue;
1481 }
1482 NativeRdb::ValuesBucket value = GetInsertValue(albumInfos[i], tableName);
1483 values.emplace_back(value);
1484 }
1485 return values;
1486 }
1487
HasSameAlbum(const AlbumInfo & albumInfo,const string & tableName)1488 bool CloneRestore::HasSameAlbum(const AlbumInfo &albumInfo, const string &tableName)
1489 {
1490 // check if the album already exists
1491 CHECK_AND_RETURN_RET(tableName != PhotoAlbumColumns::TABLE,
1492 this->photoAlbumClone_.HasSameAlbum(albumInfo.lPath));
1493 string querySql = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + tableName + " WHERE " +
1494 PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(albumInfo.albumType) + " AND " +
1495 PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(albumInfo.albumSubType) + " AND " +
1496 PhotoAlbumColumns::ALBUM_NAME + " = '" + albumInfo.albumName + "'";
1497 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1498 bool cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
1499 CHECK_AND_RETURN_RET(!cond, false);
1500 int32_t count = GetInt32Val(MEDIA_COLUMN_COUNT_1, resultSet);
1501 return count > 0;
1502 }
1503
BatchQueryAlbum(vector<AlbumInfo> & albumInfos,const string & tableName)1504 void CloneRestore::BatchQueryAlbum(vector<AlbumInfo> &albumInfos, const string &tableName)
1505 {
1506 auto &albumIdMap = tableAlbumIdMap_[tableName];
1507 for (auto &albumInfo : albumInfos) {
1508 if (albumInfo.albumIdOld <= 0) {
1509 continue;
1510 }
1511 string querySql = "SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " + tableName + " WHERE " +
1512 PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(albumInfo.albumType) + " AND " +
1513 PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(albumInfo.albumSubType) + " AND " +
1514 PhotoAlbumColumns::ALBUM_NAME + " = '" + albumInfo.albumName + "'";
1515 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1516 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1517 continue;
1518 }
1519 albumInfo.albumIdNew = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
1520 if (albumInfo.albumIdNew <= 0) {
1521 continue;
1522 }
1523 albumIdMap[albumInfo.albumIdOld] = albumInfo.albumIdNew;
1524 }
1525 }
1526
BatchInsertMap(const vector<FileInfo> & fileInfos,int64_t & totalRowNum)1527 void CloneRestore::BatchInsertMap(const vector<FileInfo> &fileInfos, int64_t &totalRowNum)
1528 {
1529 string selection;
1530 unordered_map<int32_t, int32_t> fileIdMap;
1531 SetFileIdReference(fileInfos, selection, fileIdMap);
1532 std::string tableName = ANALYSIS_ALBUM_TABLE;
1533 string garbledTableName = BackupDatabaseUtils::GarbleInfoName(tableName);
1534 string mapTableName = GetValueFromMap(CLONE_ALBUM_MAP, tableName);
1535 CHECK_AND_RETURN_LOG(!mapTableName.empty(),
1536 "Get map of table %{public}s failed", garbledTableName.c_str());
1537 auto albumIdMap = GetValueFromMap(tableAlbumIdMap_, tableName);
1538 CHECK_AND_RETURN_LOG(!albumIdMap.empty(),
1539 "Get album id map of table %{public}s empty, skip", garbledTableName.c_str());
1540 string albumSelection = GetValueFromMap(tableQueryWhereClauseMap_, tableName);
1541 unordered_set<int32_t> currentTableAlbumSet;
1542 string baseQuerySql = mapTableName + " INNER JOIN " + tableName + " ON " +
1543 mapTableName + "." + PhotoMap::ALBUM_ID + " = " + tableName + "." + PhotoAlbumColumns::ALBUM_ID +
1544 " WHERE " + mapTableName + "." + PhotoMap::ASSET_ID + " IN (" + selection + ")";
1545 baseQuerySql += albumSelection.empty() ? "" : " AND " + albumSelection;
1546 int32_t totalNumber = QueryMapTotalNumber(baseQuerySql);
1547 MEDIA_INFO_LOG("QueryMapTotalNumber of table %{public}s, totalNumber = %{public}d", garbledTableName.c_str(),
1548 totalNumber);
1549 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
1550 int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1551 vector<MapInfo> mapInfos = QueryMapInfos(mapTableName, baseQuerySql, offset, fileIdMap, albumIdMap);
1552 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
1553 int64_t rowNum = InsertMapByTable(mapTableName, mapInfos, currentTableAlbumSet);
1554 totalRowNum += rowNum;
1555 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1556 MEDIA_INFO_LOG("query %{public}zu map infos cost %{public}ld, insert %{public}ld maps cost %{public}ld",
1557 mapInfos.size(), (long)(startInsert - startQuery), (long)rowNum, (long)(end - startInsert));
1558 }
1559 }
1560
GetInsertValue(const MapInfo & mapInfo) const1561 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const MapInfo &mapInfo) const
1562 {
1563 NativeRdb::ValuesBucket values;
1564 values.PutInt(PhotoMap::ASSET_ID, mapInfo.fileId);
1565 values.PutInt(PhotoMap::ALBUM_ID, mapInfo.albumId);
1566 return values;
1567 }
1568
CheckTableColumnStatus(shared_ptr<NativeRdb::RdbStore> rdbStore,const vector<vector<string>> & cloneTableList)1569 void CloneRestore::CheckTableColumnStatus(shared_ptr<NativeRdb::RdbStore> rdbStore,
1570 const vector<vector<string>> &cloneTableList)
1571 {
1572 unordered_map<string, unordered_map<string, string>> tableColumnInfoMap;
1573 for (const auto &tableList : cloneTableList) {
1574 bool columnStatusGlobal = true;
1575 for (const auto &tableName : tableList) {
1576 auto &columnInfoMap = tableColumnInfoMap[tableName];
1577 columnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(rdbStore, tableName);
1578 auto neededColumns = GetValueFromMap(NEEDED_COLUMNS_MAP, tableName);
1579 columnStatusGlobal = columnStatusGlobal && HasColumns(columnInfoMap, neededColumns);
1580 }
1581 for (const auto &tableName : tableList) {
1582 tableColumnStatusMap_[tableName] = columnStatusGlobal;
1583 }
1584 }
1585 for (const auto &tableList : cloneTableList) {
1586 for (const auto &tableName : tableList) {
1587 if (!IsReadyForRestore(tableName)) {
1588 MEDIA_ERR_LOG("Column status is false");
1589 break;
1590 }
1591 auto columnInfoMap = GetValueFromMap(tableColumnInfoMap, tableName);
1592 GetQueryWhereClause(tableName, columnInfoMap);
1593 }
1594 }
1595 }
1596
HasColumns(const unordered_map<string,string> & columnInfoMap,const unordered_set<string> & columnSet)1597 bool CloneRestore::HasColumns(const unordered_map<string, string> &columnInfoMap,
1598 const unordered_set<string> &columnSet)
1599 {
1600 for (const auto &columnName : columnSet) {
1601 if (!HasColumn(columnInfoMap, columnName)) {
1602 MEDIA_ERR_LOG("Lack of column %{public}s", columnName.c_str());
1603 return false;
1604 }
1605 }
1606 return true;
1607 }
1608
HasColumn(const unordered_map<string,string> & columnInfoMap,const string & columnName)1609 bool CloneRestore::HasColumn(const unordered_map<string, string> &columnInfoMap, const string &columnName)
1610 {
1611 return columnInfoMap.count(columnName) > 0;
1612 }
1613
IsReadyForRestore(const string & tableName)1614 bool CloneRestore::IsReadyForRestore(const string &tableName)
1615 {
1616 return GetValueFromMap(tableColumnStatusMap_, tableName, false);
1617 }
1618
PrepareEditTimeVal(NativeRdb::ValuesBucket & values,int64_t editTime,const FileInfo & fileInfo,const unordered_map<string,string> & commonColumnInfoMap) const1619 void CloneRestore::PrepareEditTimeVal(NativeRdb::ValuesBucket &values, int64_t editTime, const FileInfo &fileInfo,
1620 const unordered_map<string, string> &commonColumnInfoMap) const
1621 {
1622 string editDataPath = backupRestoreDir_ +
1623 BackupFileUtils::GetFullPathByPrefixType(PrefixType::LOCAL_EDIT_DATA, fileInfo.relativePath);
1624 int64_t newEditTime = editTime > 0 && IsFilePathExist(editDataPath) ? editTime : 0;
1625 PrepareCommonColumnVal(values, PhotoColumn::PHOTO_EDIT_TIME, newEditTime, commonColumnInfoMap);
1626 }
1627
RestoreGallery()1628 void CloneRestore::RestoreGallery()
1629 {
1630 CheckTableColumnStatus(mediaRdb_, CLONE_TABLE_LISTS_PHOTO);
1631 // Upgrade original MediaLibrary Database
1632 DataTransfer::MediaLibraryDbUpgrade medialibraryDbUpgrade;
1633 medialibraryDbUpgrade.OnUpgrade(*this->mediaRdb_);
1634 // Report the old db info.
1635 DatabaseReport()
1636 .SetSceneCode(this->sceneCode_)
1637 .SetTaskId(this->taskId_)
1638 .ReportMedia(this->mediaRdb_, DatabaseReport::PERIOD_OLD)
1639 .ReportMedia(this->mediaLibraryRdb_, DatabaseReport::PERIOD_BEFORE);
1640 // Restore the backup db info.
1641 RestoreAlbum();
1642 RestorePhoto();
1643 MEDIA_INFO_LOG("the isAccountValid_ is %{public}d, sync switch open is %{public}d", isAccountValid_,
1644 isSyncSwitchOn_);
1645 if (IsCloudRestoreSatisfied()) {
1646 MEDIA_INFO_LOG("singlCloud cloud clone");
1647 RestorePhotoForCloud();
1648 }
1649 MEDIA_INFO_LOG("singlCloud migrate database photo number: %{public}lld, file number: %{public}lld (%{public}lld + "
1650 "%{public}lld), duplicate number: %{public}lld + %{public}lld, album number: %{public}lld, map number: "
1651 "%{public}lld", (long long)migrateDatabaseNumber_, (long long)migrateFileNumber_,
1652 (long long)(migrateFileNumber_ - migrateVideoFileNumber_), (long long)migrateVideoFileNumber_,
1653 (long long)migratePhotoDuplicateNumber_, (long long)migrateVideoDuplicateNumber_,
1654 (long long)migrateDatabaseAlbumNumber_, (long long)migrateDatabaseMapNumber_);
1655 MEDIA_INFO_LOG("singlCloud Start update group tags");
1656 BackupDatabaseUtils::UpdateFaceGroupTagsUnion(mediaLibraryRdb_);
1657 BackupDatabaseUtils::UpdateFaceAnalysisTblStatus(mediaLibraryRdb_);
1658 BackupDatabaseUtils::UpdateAnalysisPhotoMapStatus(mediaLibraryRdb_);
1659 cloneRestoreClassify_.ReportClassifyRestoreTask();
1660 cloneRestoreGeo_.ReportGeoRestoreTask();
1661 cloneRestoreGeoDictionary_.ReportGeoRestoreTask();
1662 cloneRestoreHighlight_.UpdateAlbums();
1663 cloneRestoreCVAnalysis_.RestoreAlbums(cloneRestoreHighlight_);
1664 ReportPortraitCloneStat(sceneCode_);
1665 }
1666
PrepareCloudPath(const string & tableName,FileInfo & fileInfo)1667 bool CloneRestore::PrepareCloudPath(const string &tableName, FileInfo &fileInfo)
1668 {
1669 fileInfo.cloudPath = BackupFileUtils::GetFullPathByPrefixType(PrefixType::CLOUD, fileInfo.relativePath);
1670 CHECK_AND_RETURN_RET_LOG(!fileInfo.cloudPath.empty(), false, "Get cloudPath empty");
1671 if (IsSameFileForClone(tableName, fileInfo)) {
1672 // should not delete the file, if the FileInfo is came from PhotoMap.
1673 if (fileInfo.isRelatedToPhotoMap != 1) {
1674 MEDIA_INFO_LOG("File (%{public}s) already exists. delete it.",
1675 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str());
1676 (void)MediaFileUtils::DeleteFile(fileInfo.filePath);
1677 }
1678 UpdateDuplicateNumber(fileInfo.fileType);
1679 return false;
1680 }
1681 // If the device originally has dentry file in the cloud path, no need to generate new cloud path.
1682 if (fileInfo.isNew && (MediaFileUtils::IsFileExists(fileInfo.cloudPath) || fileInfo.isRelatedToPhotoMap == 1)) {
1683 int32_t uniqueId = GetUniqueId(fileInfo.fileType);
1684 int32_t errCode = BackupFileUtils::CreateAssetPathById(uniqueId, fileInfo.fileType,
1685 MediaFileUtils::GetExtensionFromPath(fileInfo.displayName), fileInfo.cloudPath);
1686 if (errCode != E_OK) {
1687 ErrorInfo errorInfo(RestoreError::CREATE_PATH_FAILED, 1, std::to_string(errCode),
1688 BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1689 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1690 fileInfo.cloudPath.clear();
1691 return false;
1692 }
1693 }
1694 int32_t errCode = BackupFileUtils::PreparePath(
1695 BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL, fileInfo.cloudPath));
1696 if (errCode != E_OK) {
1697 MEDIA_ERR_LOG("Prepare cloudPath failed, path: %{public}s, cloudPath: %{public}s",
1698 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str(),
1699 BackupFileUtils::GarbleFilePath(fileInfo.cloudPath, DEFAULT_RESTORE_ID, garbagePath_).c_str());
1700 ErrorInfo errorInfo(RestoreError::PREPARE_PATH_FAILED, 1, std::to_string(errCode),
1701 BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1702 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1703 fileInfo.cloudPath.clear();
1704 return false;
1705 }
1706 return true;
1707 }
1708
RestoreMusic()1709 void CloneRestore::RestoreMusic()
1710 {
1711 CheckTableColumnStatus(mediaRdb_, CLONE_TABLE_LISTS_AUDIO);
1712 RestoreAudio();
1713 MEDIA_INFO_LOG("migrate database audio number: %{public}lld, file number: %{public}lld, duplicate number: "
1714 "%{public}lld", (long long)migrateAudioDatabaseNumber_, (long long)migrateAudioFileNumber_,
1715 (long long)migrateAudioDuplicateNumber_);
1716 }
1717
RestoreAudio(void)1718 void CloneRestore::RestoreAudio(void)
1719 {
1720 MEDIA_INFO_LOG("Start clone restore: audio");
1721 CHECK_AND_RETURN_LOG(IsReadyForRestore(AudioColumn::AUDIOS_TABLE),
1722 "Column status is not ready for restore audio, quit");
1723 unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_,
1724 AudioColumn::AUDIOS_TABLE);
1725 unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
1726 AudioColumn::AUDIOS_TABLE);
1727 CHECK_AND_RETURN_LOG(PrepareCommonColumnInfoMap(AudioColumn::AUDIOS_TABLE, srcColumnInfoMap,
1728 dstColumnInfoMap), "Prepare common column info failed");
1729 int32_t totalNumber = QueryTotalNumber(AudioColumn::AUDIOS_TABLE);
1730 MEDIA_INFO_LOG("QueryAudioTotalNumber, totalNumber = %{public}d", totalNumber);
1731 if (totalNumber <= 0) {
1732 return;
1733 }
1734 audioTotalNumber_ += static_cast<uint64_t>(totalNumber);
1735 MEDIA_INFO_LOG("onProcess Update audioTotalNumber_: %{public}lld", (long long)audioTotalNumber_);
1736 if (!MediaFileUtils::IsFileExists(RESTORE_MUSIC_LOCAL_DIR)) {
1737 MEDIA_INFO_LOG("music dir is not exists!!!");
1738 MediaFileUtils::CreateDirectory(RESTORE_MUSIC_LOCAL_DIR);
1739 }
1740 for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
1741 ffrt::submit([this, offset]() { RestoreAudioBatch(offset); }, { &offset }, {},
1742 ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
1743 }
1744 ffrt::wait();
1745 }
1746
QueryFileInfos(const string & tableName,int32_t offset)1747 vector<FileInfo> CloneRestore::QueryFileInfos(const string &tableName, int32_t offset)
1748 {
1749 vector<FileInfo> result;
1750 result.reserve(CLONE_QUERY_COUNT);
1751 string querySql = "SELECT * FROM " + tableName;
1752 string whereClause = GetQueryWhereClauseByTable(tableName);
1753 querySql += whereClause.empty() ? "" : " WHERE " + whereClause;
1754 querySql += " LIMIT " + to_string(offset) + ", " + to_string(CLONE_QUERY_COUNT);
1755 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
1756 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
1757 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1758 FileInfo fileInfo;
1759 if (ParseResultSet(tableName, resultSet, fileInfo)) {
1760 result.emplace_back(fileInfo);
1761 }
1762 }
1763 return result;
1764 }
1765
ParseResultSet(const string & tableName,const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)1766 bool CloneRestore::ParseResultSet(const string &tableName, const shared_ptr<NativeRdb::ResultSet> &resultSet,
1767 FileInfo &fileInfo)
1768 {
1769 fileInfo.fileType = GetInt32Val(MediaColumn::MEDIA_TYPE, resultSet);
1770 fileInfo.fileIdOld = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
1771 fileInfo.displayName = GetStringVal(MediaColumn::MEDIA_NAME, resultSet);
1772 fileInfo.oldPath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
1773 if (!ConvertPathToRealPath(fileInfo.oldPath, filePath_, fileInfo.filePath, fileInfo.relativePath)) {
1774 ErrorInfo errorInfo(RestoreError::PATH_INVALID, 1, "", BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1775 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1776 return false;
1777 }
1778 fileInfo.fileSize = GetInt64Val(MediaColumn::MEDIA_SIZE, resultSet);
1779 if (fileInfo.fileSize <= 0) {
1780 ErrorInfo errorInfo(RestoreError::SIZE_INVALID, 1, "Db size <= 0",
1781 BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1782 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1783 return false;
1784 }
1785
1786 fileInfo.dateAdded = GetInt64Val(MediaColumn::MEDIA_DATE_ADDED, resultSet);
1787 fileInfo.dateModified = GetInt64Val(MediaColumn::MEDIA_DATE_MODIFIED, resultSet);
1788 fileInfo.dateTaken = GetInt64Val(MediaColumn::MEDIA_DATE_TAKEN, resultSet);
1789 fileInfo.thumbnailReady = GetInt64Val(PhotoColumn::PHOTO_THUMBNAIL_READY, resultSet);
1790 fileInfo.lcdVisitTime = GetInt32Val(PhotoColumn::PHOTO_LCD_VISIT_TIME, resultSet);
1791 fileInfo.position = GetInt32Val(PhotoColumn::PHOTO_POSITION, resultSet);
1792 fileInfo.cloudVersion = GetInt32Val(PhotoColumn::PHOTO_CLOUD_VERSION, resultSet);
1793 fileInfo.cloudId = GetStringVal(PhotoColumn::PHOTO_CLOUD_ID, resultSet);
1794 fileInfo.oldAstcDateKey = to_string(fileInfo.dateTaken);
1795 SetSpecialAttributes(tableName, resultSet, fileInfo);
1796
1797 auto commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
1798 for (auto it = commonColumnInfoMap.begin(); it != commonColumnInfoMap.end(); ++it) {
1799 string columnName = it->first;
1800 string columnType = it->second;
1801 GetValFromResultSet(resultSet, fileInfo.valMap, columnName, columnType);
1802 }
1803 return true;
1804 }
1805
ParseResultSetForAudio(const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)1806 bool CloneRestore::ParseResultSetForAudio(const shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &fileInfo)
1807 {
1808 return ParseResultSet(AudioColumn::AUDIOS_TABLE, resultSet, fileInfo);
1809 }
1810
InsertAudio(vector<FileInfo> & fileInfos)1811 void CloneRestore::InsertAudio(vector<FileInfo> &fileInfos)
1812 {
1813 CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
1814 CHECK_AND_RETURN_LOG(!fileInfos.empty(), "fileInfos are empty");
1815 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
1816 int64_t fileMoveCount = 0;
1817 for (auto& fileInfo : fileInfos) {
1818 if (BackupFileUtils::IsFileValid(fileInfo.filePath, CLONE_RESTORE_ID) != E_OK) {
1819 MEDIA_ERR_LOG("File is invalid: size: %{public}lld, name: %{public}s, filePath: %{public}s",
1820 (long long)fileInfo.fileSize, BackupFileUtils::GarbleFileName(fileInfo.displayName).c_str(),
1821 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str());
1822 continue;
1823 }
1824 if (!PrepareCloudPath(AudioColumn::AUDIOS_TABLE, fileInfo)) {
1825 continue;
1826 }
1827 string localPath = RESTORE_MUSIC_LOCAL_DIR + fileInfo.displayName;
1828 if (MediaFileUtils::IsFileExists(localPath)) {
1829 MEDIA_INFO_LOG("localPath %{public}s already exists.",
1830 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str());
1831 UpdateDuplicateNumber(fileInfo.fileType);
1832 continue;
1833 }
1834 int32_t moveErrCode = MoveFile(fileInfo.filePath, localPath);
1835 if (moveErrCode != E_OK) {
1836 MEDIA_ERR_LOG("MoveFile failed, filePath: %{public}s, errCode: %{public}d, errno: %{public}d",
1837 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str(), moveErrCode,
1838 errno);
1839 UpdateFailedFiles(fileInfo.fileType, fileInfo, RestoreError::MOVE_FAILED);
1840 continue;
1841 }
1842 BackupFileUtils::ModifyFile(localPath, fileInfo.dateModified / MSEC_TO_SEC);
1843 fileMoveCount++;
1844 }
1845 migrateAudioFileNumber_ += fileMoveCount;
1846 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1847 MEDIA_INFO_LOG("move %{public}ld files cost %{public}ld.", (long)fileMoveCount, (long)(end - startMove));
1848 }
1849
QueryThumbPhotoSize(std::shared_ptr<NativeRdb::RdbStore> mediaRdb)1850 static size_t QueryThumbPhotoSize(std::shared_ptr<NativeRdb::RdbStore> mediaRdb)
1851 {
1852 if (mediaRdb == nullptr) {
1853 MEDIA_ERR_LOG("rdbStore is nullptr");
1854 return 0;
1855 }
1856
1857 const string sql = "SELECT SUM(" + PhotoExtColumn::THUMBNAIL_SIZE + ")" + " as " + MEDIA_DATA_DB_SIZE +
1858 " FROM " + PhotoExtColumn::PHOTOS_EXT_TABLE;
1859 auto resultSet = mediaRdb->QuerySql(sql);
1860 if (resultSet == nullptr) {
1861 MEDIA_ERR_LOG("resultSet is null!");
1862 return 0;
1863 }
1864 if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1865 MEDIA_ERR_LOG("go to first row failed");
1866 return 0;
1867 }
1868 int64_t size = get<int64_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_SIZE, resultSet, TYPE_INT64));
1869 if (size < 0) {
1870 MEDIA_ERR_LOG("Invalid thumPhoto size from db: %{public}" PRId64, size);
1871 return 0;
1872 }
1873
1874 resultSet->Close();
1875 return static_cast<size_t>(size);
1876 }
1877
StatClonetotalSize(std::shared_ptr<NativeRdb::RdbStore> mediaRdb)1878 size_t CloneRestore::StatClonetotalSize(std::shared_ptr<NativeRdb::RdbStore> mediaRdb)
1879 {
1880 if (mediaRdb == nullptr) {
1881 MEDIA_ERR_LOG("rdbStore is nullptr");
1882 return 0;
1883 }
1884
1885 // media asset size
1886 size_t thumbPhotoSize = QueryThumbPhotoSize(mediaRdb);
1887 string querySizeSql = "SELECT cast(" + std::to_string(thumbPhotoSize) +
1888 " as bigint) as " + MEDIA_DATA_DB_SIZE + ", -1 as " + MediaColumn::MEDIA_TYPE;
1889 string mediaVolumeQuery = PhotoColumn::QUERY_MEDIA_VOLUME + " UNION " + AudioColumn::QUERY_MEDIA_VOLUME +
1890 " UNION " + querySizeSql;
1891
1892 auto resultSet = mediaRdb->QuerySql(mediaVolumeQuery);
1893 if (resultSet == nullptr) {
1894 MEDIA_ERR_LOG("Failed to execute media volume query");
1895 return 0;
1896 }
1897
1898 int64_t totalVolume = 0;
1899 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1900 int64_t mediaSize = GetInt64Val(MediaColumn::MEDIA_SIZE, resultSet);
1901 totalVolume += mediaSize;
1902 }
1903 resultSet->Close();
1904 size_t totalAssetSize = static_cast<size_t>(totalVolume);
1905 // other meta data dir size
1906 size_t editDataTotalSize {0};
1907 size_t rdbTotalSize {0};
1908 size_t kvdbTotalSize {0};
1909 size_t highlightTotalSize {0};
1910 MediaFileUtils::StatDirSize(CLONE_STAT_EDIT_DATA_DIR, editDataTotalSize);
1911 MediaFileUtils::StatDirSize(CLONE_STAT_RDB_DIR, rdbTotalSize);
1912 MediaFileUtils::StatDirSize(CLONE_STAT_KVDB_DIR, kvdbTotalSize);
1913 MediaFileUtils::StatDirSize(CLONE_STAT_HIGHLIGHT_DIR, highlightTotalSize);
1914 size_t totalSize = totalAssetSize + editDataTotalSize + rdbTotalSize + kvdbTotalSize + highlightTotalSize;
1915 return totalSize;
1916 }
1917
GetBackupInfo()1918 string CloneRestore::GetBackupInfo()
1919 {
1920 CHECK_AND_RETURN_RET_LOG(BaseRestore::Init() == E_OK, "", "GetBackupInfo init failed");
1921 CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, "", "GetBackupInfo Rdbstore is null");
1922
1923 CheckTableColumnStatus(mediaLibraryRdb_, CLONE_TABLE_LISTS_OLD_DEVICE);
1924 int32_t photoCount = QueryTotalNumberByMediaType(mediaLibraryRdb_, PhotoColumn::PHOTOS_TABLE,
1925 MediaType::MEDIA_TYPE_IMAGE);
1926 int32_t videoCount = QueryTotalNumberByMediaType(mediaLibraryRdb_, PhotoColumn::PHOTOS_TABLE,
1927 MediaType::MEDIA_TYPE_VIDEO);
1928 int32_t audioCount = QueryTotalNumberByMediaType(mediaLibraryRdb_, AudioColumn::AUDIOS_TABLE,
1929 MediaType::MEDIA_TYPE_AUDIO);
1930
1931 size_t totalSize = StatClonetotalSize(mediaLibraryRdb_);
1932 MEDIA_INFO_LOG("QueryTotalNumber, photo: %{public}d, video: %{public}d, audio: %{public}d, totalSize: "
1933 "%{public}lld bytes", photoCount, videoCount, audioCount, static_cast<long long>(totalSize));
1934
1935 return GetBackupInfoByCount(photoCount, videoCount, audioCount, totalSize);
1936 }
1937
QueryTotalNumberByMediaType(shared_ptr<NativeRdb::RdbStore> rdbStore,const string & tableName,MediaType mediaType)1938 int32_t CloneRestore::QueryTotalNumberByMediaType(shared_ptr<NativeRdb::RdbStore> rdbStore, const string &tableName,
1939 MediaType mediaType)
1940 {
1941 string querySql = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + tableName + " WHERE " + MediaColumn::MEDIA_TYPE +
1942 " = " + to_string(static_cast<int32_t>(mediaType));
1943 string whereClause = GetQueryWhereClauseByTable(tableName);
1944 querySql += whereClause.empty() ? "" : " AND " + whereClause;
1945 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(rdbStore, querySql);
1946 bool cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
1947 CHECK_AND_RETURN_RET(!cond, 0);
1948 int32_t result = GetInt32Val(MEDIA_COLUMN_COUNT_1, resultSet);
1949 return result;
1950 }
1951
GetBackupInfoByCount(int32_t photoCount,int32_t videoCount,int32_t audioCount,size_t totalSize)1952 string CloneRestore::GetBackupInfoByCount(int32_t photoCount, int32_t videoCount, int32_t audioCount, size_t totalSize)
1953 {
1954 nlohmann::json jsonObject = {
1955 {
1956 { STAT_KEY_BACKUP_INFO, STAT_TYPE_PHOTO },
1957 { STAT_KEY_NUMBER, photoCount }
1958 },
1959 {
1960 { STAT_KEY_BACKUP_INFO, STAT_TYPE_VIDEO },
1961 { STAT_KEY_NUMBER, videoCount }
1962 },
1963 {
1964 { STAT_KEY_BACKUP_INFO, STAT_TYPE_AUDIO },
1965 { STAT_KEY_NUMBER, audioCount }
1966 },
1967 {
1968 { STAT_KEY_BACKUP_INFO, STAT_TYPE_TOTAL_SIZE },
1969 { STAT_KEY_NUMBER, totalSize }
1970 }
1971 };
1972 return jsonObject.dump();
1973 }
1974
RestorePhotoBatch(int32_t offset,int32_t isRelatedToPhotoMap)1975 void CloneRestore::RestorePhotoBatch(int32_t offset, int32_t isRelatedToPhotoMap)
1976 {
1977 MEDIA_INFO_LOG(
1978 "start restore photo, offset: %{public}d, isRelatedToPhotoMap: %{public}d", offset, isRelatedToPhotoMap);
1979 vector<FileInfo> fileInfos = QueryFileInfos(offset, isRelatedToPhotoMap);
1980 if (InsertPhoto(fileInfos) != E_OK) {
1981 photosFailedOffsets.push_back(offset);
1982 }
1983 BatchNotifyPhoto(fileInfos);
1984 RestoreImageFaceInfo(fileInfos);
1985
1986 auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
1987 BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
1988 MEDIA_INFO_LOG("end restore photo, offset: %{public}d", offset);
1989 }
1990
RestoreBatchForCloud(int32_t offset,int32_t isRelatedToPhotoMap)1991 void CloneRestore::RestoreBatchForCloud(int32_t offset, int32_t isRelatedToPhotoMap)
1992 {
1993 MEDIA_INFO_LOG(
1994 "singlCloud restore photo, offset: %{public}d, isRelated: %{public}d", offset, isRelatedToPhotoMap);
1995 vector<FileInfo> fileInfos = QueryCloudFileInfos(offset, isRelatedToPhotoMap);
1996 if (InsertCloudPhoto(sceneCode_, fileInfos, SourceType::PHOTOS) != E_OK) {
1997 photosFailedOffsets.push_back(offset);
1998 }
1999 BatchNotifyPhoto(fileInfos);
2000 RestoreImageFaceInfo(fileInfos);
2001
2002 auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2003 BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
2004 MEDIA_INFO_LOG("singleCloud end restore photo, offset: %{public}d", offset);
2005 }
2006
InsertCloudPhoto(int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)2007 int CloneRestore::InsertCloudPhoto(int32_t sceneCode, std::vector<FileInfo> &fileInfos, int32_t sourceType)
2008 {
2009 MEDIA_INFO_LOG("singleCloud start insert cloud %{public}zu photos", fileInfos.size());
2010 if (mediaLibraryRdb_ == nullptr) {
2011 MEDIA_ERR_LOG("singleCloud mediaLibraryRdb_ iS null in cloud clone");
2012 return E_OK;
2013 }
2014 if (fileInfos.empty()) {
2015 MEDIA_ERR_LOG("singleCloud fileInfos are empty in cloud clone");
2016 return E_OK;
2017 }
2018 int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
2019 vector<NativeRdb::ValuesBucket> values = GetCloudInsertValues(sceneCode, fileInfos, sourceType);
2020 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
2021 int64_t rowNum = 0;
2022 int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, rowNum);
2023 MEDIA_INFO_LOG("singleCloud insertCloudPhoto is %{public}d, the rowNum is %{public}" PRId64, errCode, rowNum);
2024 migrateCloudSuccessNumber_ += rowNum;
2025 if (errCode != E_OK) {
2026 if (needReportFailed_) {
2027 UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
2028 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(fileInfos.size()), errCode);
2029 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
2030 }
2031 return errCode;
2032 }
2033
2034 int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
2035 InsertPhotoRelated(fileInfos);
2036
2037 // create dentry file for cloud origin, save failed cloud id
2038 std::vector<std::string> dentryFailedOrigin;
2039 if (BatchCreateDentryFile(fileInfos, dentryFailedOrigin, DENTRY_INFO_ORIGIN) == E_OK) {
2040 HandleFailData(fileInfos, dentryFailedOrigin, DENTRY_INFO_ORIGIN);
2041 }
2042
2043 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
2044 migrateDatabaseNumber_ += rowNum;
2045 int32_t fileMoveCount = 0;
2046 int32_t videoFileMoveCount = 0;
2047 MoveMigrateCloudFile(fileInfos, fileMoveCount, videoFileMoveCount, sceneCode);
2048 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2049 MEDIA_INFO_LOG("singleCloud generate values cost %{public}ld, insert %{public}ld assets cost %{public}ld, insert"
2050 " photo related cost %{public}ld, and move %{public}ld files (%{public}ld + %{public}ld) cost %{public}ld.",
2051 (long)(startInsert - startGenerate), (long)rowNum, (long)(startInsertRelated - startInsert),
2052 (long)(startMove - startInsertRelated), (long)fileMoveCount, (long)(fileMoveCount - videoFileMoveCount),
2053 (long)videoFileMoveCount, (long)(end - startMove));
2054 MEDIA_INFO_LOG("singleCLoud insert cloud end");
2055 return E_OK;
2056 }
2057
RestoreAudioBatch(int32_t offset)2058 void CloneRestore::RestoreAudioBatch(int32_t offset)
2059 {
2060 MEDIA_INFO_LOG("start restore audio, offset: %{public}d", offset);
2061 vector<FileInfo> fileInfos = QueryFileInfos(AudioColumn::AUDIOS_TABLE, offset);
2062 InsertAudio(fileInfos);
2063 MEDIA_INFO_LOG("end restore audio, offset: %{public}d", offset);
2064 }
2065
InsertPhotoRelated(vector<FileInfo> & fileInfos)2066 void CloneRestore::InsertPhotoRelated(vector<FileInfo> &fileInfos)
2067 {
2068 int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
2069 BatchQueryPhoto(fileInfos);
2070 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
2071 int64_t mapRowNum = 0;
2072 BatchInsertMap(fileInfos, mapRowNum);
2073 migrateDatabaseMapNumber_ += mapRowNum;
2074 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2075 MEDIA_INFO_LOG("query new file_id cost %{public}ld, insert %{public}ld maps cost %{public}ld",
2076 (long)(startInsert - startQuery), (long)mapRowNum, (long)(end - startInsert));
2077 cloneRestoreClassify_.RestoreMaps(fileInfos);
2078 cloneRestoreClassify_.RestoreVideoMaps(fileInfos);
2079 cloneRestoreGeo_.RestoreMaps(fileInfos);
2080 cloneRestoreHighlight_.RestoreMaps(fileInfos);
2081 }
2082
SetFileIdReference(const vector<FileInfo> & fileInfos,string & selection,unordered_map<int32_t,int32_t> & fileIdMap)2083 void CloneRestore::SetFileIdReference(const vector<FileInfo> &fileInfos, string &selection,
2084 unordered_map<int32_t, int32_t> &fileIdMap)
2085 {
2086 for (const auto &fileInfo : fileInfos) {
2087 if (fileInfo.fileIdOld <= 0 || fileInfo.fileIdNew <= 0) {
2088 continue;
2089 }
2090 BackupDatabaseUtils::UpdateSelection(selection, to_string(fileInfo.fileIdOld), false);
2091 fileIdMap[fileInfo.fileIdOld] = fileInfo.fileIdNew;
2092 }
2093 }
2094
QueryMapTotalNumber(const string & baseQuerySql)2095 int32_t CloneRestore::QueryMapTotalNumber(const string &baseQuerySql)
2096 {
2097 string querySql = "SELECT count(1) as count FROM " + baseQuerySql;
2098 return BackupDatabaseUtils::QueryInt(mediaRdb_, querySql, CUSTOM_COUNT);
2099 }
2100
QueryMapInfos(const string & tableName,const string & baseQuerySql,int32_t offset,const unordered_map<int32_t,int32_t> & fileIdMap,const unordered_map<int32_t,int32_t> & albumIdMap)2101 vector<MapInfo> CloneRestore::QueryMapInfos(const string &tableName, const string &baseQuerySql, int32_t offset,
2102 const unordered_map<int32_t, int32_t> &fileIdMap, const unordered_map<int32_t, int32_t> &albumIdMap)
2103 {
2104 vector<MapInfo> mapInfos;
2105 mapInfos.reserve(CLONE_QUERY_COUNT);
2106 string columnMapAlbum = tableName + "." + PhotoMap::ALBUM_ID;
2107 string columnMapAsset = tableName + "." + PhotoMap::ASSET_ID;
2108 string querySql = "SELECT " + columnMapAlbum + ", " + columnMapAsset + " FROM " + baseQuerySql;
2109 querySql += " LIMIT " + to_string(offset) + ", " + to_string(CLONE_QUERY_COUNT);
2110 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2111 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, mapInfos, "Query resultSql is null.");
2112 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2113 int32_t albumIdOld = GetInt32Val(columnMapAlbum, resultSet);
2114 int32_t fileIdOld = GetInt32Val(columnMapAsset, resultSet);
2115 if (albumIdOld <= 0 || albumIdMap.count(albumIdOld) == 0 || fileIdOld <= 0 || fileIdMap.count(fileIdOld) <= 0) {
2116 continue;
2117 }
2118 MapInfo mapInfo;
2119 mapInfo.albumId = albumIdMap.at(albumIdOld);
2120 mapInfo.fileId = fileIdMap.at(fileIdOld);
2121 mapInfos.emplace_back(mapInfo);
2122 }
2123 return mapInfos;
2124 }
2125
InsertMapByTable(const string & tableName,const vector<MapInfo> & mapInfos,unordered_set<int32_t> & albumSet)2126 int64_t CloneRestore::InsertMapByTable(const string &tableName, const vector<MapInfo> &mapInfos,
2127 unordered_set<int32_t> &albumSet)
2128 {
2129 vector<NativeRdb::ValuesBucket> values = GetInsertValues(mapInfos);
2130 int64_t rowNum = 0;
2131 int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
2132 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, 0,
2133 "Batch insert map failed, errCode: %{public}d", errCode);
2134 for (const auto &mapInfo : mapInfos) {
2135 albumSet.insert(mapInfo.albumId);
2136 }
2137 return rowNum;
2138 }
2139
GetInsertValues(const vector<MapInfo> & mapInfos)2140 vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(const vector<MapInfo> &mapInfos)
2141 {
2142 vector<NativeRdb::ValuesBucket> values;
2143 for (const auto &mapInfo : mapInfos) {
2144 NativeRdb::ValuesBucket value = GetInsertValue(mapInfo);
2145 values.emplace_back(value);
2146 }
2147 return values;
2148 }
2149
GetQueryWhereClauseByTable(const string & tableName)2150 string CloneRestore::GetQueryWhereClauseByTable(const string &tableName)
2151 {
2152 string whereClause;
2153 if (tableQueryWhereClauseMap_.count(tableName)) {
2154 whereClause += tableQueryWhereClauseMap_.at(tableName);
2155 }
2156 if (tableExtraQueryWhereClauseMap_.count(tableName)) {
2157 whereClause += whereClause.empty() ? "" : " AND " + tableExtraQueryWhereClauseMap_.at(tableName);
2158 }
2159 return whereClause;
2160 }
2161
SetSpecialAttributes(const string & tableName,const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)2162 void CloneRestore::SetSpecialAttributes(const string &tableName, const shared_ptr<NativeRdb::ResultSet> &resultSet,
2163 FileInfo &fileInfo)
2164 {
2165 if (tableName != PhotoColumn::PHOTOS_TABLE) {
2166 return;
2167 }
2168 fileInfo.lPath = GetStringVal(PhotoAlbumColumns::ALBUM_LPATH, resultSet);
2169 fileInfo.sourcePath = GetStringVal(PhotoColumn::PHOTO_SOURCE_PATH, resultSet);
2170 fileInfo.orientation = GetInt32Val(PhotoColumn::PHOTO_ORIENTATION, resultSet);
2171 fileInfo.subtype = GetInt32Val(PhotoColumn::PHOTO_SUBTYPE, resultSet);
2172 fileInfo.associateFileId = GetInt32Val(PhotoColumn::PHOTO_ASSOCIATE_FILE_ID, resultSet);
2173 fileInfo.photoQuality = GetInt32Val(PhotoColumn::PHOTO_QUALITY, resultSet);
2174 fileInfo.recycledTime = GetInt64Val(MediaColumn::MEDIA_DATE_TRASHED, resultSet);
2175 fileInfo.hidden = GetInt32Val(MediaColumn::MEDIA_HIDDEN, resultSet);
2176 // find PhotoAlbum info in target database. PackageName and BundleName should be fixed after clone.
2177 fileInfo.lPath = this->photosClone_.FindlPath(fileInfo);
2178 fileInfo.ownerAlbumId = this->photosClone_.FindAlbumId(fileInfo);
2179 fileInfo.packageName = this->photosClone_.FindPackageName(fileInfo);
2180 fileInfo.bundleName = this->photosClone_.FindBundleName(fileInfo);
2181 fileInfo.photoQuality = this->photosClone_.FindPhotoQuality(fileInfo);
2182 fileInfo.sourcePath = this->photosClone_.FindSourcePath(fileInfo);
2183 fileInfo.latitude = GetDoubleVal("latitude", resultSet);
2184 fileInfo.longitude = GetDoubleVal("longitude", resultSet);
2185 }
2186
IsSameFileForClone(const string & tableName,FileInfo & fileInfo)2187 bool CloneRestore::IsSameFileForClone(const string &tableName, FileInfo &fileInfo)
2188 {
2189 CHECK_AND_RETURN_RET(tableName == PhotoColumn::PHOTOS_TABLE,
2190 IsSameAudioFile(mediaLibraryRdb_, tableName, fileInfo));
2191 PhotosDao::PhotosRowData rowData = this->photosClone_.FindSameFile(fileInfo);
2192 int32_t fileId = rowData.fileId;
2193 std::string cloudPath = rowData.data;
2194 bool cond = (fileId <= 0 || cloudPath.empty());
2195 CHECK_AND_RETURN_RET(!cond, false);
2196 // Meed extra check to determine whether or not to drop the duplicate file.
2197 return ExtraCheckForCloneSameFile(fileInfo, rowData);
2198 }
2199
RestoreFromGalleryPortraitAlbum()2200 void CloneRestore::RestoreFromGalleryPortraitAlbum()
2201 {
2202 int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2203 RecordOldPortraitAlbumDfx();
2204
2205 std::string querySql = "SELECT count(1) AS count FROM " + ANALYSIS_ALBUM_TABLE + " WHERE ";
2206 std::string whereClause = "(" + SMARTALBUM_DB_ALBUM_TYPE + " = " + std::to_string(SMART) + " AND " +
2207 "album_subtype" + " = " + std::to_string(PORTRAIT) + ")";
2208 AppendExtraWhereClause(whereClause, ANALYSIS_ALBUM_TABLE);
2209 querySql += whereClause;
2210
2211 int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb_, querySql, CUSTOM_COUNT);
2212 MEDIA_INFO_LOG("QueryPortraitAlbum totalNumber = %{public}d", totalNumber);
2213
2214 std::vector<std::string> commonColumn = BackupDatabaseUtils::GetCommonColumnInfos(mediaRdb_, mediaLibraryRdb_,
2215 ANALYSIS_ALBUM_TABLE);
2216 std::vector<std::string> commonColumns = BackupDatabaseUtils::filterColumns(commonColumn,
2217 EXCLUDED_PORTRAIT_COLUMNS);
2218
2219 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
2220 std::vector<AnalysisAlbumTbl> analysisAlbumTbl = QueryPortraitAlbumTbl(offset, commonColumns);
2221 for (const auto& album : analysisAlbumTbl) {
2222 if (album.tagId.has_value() && album.coverUri.has_value()) {
2223 coverUriInfo_.emplace_back(album.tagId.value(),
2224 std::make_pair(album.coverUri.value(),
2225 album.isCoverSatisfied.value_or(INVALID_COVER_SATISFIED_STATUS)));
2226 }
2227 }
2228
2229 InsertPortraitAlbum(analysisAlbumTbl);
2230 }
2231
2232 LogPortraitCloneDfx();
2233 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2234 migratePortraitTotalTimeCost_ += end - start;
2235 }
2236
QueryPortraitAlbumTbl(int32_t offset,const std::vector<std::string> & commonColumns)2237 vector<AnalysisAlbumTbl> CloneRestore::QueryPortraitAlbumTbl(int32_t offset,
2238 const std::vector<std::string>& commonColumns)
2239 {
2240 vector<AnalysisAlbumTbl> result;
2241 result.reserve(QUERY_COUNT);
2242
2243 std::string inClause = BackupDatabaseUtils::JoinValues<string>(commonColumns, ", ");
2244 std::string querySql =
2245 "SELECT " + inClause +
2246 " FROM " + ANALYSIS_ALBUM_TABLE +
2247 " WHERE ";
2248 std::string whereClause = "(" +
2249 SMARTALBUM_DB_ALBUM_TYPE + " = " + std::to_string(SMART) + " AND " +
2250 "album_subtype" + " = " + std::to_string(PORTRAIT) + ")";
2251 AppendExtraWhereClause(whereClause, ANALYSIS_ALBUM_TABLE);
2252 querySql += whereClause;
2253 querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
2254
2255 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2256 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
2257
2258 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2259 AnalysisAlbumTbl analysisAlbumTbl;
2260 ParsePortraitAlbumResultSet(resultSet, analysisAlbumTbl);
2261 result.emplace_back(analysisAlbumTbl);
2262 }
2263
2264 return result;
2265 }
2266
ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,AnalysisAlbumTbl & analysisAlbumTbl)2267 void CloneRestore::ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
2268 AnalysisAlbumTbl &analysisAlbumTbl)
2269 {
2270 analysisAlbumTbl.albumType = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_ALBUM_TYPE);
2271 analysisAlbumTbl.albumSubtype = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2272 ANALYSIS_COL_ALBUM_SUBTYPE);
2273 analysisAlbumTbl.albumName = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_ALBUM_NAME);
2274 analysisAlbumTbl.coverUri = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_COVER_URI);
2275 analysisAlbumTbl.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_TAG_ID);
2276 analysisAlbumTbl.userOperation = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2277 ANALYSIS_COL_USER_OPERATION);
2278 analysisAlbumTbl.groupTag = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_GROUP_TAG);
2279 analysisAlbumTbl.userDisplayLevel = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2280 ANALYSIS_COL_USER_DISPLAY_LEVEL);
2281 analysisAlbumTbl.isMe = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_IS_ME);
2282 analysisAlbumTbl.isRemoved = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_IS_REMOVED);
2283 analysisAlbumTbl.renameOperation = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2284 ANALYSIS_COL_RENAME_OPERATION);
2285 analysisAlbumTbl.isLocal = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_IS_LOCAL);
2286 analysisAlbumTbl.isCoverSatisfied = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2287 ANALYSIS_COL_IS_COVER_SATISFIED);
2288 }
2289
ParseFaceTagResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FaceTagTbl & faceTagTbl)2290 void CloneRestore::ParseFaceTagResultSet(const std::shared_ptr<NativeRdb::ResultSet>& resultSet, FaceTagTbl& faceTagTbl)
2291 {
2292 faceTagTbl.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_TAG_ID);
2293 faceTagTbl.tagName = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_TAG_NAME);
2294 faceTagTbl.groupTag = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_GROUP_TAG);
2295 faceTagTbl.centerFeatures = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2296 FACE_TAG_COL_CENTER_FEATURES);
2297 faceTagTbl.tagVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_TAG_VERSION);
2298 faceTagTbl.analysisVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2299 FACE_TAG_COL_ANALYSIS_VERSION);
2300 }
2301
InsertPortraitAlbum(std::vector<AnalysisAlbumTbl> & analysisAlbumTbl)2302 void CloneRestore::InsertPortraitAlbum(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl)
2303 {
2304 CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
2305 CHECK_AND_RETURN_LOG(!analysisAlbumTbl.empty(), "analysisAlbumTbl are empty");
2306
2307 std::vector<std::string> albumNames;
2308 std::vector<std::string> tagIds;
2309
2310 for (const auto &album : analysisAlbumTbl) {
2311 if (album.albumName.has_value()) {
2312 albumNames.emplace_back(album.albumName.value());
2313 }
2314 if (album.tagId.has_value()) {
2315 tagIds.emplace_back(album.tagId.value());
2316 }
2317 }
2318 MEDIA_INFO_LOG("Total albums: %{public}zu, Albums with names: %{public}zu, Albums with tagIds: %{public}zu",
2319 analysisAlbumTbl.size(), albumNames.size(), tagIds.size());
2320
2321 CHECK_AND_RETURN_LOG(BackupDatabaseUtils::DeleteDuplicatePortraitAlbum(albumNames,
2322 tagIds, mediaLibraryRdb_), "Batch delete failed.");
2323
2324 int32_t albumRowNum = InsertPortraitAlbumByTable(analysisAlbumTbl);
2325 CHECK_AND_PRINT_LOG(albumRowNum != E_ERR, "Failed to insert album");
2326
2327 migratePortraitAlbumNumber_ += static_cast<uint64_t>(albumRowNum);
2328 return;
2329 }
2330
InsertPortraitAlbumByTable(std::vector<AnalysisAlbumTbl> & analysisAlbumTbl)2331 int32_t CloneRestore::InsertPortraitAlbumByTable(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl)
2332 {
2333 std::vector<NativeRdb::ValuesBucket> valuesBuckets = GetInsertValues(analysisAlbumTbl);
2334
2335 int64_t rowNum = 0;
2336 int32_t ret = BatchInsertWithRetry(ANALYSIS_ALBUM_TABLE, valuesBuckets, rowNum);
2337 CHECK_AND_RETURN_RET(ret == E_OK, E_ERR);
2338 return rowNum;
2339 }
2340
GetInsertValues(std::vector<AnalysisAlbumTbl> & analysisAlbumTbl)2341 std::vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl)
2342 {
2343 std::vector<NativeRdb::ValuesBucket> values;
2344 for (auto &portraitAlbumInfo : analysisAlbumTbl) {
2345 NativeRdb::ValuesBucket value = GetInsertValue(portraitAlbumInfo);
2346 values.emplace_back(value);
2347 }
2348 return values;
2349 }
2350
GetInsertValue(const AnalysisAlbumTbl & portraitAlbumInfo)2351 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const AnalysisAlbumTbl &portraitAlbumInfo)
2352 {
2353 NativeRdb::ValuesBucket values;
2354
2355 PutIfPresent(values, ANALYSIS_COL_ALBUM_TYPE, portraitAlbumInfo.albumType);
2356 PutIfPresent(values, ANALYSIS_COL_ALBUM_SUBTYPE, portraitAlbumInfo.albumSubtype);
2357 PutIfPresent(values, ANALYSIS_COL_ALBUM_NAME, portraitAlbumInfo.albumName);
2358 PutIfPresent(values, ANALYSIS_COL_TAG_ID, portraitAlbumInfo.tagId);
2359 PutIfPresent(values, ANALYSIS_COL_USER_OPERATION, portraitAlbumInfo.userOperation);
2360 PutIfPresent(values, ANALYSIS_COL_GROUP_TAG, portraitAlbumInfo.groupTag);
2361 PutIfPresent(values, ANALYSIS_COL_USER_DISPLAY_LEVEL, portraitAlbumInfo.userDisplayLevel);
2362 PutIfPresent(values, ANALYSIS_COL_IS_ME, portraitAlbumInfo.isMe);
2363 PutIfPresent(values, ANALYSIS_COL_IS_REMOVED, portraitAlbumInfo.isRemoved);
2364 PutIfPresent(values, ANALYSIS_COL_RENAME_OPERATION, portraitAlbumInfo.renameOperation);
2365 PutIfPresent(values, ANALYSIS_COL_IS_LOCAL, portraitAlbumInfo.isLocal);
2366
2367 return values;
2368 }
2369
CreateValuesBucketFromFaceTagTbl(const FaceTagTbl & faceTagTbl)2370 NativeRdb::ValuesBucket CloneRestore::CreateValuesBucketFromFaceTagTbl(const FaceTagTbl& faceTagTbl)
2371 {
2372 NativeRdb::ValuesBucket values;
2373
2374 PutIfPresent(values, FACE_TAG_COL_TAG_ID, faceTagTbl.tagId);
2375 PutIfPresent(values, FACE_TAG_COL_TAG_NAME, faceTagTbl.tagName);
2376 PutIfPresent(values, FACE_TAG_COL_CENTER_FEATURES, faceTagTbl.centerFeatures);
2377 PutIfPresent(values, FACE_TAG_COL_TAG_VERSION, faceTagTbl.tagVersion);
2378 PutIfPresent(values, FACE_TAG_COL_ANALYSIS_VERSION, faceTagTbl.analysisVersion);
2379
2380 return values;
2381 }
2382
QueryAllPortraitAlbum(int32_t & offset,int32_t & rowCount)2383 std::vector<PortraitAlbumDfx> CloneRestore::QueryAllPortraitAlbum(int32_t& offset, int32_t& rowCount)
2384 {
2385 std::vector<PortraitAlbumDfx> result;
2386 result.reserve(QUERY_COUNT);
2387
2388 const std::string querySql = "SELECT album_name, cover_uri, tag_id, count "
2389 "FROM AnalysisAlbum "
2390 "WHERE album_type = ? "
2391 "AND album_subtype = ? "
2392 "LIMIT ?, ?";
2393
2394 std::vector<NativeRdb::ValueObject> bindArgs = { SMART, PORTRAIT, offset, QUERY_COUNT };
2395 CHECK_AND_RETURN_RET_LOG(this->mediaRdb_ != nullptr, result, "Media_Restore: mediaRdb_ is null.");
2396 auto resultSet = mediaRdb_->QuerySql(querySql, bindArgs);
2397 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
2398
2399 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2400 PortraitAlbumDfx dfxInfo;
2401 dfxInfo.albumName = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_ALBUM_NAME);
2402 dfxInfo.coverUri = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_COVER_URI);
2403 dfxInfo.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_TAG_ID);
2404 dfxInfo.count = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_COUNT);
2405
2406 result.push_back(dfxInfo);
2407 }
2408 resultSet->GetRowCount(rowCount);
2409 return result;
2410 }
2411
RecordOldPortraitAlbumDfx()2412 void CloneRestore::RecordOldPortraitAlbumDfx()
2413 {
2414 int32_t offset {0};
2415 int32_t rowCount {0};
2416 std::vector<PortraitAlbumDfx> albums;
2417
2418 do {
2419 auto batchResults = QueryAllPortraitAlbum(offset, rowCount);
2420 if (!batchResults.empty()) {
2421 albums.insert(albums.end(), batchResults.begin(), batchResults.end());
2422 }
2423
2424 offset += QUERY_COUNT;
2425 } while (rowCount > 0);
2426
2427 for (const auto& album : albums) {
2428 PortraitAlbumDfx dfxInfo;
2429 if (album.albumName.has_value()) {
2430 dfxInfo.albumName = album.albumName.value();
2431 }
2432 if (album.coverUri.has_value()) {
2433 auto uriParts = BackupDatabaseUtils::SplitString(album.coverUri.value(), '/');
2434 if (uriParts.size() >= COVER_URI_NUM) {
2435 std::string fileName = uriParts[uriParts.size() - 1];
2436 dfxInfo.coverUri = BackupFileUtils::GarbleFileName(fileName);
2437 }
2438 }
2439 if (album.tagId.has_value()) {
2440 dfxInfo.tagId = album.tagId.value();
2441 }
2442 if (album.count.has_value()) {
2443 dfxInfo.count = album.count.value();
2444 }
2445
2446 portraitAlbumDfx_.push_back(dfxInfo);
2447 }
2448 }
2449
QueryAllPortraitAlbum()2450 std::unordered_set<std::string> CloneRestore::QueryAllPortraitAlbum()
2451 {
2452 std::unordered_set<std::string> result;
2453 std::vector<std::string> tagIds;
2454 for (const auto& oldAlbum : portraitAlbumDfx_) {
2455 if (oldAlbum.tagId.has_value()) {
2456 tagIds.push_back(oldAlbum.tagId.value());
2457 }
2458 }
2459
2460 CHECK_AND_RETURN_RET_LOG(!tagIds.empty(), result, "No valid tag_ids found in old albums");
2461
2462 std::string querySql = "SELECT tag_id FROM " + ANALYSIS_ALBUM_TABLE +
2463 " WHERE tag_id IN (" + BackupDatabaseUtils::JoinSQLValues<string>(tagIds, ", ") + ")";
2464
2465 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
2466 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
2467
2468 std::string dfxInfo;
2469 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2470 dfxInfo =
2471 BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_TAG_ID).value_or("");
2472 result.insert(dfxInfo);
2473 }
2474
2475 return result;
2476 }
2477
LogPortraitCloneDfx()2478 void CloneRestore::LogPortraitCloneDfx()
2479 {
2480 std::vector<std::string> failedAlbums;
2481 std::unordered_set<std::string> existingTagIds = QueryAllPortraitAlbum();
2482
2483 for (const auto& oldAlbum : portraitAlbumDfx_) {
2484 if (!oldAlbum.tagId.has_value()) {
2485 continue;
2486 }
2487
2488 if (existingTagIds.find(oldAlbum.tagId.value()) == existingTagIds.end()) {
2489 std::string albumInfo = "Album: " + oldAlbum.albumName.value_or("Unknown") +
2490 ", TagId: " + oldAlbum.tagId.value() +
2491 ", Cover: " + oldAlbum.coverUri.value_or("Unknown") +
2492 ", Count: " + std::to_string(oldAlbum.count.value_or(0));
2493 failedAlbums.push_back(albumInfo);
2494 }
2495 }
2496
2497 if (!failedAlbums.empty()) {
2498 MEDIA_ERR_LOG("Following portrait albums failed to clone completely:");
2499 for (const auto& failedAlbum : failedAlbums) {
2500 MEDIA_ERR_LOG("%{public}s", failedAlbum.c_str());
2501 }
2502 } else {
2503 MEDIA_INFO_LOG("All portrait albums cloned successfully");
2504 }
2505
2506 MEDIA_INFO_LOG("Stat: Total albums: %{public}zu, Failed albums count: %{public}zu",
2507 portraitAlbumDfx_.size(), failedAlbums.size());
2508 }
2509
RestorePortraitClusteringInfo()2510 void CloneRestore::RestorePortraitClusteringInfo()
2511 {
2512 int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2513 int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb_, QUERY_FACE_TAG_COUNT, CUSTOM_COUNT);
2514 MEDIA_INFO_LOG("QueryPortraitClustering totalNumber = %{public}d", totalNumber);
2515
2516 std::vector<std::string> commonColumn = BackupDatabaseUtils::GetCommonColumnInfos(mediaRdb_, mediaLibraryRdb_,
2517 VISION_FACE_TAG_TABLE);
2518 std::vector<std::string> commonColumns = BackupDatabaseUtils::filterColumns(commonColumn,
2519 EXCLUDED_FACE_TAG_COLUMNS);
2520 BackupDatabaseUtils::LeftJoinValues<string>(commonColumns, "vft.");
2521 std::string inClause = BackupDatabaseUtils::JoinValues<string>(commonColumns, ", ");
2522 BackupDatabaseUtils::ExecuteSQL(mediaRdb_, CREATE_FACE_TAG_INDEX);
2523 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
2524 vector<FaceTagTbl> faceTagTbls = QueryFaceTagTbl(offset, inClause);
2525 BatchInsertFaceTags(faceTagTbls);
2526 if (static_cast<std::int32_t>(faceTagTbls.size()) < QUERY_COUNT) {
2527 break;
2528 }
2529 }
2530 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2531 migratePortraitTotalTimeCost_ += end - start;
2532 }
2533
QueryFaceTagTbl(int32_t offset,const std::string & inClause)2534 std::vector<FaceTagTbl> CloneRestore::QueryFaceTagTbl(int32_t offset, const std::string &inClause)
2535 {
2536 std::vector<FaceTagTbl> result;
2537
2538 std::string querySql = "SELECT DISTINCT " + inClause +
2539 " FROM " + VISION_FACE_TAG_TABLE + " vft" +
2540 " LEFT JOIN AnalysisAlbum aa ON aa.tag_id = vft.tag_id" +
2541 " LEFT JOIN AnalysisPhotoMap apm ON aa.album_id = apm.map_album" +
2542 " LEFT JOIN Photos ph ON ph.file_id = apm.map_asset" +
2543 " WHERE " +
2544 (IsCloudRestoreSatisfied() ? "ph.position IN (1, 2, 3)" : "ph.position IN (1, 3)");
2545
2546 querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
2547
2548 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2549 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSet is null.");
2550 int resultRowCount = 0;
2551 resultSet->GetRowCount(resultRowCount);
2552 result.reserve(resultRowCount);
2553 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2554 FaceTagTbl faceTagTbl;
2555 ParseFaceTagResultSet(resultSet, faceTagTbl);
2556 result.emplace_back(faceTagTbl);
2557 }
2558
2559 return result;
2560 }
2561
BatchInsertFaceTags(const std::vector<FaceTagTbl> & faceTagTbls)2562 void CloneRestore::BatchInsertFaceTags(const std::vector<FaceTagTbl>& faceTagTbls)
2563 {
2564 std::vector<NativeRdb::ValuesBucket> valuesBuckets;
2565 for (const auto& faceTagTbl : faceTagTbls) {
2566 valuesBuckets.push_back(CreateValuesBucketFromFaceTagTbl(faceTagTbl));
2567 }
2568
2569 int64_t rowNum = 0;
2570 int32_t ret = BatchInsertWithRetry(VISION_FACE_TAG_TABLE, valuesBuckets, rowNum);
2571 CHECK_AND_RETURN_LOG(ret == E_OK, "Failed to batch insert face tags");
2572 }
2573
RestoreImageFaceInfo(std::vector<FileInfo> & fileInfos)2574 void CloneRestore::RestoreImageFaceInfo(std::vector<FileInfo> &fileInfos)
2575 {
2576 int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2577 auto uniqueFileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2578 auto [oldFileIds, newFileIds] = BackupDatabaseUtils::UnzipFileIdPairs(uniqueFileIdPairs);
2579
2580 std::string fileIdOldInClause = "(" + BackupDatabaseUtils::JoinValues<int>(oldFileIds, ", ") + ")";
2581
2582 std::string querySql = QUERY_IMAGE_FACE_COUNT;
2583 querySql += " WHERE " + IMAGE_FACE_COL_FILE_ID + " IN " + fileIdOldInClause;
2584 int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb_, querySql, CUSTOM_COUNT);
2585 MEDIA_INFO_LOG("QueryImageFaceTotalNumber, totalNumber = %{public}d", totalNumber);
2586 if (totalNumber == 0) {
2587 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2588 migratePortraitTotalTimeCost_ += end - start;
2589 return;
2590 }
2591
2592 std::vector<std::string> commonColumn = BackupDatabaseUtils::GetCommonColumnInfos(mediaRdb_, mediaLibraryRdb_,
2593 VISION_IMAGE_FACE_TABLE);
2594 std::vector<std::string> commonColumns = BackupDatabaseUtils::filterColumns(commonColumn,
2595 EXCLUDED_IMAGE_FACE_COLUMNS);
2596
2597 BackupDatabaseUtils::DeleteExistingImageFaceData(mediaLibraryRdb_, uniqueFileIdPairs);
2598 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
2599 std::vector<ImageFaceTbl> imageFaceTbls = QueryImageFaceTbl(offset, fileIdOldInClause, commonColumns);
2600 auto imageFaces = ProcessImageFaceTbls(imageFaceTbls, uniqueFileIdPairs);
2601 BatchInsertImageFaces(imageFaces);
2602 }
2603
2604 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2605 migratePortraitTotalTimeCost_ += end - start;
2606
2607 GenNewCoverUris(coverUriInfo_, fileInfos);
2608 }
2609
QueryImageFaceTbl(int32_t offset,std::string & fileIdClause,const std::vector<std::string> & commonColumns)2610 std::vector<ImageFaceTbl> CloneRestore::QueryImageFaceTbl(int32_t offset, std::string &fileIdClause,
2611 const std::vector<std::string> &commonColumns)
2612 {
2613 std::vector<ImageFaceTbl> result;
2614 result.reserve(QUERY_COUNT);
2615
2616 std::string inClause = BackupDatabaseUtils::JoinValues<string>(commonColumns, ", ");
2617 std::string querySql =
2618 "SELECT " + inClause +
2619 " FROM " + VISION_IMAGE_FACE_TABLE;
2620 querySql += " WHERE " + IMAGE_FACE_COL_FILE_ID + " IN " + fileIdClause;
2621 querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
2622
2623 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2624 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSet is null.");
2625
2626 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2627 ImageFaceTbl imageFaceTbl;
2628 ParseImageFaceResultSet(resultSet, imageFaceTbl);
2629 result.emplace_back(imageFaceTbl);
2630 }
2631
2632 return result;
2633 }
2634
GetFileInfoByFileId(int32_t fileId,const std::vector<FileInfo> & fileInfos,FileInfo & outFileInfo)2635 bool CloneRestore::GetFileInfoByFileId(int32_t fileId, const std::vector<FileInfo>& fileInfos, FileInfo& outFileInfo)
2636 {
2637 auto it = std::find_if(fileInfos.begin(), fileInfos.end(),
2638 [fileId](const FileInfo& info) { return info.fileIdNew == fileId; });
2639 if (it != fileInfos.end()) {
2640 outFileInfo = *it;
2641 return true;
2642 }
2643
2644 return false;
2645 }
2646
GenNewCoverUris(const std::vector<CloneRestore::CoverUriInfo> & coverUriInfo,std::vector<FileInfo> & fileInfos)2647 void CloneRestore::GenNewCoverUris(const std::vector<CloneRestore::CoverUriInfo>& coverUriInfo,
2648 std::vector<FileInfo> &fileInfos)
2649 {
2650 bool cond = (coverUriInfo.empty() && fileInfos.empty());
2651 CHECK_AND_RETURN_LOG(!cond, "Empty coverUriInfo or fileIdPairs, skipping.");
2652
2653 std::unordered_map<std::string, std::pair<std::string, int32_t>> tagIdToCoverInfo;
2654 for (const auto& [tagId, coverInfo] : coverUriInfo) {
2655 tagIdToCoverInfo[tagId] = coverInfo;
2656 }
2657
2658 auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2659 std::unordered_map<std::string, int32_t> oldToNewFileId;
2660 for (const auto& [oldId, newId] : fileIdPairs) {
2661 oldToNewFileId[std::to_string(oldId)] = newId;
2662 }
2663
2664 std::vector<std::string> tagIds;
2665 std::string updateSql = GenCoverUriUpdateSql(tagIdToCoverInfo, oldToNewFileId, fileInfos, tagIds);
2666 if (updateSql.empty()) {
2667 return;
2668 }
2669
2670 BackupDatabaseUtils::ExecuteSQL(mediaLibraryRdb_, updateSql);
2671 }
2672
GenCoverUriUpdateSql(const std::unordered_map<std::string,std::pair<std::string,int32_t>> & tagIdToCoverInfo,const std::unordered_map<std::string,int32_t> & oldToNewFileId,const std::vector<FileInfo> & fileInfos,std::vector<std::string> & tagIds)2673 std::string CloneRestore::GenCoverUriUpdateSql(const std::unordered_map<std::string, std::pair<std::string, int32_t>>&
2674 tagIdToCoverInfo, const std::unordered_map<std::string, int32_t>& oldToNewFileId,
2675 const std::vector<FileInfo>& fileInfos, std::vector<std::string>& tagIds)
2676 {
2677 std::unordered_map<std::string, std::string> coverUriUpdates;
2678 std::unordered_map<std::string, int32_t> isCoverSatisfiedUpdates;
2679
2680 for (const auto& [tagId, coverInfo] : tagIdToCoverInfo) {
2681 const auto& [oldCoverUri, isCoverSatisfied] = coverInfo;
2682 std::string newUri = ProcessUriAndGenNew(tagId, oldCoverUri, oldToNewFileId, fileInfos);
2683 if (!newUri.empty()) {
2684 coverUriUpdates[tagId] = newUri;
2685 isCoverSatisfiedUpdates[tagId] = isCoverSatisfied;
2686 tagIds.push_back(tagId);
2687 }
2688 }
2689
2690 bool cond = (coverUriUpdates.empty() || isCoverSatisfiedUpdates.empty());
2691 CHECK_AND_RETURN_RET(!cond, "");
2692
2693 std::string updateSql = "UPDATE AnalysisAlbum SET ";
2694
2695 updateSql += "cover_uri = CASE ";
2696 for (const auto& [tagId, newUri] : coverUriUpdates) {
2697 updateSql += "WHEN tag_id = '" + tagId + "' THEN '" + newUri + "' ";
2698 }
2699 updateSql += "ELSE cover_uri END";
2700
2701 bool hasValidIsCoverSatisfied = false;
2702 std::string isCoverSatisfiedSql = ", is_cover_satisfied = CASE ";
2703 for (const auto& [tagId, isCoverSatisfied] : isCoverSatisfiedUpdates) {
2704 if (isCoverSatisfied != INVALID_COVER_SATISFIED_STATUS) {
2705 hasValidIsCoverSatisfied = true;
2706 isCoverSatisfiedSql += "WHEN tag_id = '" + tagId + "' THEN " + std::to_string(isCoverSatisfied) + " ";
2707 }
2708 }
2709
2710 isCoverSatisfiedSql += "ELSE is_cover_satisfied END ";
2711 if (hasValidIsCoverSatisfied) {
2712 updateSql += isCoverSatisfiedSql;
2713 }
2714
2715 updateSql += "WHERE tag_id IN ('" +
2716 BackupDatabaseUtils::JoinValues(tagIds, "','") + "')";
2717
2718 return updateSql;
2719 }
2720
ProcessUriAndGenNew(const std::string & tagId,const std::string & oldCoverUri,const std::unordered_map<std::string,int32_t> & oldToNewFileId,const std::vector<FileInfo> & fileInfos)2721 std::string CloneRestore::ProcessUriAndGenNew(const std::string& tagId, const std::string& oldCoverUri,
2722 const std::unordered_map<std::string, int32_t>& oldToNewFileId, const std::vector<FileInfo>& fileInfos)
2723 {
2724 auto uriParts = BackupDatabaseUtils::SplitString(oldCoverUri, '/');
2725 if (uriParts.size() >= COVER_URI_NUM) {
2726 std::string fileIdOld = uriParts[uriParts.size() - 3];
2727 auto it = oldToNewFileId.find(fileIdOld);
2728 if (it != oldToNewFileId.end()) {
2729 int32_t fileIdNew = it->second;
2730 FileInfo fileInfo {};
2731 if (GetFileInfoByFileId(fileIdNew, fileInfos, fileInfo)) {
2732 std::string extraUri = MediaFileUtils::GetExtraUri(fileInfo.displayName, fileInfo.cloudPath);
2733 return MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
2734 std::to_string(fileIdNew), extraUri);
2735 }
2736 }
2737 }
2738 return "";
2739 }
2740
ProcessImageFaceTbls(const std::vector<ImageFaceTbl> & imageFaceTbls,const std::vector<FileIdPair> & fileIdPairs)2741 std::vector<ImageFaceTbl> CloneRestore::ProcessImageFaceTbls(const std::vector<ImageFaceTbl>& imageFaceTbls,
2742 const std::vector<FileIdPair>& fileIdPairs)
2743 {
2744 CHECK_AND_RETURN_RET_LOG(!imageFaceTbls.empty(), {}, "image faces tbl empty");
2745
2746 std::vector<ImageFaceTbl> imageFaceNewTbls;
2747 imageFaceNewTbls.reserve(imageFaceTbls.size());
2748
2749 for (const auto& imageFaceTbl : imageFaceTbls) {
2750 if (imageFaceTbl.fileId.has_value()) {
2751 int32_t oldFileId = imageFaceTbl.fileId.value();
2752 auto it = std::find_if(fileIdPairs.begin(), fileIdPairs.end(),
2753 [oldFileId](const FileIdPair& pair) { return pair.first == oldFileId; });
2754 if (it != fileIdPairs.end()) {
2755 ImageFaceTbl updatedFace = imageFaceTbl;
2756 updatedFace.fileId = it->second;
2757 imageFaceNewTbls.push_back(std::move(updatedFace));
2758 }
2759 }
2760 }
2761
2762 return imageFaceNewTbls;
2763 }
2764
BatchInsertImageFaces(const std::vector<ImageFaceTbl> & imageFaceTbls)2765 void CloneRestore::BatchInsertImageFaces(const std::vector<ImageFaceTbl>& imageFaceTbls)
2766 {
2767 std::vector<NativeRdb::ValuesBucket> valuesBuckets;
2768 std::unordered_set<int32_t> fileIdSet;
2769 for (const auto& imageFaceTbl : imageFaceTbls) {
2770 valuesBuckets.push_back(CreateValuesBucketFromImageFaceTbl(imageFaceTbl));
2771 }
2772
2773 int64_t rowNum = 0;
2774 int32_t ret = BatchInsertWithRetry(VISION_IMAGE_FACE_TABLE, valuesBuckets, rowNum);
2775 CHECK_AND_RETURN_LOG(ret == E_OK, "Failed to batch insert image faces");
2776
2777 for (const auto& imageFaceTbl : imageFaceTbls) {
2778 if (imageFaceTbl.fileId.has_value()) {
2779 fileIdSet.insert(imageFaceTbl.fileId.value());
2780 }
2781 }
2782
2783 migratePortraitFaceNumber_ += rowNum;
2784 migratePortraitPhotoNumber_ += fileIdSet.size();
2785 }
2786
CreateValuesBucketFromImageFaceTbl(const ImageFaceTbl & imageFaceTbl)2787 NativeRdb::ValuesBucket CloneRestore::CreateValuesBucketFromImageFaceTbl(const ImageFaceTbl& imageFaceTbl)
2788 {
2789 NativeRdb::ValuesBucket values;
2790
2791 PutIfPresent(values, IMAGE_FACE_COL_FILE_ID, imageFaceTbl.fileId);
2792 PutIfPresent(values, IMAGE_FACE_COL_FACE_ID, imageFaceTbl.faceId);
2793 PutIfPresent(values, IMAGE_FACE_COL_TAG_ID, imageFaceTbl.tagId);
2794 PutIfPresent(values, IMAGE_FACE_COL_SCALE_X, imageFaceTbl.scaleX);
2795 PutIfPresent(values, IMAGE_FACE_COL_SCALE_Y, imageFaceTbl.scaleY);
2796 PutIfPresent(values, IMAGE_FACE_COL_SCALE_WIDTH, imageFaceTbl.scaleWidth);
2797 PutIfPresent(values, IMAGE_FACE_COL_SCALE_HEIGHT, imageFaceTbl.scaleHeight);
2798 PutIfPresent(values, IMAGE_FACE_COL_LANDMARKS, imageFaceTbl.landmarks);
2799 PutIfPresent(values, IMAGE_FACE_COL_PITCH, imageFaceTbl.pitch);
2800 PutIfPresent(values, IMAGE_FACE_COL_YAW, imageFaceTbl.yaw);
2801 PutIfPresent(values, IMAGE_FACE_COL_ROLL, imageFaceTbl.roll);
2802 PutIfPresent(values, IMAGE_FACE_COL_PROB, imageFaceTbl.prob);
2803 PutIfPresent(values, IMAGE_FACE_COL_TOTAL_FACES, imageFaceTbl.totalFaces);
2804 PutIfPresent(values, IMAGE_FACE_COL_FACE_VERSION, imageFaceTbl.faceVersion);
2805 PutIfPresent(values, IMAGE_FACE_COL_FEATURES_VERSION, imageFaceTbl.featuresVersion);
2806 PutIfPresent(values, IMAGE_FACE_COL_FEATURES, imageFaceTbl.features);
2807 PutIfPresent(values, IMAGE_FACE_COL_FACE_OCCLUSION, imageFaceTbl.faceOcclusion);
2808 PutIfPresent(values, IMAGE_FACE_COL_ANALYSIS_VERSION, imageFaceTbl.analysisVersion);
2809 PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_X, imageFaceTbl.beautyBounderX);
2810 PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_Y, imageFaceTbl.beautyBounderY);
2811 PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_WIDTH, imageFaceTbl.beautyBounderWidth);
2812 PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_HEIGHT, imageFaceTbl.beautyBounderHeight);
2813 PutIfPresent(values, IMAGE_FACE_COL_AESTHETICS_SCORE, imageFaceTbl.aestheticsScore);
2814 PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_VERSION, imageFaceTbl.beautyBounderVersion);
2815 PutWithDefault(values, IMAGE_FACE_COL_IS_EXCLUDED, imageFaceTbl.isExcluded, 0);
2816
2817 return values;
2818 }
2819
ParseImageFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,ImageFaceTbl & imageFaceTbl)2820 void CloneRestore::ParseImageFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
2821 ImageFaceTbl& imageFaceTbl)
2822 {
2823 imageFaceTbl.fileId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, IMAGE_FACE_COL_FILE_ID);
2824 imageFaceTbl.faceId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_FACE_ID);
2825 imageFaceTbl.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_TAG_ID);
2826 imageFaceTbl.scaleX = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_X);
2827 imageFaceTbl.scaleY = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_Y);
2828 imageFaceTbl.scaleWidth = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_WIDTH);
2829 imageFaceTbl.scaleHeight = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_HEIGHT);
2830 imageFaceTbl.landmarks = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_LANDMARKS);
2831 imageFaceTbl.pitch = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_PITCH);
2832 imageFaceTbl.yaw = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_YAW);
2833 imageFaceTbl.roll = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_ROLL);
2834 imageFaceTbl.prob = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_PROB);
2835 imageFaceTbl.totalFaces = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, IMAGE_FACE_COL_TOTAL_FACES);
2836 imageFaceTbl.faceVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2837 IMAGE_FACE_COL_FACE_VERSION);
2838 imageFaceTbl.featuresVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2839 IMAGE_FACE_COL_FEATURES_VERSION);
2840 imageFaceTbl.features = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_FEATURES);
2841 imageFaceTbl.faceOcclusion = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2842 IMAGE_FACE_COL_FACE_OCCLUSION);
2843 imageFaceTbl.analysisVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2844 IMAGE_FACE_COL_ANALYSIS_VERSION);
2845 imageFaceTbl.beautyBounderX = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2846 IMAGE_FACE_COL_BEAUTY_BOUNDER_X);
2847 imageFaceTbl.beautyBounderY = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2848 IMAGE_FACE_COL_BEAUTY_BOUNDER_Y);
2849 imageFaceTbl.beautyBounderWidth = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2850 IMAGE_FACE_COL_BEAUTY_BOUNDER_WIDTH);
2851 imageFaceTbl.beautyBounderHeight = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2852 IMAGE_FACE_COL_BEAUTY_BOUNDER_HEIGHT);
2853 imageFaceTbl.aestheticsScore = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2854 IMAGE_FACE_COL_AESTHETICS_SCORE);
2855 imageFaceTbl.beautyBounderVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2856 IMAGE_FACE_COL_BEAUTY_BOUNDER_VERSION);
2857 imageFaceTbl.isExcluded = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, IMAGE_FACE_COL_IS_EXCLUDED);
2858 }
2859
ReportPortraitCloneStat(int32_t sceneCode)2860 void CloneRestore::ReportPortraitCloneStat(int32_t sceneCode)
2861 {
2862 CHECK_AND_RETURN_LOG(sceneCode == CLONE_RESTORE_ID, "err scencecode %{public}d", sceneCode);
2863
2864 MEDIA_INFO_LOG("PortraitStat: album %{public}lld, photo %{public}lld, face %{public}lld, cost %{public}lld",
2865 (long long)migratePortraitAlbumNumber_, (long long)migratePortraitPhotoNumber_,
2866 (long long)migratePortraitFaceNumber_, (long long)migratePortraitTotalTimeCost_);
2867
2868 BackupDfxUtils::PostPortraitStat(static_cast<uint32_t>(migratePortraitAlbumNumber_), migratePortraitPhotoNumber_,
2869 migratePortraitFaceNumber_, migratePortraitTotalTimeCost_);
2870 }
2871
AppendExtraWhereClause(std::string & whereClause,const std::string & tableName)2872 void CloneRestore::AppendExtraWhereClause(std::string& whereClause, const std::string& tableName)
2873 {
2874 auto it = tableExtraQueryWhereClauseMap_.find(tableName);
2875 if (it != tableExtraQueryWhereClauseMap_.end()) {
2876 whereClause += whereClause.empty() ? "" : " AND ";
2877 whereClause += it->second;
2878 }
2879 }
2880
InitAllKvStore()2881 bool CloneRestore::InitAllKvStore()
2882 {
2883 std::string oldBaseDir = backupRestoreDir_ + CLONE_KVDB_BACKUP_DIR;
2884 std::string newBaseDir = MEDIA_KVDB_DIR;
2885 oldMonthKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
2886 .GetSingleKvStore(KvStoreRoleType::OWNER, CLONE_KVSTORE_MONTH_STOREID, oldBaseDir);
2887 oldYearKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
2888 .GetSingleKvStore(KvStoreRoleType::OWNER, CLONE_KVSTORE_YEAR_STOREID, oldBaseDir);
2889 newMonthKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
2890 .GetSingleKvStore(KvStoreRoleType::OWNER, MEDIA_KVSTORE_MONTH_STOREID, newBaseDir);
2891 newYearKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
2892 .GetSingleKvStore(KvStoreRoleType::OWNER, MEDIA_KVSTORE_YEAR_STOREID, newBaseDir);
2893
2894 bool cond = (oldMonthKvStorePtr_ == nullptr || oldYearKvStorePtr_ == nullptr ||
2895 newMonthKvStorePtr_ == nullptr || newYearKvStorePtr_ == nullptr);
2896 CHECK_AND_RETURN_RET_LOG(!cond, false, "Init all kvstore failed");
2897 return true;
2898 }
2899
CloseAllKvStore()2900 void CloneRestore::CloseAllKvStore()
2901 {
2902 oldMonthKvStorePtr_ != nullptr && oldMonthKvStorePtr_->Close();
2903 oldYearKvStorePtr_ != nullptr && oldYearKvStorePtr_->Close();
2904 newMonthKvStorePtr_ != nullptr && newMonthKvStorePtr_->Close();
2905 newYearKvStorePtr_ != nullptr && newYearKvStorePtr_->Close();
2906 }
2907
StartBackup()2908 void CloneRestore::StartBackup()
2909 {
2910 MEDIA_INFO_LOG("Start clone backup");
2911 bool cond = (!BackupKvStore() && !MediaFileUtils::DeleteDir(CLONE_KVDB_BACKUP_DIR));
2912 CHECK_AND_PRINT_LOG(!cond, "BackupKvStore failed and delete old backup kvdb failed, errno:%{public}d", errno);
2913 MEDIA_INFO_LOG("End clone backup");
2914 }
2915
BackupKvStore()2916 bool CloneRestore::BackupKvStore()
2917 {
2918 MEDIA_INFO_LOG("Start BackupKvstore");
2919 if (MediaFileUtils::IsFileExists(CLONE_KVDB_BACKUP_DIR)) {
2920 // Delete only redundant data and do not need to be returned.
2921 MediaFileUtils::DeleteDir(CLONE_KVDB_BACKUP_DIR);
2922 }
2923
2924 std::string backupKvdbPath = CLONE_KVDB_BACKUP_DIR + "/kvdb";
2925 CHECK_AND_RETURN_RET_LOG(BackupFileUtils::PreparePath(backupKvdbPath) == E_OK,
2926 false, "Prepare backup dir failed");
2927
2928 int32_t status = MediaLibraryKvStoreManager::GetInstance().CloneKvStore(
2929 MEDIA_KVSTORE_MONTH_STOREID, MEDIA_KVDB_DIR, CLONE_KVSTORE_MONTH_STOREID, CLONE_KVDB_BACKUP_DIR);
2930 CHECK_AND_RETURN_RET(status == E_OK, false);
2931 status = MediaLibraryKvStoreManager::GetInstance().CloneKvStore(
2932 MEDIA_KVSTORE_YEAR_STOREID, MEDIA_KVDB_DIR, CLONE_KVSTORE_YEAR_STOREID, CLONE_KVDB_BACKUP_DIR);
2933 CHECK_AND_RETURN_RET(status == E_OK, false);
2934 MEDIA_INFO_LOG("End BackupKvstore");
2935 return true;
2936 }
2937
BatchUpdateFileInfoData(std::vector<FileInfo> & fileInfos,unordered_map<string,CloudPhotoFileExistFlag> & resultExistMap)2938 void CloneRestore::BatchUpdateFileInfoData(std::vector<FileInfo> &fileInfos,
2939 unordered_map<string, CloudPhotoFileExistFlag> &resultExistMap)
2940 {
2941 for (size_t i = 0; i < fileInfos.size(); i++) {
2942 CloudPhotoFileExistFlag fileExistFlag;
2943 unordered_map<string, CloudPhotoFileExistFlag>::iterator iter =
2944 resultExistMap.find(fileInfos[i].cloudPath);
2945 if (iter == resultExistMap.end()) {
2946 continue;
2947 }
2948 fileExistFlag = iter->second;
2949 int32_t thumbReady = CheckThumbReady(fileInfos[i], fileExistFlag);
2950 int32_t thumbStatus = CheckThumbStatus(fileInfos[i], fileExistFlag);
2951 int32_t lcdVisitTime = CheckLcdVisitTime(fileExistFlag);
2952
2953 std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
2954 std::make_unique<NativeRdb::AbsRdbPredicates>(PhotoColumn::PHOTOS_TABLE);
2955 std::string whereClause = "data = '" + fileInfos[i].cloudPath + "'";
2956 predicates->SetWhereClause(whereClause);
2957
2958 int32_t updatedRows = 0;
2959 NativeRdb::ValuesBucket updateBucket;
2960 updateBucket.PutInt(PhotoColumn::PHOTO_THUMB_STATUS, thumbStatus);
2961 updateBucket.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY,
2962 thumbReady == 0 ? 0 : fileInfos[i].thumbnailReady);
2963 updateBucket.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, lcdVisitTime);
2964 updateBucket.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE,
2965 thumbReady == 0 ? 0 : RESTORE_THUMBNAIL_VISIBLE_TRUE);
2966
2967 int32_t ret = BackupDatabaseUtils::Update(mediaLibraryRdb_, updatedRows, updateBucket, predicates);
2968 bool cond = (updatedRows < 0 || ret < 0);
2969 CHECK_AND_PRINT_LOG(!cond, "BatchInsertFileInfoData Failed to update column: %s",
2970 fileInfos[i].cloudPath.c_str());
2971 MediaLibraryPhotoOperations::StoreThumbnailSize(to_string(fileInfos[i].fileIdNew),
2972 fileInfos[i].cloudPath);
2973 }
2974 }
2975
CheckThumbReady(const FileInfo & fileInfo,const CloudPhotoFileExistFlag & cloudPhotoFileExistFlag)2976 int32_t CloneRestore::CheckThumbReady(const FileInfo &fileInfo,
2977 const CloudPhotoFileExistFlag &cloudPhotoFileExistFlag)
2978 {
2979 if (fileInfo.orientation == ORIETATION_ZERO) {
2980 bool cond = (cloudPhotoFileExistFlag.isThmExist &&
2981 cloudPhotoFileExistFlag.isDayAstcExist &&
2982 cloudPhotoFileExistFlag.isYearAstcExist);
2983 CHECK_AND_RETURN_RET(!cond, RESTORE_THUMBNAIL_READY_ALL_SUCCESS);
2984 } else {
2985 bool cond = (cloudPhotoFileExistFlag.isExThmExist &&
2986 cloudPhotoFileExistFlag.isDayAstcExist &&
2987 cloudPhotoFileExistFlag.isYearAstcExist);
2988 CHECK_AND_RETURN_RET(!cond, RESTORE_THUMBNAIL_READY_ALL_SUCCESS);
2989 }
2990 return RESTORE_THUMBNAIL_READY_FAIL;
2991 }
2992
CheckThumbStatus(const FileInfo & fileInfo,const CloudPhotoFileExistFlag & cloudPhotoFileExistFlag)2993 int32_t CloneRestore::CheckThumbStatus(const FileInfo &fileInfo,
2994 const CloudPhotoFileExistFlag &cloudPhotoFileExistFlag)
2995 {
2996 if (fileInfo.orientation == ORIETATION_ZERO) {
2997 if (cloudPhotoFileExistFlag.isThmExist &&
2998 cloudPhotoFileExistFlag.isLcdExist) {
2999 return RESTORE_THUMBNAIL_STATUS_ALL;
3000 } else if (cloudPhotoFileExistFlag.isThmExist &&
3001 !cloudPhotoFileExistFlag.isLcdExist) {
3002 return RESTORE_THUMBNAIL_STATUS_NOT_LCD;
3003 } else if (!cloudPhotoFileExistFlag.isThmExist &&
3004 cloudPhotoFileExistFlag.isLcdExist) {
3005 return RESTORE_THUMBNAIL_STATUS_NOT_THUMB;
3006 } else {
3007 return RESTORE_THUMBNAIL_STATUS_NOT_ALL;
3008 }
3009 }
3010 if (cloudPhotoFileExistFlag.isExThmExist &&
3011 cloudPhotoFileExistFlag.isExLcdExist) {
3012 return RESTORE_THUMBNAIL_STATUS_ALL;
3013 } else if (cloudPhotoFileExistFlag.isExThmExist &&
3014 !cloudPhotoFileExistFlag.isExLcdExist) {
3015 return RESTORE_THUMBNAIL_STATUS_NOT_LCD;
3016 } else if (!cloudPhotoFileExistFlag.isExThmExist &&
3017 cloudPhotoFileExistFlag.isExLcdExist) {
3018 return RESTORE_THUMBNAIL_STATUS_NOT_THUMB;
3019 }
3020 return RESTORE_THUMBNAIL_STATUS_NOT_ALL;
3021 }
3022
CheckLcdVisitTime(const CloudPhotoFileExistFlag & cloudPhotoFileExistFlag)3023 int32_t CloneRestore::CheckLcdVisitTime(const CloudPhotoFileExistFlag &cloudPhotoFileExistFlag)
3024 {
3025 CHECK_AND_RETURN_RET(!cloudPhotoFileExistFlag.isLcdExist, RESTORE_LCD_VISIT_TIME_SUCCESS);
3026 return RESTORE_LCD_VISIT_TIME_NO_LCD;
3027 }
GetNoNeedMigrateCount()3028 int32_t CloneRestore::GetNoNeedMigrateCount()
3029 {
3030 return this->photosClone_.GetNoNeedMigrateCount();
3031 }
3032 } // namespace Media
3033 } // namespace OHOS
3034