• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "RdbStore"
16 
17 #include "medialibrary_rdbstore.h"
18 
19 #include "media_log.h"
20 #include "medialibrary_device.h"
21 #include "medialibrary_errno.h"
22 #include "medialibrary_sync_table.h"
23 #include "sqlite_database_utils.h"
24 using namespace std;
25 using namespace OHOS::NativeRdb;
26 
27 namespace OHOS {
28 namespace Media {
MediaLibraryRdbStore(const shared_ptr<OHOS::AbilityRuntime::Context> & context)29 MediaLibraryRdbStore::MediaLibraryRdbStore(const shared_ptr<OHOS::AbilityRuntime::Context> &context)
30 {
31     if (context == nullptr) {
32         MEDIA_ERR_LOG("Failed to get context");
33         return;
34     }
35     string databaseDir = context->GetDatabaseDir();
36     string name = MEDIA_DATA_ABILITY_DB_NAME;
37     int32_t errCode = 0;
38     std::string realPath = SqliteDatabaseUtils::GetDefaultDatabasePath(databaseDir, name, errCode);
39     config_.SetName(name);
40     config_.SetPath(realPath);
41     config_.SetBundleName(context->GetBundleName());
42     config_.SetArea(context->GetArea());
43     MEDIA_INFO_LOG("rdb config: name: %{private}s realPath: %{private}s bundleName: %{private}s area: %{private}d",
44         name.c_str(), realPath.c_str(), context->GetBundleName().c_str(), context->GetArea());
45     Init();
46 }
47 
Init()48 void MediaLibraryRdbStore::Init()
49 {
50     MEDIA_INFO_LOG("Init rdb store");
51     if (rdbStore_ != nullptr) {
52         return;
53     }
54 
55     int32_t errCode = 0;
56     MediaLibraryDataCallBack rdbDataCallBack;
57     rdbStore_ = RdbHelper::GetRdbStore(config_, MEDIA_RDB_VERSION, rdbDataCallBack, errCode);
58     if (rdbStore_ == nullptr) {
59         MEDIA_ERR_LOG("GetRdbStore is failed ");
60         return;
61     }
62 
63     if (rdbDataCallBack.HasDistributedTables()) {
64         int ret = rdbStore_->SetDistributedTables(
65             {MEDIALIBRARY_TABLE, SMARTALBUM_TABLE, SMARTALBUM_MAP_TABLE, CATEGORY_SMARTALBUM_MAP_TABLE});
66         MEDIA_DEBUG_LOG("ret = %{private}d", ret);
67     }
68 
69     if (!SubscribeRdbStoreObserver()) {
70         MEDIA_ERR_LOG("subscribe rdb observer err");
71         return;
72     }
73 
74     MEDIA_INFO_LOG("SUCCESS");
75 }
76 
~MediaLibraryRdbStore()77 MediaLibraryRdbStore::~MediaLibraryRdbStore()
78 {}
79 
Stop()80 void MediaLibraryRdbStore::Stop()
81 {
82     if (rdbStore_ == nullptr) {
83         return;
84     }
85 
86     UnSubscribeRdbStoreObserver();
87     rdbStore_ = nullptr;
88 }
89 
SubscribeRdbStoreObserver()90 bool MediaLibraryRdbStore::SubscribeRdbStoreObserver()
91 {
92     if (rdbStore_ == nullptr) {
93         MEDIA_ERR_LOG("SubscribeRdbStoreObserver rdbStore is null");
94         return false;
95     }
96     rdbStoreObs_ = make_shared<MediaLibraryRdbStoreObserver>(bundleName_);
97     if (rdbStoreObs_ == nullptr) {
98         return false;
99     }
100 
101     DistributedRdb::SubscribeOption option;
102     option.mode = DistributedRdb::SubscribeMode::REMOTE;
103     int ret = rdbStore_->Subscribe(option, rdbStoreObs_.get());
104     MEDIA_DEBUG_LOG("Subscribe ret = %d", ret);
105 
106     return ret == E_OK;
107 }
108 
UnSubscribeRdbStoreObserver()109 bool MediaLibraryRdbStore::UnSubscribeRdbStoreObserver()
110 {
111     if (rdbStore_ == nullptr) {
112         MEDIA_ERR_LOG("UnSubscribeRdbStoreObserver rdbStore is null");
113         return false;
114     }
115 
116     DistributedRdb::SubscribeOption option;
117     option.mode = DistributedRdb::SubscribeMode::REMOTE;
118     int ret = rdbStore_->UnSubscribe(option, rdbStoreObs_.get());
119     MEDIA_DEBUG_LOG("UnSubscribe ret = %d", ret);
120     if (ret == E_OK) {
121         rdbStoreObs_ = nullptr;
122         return true;
123     }
124 
125     return false;
126 }
127 
Insert(MediaLibraryCommand & cmd,int64_t & rowId)128 int32_t MediaLibraryRdbStore::Insert(MediaLibraryCommand &cmd, int64_t &rowId)
129 {
130     MEDIA_DEBUG_LOG("Insert");
131     if (rdbStore_ == nullptr) {
132         MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
133         return E_HAS_DB_ERROR;
134     }
135 
136     int32_t ret = rdbStore_->Insert(rowId, cmd.GetTableName(), cmd.GetValueBucket());
137     if (ret != NativeRdb::E_OK) {
138         MEDIA_ERR_LOG("rdbStore_->Insert failed, ret = %{public}d", ret);
139         return E_HAS_DB_ERROR;
140     }
141 
142     std::vector<std::string> devices = std::vector<std::string>();
143     if (!SyncPushTable(bundleName_, cmd.GetTableName(), devices)) {
144         MEDIA_ERR_LOG("SyncPushTable Error");
145     }
146     MEDIA_DEBUG_LOG("rdbStore_->Insert end, rowId = %d, ret = %{public}d", (int)rowId, ret);
147     return ret;
148 }
149 
Delete(MediaLibraryCommand & cmd,int32_t & rowId)150 int32_t MediaLibraryRdbStore::Delete(MediaLibraryCommand &cmd, int32_t &rowId)
151 {
152     MEDIA_DEBUG_LOG("Delete");
153     if (rdbStore_ == nullptr) {
154         MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
155         return E_HAS_DB_ERROR;
156     }
157 
158     int32_t ret = rdbStore_->Delete(rowId, cmd.GetTableName(), cmd.GetAbsRdbPredicates()->GetWhereClause(),
159         cmd.GetAbsRdbPredicates()->GetWhereArgs());
160     if (ret != NativeRdb::E_OK) {
161         MEDIA_ERR_LOG("rdbStore_->Delete failed, ret = %{public}d", ret);
162         return E_HAS_DB_ERROR;
163     }
164 
165     std::vector<std::string> devices = std::vector<std::string>();
166     if (!SyncPushTable(bundleName_, cmd.GetTableName(), devices)) {
167         MEDIA_ERR_LOG("SyncPushTable Error");
168     }
169 
170     return ret;
171 }
172 
Update(MediaLibraryCommand & cmd,int32_t & rowId)173 int32_t MediaLibraryRdbStore::Update(MediaLibraryCommand &cmd, int32_t &rowId)
174 {
175     MEDIA_DEBUG_LOG("Update");
176     if (rdbStore_ == nullptr) {
177         MEDIA_ERR_LOG("rdbStore_ is nullptr");
178         return E_HAS_DB_ERROR;
179     }
180 
181     int32_t ret = rdbStore_->Update(rowId, cmd.GetTableName(), cmd.GetValueBucket(),
182         cmd.GetAbsRdbPredicates()->GetWhereClause(), cmd.GetAbsRdbPredicates()->GetWhereArgs());
183     if (ret != NativeRdb::E_OK) {
184         MEDIA_ERR_LOG("rdbStore_->Update failed, ret = %{public}d", ret);
185         return E_HAS_DB_ERROR;
186     }
187 
188     std::vector<std::string> devices = std::vector<std::string>();
189     if (!SyncPushTable(bundleName_, cmd.GetTableName(), devices)) {
190         MEDIA_ERR_LOG("SyncPushTable Error");
191     }
192 
193     return ret;
194 }
195 
Query(MediaLibraryCommand & cmd,const vector<string> & columns)196 std::shared_ptr<NativeRdb::AbsSharedResultSet> MediaLibraryRdbStore::Query(MediaLibraryCommand &cmd,
197     const vector<string> &columns)
198 {
199     if (rdbStore_ == nullptr) {
200         MEDIA_ERR_LOG("rdbStore_ is nullptr");
201         return nullptr;
202     }
203 
204     auto predicates = cmd.GetAbsRdbPredicates();
205     return rdbStore_->Query(*predicates, columns);
206 }
207 
ExecuteSql(const std::string & sql)208 int32_t MediaLibraryRdbStore::ExecuteSql(const std::string &sql)
209 {
210     MEDIA_DEBUG_LOG("ExecuteSql");
211 
212     if (rdbStore_ == nullptr) {
213         MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
214         return E_HAS_DB_ERROR;
215     }
216 
217     int32_t ret = rdbStore_->ExecuteSql(sql);
218     if (ret != NativeRdb::E_OK) {
219         MEDIA_ERR_LOG("rdbStore_->ExecuteSql failed, ret = %{public}d", ret);
220         return E_HAS_DB_ERROR;
221     }
222     return ret;
223 }
224 
QuerySql(const std::string & sql)225 std::shared_ptr<NativeRdb::AbsSharedResultSet> MediaLibraryRdbStore::QuerySql(const std::string &sql)
226 {
227     MEDIA_DEBUG_LOG("ExecuteSql");
228 
229     if (rdbStore_ == nullptr) {
230         MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
231         return nullptr;
232     }
233 
234     auto ret = rdbStore_->QuerySql(sql);
235     if (ret != nullptr) {
236         int count;
237         ret->GetRowCount(count);
238         MEDIA_DEBUG_LOG("GetRowCount() = %{public}d", count);
239     }
240     return ret;
241 }
242 
GetRaw() const243 std::shared_ptr<NativeRdb::RdbStore> MediaLibraryRdbStore::GetRaw() const
244 {
245     return rdbStore_;
246 }
247 
ObtainTableName(MediaLibraryCommand & cmd)248 std::string MediaLibraryRdbStore::ObtainTableName(MediaLibraryCommand &cmd)
249 {
250     const std::string &networkId = cmd.GetOprnDevice();
251     int errCode = E_ERR;
252     if (!networkId.empty()) {
253         return rdbStore_->ObtainDistributedTableName(networkId, cmd.GetTableName(), errCode);
254     }
255 
256     return cmd.GetTableName();
257 }
258 
SyncPullAllTableByDeviceId(const std::string & bundleName,std::vector<std::string> & devices)259 bool MediaLibraryRdbStore::SyncPullAllTableByDeviceId(const std::string &bundleName, std::vector<std::string> &devices)
260 {
261     return MediaLibrarySyncTable::SyncPullAllTableByDeviceId(rdbStore_, bundleName, devices);
262 }
263 
SyncPullTable(const std::string & bundleName,const std::string & tableName,const std::vector<std::string> & devices,bool isLast)264 bool MediaLibraryRdbStore::SyncPullTable(const std::string &bundleName, const std::string &tableName,
265                                          const std::vector<std::string> &devices, bool isLast)
266 {
267     std::vector<std::string> devList(devices);
268     return MediaLibrarySyncTable::SyncPullTable(rdbStore_, bundleName, tableName, devList, isLast);
269 }
270 
SyncPushTable(const std::string & bundleName,const std::string & tableName,const std::vector<std::string> & devices,bool isLast)271 bool MediaLibraryRdbStore::SyncPushTable(const std::string &bundleName, const std::string &tableName,
272                                          const std::vector<std::string> &devices, bool isLast)
273 {
274     std::vector<std::string> devList(devices);
275     return MediaLibrarySyncTable::SyncPushTable(rdbStore_, bundleName, tableName, devList, isLast);
276 }
277 
PrepareDir(RdbStore & store)278 int32_t MediaLibraryDataCallBack::PrepareDir(RdbStore &store)
279 {
280     DirValuesBucket cameraDir = {
281         CAMERA_DIRECTORY_TYPE_VALUES, CAMERA_DIR_VALUES, CAMERA_TYPE_VALUES, CAMERA_EXTENSION_VALUES
282     };
283     DirValuesBucket videoDir = {
284         VIDEO_DIRECTORY_TYPE_VALUES, VIDEO_DIR_VALUES, VIDEO_TYPE_VALUES, VIDEO_EXTENSION_VALUES
285     };
286     DirValuesBucket pictureDir = {
287         PIC_DIRECTORY_TYPE_VALUES, PIC_DIR_VALUES, PIC_TYPE_VALUES, PIC_EXTENSION_VALUES
288     };
289     DirValuesBucket audioDir = {
290         AUDIO_DIRECTORY_TYPE_VALUES, AUDIO_DIR_VALUES, AUDIO_TYPE_VALUES, AUDIO_EXTENSION_VALUES
291     };
292     DirValuesBucket documentDir = {
293         DOC_DIRECTORY_TYPE_VALUES, DOC_DIR_VALUES, DOC_TYPE_VALUES, DOC_EXTENSION_VALUES
294     };
295     DirValuesBucket downloadDir = {
296         DOWNLOAD_DIRECTORY_TYPE_VALUES, DOWNLOAD_DIR_VALUES, DOWNLOAD_TYPE_VALUES, DOWNLOAD_EXTENSION_VALUES
297     };
298 
299     vector<DirValuesBucket> dirValuesBuckets = {
300         cameraDir, videoDir, pictureDir, audioDir, documentDir, downloadDir
301     };
302 
303     for (auto dirValuesBucket : dirValuesBuckets) {
304         if (InsertDirValues(dirValuesBucket, store) != NativeRdb::E_OK) {
305             MEDIA_ERR_LOG("PrepareDir failed");
306             return NativeRdb::E_ERROR;
307         }
308     }
309     return NativeRdb::E_OK;
310 }
311 
InsertDirValues(const DirValuesBucket & dirValuesBucket,RdbStore & store)312 int32_t MediaLibraryDataCallBack::InsertDirValues(const DirValuesBucket &dirValuesBucket, RdbStore &store)
313 {
314     ValuesBucket valuesBucket;
315     valuesBucket.PutInt(CATEGORY_MEDIATYPE_DIRECTORY_DB_DIRECTORY_TYPE, dirValuesBucket.directoryType);
316     valuesBucket.PutString(CATEGORY_MEDIATYPE_DIRECTORY_DB_DIRECTORY, dirValuesBucket.dirValues);
317     valuesBucket.PutString(CATEGORY_MEDIATYPE_DIRECTORY_DB_MEDIA_TYPE, dirValuesBucket.typeValues);
318     valuesBucket.PutString(CATEGORY_MEDIATYPE_DIRECTORY_DB_EXTENSION, dirValuesBucket.extensionValues);
319     int64_t outRowId = -1;
320     int32_t insertResult = store.Insert(outRowId, MEDIATYPE_DIRECTORY_TABLE, valuesBucket);
321     MEDIA_DEBUG_LOG("insert dir outRowId: %{public}ld insertResult: %{public}d", (long)outRowId, insertResult);
322     return insertResult;
323 }
324 
PrepareSmartAlbum(RdbStore & store)325 int32_t MediaLibraryDataCallBack::PrepareSmartAlbum(RdbStore &store)
326 {
327     SmartAlbumValuesBucket trashAlbum = {
328         TRASH_ALBUM_ID_VALUES, TRASH_ALBUM_NAME_VALUES, TRASH_ALBUM_TYPE_VALUES
329     };
330 
331     SmartAlbumValuesBucket favAlbum = {
332         FAVOURITE_ALBUM_ID_VALUES, FAVOURTIE_ALBUM_NAME_VALUES, FAVOURITE_ALBUM_TYPE_VALUES
333     };
334 
335     vector<SmartAlbumValuesBucket> smartAlbumValuesBuckets = {
336         trashAlbum, favAlbum
337     };
338 
339     for (auto smartAlbum : smartAlbumValuesBuckets) {
340         if (InsertSmartAlbumValues(smartAlbum, store) != NativeRdb::E_OK) {
341             MEDIA_ERR_LOG("Prepare smartAlbum failed");
342             return NativeRdb::E_ERROR;
343         }
344     }
345     return NativeRdb::E_OK;
346 }
347 
InsertSmartAlbumValues(const SmartAlbumValuesBucket & smartAlbum,RdbStore & store)348 int32_t MediaLibraryDataCallBack::InsertSmartAlbumValues(const SmartAlbumValuesBucket &smartAlbum, RdbStore &store)
349 {
350     ValuesBucket valuesBucket;
351     valuesBucket.PutInt(SMARTALBUM_DB_ID, smartAlbum.albumId);
352     valuesBucket.PutString(SMARTALBUM_DB_NAME, smartAlbum.albumName);
353     valuesBucket.PutInt(SMARTALBUM_DB_ALBUM_TYPE, smartAlbum.albumType);
354     int64_t outRowId = -1;
355     int32_t insertResult = store.Insert(outRowId, SMARTALBUM_TABLE, valuesBucket);
356     return insertResult;
357 }
358 
OnCreate(RdbStore & store)359 int32_t MediaLibraryDataCallBack::OnCreate(RdbStore &store)
360 {
361     vector<string> executeSqlStrs = {
362         CREATE_MEDIA_TABLE,
363         CREATE_SMARTALBUM_TABLE,
364         CREATE_SMARTALBUMMAP_TABLE,
365         CREATE_DEVICE_TABLE,
366         CREATE_CATEGORY_SMARTALBUMMAP_TABLE,
367         CREATE_IMAGE_VIEW,
368         CREATE_VIDEO_VIEW,
369         CREATE_AUDIO_VIEW,
370         CREATE_ABLUM_VIEW,
371         CREATE_SMARTABLUMASSETS_VIEW,
372         CREATE_ASSETMAP_VIEW,
373         CREATE_MEDIATYPE_DIRECTORY_TABLE,
374         CREATE_BUNDLE_PREMISSION_TABLE,
375     };
376 
377     for (string sqlStr : executeSqlStrs) {
378         if (store.ExecuteSql(sqlStr) != NativeRdb::E_OK) {
379             return NativeRdb::E_ERROR;
380         }
381     }
382 
383     if (PrepareDir(store) != NativeRdb::E_OK) {
384         return NativeRdb::E_ERROR;
385     }
386 
387     if (PrepareSmartAlbum(store) != NativeRdb::E_OK) {
388         return NativeRdb::E_ERROR;
389     }
390 
391     isDistributedTables = true;
392     return NativeRdb::E_OK;
393 }
394 
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)395 int32_t MediaLibraryDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
396 {
397 #ifdef RDB_UPGRADE_MOCK
398     const std::string ALTER_MOCK_COLUMN = "ALTER TABLE " + MEDIALIBRARY_TABLE +
399         " ADD COLUMN upgrade_test_column INT DEFAULT 0";
400     MEDIA_DEBUG_LOG("OnUpgrade |Rdb Verison %{private}d => %{private}d", oldVersion, newVersion);
401     int32_t result = NativeRdb::E_ERROR;
402     result = store.ExecuteSql(ALTER_MOCK_COLUMN);
403     if (result != NativeRdb::E_OK) {
404         MEDIA_ERR_LOG("Upgrade rdb error %{private}d", result);
405     }
406 #endif
407     return NativeRdb::E_OK;
408 }
409 
HasDistributedTables()410 bool MediaLibraryDataCallBack::HasDistributedTables()
411 {
412     return isDistributedTables;
413 }
414 
MediaLibraryRdbStoreObserver(const string & bundleName)415 MediaLibraryRdbStoreObserver::MediaLibraryRdbStoreObserver(const string &bundleName)
416 {
417     bundleName_ = bundleName;
418     isNotifyDeviceChange_ = false;
419 
420     if (timer_ == nullptr) {
421         timer_ = make_unique<OHOS::Utils::Timer>(bundleName_);
422         timerId_ = timer_->Register(bind(&MediaLibraryRdbStoreObserver::NotifyDeviceChange, this),
423             NOTIFY_TIME_INTERVAL);
424         timer_->Setup();
425     }
426 }
427 
~MediaLibraryRdbStoreObserver()428 MediaLibraryRdbStoreObserver::~MediaLibraryRdbStoreObserver()
429 {
430     if (timer_ != nullptr) {
431         timer_->Shutdown();
432         timer_->Unregister(timerId_);
433         timer_ = nullptr;
434     }
435 }
436 
OnChange(const vector<string> & devices)437 void MediaLibraryRdbStoreObserver::OnChange(const vector<string> &devices)
438 {
439     MEDIA_INFO_LOG("MediaLibraryRdbStoreObserver OnChange call");
440     if (devices.empty() || bundleName_.empty()) {
441         return;
442     }
443     MediaLibraryDevice::GetInstance()->NotifyRemoteFileChange();
444 }
445 
NotifyDeviceChange()446 void MediaLibraryRdbStoreObserver::NotifyDeviceChange()
447 {
448     if (isNotifyDeviceChange_) {
449         MediaLibraryDevice::GetInstance()->NotifyDeviceChange();
450         isNotifyDeviceChange_ = false;
451     }
452 }
453 } // namespace Media
454 } // namespace OHOS
455