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_log.h"
23
24 using namespace OHOS::DistributedKv;
25 namespace OHOS::Media {
26 std::mutex MediaLibraryKvStoreManager::mutex_;
27 Utils::Timer MediaLibraryKvStoreManager::timer_("close_kvStore");
28 std::atomic<uint32_t> MediaLibraryKvStoreManager::insertImageCount_ = 0;
29 uint32_t MediaLibraryKvStoreManager::timerId_ = 0;
30
~MediaLibraryKvStoreManager()31 MediaLibraryKvStoreManager::~MediaLibraryKvStoreManager()
32 {
33 timer_.Unregister(timerId_);
34 timer_.Shutdown();
35 timerId_ = 0;
36 }
37
InitKvStore(const KvStoreRoleType & roleType,const KvStoreValueType & valueType)38 int32_t MediaLibraryKvStoreManager::InitKvStore(const KvStoreRoleType &roleType, const KvStoreValueType &valueType)
39 {
40 std::lock_guard<std::mutex> lock(mutex_);
41 KvStoreSharedPtr ptr;
42 if (kvStoreMap_.Find(valueType, ptr)) {
43 return E_OK;
44 }
45
46 std::string baseDir = "";
47 if (roleType == KvStoreRoleType::OWNER) {
48 baseDir = KV_STORE_OWNER_DIR;
49 } else if (roleType == KvStoreRoleType::VISITOR) {
50 baseDir = KV_STORE_VISITOR_DIR;
51 } else {
52 MEDIA_ERR_LOG("invalid role type");
53 return E_ERR;
54 }
55
56 ptr = std::make_shared<MediaLibraryKvStore>();
57 int32_t status = ptr->Init(roleType, valueType, baseDir);
58 if (status != E_OK) {
59 MEDIA_ERR_LOG("init kvStore failed, status %{public}d", status);
60 return status;
61 }
62 kvStoreMap_.Insert(valueType, ptr);
63 return E_OK;
64 }
65
GetKvStore(const KvStoreRoleType & roleType,const KvStoreValueType & valueType)66 std::shared_ptr<MediaLibraryKvStore> MediaLibraryKvStoreManager::GetKvStore(
67 const KvStoreRoleType &roleType, const KvStoreValueType &valueType)
68 {
69 RegisterTimer(roleType, valueType);
70 KvStoreSharedPtr ptr;
71 if (kvStoreMap_.Find(valueType, ptr)) {
72 return ptr;
73 }
74
75 InitKvStore(roleType, valueType);
76 kvStoreMap_.Find(valueType, ptr);
77 return ptr;
78 }
79
CloseAllKvStore()80 void MediaLibraryKvStoreManager::CloseAllKvStore()
81 {
82 std::lock_guard<std::mutex> lock(mutex_);
83 if (kvStoreMap_.IsEmpty()) {
84 return;
85 }
86
87 kvStoreMap_.Clear();
88 }
89
CloseKvStore(const KvStoreValueType & valueType)90 bool MediaLibraryKvStoreManager::CloseKvStore(const KvStoreValueType &valueType)
91 {
92 std::lock_guard<std::mutex> lock(mutex_);
93 KvStoreSharedPtr ptr;
94 if (!kvStoreMap_.Find(valueType, ptr)) {
95 return false;
96 }
97
98 if (ptr != nullptr && ptr->Close()) {
99 kvStoreMap_.Erase(valueType);
100 MEDIA_INFO_LOG("CloseKvStore success, valueType %{public}d", valueType);
101 return true;
102 }
103 return false;
104 }
105
RegisterTimer(const KvStoreRoleType & roleType,const KvStoreValueType & valueType)106 void MediaLibraryKvStoreManager::RegisterTimer(const KvStoreRoleType &roleType, const KvStoreValueType &valueType)
107 {
108 if (roleType != KvStoreRoleType::OWNER) {
109 return;
110 }
111
112 Utils::Timer::TimerCallback timerCallback = [this]() {
113 MEDIA_INFO_LOG("KvStore timerCallback, CloseAllKvStore");
114 insertImageCount_ = 0;
115 CloseAllKvStore();
116 };
117
118 std::lock_guard<std::mutex> lock(mutex_);
119 if (timerId_ == 0) {
120 MEDIA_INFO_LOG("KvStore timer Setup");
121 timer_.Setup();
122 }
123
124 if (insertImageCount_ == 0 || insertImageCount_ >= KVSTORE_INSERT_COUNT) {
125 timer_.Unregister(timerId_);
126 insertImageCount_ = 0;
127 timerId_ = timer_.Register(timerCallback, CLOSE_KVSTORE_TIME_INTERVAL, true);
128 MEDIA_INFO_LOG("KvStore timer Restart");
129 }
130 insertImageCount_++;
131 }
132
InitMonthAndYearKvStore(const KvStoreRoleType & roleType)133 bool MediaLibraryKvStoreManager::InitMonthAndYearKvStore(const KvStoreRoleType& roleType)
134 {
135 if (roleType != KvStoreRoleType::OWNER) {
136 return false;
137 }
138 if (GetKvStore(roleType, KvStoreValueType::MONTH_ASTC) == nullptr ||
139 GetKvStore(roleType, KvStoreValueType::YEAR_ASTC) == nullptr) {
140 return false;
141 }
142 return true;
143 }
144
IsKvStoreValid(const KvStoreValueType & valueType)145 bool MediaLibraryKvStoreManager::IsKvStoreValid(const KvStoreValueType &valueType)
146 {
147 KvStoreSharedPtr ptr;
148 if (kvStoreMap_.Find(valueType, ptr)) {
149 return true;
150 }
151
152 ptr = std::make_shared<MediaLibraryKvStore>();
153 int32_t status = ptr->Init(KvStoreRoleType::OWNER, valueType, KV_STORE_OWNER_DIR);
154 if (status == static_cast<int32_t>(Status::DATA_CORRUPTED)) {
155 MEDIA_ERR_LOG("KvStore is invalid and needs to be deleted, status %{public}d, type %{public}d",
156 status, valueType);
157 return false;
158 }
159
160 if (status == E_OK && ptr != nullptr) {
161 ptr->Close();
162 }
163 return true;
164 }
165
RebuildInvalidKvStore(const KvStoreValueType & valueType)166 int32_t MediaLibraryKvStoreManager::RebuildInvalidKvStore(const KvStoreValueType &valueType)
167 {
168 std::lock_guard<std::mutex> lock(mutex_);
169 KvStoreSharedPtr ptr = std::make_shared<MediaLibraryKvStore>();
170 return ptr->RebuildKvStore(valueType, KV_STORE_OWNER_DIR);
171 }
172
GetSingleKvStore(const KvStoreRoleType & roleType,const std::string & storeId,const std::string & baseDir)173 std::shared_ptr<MediaLibraryKvStore> MediaLibraryKvStoreManager::GetSingleKvStore(
174 const KvStoreRoleType &roleType, const std::string &storeId, const std::string &baseDir)
175 {
176 KvStoreSharedPtr ptr = std::make_shared<MediaLibraryKvStore>();
177 int32_t status = ptr->InitSingleKvstore(roleType, storeId, baseDir);
178 if (status != E_OK) {
179 MEDIA_ERR_LOG("Init kvStore failed, status %{public}d", status);
180 return nullptr;
181 }
182 return ptr;
183 }
184
CloneKvStore(const std::string & oldKvStoreId,const std::string & oldBaseDir,const std::string & newKvStoreId,const std::string & newBaseDir)185 int32_t MediaLibraryKvStoreManager::CloneKvStore(const std::string &oldKvStoreId, const std::string &oldBaseDir,
186 const std::string &newKvStoreId, const std::string &newBaseDir)
187 {
188 KvStoreSharedPtr oldKvStore = std::make_shared<MediaLibraryKvStore>();
189 int32_t status = oldKvStore->InitSingleKvstore(KvStoreRoleType::OWNER, oldKvStoreId, oldBaseDir);
190 if (status != E_OK) {
191 MEDIA_ERR_LOG("Init old kvStore failed, status %{public}d", status);
192 return status;
193 }
194
195 KvStoreSharedPtr newKvStore = std::make_shared<MediaLibraryKvStore>();
196 status = newKvStore->InitSingleKvstore(KvStoreRoleType::OWNER, newKvStoreId, newBaseDir);
197 if (status != E_OK) {
198 MEDIA_ERR_LOG("Init new kvStore failed, status %{public}d", status);
199 return status;
200 }
201
202 status = oldKvStore->PutAllValueToNewKvStore(newKvStore);
203 if (status != E_OK) {
204 MEDIA_ERR_LOG("Clone kvstore failed, status %{public}d", status);
205 return status;
206 }
207 return E_OK;
208 }
209 } // namespace OHOS::Media