• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.h"
17 
18 #include <algorithm>
19 
20 #include "medialibrary_errno.h"
21 #include "medialibrary_tracer.h"
22 #include "media_log.h"
23 
24 using namespace OHOS::DistributedKv;
25 namespace OHOS::Media {
26 const OHOS::DistributedKv::AppId KVSTORE_APPID = {"com.ohos.medialibrary.medialibrarydata"};
27 const OHOS::DistributedKv::StoreId KVSTORE_MONTH_STOREID = {"medialibrary_month_astc_data"};
28 const OHOS::DistributedKv::StoreId KVSTORE_YEAR_STOREID = {"medialibrary_year_astc_data"};
29 
30 // Different storeId used to distinguish different database
31 const OHOS::DistributedKv::StoreId KVSTORE_MONTH_STOREID_OLD_VERSION = {"medialibrary_month_astc"};
32 const OHOS::DistributedKv::StoreId KVSTORE_YEAR_STOREID_OLD_VERSION = {"medialibrary_year_astc"};
33 
~MediaLibraryKvStore()34 MediaLibraryKvStore::~MediaLibraryKvStore()
35 {
36     Close();
37 }
38 
Init(const KvStoreRoleType & roleType,const KvStoreValueType & valueType,const std::string & baseDir)39 int32_t MediaLibraryKvStore::Init(
40     const KvStoreRoleType &roleType, const KvStoreValueType &valueType, const std::string &baseDir)
41 {
42     MediaLibraryTracer tracer;
43     tracer.Start("MediaLibraryKvStore::InitKvStore");
44     Options options;
45     if (!GetKvStoreOption(options, roleType, baseDir)) {
46         MEDIA_ERR_LOG("failed to GetKvStoreOption");
47         return E_ERR;
48     }
49 
50     MEDIA_INFO_LOG("InitKvStore baseDir %{public}s", options.group.groupDir.c_str());
51     Status status;
52     if (valueType == KvStoreValueType::MONTH_ASTC) {
53         status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, KVSTORE_MONTH_STOREID, kvStorePtr_);
54     } else if (valueType == KvStoreValueType::YEAR_ASTC) {
55         status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, KVSTORE_YEAR_STOREID, kvStorePtr_);
56     } else if (valueType == KvStoreValueType::MONTH_ASTC_OLD_VERSION) {
57         status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, KVSTORE_MONTH_STOREID_OLD_VERSION, kvStorePtr_);
58     } else if (valueType == KvStoreValueType::YEAR_ASTC_OLD_VERSION) {
59         status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, KVSTORE_YEAR_STOREID_OLD_VERSION, kvStorePtr_);
60     } else {
61         MEDIA_ERR_LOG("invalid value type");
62         return E_ERR;
63     }
64 
65     if (status != Status::SUCCESS || kvStorePtr_ == nullptr) {
66         MEDIA_ERR_LOG("init KvStore failed, status %{public}d", status);
67         return static_cast<int32_t>(status);
68     }
69     return E_OK;
70 }
71 
Insert(const std::string & key,const std::vector<uint8_t> & value)72 int32_t MediaLibraryKvStore::Insert(const std::string &key, const std::vector<uint8_t> &value)
73 {
74     if (kvStorePtr_ == nullptr) {
75         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
76         return E_HAS_DB_ERROR;
77     }
78 
79     MediaLibraryTracer tracer;
80     tracer.Start("MediaLibraryKvStore::Insert");
81     Key k(key);
82     Value v(value);
83     Status status = kvStorePtr_->Put(k, v);
84     if (status != Status::SUCCESS) {
85         MEDIA_ERR_LOG("insert failed, status %{public}d", status);
86     }
87     return static_cast<int32_t>(status);
88 }
89 
Delete(const std::string & key)90 int32_t MediaLibraryKvStore::Delete(const std::string &key)
91 {
92     if (kvStorePtr_ == nullptr) {
93         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
94         return E_HAS_DB_ERROR;
95     }
96 
97     MediaLibraryTracer tracer;
98     tracer.Start("MediaLibraryKvStore::Delete");
99     Key k(key);
100     Status status = kvStorePtr_->Delete(k);
101     if (status != Status::SUCCESS) {
102         MEDIA_ERR_LOG("delete failed, status %{public}d", status);
103     }
104     return static_cast<int32_t>(status);
105 }
106 
Query(const std::string & key,std::vector<uint8_t> & value)107 int32_t MediaLibraryKvStore::Query(const std::string &key, std::vector<uint8_t> &value)
108 {
109     if (kvStorePtr_ == nullptr) {
110         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
111         return E_HAS_DB_ERROR;
112     }
113 
114     MediaLibraryTracer tracer;
115     tracer.Start("MediaLibraryKvStore::Query");
116     std::vector<uint8_t> tmp;
117     Key k(key);
118     Value v(tmp);
119     Status status = kvStorePtr_->Get(k, v);
120     value = v.Data();
121     if (status != Status::SUCCESS) {
122         MEDIA_ERR_LOG("query failed, status %{public}d", status);
123     }
124     return static_cast<int32_t>(status);
125 }
126 
AddEmptyValue(std::vector<std::vector<uint8_t>> & values)127 void AddEmptyValue(std::vector<std::vector<uint8_t>> &values)
128 {
129     std::vector<uint8_t> value = {};
130     values.emplace_back(std::move(value));
131 }
132 
GenEmptyValues(std::vector<std::string> & batchKeys,std::vector<std::vector<uint8_t>> & values)133 void GenEmptyValues(std::vector<std::string> &batchKeys, std::vector<std::vector<uint8_t>> &values)
134 {
135     for (size_t i = 0; i < batchKeys.size(); i++) {
136         std::vector<uint8_t> value = {};
137         values.emplace_back(std::move(value));
138     }
139 }
140 
FillBatchValues(std::vector<std::string> & batchKeys,std::vector<std::vector<uint8_t>> & values,std::shared_ptr<DistributedKv::SingleKvStore> kvStorePtr)141 int32_t FillBatchValues(std::vector<std::string> &batchKeys, std::vector<std::vector<uint8_t>> &values,
142     std::shared_ptr<DistributedKv::SingleKvStore> kvStorePtr)
143 {
144     DataQuery dataQuery;
145     dataQuery.Between(batchKeys.back(), batchKeys.front());
146     std::shared_ptr<KvStoreResultSet> resultSet;
147     Status status = kvStorePtr->GetResultSet(dataQuery, resultSet);
148     if (status != Status::SUCCESS || resultSet == nullptr) {
149         MEDIA_ERR_LOG("GetResultSet error occur, status: %{public}d", status);
150         return static_cast<int32_t>(status);
151     }
152 
153     if (!resultSet->MoveToNext()) {
154         // This may happen if all images in this group is not generated.
155         MEDIA_ERR_LOG("ResultSet is empty.");
156         GenEmptyValues(batchKeys, values);
157         return static_cast<int32_t>(status);
158     }
159     auto begin = batchKeys.crbegin();
160     auto end = batchKeys.crend();
161     bool isEndOfResultSet = false;
162     while (begin != end) {
163         if (isEndOfResultSet) {
164             AddEmptyValue(values);
165             ++begin;
166             continue;
167         }
168         Entry entry;
169         status = resultSet->GetEntry(entry);
170         if (status != Status::SUCCESS) {
171             MEDIA_ERR_LOG("GetEntry error occur, status: %{public}d", status);
172             return static_cast<int32_t>(status);
173         }
174 
175         int result = std::strcmp(entry.key.ToString().c_str(), (*begin).c_str());
176         if (result == 0) {
177             std::vector<uint8_t>&& value = entry.value;
178             values.emplace_back(std::move(value));
179             ++begin;
180             if (!resultSet->MoveToNext()) {
181                 isEndOfResultSet = true;
182             }
183         } else if (result < 0) {
184             // This may happen if image is hidden or trashed by user.
185             if (!resultSet->MoveToNext()) {
186                 isEndOfResultSet = true;
187             }
188         } else {
189             // This may happen if image is not generated.
190             AddEmptyValue(values);
191             ++begin;
192         }
193     }
194     status = kvStorePtr->CloseResultSet(resultSet);
195     return static_cast<int32_t>(status);
196 }
197 
BatchQuery(std::vector<std::string> & batchKeys,std::vector<std::vector<uint8_t>> & values)198 int32_t MediaLibraryKvStore::BatchQuery(
199     std::vector<std::string> &batchKeys, std::vector<std::vector<uint8_t>> &values)
200 {
201     if (kvStorePtr_ == nullptr) {
202         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
203         return E_HAS_DB_ERROR;
204     }
205 
206     if (batchKeys.empty()) {
207         MEDIA_ERR_LOG("batchKeys is empty");
208         return E_ERR;
209     }
210 
211     std::sort(batchKeys.begin(), batchKeys.end(), [](std::string a, std::string b) {return a > b;});
212     MediaLibraryTracer tracer;
213     tracer.Start("MediaLibraryKvStore::BatchQuery");
214     return FillBatchValues(batchKeys, values, kvStorePtr_);
215 }
216 
Close()217 bool MediaLibraryKvStore::Close()
218 {
219     MediaLibraryTracer tracer;
220     tracer.Start("MediaLibraryKvStore::Close");
221     if (kvStorePtr_ == nullptr) {
222         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
223         return true;
224     }
225 
226     Status status = dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
227     if (status != Status::SUCCESS) {
228         MEDIA_ERR_LOG("close KvStore failed, status %{public}d", status);
229         return false;
230     }
231     kvStorePtr_ = nullptr;
232     return true;
233 }
234 
GetKvStoreOption(DistributedKv::Options & options,const KvStoreRoleType & roleType,const std::string & baseDir)235 bool MediaLibraryKvStore::GetKvStoreOption(
236     DistributedKv::Options &options, const KvStoreRoleType &roleType, const std::string &baseDir)
237 {
238     if (roleType == KvStoreRoleType::OWNER) {
239         options.createIfMissing = true;
240         options.role = RoleType::OWNER;
241     } else if (roleType == KvStoreRoleType::VISITOR) {
242         options.createIfMissing = false;
243         options.role = RoleType::VISITOR;
244     } else {
245         MEDIA_ERR_LOG("GetKvStoreOption invalid role");
246         return false;
247     }
248     options.group.groupDir = baseDir;
249     options.encrypt = false;
250     options.backup = false;
251     options.autoSync = false;
252     options.securityLevel = SecurityLevel::S3;
253     options.kvStoreType = KvStoreType::LOCAL_ONLY;
254     return true;
255 }
256 
RebuildKvStore(const KvStoreValueType & valueType,const std::string & baseDir)257 int32_t MediaLibraryKvStore::RebuildKvStore(const KvStoreValueType &valueType, const std::string &baseDir)
258 {
259     MEDIA_INFO_LOG("Start RebuildKvStore, type %{public}d", valueType);
260     MediaLibraryTracer tracer;
261     tracer.Start("MediaLibraryKvStore::RebuildKvStore");
262     Status status;
263     tracer.Start("DeleteKvStore");
264     if (valueType == KvStoreValueType::MONTH_ASTC) {
265         status = dataManager_.DeleteKvStore(KVSTORE_APPID, KVSTORE_MONTH_STOREID, baseDir);
266     } else if (valueType == KvStoreValueType::YEAR_ASTC) {
267         status = dataManager_.DeleteKvStore(KVSTORE_APPID, KVSTORE_YEAR_STOREID, baseDir);
268     } else {
269         MEDIA_ERR_LOG("Invalid value type: %{public}d", valueType);
270         return E_ERR;
271     }
272     tracer.Finish();
273 
274     if (status != Status::SUCCESS) {
275         MEDIA_ERR_LOG("Delete kvstore failed, type %{public}d, status %{public}d", valueType, status);
276         return static_cast<int32_t>(status);
277     }
278 
279     int32_t err = Init(KvStoreRoleType::OWNER, valueType, baseDir);
280     if (err != E_OK) {
281         MEDIA_ERR_LOG("Rebuild kvstore failed, type %{public}d, status %{public}d", valueType, err);
282         return err;
283     }
284 
285     if (!Close()) {
286         return E_ERR;
287     }
288     MEDIA_INFO_LOG("RebuildKvStore finish, type %{public}d", valueType);
289     return E_OK;
290 }
291 } // namespace OHOS::Media
292