• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define MLOG_TAG "CloneRestoreClassify"
16 
17 #include "clone_restore_classify.h"
18 
19 #include "classify_aggregate_types.h"
20 #include "backup_database_utils.h"
21 #include "media_library_db_upgrade.h"
22 #include "medialibrary_unistore_manager.h"
23 #include "media_file_utils.h"
24 #include "media_log.h"
25 #include "result_set_utils.h"
26 #include "upgrade_restore_task_report.h"
27 
28 namespace OHOS::Media {
29 const int32_t PAGE_SIZE = 200;
30 
31 const string ID = "id";
32 const string FILE_ID = "file_id";
33 const string CATEGORY_ID = "category_id";
34 const string SUB_LABEL = "sub_label";
35 const string PROB = "prob";
36 const string FEATURE = "feature";
37 const string SIM_RESULT = "sim_result";
38 const string LABEL_VERSION = "label_version";
39 const string SALIENCY_SUB_PROB = "saliency_sub_prob";
40 const string ANALYSIS_VERSION = "analysis_version";
41 const string CAPTION_RESULT = "caption_result";
42 const string CAPTION_VERSION = "caption_version";
43 
44 const string CONFIDENCE_PROBABILITY = "confidence_probability";
45 const string SUB_CATEGORY = "sub_category";
46 const string SUB_CONFIDENCE_PROB = "sub_confidence_prob";
47 const string SUB_LABEL_PROB = "sub_label_prob";
48 const string SUB_LABEL_TYPE = "sub_label_type";
49 const string TRACKS = "tracks";
50 const string VIDEO_PART_FEATURE = "video_part_feature";
51 const string FILTER_TAG = "filter_tag";
52 const string ALGO_VERSION = "algo_version";
53 const string TRIGGER_GENERATE_THUMBNAIL = "trigger_generate_thumbnail";
54 
55 const string ANALYSIS_LABEL_TABLE = "tab_analysis_label";
56 const string ANALYSIS_VIDEO_TABLE = "tab_analysis_video_label";
57 const string FIELD_TYPE_INT = "INT";
58 
59 const int32_t CLASSIFY_STATUS_SUCCESS = 1;
60 const int32_t CLASSIFY_TYPE = 4097;
61 const int32_t FRONT_CAMERA = 1;
62 
63 const unordered_map<string, unordered_set<string>> COMPARED_COLUMNS_MAP = {
64     { "tab_analysis_label",
65         {
66             "id",
67             "file_id",
68             "category_id",
69             "sub_label",
70             "prob",
71             "feature",
72             "sim_result",
73             "label_version",
74             "saliency_sub_prob",
75             "analysis_version",
76             "caption_result",
77             "caption_version",
78         }
79     },
80     { "tab_analysis_video_label",
81         {
82             "id",
83             "file_id",
84             "category_id",
85             "confidence_probability",
86             "sub_category",
87             "sub_confidence_prob",
88             "sub_label",
89             "sub_label_prob",
90             "sub_label_type",
91             "tracks",
92             "video_part_feature",
93             "filter_tag",
94             "algo_version",
95             "analysis_version",
96             "trigger_generate_thumbnail",
97         }
98     }
99 };
100 
101 template<typename Key, typename Value>
GetValueFromMap(const unordered_map<Key,Value> & map,const Key & key,const Value & defaultValue=Value ())102 Value GetValueFromMap(const unordered_map<Key, Value> &map, const Key &key, const Value &defaultValue = Value())
103 {
104     auto it = map.find(key);
105     CHECK_AND_RETURN_RET(it == map.end(), it->second);
106     return defaultValue;
107 }
108 
Init(int32_t sceneCode,const std::string & taskId,std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb,std::shared_ptr<NativeRdb::RdbStore> mediaRdb)109 void CloneRestoreClassify::Init(int32_t sceneCode, const std::string &taskId,
110     std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb, std::shared_ptr<NativeRdb::RdbStore> mediaRdb)
111 {
112     sceneCode_ = sceneCode;
113     taskId_ = taskId;
114     mediaLibraryRdb_ = mediaLibraryRdb;
115     mediaRdb_ = mediaRdb;
116     analysisType_ = "label";
117 }
118 
Restore(const std::unordered_map<int32_t,PhotoInfo> & photoInfoMap)119 void CloneRestoreClassify::Restore(const std::unordered_map<int32_t, PhotoInfo> &photoInfoMap)
120 {
121     CHECK_AND_RETURN_LOG(mediaRdb_ != nullptr && mediaLibraryRdb_ != nullptr,
122         "ClassifyRestore failed, rdbStore is nullptr");
123 
124     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
125     GetMaxIds();
126     cloneRestoreAnalysisTotal_.Init(analysisType_, PAGE_SIZE, mediaRdb_, mediaLibraryRdb_);
127     int32_t totalNumber = cloneRestoreAnalysisTotal_.GetTotalNumber();
128     for (int32_t offset = 0; offset < totalNumber; offset += PAGE_SIZE) {
129         RestoreBatch(photoInfoMap);
130     }
131     AddSpecialAlbum();
132     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
133     restoreTimeCost_ = end - start;
134     ReportRestoreTask();
135     MEDIA_INFO_LOG("TimeCost: ClassifyRestore: %{public}" PRId64, end - start);
136 }
137 
GetMaxIds()138 void CloneRestoreClassify::GetMaxIds()
139 {
140     maxIdOfLabel_ = BackupDatabaseUtils::QueryMaxId(mediaLibraryRdb_, ANALYSIS_LABEL_TABLE, ID);
141     maxIdOfVideoLabel_ = BackupDatabaseUtils::QueryMaxId(mediaLibraryRdb_, ANALYSIS_VIDEO_TABLE, ID);
142 }
143 
RestoreBatch(const std::unordered_map<int32_t,PhotoInfo> & photoInfoMap)144 void CloneRestoreClassify::RestoreBatch(const std::unordered_map<int32_t, PhotoInfo> &photoInfoMap)
145 {
146     int64_t startGet = MediaFileUtils::UTCTimeMilliSeconds();
147     cloneRestoreAnalysisTotal_.GetInfos(photoInfoMap);
148     int64_t startRestoreMaps = MediaFileUtils::UTCTimeMilliSeconds();
149     RestoreMaps();
150     int64_t startRestoreVideoMaps = MediaFileUtils::UTCTimeMilliSeconds();
151     RestoreVideoMaps();
152     int64_t startUpdate = MediaFileUtils::UTCTimeMilliSeconds();
153     cloneRestoreAnalysisTotal_.UpdateDatabase();
154     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
155     MEDIA_INFO_LOG("TimeCost: GetAnalysisTotalInfos: %{public}" PRId64 ", RestoreMaps: %{public}" PRId64
156         ", RestoreVideoMaps: %{public}" PRId64 ", UpdateDatabase: %{public}" PRId64,
157         startRestoreMaps - startGet, startRestoreVideoMaps - startRestoreMaps, startUpdate - startRestoreVideoMaps,
158         end - startUpdate);
159 }
160 
RestoreMaps()161 void CloneRestoreClassify::RestoreMaps()
162 {
163     bool cond = (mediaRdb_ == nullptr || mediaLibraryRdb_ == nullptr);
164     CHECK_AND_RETURN_LOG(!cond, "rdbStore is nullptr");
165 
166     MEDIA_INFO_LOG("restore classify albums start.");
167     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
168     std::vector<ClassifyCloneInfo> classifyInfos;
169     GetClassifyInfos(classifyInfos);
170     int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
171     InsertClassifyAlbums(classifyInfos);
172     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
173     MEDIA_INFO_LOG("TimeCost: GetClassifyInfos: %{public}" PRId64 ", InsertClassifyAlbums: %{public}" PRId64,
174         startInsert - start, end - startInsert);
175     restoreLabelTimeCost_ += end - start;
176     MEDIA_INFO_LOG("restore classify albums end.");
177 }
178 
RestoreVideoMaps()179 void CloneRestoreClassify::RestoreVideoMaps()
180 {
181     bool cond = (mediaRdb_ == nullptr || mediaLibraryRdb_ == nullptr);
182     CHECK_AND_RETURN_LOG(!cond, "rdbStore is nullptr");
183 
184     MEDIA_INFO_LOG("restore classify video albums start.");
185     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
186     std::vector<ClassifyVideoCloneInfo> classifyVideoInfos;
187     GetClassifyVideoInfos(classifyVideoInfos);
188     int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
189     InsertClassifyVideoAlbums(classifyVideoInfos);
190     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
191     MEDIA_INFO_LOG("TimeCost: GetClassifyVideoInfos: %{public}" PRId64 ", InsertClassifyVideoAlbums: %{public}" PRId64,
192         startInsert - start, end - startInsert);
193     restoreVideoLabelTimeCost_ += end - start;
194     MEDIA_INFO_LOG("restore classify video albums end.");
195 }
196 
GetClassifyInfos(std::vector<ClassifyCloneInfo> & classifyInfos)197 void CloneRestoreClassify::GetClassifyInfos(std::vector<ClassifyCloneInfo> &classifyInfos)
198 {
199     std::unordered_map<std::string, std::string> columns;
200     columns[FILE_ID] = FIELD_TYPE_INT;
201     bool hasRequiredColumns = CheckTableColumns(ANALYSIS_LABEL_TABLE, columns);
202     if (!hasRequiredColumns) {
203         MEDIA_ERR_LOG("The tab_analysis_label does not contain the required columns.");
204         ErrorInfo errorInfo(RestoreError::TABLE_LACK_OF_COLUMN, static_cast<int32_t>(columns.size()),
205             "", "The tab_analysis_label does not contain id or file_id");
206         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
207         return;
208     }
209 
210     std::stringstream querySql;
211     std::string placeHolders;
212     std::vector<NativeRdb::ValueObject> params;
213     cloneRestoreAnalysisTotal_.SetPlaceHoldersAndParamsByFileIdOld(placeHolders, params);
214     querySql << "SELECT * FROM " + ANALYSIS_LABEL_TABLE + " WHERE " + FILE_ID + " IN (" << placeHolders << ")";
215 
216     auto resultSet = BackupDatabaseUtils::QuerySql(mediaRdb_, querySql.str(), params);
217     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Query resultSql is null.");
218     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
219         ClassifyCloneInfo info;
220         GetClassifyInfo(info, resultSet);
221         classifyInfos.emplace_back(info);
222     }
223     resultSet->Close();
224     MEDIA_INFO_LOG("query tab_analysis_label nums: %{public}zu", classifyInfos.size());
225 }
226 
GetClassifyVideoInfos(std::vector<ClassifyVideoCloneInfo> & classifyVideoInfos)227 void CloneRestoreClassify::GetClassifyVideoInfos(std::vector<ClassifyVideoCloneInfo> &classifyVideoInfos)
228 {
229     std::unordered_map<std::string, std::string> columns;
230     columns[FILE_ID] = FIELD_TYPE_INT;
231     bool hasRequiredColumns = CheckTableColumns(ANALYSIS_VIDEO_TABLE, columns);
232     if (!hasRequiredColumns) {
233         MEDIA_ERR_LOG("The tab_analysis_video_label does not contain the required columns.");
234         ErrorInfo errorInfo(RestoreError::TABLE_LACK_OF_COLUMN, static_cast<int32_t>(columns.size()),
235             "", "The tab_analysis_video_label does not contain file_id");
236         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
237         return;
238     }
239 
240     std::stringstream querySql;
241     std::string placeHolders;
242     std::vector<NativeRdb::ValueObject> params;
243     cloneRestoreAnalysisTotal_.SetPlaceHoldersAndParamsByFileIdOld(placeHolders, params);
244     querySql << "SELECT * FROM " + ANALYSIS_VIDEO_TABLE + " WHERE " + FILE_ID + " IN (" << placeHolders << ")";
245 
246     auto resultSet = BackupDatabaseUtils::QuerySql(mediaRdb_, querySql.str(), params);
247     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Query resultSql is null.");
248     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
249         ClassifyVideoCloneInfo info;
250         GetClassifyVideoInfo(info, resultSet);
251         classifyVideoInfos.emplace_back(info);
252     }
253     resultSet->Close();
254     MEDIA_INFO_LOG("query tab_analysis_video_label nums: %{public}zu", classifyVideoInfos.size());
255 }
256 
DeduplicateClassifyInfos(std::vector<ClassifyCloneInfo> & infos)257 void CloneRestoreClassify::DeduplicateClassifyInfos(std::vector<ClassifyCloneInfo> &infos)
258 {
259     CHECK_AND_RETURN(!infos.empty());
260     std::unordered_set<int32_t> existingFileIds = GetExistingFileIds(ANALYSIS_LABEL_TABLE);
261     RemoveDuplicateClassifyInfos(infos, existingFileIds);
262     MEDIA_INFO_LOG("existing: %{public}zu, after deduplicate: %{public}zu", existingFileIds.size(), infos.size());
263 }
264 
DeduplicateClassifyVideoInfos(std::vector<ClassifyVideoCloneInfo> & infos)265 void CloneRestoreClassify::DeduplicateClassifyVideoInfos(std::vector<ClassifyVideoCloneInfo> &infos)
266 {
267     CHECK_AND_RETURN(!infos.empty());
268     std::unordered_set<int32_t> existingFileIds = GetExistingFileIds(ANALYSIS_VIDEO_TABLE);
269     RemoveDuplicateClassifyVideoInfos(infos, existingFileIds);
270     MEDIA_INFO_LOG("existing: %{public}zu, after deduplicate: %{public}zu", existingFileIds.size(), infos.size());
271 }
272 
GetExistingFileIds(const std::string & tableName)273 std::unordered_set<int32_t> CloneRestoreClassify::GetExistingFileIds(const std::string &tableName)
274 {
275     std::unordered_set<int32_t> existingFileIds;
276     std::stringstream querySql;
277     std::string placeHolders;
278     std::vector<NativeRdb::ValueObject> params;
279     cloneRestoreAnalysisTotal_.SetPlaceHoldersAndParamsByFileIdNew(placeHolders, params);
280     querySql << "SELECT file_id FROM " + tableName + " WHERE " + FILE_ID + " IN (" << placeHolders << ")";
281 
282     auto resultSet = BackupDatabaseUtils::QuerySql(mediaLibraryRdb_, querySql.str(), params);
283     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, existingFileIds, "Query resultSql is null.");
284     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
285         int32_t fileId = GetInt32Val("file_id", resultSet);
286         existingFileIds.insert(fileId);
287     }
288     resultSet->Close();
289     return existingFileIds;
290 }
291 
RemoveDuplicateClassifyInfos(std::vector<ClassifyCloneInfo> & infos,const std::unordered_set<int32_t> & existingFileIds)292 void CloneRestoreClassify::RemoveDuplicateClassifyInfos(std::vector<ClassifyCloneInfo> &infos,
293     const std::unordered_set<int32_t> &existingFileIds)
294 {
295     infos.erase(std::remove_if(infos.begin(), infos.end(), [&](ClassifyCloneInfo &info) {
296         if (!info.fileIdOld.has_value()) {
297             return true;
298         }
299 
300         size_t index = cloneRestoreAnalysisTotal_.FindIndexByFileIdOld(info.fileIdOld.value());
301         if (index == std::string::npos) {
302             return true;
303         }
304 
305         int32_t fileIdNew = cloneRestoreAnalysisTotal_.GetFileIdNewByIndex(index);
306         info.fileIdNew = fileIdNew;
307         if (existingFileIds.count(fileIdNew) == 0) {
308             return false;
309         }
310         cloneRestoreAnalysisTotal_.UpdateRestoreStatusAsDuplicateByIndex(index);
311         duplicateLabelCnt_++;
312         return true;
313     }),
314         infos.end());
315 }
316 
RemoveDuplicateClassifyVideoInfos(std::vector<ClassifyVideoCloneInfo> & infos,const std::unordered_set<int32_t> & existingFileIds)317 void CloneRestoreClassify::RemoveDuplicateClassifyVideoInfos(std::vector<ClassifyVideoCloneInfo> &infos,
318     const std::unordered_set<int32_t> &existingFileIds)
319 {
320     infos.erase(std::remove_if(infos.begin(), infos.end(), [&](ClassifyVideoCloneInfo &info) {
321         if (!info.fileIdOld.has_value()) {
322             return true;
323         }
324 
325         size_t index = cloneRestoreAnalysisTotal_.FindIndexByFileIdOld(info.fileIdOld.value());
326         if (index == std::string::npos) {
327             return true;
328         }
329 
330         int32_t fileIdNew = cloneRestoreAnalysisTotal_.GetFileIdNewByIndex(index);
331         info.fileIdNew = fileIdNew;
332         if (existingFileIds.count(fileIdNew) == 0) {
333             return false;
334         }
335         cloneRestoreAnalysisTotal_.UpdateRestoreStatusAsDuplicateByIndex(index);
336         duplicateVideoLabelCnt_++;
337         return true;
338     }),
339         infos.end());
340 }
341 
InsertClassifyAlbums(std::vector<ClassifyCloneInfo> & classifyInfos)342 void CloneRestoreClassify::InsertClassifyAlbums(std::vector<ClassifyCloneInfo> &classifyInfos)
343 {
344     DeduplicateClassifyInfos(classifyInfos);
345     CHECK_AND_RETURN(!classifyInfos.empty());
346 
347     std::unordered_set<std::string> intersection = GetCommonColumns(ANALYSIS_LABEL_TABLE);
348     size_t offset = 0;
349     do {
350         std::vector<NativeRdb::ValuesBucket> values;
351         for (size_t index = 0; index < PAGE_SIZE && index + offset < classifyInfos.size(); index++) {
352             CHECK_AND_CONTINUE(classifyInfos[index + offset].fileIdNew.has_value());
353             NativeRdb::ValuesBucket value;
354             GetMapInsertValue(value, classifyInfos[index + offset], intersection);
355             values.emplace_back(value);
356         }
357         MEDIA_INFO_LOG("Insert classify albums, values size: %{public}zu", values.size());
358         int64_t rowNum = 0;
359         int32_t errCode = BatchInsertWithRetry(ANALYSIS_LABEL_TABLE, values, rowNum);
360         if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
361             int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
362             MEDIA_ERR_LOG("Insert classify albums fail, num: %{public}" PRId64, failNums);
363             ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(values.size()),
364                 "errCode: " + std::to_string(errCode), "Insert classify albums fail");
365             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
366             cloneRestoreAnalysisTotal_.UpdateRestoreStatusAsFailed();
367             failInsertLabelCnt_ += failNums;
368         }
369         offset += PAGE_SIZE;
370         successInsertLabelCnt_ += rowNum;
371     } while (offset < classifyInfos.size());
372 }
373 
InsertClassifyVideoAlbums(std::vector<ClassifyVideoCloneInfo> & classifyVideoInfos)374 void CloneRestoreClassify::InsertClassifyVideoAlbums(std::vector<ClassifyVideoCloneInfo> &classifyVideoInfos)
375 {
376     DeduplicateClassifyVideoInfos(classifyVideoInfos);
377     CHECK_AND_RETURN(!classifyVideoInfos.empty());
378 
379     std::unordered_set<std::string> intersection = GetCommonColumns(ANALYSIS_VIDEO_TABLE);
380     size_t offset = 0;
381     do {
382         std::vector<NativeRdb::ValuesBucket> values;
383         for (size_t index = 0; index < PAGE_SIZE && index + offset < classifyVideoInfos.size(); index++) {
384             CHECK_AND_CONTINUE(classifyVideoInfos[index + offset].fileIdNew.has_value());
385             NativeRdb::ValuesBucket value;
386             GetVideoMapInsertValue(value, classifyVideoInfos[index + offset], intersection);
387             values.emplace_back(value);
388         }
389         MEDIA_INFO_LOG("Insert classify video albums, values size: %{public}zu", values.size());
390         int64_t rowNum = 0;
391         int32_t errCode = BatchInsertWithRetry(ANALYSIS_VIDEO_TABLE, values, rowNum);
392         if (errCode != E_OK || rowNum != static_cast<int64_t>(values.size())) {
393             int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
394             MEDIA_ERR_LOG("Insert classify video albums fail, num: %{public}" PRId64, failNums);
395             ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(values.size()),
396                 "errCode: " + std::to_string(errCode), "Insert classify video albums fail");
397             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
398             cloneRestoreAnalysisTotal_.UpdateRestoreStatusAsFailed();
399             failInsertVideoLabelCnt_ += failNums;
400         }
401         offset += PAGE_SIZE;
402         successInsertVideoLabelCnt_ += rowNum;
403     } while (offset < classifyVideoInfos.size());
404 }
405 
GetClassifyInfo(ClassifyCloneInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)406 void CloneRestoreClassify::GetClassifyInfo(ClassifyCloneInfo &info,
407     std::shared_ptr<NativeRdb::ResultSet> resultSet)
408 {
409     info.id = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ID);
410     info.fileIdOld = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, FILE_ID);
411     info.categoryId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, CATEGORY_ID);
412     info.subLabel = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SUB_LABEL);
413     info.prob = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, PROB);
414     info.feature = BackupDatabaseUtils::GetOptionalValue<std::vector<uint8_t>>(resultSet, FEATURE);
415     info.simResult = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SIM_RESULT);
416     info.labelVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, LABEL_VERSION);
417     info.saliencySubProb = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SALIENCY_SUB_PROB);
418     info.analysisVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_VERSION);
419     info.captionResult = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, CAPTION_RESULT);
420     info.captionVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, CAPTION_VERSION);
421 }
422 
GetMapInsertValue(NativeRdb::ValuesBucket & value,ClassifyCloneInfo info,const std::unordered_set<std::string> & intersection)423 void CloneRestoreClassify::GetMapInsertValue(NativeRdb::ValuesBucket &value, ClassifyCloneInfo info,
424     const std::unordered_set<std::string> &intersection)
425 {
426     PutIfInIntersection(value, FILE_ID, info.fileIdNew, intersection);
427     PutIfInIntersection(value, CATEGORY_ID, info.categoryId, intersection);
428     PutIfInIntersection(value, SUB_LABEL, info.subLabel, intersection);
429     PutIfInIntersection(value, PROB, info.prob, intersection);
430     PutIfInIntersection(value, FEATURE, info.feature, intersection);
431     PutIfInIntersection(value, SIM_RESULT, info.simResult, intersection);
432     PutIfInIntersection(value, LABEL_VERSION, info.labelVersion, intersection);
433     PutIfInIntersection(value, SALIENCY_SUB_PROB, info.saliencySubProb, intersection);
434     PutIfInIntersection(value, ANALYSIS_VERSION, info.analysisVersion, intersection);
435     PutIfInIntersection(value, CAPTION_RESULT, info.captionResult, intersection);
436     PutIfInIntersection(value, CAPTION_VERSION, info.captionVersion, intersection);
437 }
438 
GetClassifyVideoInfo(ClassifyVideoCloneInfo & info,std::shared_ptr<NativeRdb::ResultSet> resultSet)439 void CloneRestoreClassify::GetClassifyVideoInfo(ClassifyVideoCloneInfo &info,
440     std::shared_ptr<NativeRdb::ResultSet> resultSet)
441 {
442     info.id = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ID);
443     info.fileIdOld = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, FILE_ID);
444     info.categoryId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, CATEGORY_ID);
445     info.confidenceProbability = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, CONFIDENCE_PROBABILITY);
446     info.subCategory = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SUB_CATEGORY);
447     info.subConfidenceProb = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SUB_CONFIDENCE_PROB);
448     info.subLabel = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SUB_LABEL);
449     info.subLabelProb = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SUB_LABEL_PROB);
450     info.subLabelType = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, SUB_LABEL_TYPE);
451     info.tracks = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, TRACKS);
452     info.videoPartFeature = BackupDatabaseUtils::GetOptionalValue<std::vector<uint8_t>>(resultSet, VIDEO_PART_FEATURE);
453     info.filterTag = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FILTER_TAG);
454     info.algoVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ALGO_VERSION);
455     info.analysisVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_VERSION);
456     info.triggerGenerateThumbnail = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
457         TRIGGER_GENERATE_THUMBNAIL);
458 }
459 
GetVideoMapInsertValue(NativeRdb::ValuesBucket & value,ClassifyVideoCloneInfo info,const std::unordered_set<std::string> & intersection)460 void CloneRestoreClassify::GetVideoMapInsertValue(NativeRdb::ValuesBucket &value, ClassifyVideoCloneInfo info,
461     const std::unordered_set<std::string> &intersection)
462 {
463     PutIfInIntersection(value, FILE_ID, info.fileIdNew, intersection);
464     PutIfInIntersection(value, CATEGORY_ID, info.categoryId, intersection);
465     PutIfInIntersection(value, CONFIDENCE_PROBABILITY, info.confidenceProbability, intersection);
466     PutIfInIntersection(value, SUB_CATEGORY, info.subCategory, intersection);
467     PutIfInIntersection(value, SUB_CONFIDENCE_PROB, info.subConfidenceProb, intersection);
468     PutIfInIntersection(value, SUB_LABEL, info.subLabel, intersection);
469     PutIfInIntersection(value, SUB_LABEL_PROB, info.subLabelProb, intersection);
470     PutIfInIntersection(value, SUB_LABEL_TYPE, info.subLabelType, intersection);
471     PutIfInIntersection(value, TRACKS, info.tracks, intersection);
472     PutIfInIntersection(value, VIDEO_PART_FEATURE, info.videoPartFeature, intersection);
473     PutIfInIntersection(value, FILTER_TAG, info.filterTag, intersection);
474     PutIfInIntersection(value, ALGO_VERSION, info.algoVersion, intersection);
475     PutIfInIntersection(value, ANALYSIS_VERSION, info.analysisVersion, intersection);
476     PutIfInIntersection(value, TRIGGER_GENERATE_THUMBNAIL, info.triggerGenerateThumbnail, intersection);
477 }
478 
CheckTableColumns(const std::string & tableName,std::unordered_map<std::string,std::string> & columns)479 bool CloneRestoreClassify::CheckTableColumns(const std::string& tableName,
480     std::unordered_map<std::string, std::string>& columns)
481 {
482     std::unordered_map<std::string, std::string> srcColumnInfoMap =
483         BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_, tableName);
484     for (auto it = columns.begin(); it != columns.end(); ++it) {
485         CHECK_AND_CONTINUE(srcColumnInfoMap.find(it->first) == srcColumnInfoMap.end());
486         return false;
487     }
488     return true;
489 }
490 
GetCommonColumns(const string & tableName)491 std::unordered_set<std::string> CloneRestoreClassify::GetCommonColumns(const string &tableName)
492 {
493     std::unordered_map<std::string, std::string> srcColumnInfoMap =
494         BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_, tableName);
495     std::unordered_map<std::string, std::string> dstColumnInfoMap =
496         BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_, tableName);
497     std::unordered_set<std::string> result;
498     auto comparedColumns = GetValueFromMap(COMPARED_COLUMNS_MAP, tableName);
499     for (auto it = dstColumnInfoMap.begin(); it != dstColumnInfoMap.end(); ++it) {
500         bool cond = srcColumnInfoMap.find(it->first) != srcColumnInfoMap.end() && comparedColumns.count(it->first) > 0;
501         CHECK_AND_EXECUTE(!cond, result.insert(it->first));
502     }
503     return result;
504 }
505 
BatchInsertWithRetry(const std::string & tableName,std::vector<NativeRdb::ValuesBucket> & values,int64_t & rowNum)506 int32_t CloneRestoreClassify::BatchInsertWithRetry(const std::string &tableName,
507     std::vector<NativeRdb::ValuesBucket> &values, int64_t &rowNum)
508 {
509     CHECK_AND_RETURN_RET(!values.empty(), E_OK);
510     int32_t errCode = E_ERR;
511     TransactionOperations trans{ __func__ };
512     trans.SetBackupRdbStore(mediaLibraryRdb_);
513     std::function<int(void)> func = [&]()->int {
514         errCode = trans.BatchInsert(rowNum, tableName, values);
515         CHECK_AND_PRINT_LOG(errCode == E_OK, "InsertSql failed, errCode: %{public}d, rowNum: %{public}ld.",
516             errCode, (long)rowNum);
517         return errCode;
518     };
519     errCode = trans.RetryTrans(func, true);
520     CHECK_AND_PRINT_LOG(errCode == E_OK, "BatchInsertWithRetry: tans finish fail!, ret:%{public}d", errCode);
521     return errCode;
522 }
523 
ReportRestoreTask()524 void CloneRestoreClassify::ReportRestoreTask()
525 {
526     ReportRestoreTaskOfTotal();
527     ReportRestoreTaskofImage();
528     ReportRestoreTaskofVideo();
529 }
530 
ReportRestoreTaskOfTotal()531 void CloneRestoreClassify::ReportRestoreTaskOfTotal()
532 {
533     RestoreTaskInfo info;
534     cloneRestoreAnalysisTotal_.SetRestoreTaskInfo(info);
535     info.type = "CLONE_RESTORE_CLASSIFY_TOTAL";
536     info.errorCode = std::to_string(CLASSIFY_STATUS_SUCCESS);
537     info.errorInfo = "timeCost: " + std::to_string(restoreTimeCost_);
538     UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).Report(info);
539 }
540 
ReportRestoreTaskofImage()541 void CloneRestoreClassify::ReportRestoreTaskofImage()
542 {
543     RestoreTaskInfo info;
544     info.type = "CLONE_RESTORE_CLASSIFY_IMAGE";
545     info.errorCode = std::to_string(CLASSIFY_STATUS_SUCCESS);
546     info.errorInfo =
547         "max_id: " + std::to_string(maxIdOfLabel_) +
548         ", timeCost: " + std::to_string(restoreLabelTimeCost_);
549     info.successCount = successInsertLabelCnt_;
550     info.failedCount = failInsertLabelCnt_;
551     info.duplicateCount = duplicateLabelCnt_;
552     UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).Report(info);
553 }
554 
ReportRestoreTaskofVideo()555 void CloneRestoreClassify::ReportRestoreTaskofVideo()
556 {
557     RestoreTaskInfo info;
558     info.type = "CLONE_RESTORE_CLASSIFY_VIDEO";
559     info.errorCode = std::to_string(CLASSIFY_STATUS_SUCCESS);
560     info.errorInfo =
561         "max_id: " + std::to_string(maxIdOfVideoLabel_) +
562         ", timeCost: " + std::to_string(restoreVideoLabelTimeCost_);
563     info.successCount = successInsertVideoLabelCnt_;
564     info.failedCount = failInsertVideoLabelCnt_;
565     info.duplicateCount = duplicateVideoLabelCnt_;
566     UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).Report(info);
567 }
568 
AddSpecialAlbum()569 void CloneRestoreClassify::AddSpecialAlbum()
570 {
571     MEDIA_INFO_LOG("AddSpecialAlbum start");
572     int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
573     AddSelfieAlbum();
574     AddUserCommentAlbum();
575     int64_t endTime = MediaFileUtils::UTCTimeMilliSeconds();
576     MEDIA_INFO_LOG("AddSpecialAlbum end, cost: %{public}" PRId64,
577         endTime - startTime);
578 }
579 
AddSelfieAlbum()580 void CloneRestoreClassify::AddSelfieAlbum()
581 {
582     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "AddSelfieAlbum failed, rdbStore is nullptr");
583     std::string selfieAlbum = std::to_string(static_cast<int32_t>(AggregateType::SELFIE_ALBUM));
584     DataTransfer::MediaLibraryDbUpgrade medialibraryDbUpgrade;
585     bool isExist =  medialibraryDbUpgrade.CheckClassifyAlbumExist(selfieAlbum, *this->mediaLibraryRdb_);
586     CHECK_AND_RETURN_INFO_LOG(!isExist, "SelfieAlbum already exist.");
587     std::string querySql = "SELECT count(1) AS count FROM Photos WHERE front_camera = ?;";
588     std::vector<NativeRdb::ValueObject> params;
589     params.push_back(FRONT_CAMERA);
590     auto resultSet = mediaLibraryRdb_->QuerySql(querySql, params);
591     CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr");
592     if (resultSet->GoToNextRow() == NativeRdb::E_OK && GetInt32Val("count", resultSet) > 0) {
593         resultSet->Close();
594         int32_t ret = medialibraryDbUpgrade.CreateClassifyAlbum(selfieAlbum, *this->mediaLibraryRdb_);
595         CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK, "AddSelfieAlbum failed");
596         MEDIA_INFO_LOG("AddSelfieAlbum success");
597         return;
598     }
599     resultSet->Close();
600     MEDIA_INFO_LOG("not meet the criteria for AddSelfieAlbum");
601 }
602 
AddUserCommentAlbum()603 void CloneRestoreClassify::AddUserCommentAlbum()
604 {
605     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "AddUserCommentAlbum failed, rdbStore is nullptr");
606     std::string userCommentAlbum = std::to_string(static_cast<int32_t>(AggregateType::USER_COMMENT_ALBUM));
607     DataTransfer::MediaLibraryDbUpgrade medialibraryDbUpgrade;
608     bool isExist =  medialibraryDbUpgrade.CheckClassifyAlbumExist(userCommentAlbum, *this->mediaLibraryRdb_);
609     CHECK_AND_RETURN_INFO_LOG(!isExist, "UserCommentAlbum already exist.");
610     std::string querySql = "SELECT count(1) AS count FROM Photos "
611         "WHERE user_comment IS NOT NULL AND user_comment != '';";
612     auto resultSet = mediaLibraryRdb_->QuerySql(querySql);
613     CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr");
614     if (resultSet->GoToNextRow() == NativeRdb::E_OK && GetInt32Val("count", resultSet) > 0) {
615         resultSet->Close();
616         int32_t ret = medialibraryDbUpgrade.CreateClassifyAlbum(userCommentAlbum, *this->mediaLibraryRdb_);
617         CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK, "AddUserCommentAlbum failed");
618         MEDIA_INFO_LOG("AddUserCommentAlbum success");
619         return;
620     }
621     resultSet->Close();
622     MEDIA_INFO_LOG("not meet the criteria for AddUserCommentAlbum");
623 }
624 }