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