• 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 
16 #define MLOG_TAG "AccurateRefresh::AccurateRefreshDataManager"
17 
18 #include "media_file_utils.h"
19 #include "accurate_refresh_data_manager.h"
20 #include "medialibrary_unistore_manager.h"
21 #include "accurate_debug_log.h"
22 #include "photo_asset_change_info.h"
23 #include "album_change_info.h"
24 #include "medialibrary_tracer.h"
25 
26 using namespace std;
27 using namespace OHOS::NativeRdb;
28 
29 namespace OHOS {
30 namespace Media::AccurateRefresh {
31 
32 template <typename ChangeInfo, typename ChangeData>
Init(const AbsRdbPredicates & predicates)33 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::Init(const AbsRdbPredicates &predicates)
34 {
35     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
36     PendingInfo pendingInfo(AlbumAccurateRefreshManager::GetInstance().GetCurrentRefreshTag());
37     MediaLibraryTracer tracer;
38     tracer.Start("AccurateRefreshDataManager::Init predicates");
39     auto initDatas = GetInfosByPredicates(predicates);
40     if (initDatas.empty()) {
41         MEDIA_WARN_LOG("init data empty");
42         return ACCURATE_REFRESH_INIT_EMPTY;
43     }
44     return InsertInitChangeInfos(initDatas, pendingInfo);
45 }
46 
47 template <typename ChangeInfo, typename ChangeData>
Init(const string sql,const vector<ValueObject> bindArgs)48 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::Init(const string sql, const vector<ValueObject> bindArgs)
49 {
50     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
51     CHECK_AND_RETURN_RET_LOG(!sql.empty(), ACCURATE_REFRESH_INPUT_PARA_ERR, "input sql empty");
52     PendingInfo pendingInfo(AlbumAccurateRefreshManager::GetInstance().GetCurrentRefreshTag());
53     MediaLibraryTracer tracer;
54     tracer.Start("AccurateRefreshDataManager::Init sql");
55     shared_ptr<ResultSet> resultSet;
56     if (CanTransOperate()) {
57         resultSet = trans_->QueryByStep(sql, bindArgs);
58     } else {
59         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
60         CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, ACCURATE_REFRESH_RDB_NULL, "rdbStore null");
61         resultSet = rdbStore->QueryByStep(sql, bindArgs);
62     }
63     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, ACCURATE_REFRESH_RDB_NULL, "resultSet null");
64 
65     auto initDatas = GetInfosByResult(resultSet);
66     resultSet->Close();
67     if (initDatas.empty()) {
68         MEDIA_WARN_LOG("initDatas empty");
69         return ACCURATE_REFRESH_INIT_EMPTY;
70     }
71 
72     return InsertInitChangeInfos(initDatas, pendingInfo);
73 }
74 
75 template <typename ChangeInfo, typename ChangeData>
Init(const vector<int32_t> & keys)76 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::Init(const vector<int32_t> &keys)
77 {
78     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(keys.size()), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
79     CHECK_AND_RETURN_RET_LOG(!keys.empty(), ACCURATE_REFRESH_INPUT_PARA_ERR, "input keys empty");
80     PendingInfo pendingInfo(AlbumAccurateRefreshManager::GetInstance().GetCurrentRefreshTag());
81     MediaLibraryTracer tracer;
82     tracer.Start("AccurateRefreshDataManager::Init keys");
83     auto initDatas = GetInfoByKeys(keys);
84     if (initDatas.empty()) {
85         MEDIA_WARN_LOG("initDatas empty");
86         return ACCURATE_REFRESH_INPUT_PARA_ERR;
87     }
88 
89     return InsertInitChangeInfos(initDatas, pendingInfo);
90 }
91 
92 template <typename ChangeInfo, typename ChangeData>
UpdateModifiedDatasInner(const vector<int32_t> & keys,RdbOperation operation,PendingInfo & pendingInfo)93 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::UpdateModifiedDatasInner(const vector<int32_t> &keys,
94     RdbOperation operation, PendingInfo &pendingInfo)
95 {
96     if (keys.empty() || operation == RDB_OPERATION_UNDEFINED) {
97         MEDIA_WARN_LOG("input keys empty or operation error");
98         return ACCURATE_REFRESH_INPUT_PARA_ERR;
99     }
100     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(keys.size()), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
101     auto ret = ACCURATE_REFRESH_RET_OK;
102     switch (operation) {
103         case RDB_OPERATION_REMOVE:
104             ret = UpdateModifiedDatasForRemove(keys, pendingInfo);
105             break;
106 
107         case RDB_OPERATION_ADD:
108             ret = UpdateModifiedDatasForAdd(keys, pendingInfo);
109             break;
110 
111         case RDB_OPERATION_UPDATE:
112             ret = UpdateModifiedDatasForUpdate(keys, pendingInfo);
113             break;
114 
115         default:
116             return ACCURATE_REFRESH_INPUT_PARA_ERR;
117     }
118     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(true), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
119     return ret;
120 }
121 
122 template <typename ChangeInfo, typename ChangeData>
InsertInitChangeInfos(const vector<ChangeInfo> & changeInfos,PendingInfo pendingInfo)123 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::InsertInitChangeInfos(
124     const vector<ChangeInfo> &changeInfos, PendingInfo pendingInfo)
125 {
126     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(changeInfos.size()), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
127     for (auto const &changeInfo : changeInfos) {
128         auto key = GetChangeInfoKey(changeInfo);
129         if (changeDatas_.find(key) != changeDatas_.end()) {
130             // 数据重复:打印异常,不替换已有数据继续执行
131             MEDIA_INFO_LOG("operate duplicate init key: %{public}d", key);
132             continue;
133         }
134         ChangeData changeData;
135         changeData.infoBeforeChange_ = changeInfo;
136         PostInsertBeforeData(changeData, pendingInfo);
137         changeDatas_.insert_or_assign(key, changeData); // 插入新值或者替换已有
138     }
139     CHECK_AND_RETURN_RET_WARN_LOG(!CheckIsExceed(true), ACCURATE_REFRESH_DATA_EXCEED, "data size exceed");
140     return ACCURATE_REFRESH_RET_OK;
141 }
142 
143 template <typename ChangeInfo, typename ChangeData>
CheckAndUpdateOperation(RdbOperation & newOperation,RdbOperation oldOperation)144 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::CheckAndUpdateOperation(RdbOperation &newOperation,
145     RdbOperation oldOperation)
146 {
147     if (newOperation == RDB_OPERATION_UNDEFINED) {
148         MEDIA_WARN_LOG("new operation undefined");
149         return ACCURATE_REFRESH_INPUT_PARA_ERR;
150     }
151 
152     if (oldOperation == RDB_OPERATION_UNDEFINED) {
153         return ACCURATE_REFRESH_RET_OK;
154     }
155 
156     // 增改场景支持,还是增
157     if (oldOperation == RDB_OPERATION_ADD && newOperation == RDB_OPERATION_UPDATE) {
158         newOperation = RDB_OPERATION_ADD;
159         return ACCURATE_REFRESH_RET_OK;
160     }
161 
162     // 改改场景支持
163     if (oldOperation == RDB_OPERATION_UPDATE && newOperation == RDB_OPERATION_UPDATE) {
164         return ACCURATE_REFRESH_RET_OK;
165     }
166 
167     MEDIA_WARN_LOG("duplicate operation, oldOperation:%{public}d, newOperation:%{public}d",
168         static_cast<int32_t>(oldOperation), static_cast<int32_t>(newOperation));
169     return ACCURATE_REFRESH_RET_OK;
170 }
171 
172 template <typename ChangeInfo, typename ChangeData>
UpdateModifiedDatasForRemove(const vector<int32_t> & keys,PendingInfo & pendingInfo)173 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::UpdateModifiedDatasForRemove(const vector<int32_t> &keys,
174     PendingInfo &pendingInfo)
175 {
176     ACCURATE_DEBUG("keys size: %{public}zu", keys.size());
177     auto timestamp = MediaFileUtils::UTCTimeMilliSeconds();
178     pendingInfo.end_ = AlbumAccurateRefreshManager::GetInstance().GetCurrentRefreshTag();
179     for (auto key : keys) {
180         auto iter = changeDatas_.find(key);
181         if (iter == changeDatas_.end()) {
182             MEDIA_WARN_LOG("not init info for remove.");
183             return ACCURATE_REFRESH_MODIFIED_NO_INIT;
184         }
185         ChangeData &changeData = iter->second;
186         RdbOperation operation = RDB_OPERATION_REMOVE;
187         auto ret = CheckAndUpdateOperation(operation, changeData.operation_);
188         if (ret != ACCURATE_REFRESH_RET_OK) {
189             return ret;
190         }
191         changeData.operation_ = operation;
192         changeData.isDelete_ = true;
193         changeData.version_ = timestamp;
194         changeData.infoAfterChange_ = ChangeInfo();
195         PostInsertAfterData(changeData, pendingInfo);
196         ACCURATE_INFO("[remove] info: %{public}s", changeData.infoBeforeChange_.ToString(true).c_str());
197     }
198     return ACCURATE_REFRESH_RET_OK;
199 }
200 
201 template <typename ChangeInfo, typename ChangeData>
UpdateModifiedDatasForUpdate(const vector<int32_t> & keys,PendingInfo & pendingInfo)202 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::UpdateModifiedDatasForUpdate(const vector<int32_t> &keys,
203     PendingInfo &pendingInfo)
204 {
205     MediaLibraryTracer tracer;
206     tracer.Start("AccurateRefreshDataManager::UpdateModifiedDatasForUpdate");
207     auto &modifiedKeys = keys;
208     auto modifiedDatas = GetInfoByKeys(modifiedKeys);
209     if (modifiedDatas.empty()) {
210         MEDIA_WARN_LOG("modifiedDatas empty");
211         return ACCURATE_REFRESH_MODIFY_EMPTY;
212     }
213     auto timestamp = MediaFileUtils::UTCTimeMilliSeconds();
214     pendingInfo.end_ = AlbumAccurateRefreshManager::GetInstance().GetCurrentRefreshTag();
215     for (auto modifiedInfo : modifiedDatas) {
216         // 找到key
217         auto key = GetChangeInfoKey(modifiedInfo);
218         // 根据key值,找changeData
219         auto iter = changeDatas_.find(key);
220         if (iter == changeDatas_.end()) {
221             MEDIA_WARN_LOG("data no init.");
222             isForRecheck_ = true;
223             return ACCURATE_REFRESH_MODIFIED_NO_INIT;
224         }
225         ChangeData &changeData = iter->second;
226 
227         // 更新operation
228         RdbOperation operation = RDB_OPERATION_UPDATE;
229         auto ret = CheckAndUpdateOperation(operation, changeData.operation_);
230         if (ret != ACCURATE_REFRESH_RET_OK) {
231             MEDIA_WARN_LOG("check operation wrong.");
232             return ret;
233         }
234         changeData.operation_ = operation;
235         changeData.version_ = timestamp;
236 
237         // 更新infoAfterChange_
238         if (IsValidChangeInfo(changeData.infoAfterChange_)) {
239             MEDIA_INFO_LOG("operate duplicate modified key: %{public}d", key);
240         }
241         changeData.infoAfterChange_ = modifiedInfo;
242         PostInsertAfterData(changeData, pendingInfo);
243         ACCURATE_INFO("operation_: %{public}d isDelete: %{public}d", changeData.operation_, changeData.isDelete_);
244         ACCURATE_INFO("[update] info before: %{public}s", changeData.infoBeforeChange_.ToString(true).c_str());
245         ACCURATE_INFO("change: %{public}s",
246             changeData.infoBeforeChange_.GetDataDiff(changeData.infoAfterChange_).c_str());
247     }
248 
249     return ACCURATE_REFRESH_RET_OK;
250 }
251 
252 template <typename ChangeInfo, typename ChangeData>
UpdateModifiedDatasForAdd(const vector<int32_t> & keys,PendingInfo & pendingInfo)253 int32_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::UpdateModifiedDatasForAdd(const vector<int32_t> &keys,
254     PendingInfo &pendingInfo)
255 {
256     MediaLibraryTracer tracer;
257     tracer.Start("AccurateRefreshDataManager::UpdateModifiedDatasForAdd");
258     ACCURATE_DEBUG("keys size: %{public}zu", keys.size());
259     auto modifiedDatas = GetInfoByKeys(keys);
260     if (modifiedDatas.empty()) {
261         MEDIA_WARN_LOG("modifiedDatas empty");
262         return ACCURATE_REFRESH_MODIFY_EMPTY;
263     }
264     auto timestamp = MediaFileUtils::UTCTimeMilliSeconds();
265     pendingInfo.end_ = AlbumAccurateRefreshManager::GetInstance().GetCurrentRefreshTag();
266     for (auto &modifiedInfo : modifiedDatas) {
267         // 找到key
268         auto key = GetChangeInfoKey(modifiedInfo);
269         // 根据key值,找changeData
270         auto iter = changeDatas_.find(key);
271         if (iter != changeDatas_.end()) {
272             MEDIA_WARN_LOG("add already info, key: %{public}d", key);
273             return ACCURATE_REFRESH_MODIFIED_ADD_NO_MATCH;
274         }
275 
276         // 更新数据
277         ChangeData changeData;
278         changeData.infoAfterChange_ = modifiedInfo;
279         changeData.operation_ = RDB_OPERATION_ADD;
280         changeData.version_ = timestamp;
281         PostInsertAfterData(changeData, pendingInfo, true);
282         changeDatas_.emplace(key, changeData);
283         ACCURATE_INFO("[add] info: %{public}s", changeData.infoAfterChange_.ToString(true).c_str());
284     }
285 
286     return ACCURATE_REFRESH_RET_OK;
287 }
288 
289 template <typename ChangeInfo, typename ChangeData>
IsValidChangeInfo(const ChangeInfo & changeInfo)290 bool AccurateRefreshDataManager<ChangeInfo, ChangeData>::IsValidChangeInfo(const ChangeInfo &changeInfo)
291 {
292     return GetChangeInfoKey(changeInfo) != INVALID_INT32_VALUE;
293 }
294 
295 template <typename ChangeInfo, typename ChangeData>
GetChangeDatas(bool isCheckUpdate)296 vector<ChangeData> AccurateRefreshDataManager<ChangeInfo, ChangeData>::GetChangeDatas(bool isCheckUpdate)
297 {
298     vector<ChangeData> changeDatas;
299     for (auto &data: changeDatas_) {
300         if (isCheckUpdate) {
301             CheckUpdateDataForMultiThread(data.second);
302         }
303         changeDatas.push_back(data.second);
304     }
305     return changeDatas;
306 }
307 
308 template <typename ChangeInfo, typename ChangeData>
SetTransaction(std::shared_ptr<TransactionOperations> trans)309 void AccurateRefreshDataManager<ChangeInfo, ChangeData>::SetTransaction(std::shared_ptr<TransactionOperations> trans)
310 {
311     trans_ = trans;
312 }
313 
314 template <typename ChangeInfo, typename ChangeData>
GetCurrentDataLength()315 size_t AccurateRefreshDataManager<ChangeInfo, ChangeData>::GetCurrentDataLength()
316 {
317     return changeDatas_.size();
318 }
319 
320 template <typename ChangeInfo, typename ChangeData>
CheckIsExceed(bool isLengthChanged)321 bool AccurateRefreshDataManager<ChangeInfo, ChangeData>::CheckIsExceed(bool isLengthChanged)
322 {
323     if (!isLengthChanged) {
324         return isExceed_;
325     }
326 
327     if (isExceed_) {
328         return true;
329     }
330 
331     isExceed_ = GetCurrentDataLength() >= MAX_DATA_LENGTH;
332     if (isExceed_) {
333         changeDatas_.clear();
334     }
335     return isExceed_;
336 }
337 
338 template <typename ChangeInfo, typename ChangeData>
CheckIsExceed(size_t length)339 bool AccurateRefreshDataManager<ChangeInfo, ChangeData>::CheckIsExceed(size_t length)
340 {
341     if (length >= MAX_DATA_LENGTH) {
342         isExceed_ = true;
343         changeDatas_.clear();
344     }
345     return isExceed_;
346 }
347 
348 template <typename ChangeInfo, typename ChangeData>
CheckIsForRecheck()349 bool AccurateRefreshDataManager<ChangeInfo, ChangeData>::CheckIsForRecheck()
350 {
351     return isForRecheck_ || CheckIsExceed();
352 }
353 
354 template <typename ChangeInfo, typename ChangeData>
CanTransOperate()355 bool AccurateRefreshDataManager<ChangeInfo, ChangeData>::CanTransOperate()
356 {
357     return trans_ != nullptr && trans_->GetIsOperate();
358 }
359 
360 template class AccurateRefreshDataManager<PhotoAssetChangeInfo, PhotoAssetChangeData>;
361 template class AccurateRefreshDataManager<AlbumChangeInfo, AlbumChangeData>;
362 
363 } // namespace Media
364 } // namespace OHOS