1 /*
2 * Copyright (C) 2023-2024 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 #include "medialibrary_kvstore_manager.h"
17
18 #include <atomic>
19 #include <shared_mutex>
20
21 #include "medialibrary_errno.h"
22 #include "media_file_utils.h"
23 #include "media_log.h"
24
25 using namespace OHOS::DistributedKv;
26 namespace OHOS::Media {
27
InitKvStore(const KvStoreRoleType & roleType,const KvStoreValueType & valueType)28 std::shared_ptr<MediaLibraryKvStore> MediaLibraryKvStoreManager::InitKvStore(const KvStoreRoleType &roleType,
29 const KvStoreValueType &valueType)
30 {
31 std::lock_guard<std::mutex> lock(mutex_);
32 KvStoreSharedPtr ptr;
33 if (kvStoreMap_.Find(valueType, ptr)) {
34 return ptr;
35 }
36
37 std::string baseDir = "";
38 if (roleType == KvStoreRoleType::OWNER) {
39 baseDir = KV_STORE_OWNER_DIR;
40 } else if (roleType == KvStoreRoleType::VISITOR) {
41 baseDir = KV_STORE_VISITOR_DIR;
42 } else {
43 MEDIA_ERR_LOG("invalid role type");
44 return nullptr;
45 }
46
47 ptr = std::make_shared<MediaLibraryKvStore>();
48 int32_t status = ptr->Init(roleType, valueType, baseDir);
49 if (status != E_OK) {
50 MEDIA_ERR_LOG("init kvStore failed, status %{public}d", status);
51 return nullptr;
52 }
53 kvStoreMap_.Insert(valueType, ptr);
54 return ptr;
55 }
56
GetKvStore(const KvStoreRoleType & roleType,const KvStoreValueType & valueType)57 std::shared_ptr<MediaLibraryKvStore> MediaLibraryKvStoreManager::GetKvStore(
58 const KvStoreRoleType &roleType, const KvStoreValueType &valueType)
59 {
60 int64_t currentTimestamp = MediaFileUtils::UTCTimeMilliSeconds();
61 kvStoreEvokedTimeStamp_.store(currentTimestamp);
62 KvStoreSharedPtr ptr;
63 CHECK_AND_RETURN_RET(!kvStoreMap_.Find(valueType, ptr), ptr);
64
65 return InitKvStore(roleType, valueType);
66 }
67
CloseAllKvStore()68 void MediaLibraryKvStoreManager::CloseAllKvStore()
69 {
70 std::lock_guard<std::mutex> lock(mutex_);
71 if (kvStoreMap_.IsEmpty()) {
72 return;
73 }
74
75 kvStoreMap_.Clear();
76 }
77
TryCloseAllKvStore()78 void MediaLibraryKvStoreManager::TryCloseAllKvStore()
79 {
80 int64_t kvIdleTime = MediaFileUtils::UTCTimeMilliSeconds() - kvStoreEvokedTimeStamp_.load();
81 if (!kvStoreMap_.IsEmpty() && kvIdleTime > static_cast<int64_t>(CLOSE_KVSTORE_TIME_INTERVAL)) {
82 std::lock_guard<std::mutex> lock(mutex_);
83 kvStoreMap_.Clear();
84 }
85 }
86
CloseKvStore(const KvStoreValueType & valueType)87 bool MediaLibraryKvStoreManager::CloseKvStore(const KvStoreValueType &valueType)
88 {
89 std::lock_guard<std::mutex> lock(mutex_);
90 KvStoreSharedPtr ptr;
91 if (!kvStoreMap_.Find(valueType, ptr)) {
92 return false;
93 }
94
95 if (ptr != nullptr && ptr->Close()) {
96 kvStoreMap_.Erase(valueType);
97 MEDIA_INFO_LOG("CloseKvStore success, valueType %{public}d", valueType);
98 return true;
99 }
100 return false;
101 }
102
InitMonthAndYearKvStore(const KvStoreRoleType & roleType)103 bool MediaLibraryKvStoreManager::InitMonthAndYearKvStore(const KvStoreRoleType& roleType)
104 {
105 if (roleType != KvStoreRoleType::OWNER) {
106 return false;
107 }
108 if (GetKvStore(roleType, KvStoreValueType::MONTH_ASTC) == nullptr ||
109 GetKvStore(roleType, KvStoreValueType::YEAR_ASTC) == nullptr) {
110 return false;
111 }
112 return true;
113 }
114
IsKvStoreValid(const KvStoreValueType & valueType)115 bool MediaLibraryKvStoreManager::IsKvStoreValid(const KvStoreValueType &valueType)
116 {
117 KvStoreSharedPtr ptr;
118 CHECK_AND_RETURN_RET(!kvStoreMap_.Find(valueType, ptr), true);
119
120 ptr = std::make_shared<MediaLibraryKvStore>();
121 int32_t status = ptr->Init(KvStoreRoleType::OWNER, valueType, KV_STORE_OWNER_DIR);
122 CHECK_AND_RETURN_RET_LOG(status != static_cast<int32_t>(Status::DATA_CORRUPTED), false,
123 "KvStore is invalid and needs to be deleted, status %{public}d, type %{public}d",
124 status, valueType);
125
126 if (status == E_OK && ptr != nullptr) {
127 ptr->Close();
128 }
129 return true;
130 }
131
RebuildInvalidKvStore(const KvStoreValueType & valueType)132 int32_t MediaLibraryKvStoreManager::RebuildInvalidKvStore(const KvStoreValueType &valueType)
133 {
134 std::lock_guard<std::mutex> lock(mutex_);
135 kvStoreMap_.Erase(valueType);
136 KvStoreSharedPtr ptr = std::make_shared<MediaLibraryKvStore>();
137 return ptr->RebuildKvStore(valueType, KV_STORE_OWNER_DIR);
138 }
139
GetSingleKvStore(const KvStoreRoleType & roleType,const std::string & storeId,const std::string & baseDir)140 std::shared_ptr<MediaLibraryKvStore> MediaLibraryKvStoreManager::GetSingleKvStore(
141 const KvStoreRoleType &roleType, const std::string &storeId, const std::string &baseDir)
142 {
143 KvStoreSharedPtr ptr = std::make_shared<MediaLibraryKvStore>();
144 int32_t status = ptr->InitSingleKvstore(roleType, storeId, baseDir);
145 CHECK_AND_RETURN_RET_LOG(status == E_OK, nullptr, "Init kvStore failed, status %{public}d", status);
146 return ptr;
147 }
148
CloneKvStore(const std::string & oldKvStoreId,const std::string & oldBaseDir,const std::string & newKvStoreId,const std::string & newBaseDir)149 int32_t MediaLibraryKvStoreManager::CloneKvStore(const std::string &oldKvStoreId, const std::string &oldBaseDir,
150 const std::string &newKvStoreId, const std::string &newBaseDir)
151 {
152 KvStoreSharedPtr oldKvStore = std::make_shared<MediaLibraryKvStore>();
153 int32_t status = oldKvStore->InitSingleKvstore(KvStoreRoleType::OWNER, oldKvStoreId, oldBaseDir);
154 CHECK_AND_RETURN_RET_LOG(status == E_OK, status, "Init old kvStore failed, status %{public}d", status);
155
156 KvStoreSharedPtr newKvStore = std::make_shared<MediaLibraryKvStore>();
157 status = newKvStore->InitSingleKvstore(KvStoreRoleType::OWNER, newKvStoreId, newBaseDir);
158 CHECK_AND_RETURN_RET_LOG(status == E_OK, status, "Init new kvStore failed, status %{public}d", status);
159
160 status = oldKvStore->PutAllValueToNewKvStore(newKvStore);
161 CHECK_AND_RETURN_RET_LOG(status == E_OK, status, "Clone kvstore failed, status %{public}d", status);
162 return E_OK;
163 }
164 } // namespace OHOS::Media