• 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 const size_t KVSTORE_MAX_NUMBER_BATCH_INSERT = 100;
30 
31 // Different storeId used to distinguish different database
32 const OHOS::DistributedKv::StoreId KVSTORE_MONTH_STOREID_OLD_VERSION = {"medialibrary_month_astc"};
33 const OHOS::DistributedKv::StoreId KVSTORE_YEAR_STOREID_OLD_VERSION = {"medialibrary_year_astc"};
34 
~MediaLibraryKvStore()35 MediaLibraryKvStore::~MediaLibraryKvStore()
36 {
37     Close();
38 }
39 
Init(const KvStoreRoleType & roleType,const KvStoreValueType & valueType,const std::string & baseDir)40 int32_t MediaLibraryKvStore::Init(
41     const KvStoreRoleType &roleType, const KvStoreValueType &valueType, const std::string &baseDir)
42 {
43     MediaLibraryTracer tracer;
44     tracer.Start("MediaLibraryKvStore::InitKvStore");
45     Options options;
46     if (!GetKvStoreOption(options, roleType, baseDir)) {
47         MEDIA_ERR_LOG("failed to GetKvStoreOption");
48         return E_ERR;
49     }
50     MEDIA_INFO_LOG("InitKvStore baseDir %{public}s", options.group.groupDir.c_str());
51     return E_ERR;
52 }
53 
Insert(const std::string & key,const std::vector<uint8_t> & value)54 int32_t MediaLibraryKvStore::Insert(const std::string &key, const std::vector<uint8_t> &value)
55 {
56     if (kvStorePtr_ == nullptr) {
57         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
58         return E_HAS_DB_ERROR;
59     }
60 
61     MediaLibraryTracer tracer;
62     tracer.Start("MediaLibraryKvStore::Insert");
63     Key k(key);
64     Value v(value);
65     Status status = kvStorePtr_->Put(k, v);
66     if (status != Status::SUCCESS) {
67         MEDIA_ERR_LOG("insert failed, status %{public}d", status);
68     }
69     return static_cast<int32_t>(status);
70 }
71 
Delete(const std::string & key)72 int32_t MediaLibraryKvStore::Delete(const std::string &key)
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::Delete");
81     Key k(key);
82     Status status = kvStorePtr_->Delete(k);
83     if (status != Status::SUCCESS) {
84         MEDIA_ERR_LOG("delete failed, status %{public}d", status);
85     }
86     return static_cast<int32_t>(status);
87 }
88 
GetCount(const std::string & key,int32_t & count)89 int32_t MediaLibraryKvStore::GetCount(const std::string& key, int32_t& count)
90 {
91     if (kvStorePtr_ == nullptr) {
92         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
93         return E_HAS_DB_ERROR;
94     }
95 
96     MediaLibraryTracer tracer;
97     tracer.Start("MediaLibraryKvStore::GetCount");
98     DataQuery dataQuery;
99     dataQuery.Between(key, key);
100     std::shared_ptr<KvStoreResultSet> output;
101     Status status = kvStorePtr_->GetResultSet(dataQuery, output);
102     if (status != Status::SUCCESS) {
103         MEDIA_ERR_LOG("delete failed, status %{public}d", status);
104         count = 0;
105     } else {
106         count = output->GetCount();
107     }
108     status = kvStorePtr_->CloseResultSet(output);
109     return static_cast<int32_t>(status);
110 }
111 
Query(const std::string & key,std::vector<uint8_t> & value)112 int32_t MediaLibraryKvStore::Query(const std::string &key, std::vector<uint8_t> &value)
113 {
114     if (kvStorePtr_ == nullptr) {
115         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
116         return E_HAS_DB_ERROR;
117     }
118 
119     MediaLibraryTracer tracer;
120     tracer.Start("MediaLibraryKvStore::Query");
121     std::vector<uint8_t> tmp;
122     Key k(key);
123     Value v(tmp);
124     Status status = kvStorePtr_->Get(k, v);
125     value = v.Data();
126     if (status != Status::SUCCESS) {
127         MEDIA_ERR_LOG("query failed, status %{public}d", status);
128     }
129     return static_cast<int32_t>(status);
130 }
131 
AddEmptyValue(std::vector<std::vector<uint8_t>> & values)132 void AddEmptyValue(std::vector<std::vector<uint8_t>> &values)
133 {
134     std::vector<uint8_t> value = {};
135     values.emplace_back(std::move(value));
136 }
137 
GenEmptyValues(std::vector<std::string> & batchKeys,std::vector<std::vector<uint8_t>> & values)138 void GenEmptyValues(std::vector<std::string> &batchKeys, std::vector<std::vector<uint8_t>> &values)
139 {
140     for (size_t i = 0; i < batchKeys.size(); i++) {
141         std::vector<uint8_t> value = {};
142         values.emplace_back(std::move(value));
143     }
144 }
145 
FillBatchValues(std::vector<std::string> & batchKeys,std::vector<std::vector<uint8_t>> & values,std::shared_ptr<DistributedKv::SingleKvStore> kvStorePtr)146 int32_t FillBatchValues(std::vector<std::string> &batchKeys, std::vector<std::vector<uint8_t>> &values,
147     std::shared_ptr<DistributedKv::SingleKvStore> kvStorePtr)
148 {
149     DataQuery dataQuery;
150     dataQuery.Between(batchKeys.back(), batchKeys.front());
151     std::shared_ptr<KvStoreResultSet> resultSet;
152     Status status = kvStorePtr->GetResultSet(dataQuery, resultSet);
153     if (status != Status::SUCCESS || resultSet == nullptr) {
154         MEDIA_ERR_LOG("GetResultSet error occur, status: %{public}d", status);
155         return static_cast<int32_t>(status);
156     }
157 
158     if (!resultSet->MoveToNext()) {
159         // This may happen if all images in this group is not generated.
160         MEDIA_ERR_LOG("ResultSet is empty.");
161         GenEmptyValues(batchKeys, values);
162         return static_cast<int32_t>(status);
163     }
164     auto begin = batchKeys.crbegin();
165     auto end = batchKeys.crend();
166     bool isEndOfResultSet = false;
167     while (begin != end) {
168         if (isEndOfResultSet) {
169             AddEmptyValue(values);
170             ++begin;
171             continue;
172         }
173         Entry entry;
174         status = resultSet->GetEntry(entry);
175         if (status != Status::SUCCESS) {
176             MEDIA_ERR_LOG("GetEntry error occur, status: %{public}d", status);
177             return static_cast<int32_t>(status);
178         }
179 
180         int result = std::strcmp(entry.key.ToString().c_str(), (*begin).c_str());
181         if (result == 0) {
182             std::vector<uint8_t>&& value = entry.value;
183             values.emplace_back(std::move(value));
184             ++begin;
185             if (!resultSet->MoveToNext()) {
186                 isEndOfResultSet = true;
187             }
188         } else if (result < 0) {
189             // This may happen if image is hidden or trashed by user.
190             if (!resultSet->MoveToNext()) {
191                 isEndOfResultSet = true;
192             }
193         } else {
194             // This may happen if image is not generated.
195             AddEmptyValue(values);
196             ++begin;
197         }
198     }
199     status = kvStorePtr->CloseResultSet(resultSet);
200     return static_cast<int32_t>(status);
201 }
202 
BatchQuery(std::vector<std::string> & batchKeys,std::vector<std::vector<uint8_t>> & values)203 int32_t MediaLibraryKvStore::BatchQuery(
204     std::vector<std::string> &batchKeys, std::vector<std::vector<uint8_t>> &values)
205 {
206     if (kvStorePtr_ == nullptr) {
207         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
208         return E_HAS_DB_ERROR;
209     }
210 
211     if (batchKeys.empty()) {
212         MEDIA_ERR_LOG("batchKeys is empty");
213         return E_ERR;
214     }
215 
216     std::sort(batchKeys.begin(), batchKeys.end(), [](std::string a, std::string b) {return a > b;});
217     MediaLibraryTracer tracer;
218     tracer.Start("MediaLibraryKvStore::BatchQuery");
219     return FillBatchValues(batchKeys, values, kvStorePtr_);
220 }
221 
Close()222 bool MediaLibraryKvStore::Close()
223 {
224     MediaLibraryTracer tracer;
225     tracer.Start("MediaLibraryKvStore::Close");
226     if (kvStorePtr_ == nullptr) {
227         MEDIA_ERR_LOG("kvStorePtr_ is nullptr");
228         return true;
229     }
230 
231     Status status = dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
232     if (status != Status::SUCCESS) {
233         MEDIA_ERR_LOG("close KvStore failed, status %{public}d", status);
234         return false;
235     }
236     kvStorePtr_ = nullptr;
237     return true;
238 }
239 
GetKvStoreOption(DistributedKv::Options & options,const KvStoreRoleType & roleType,const std::string & baseDir)240 bool MediaLibraryKvStore::GetKvStoreOption(
241     DistributedKv::Options &options, const KvStoreRoleType &roleType, const std::string &baseDir)
242 {
243     if (roleType == KvStoreRoleType::OWNER) {
244         options.createIfMissing = true;
245         options.role = RoleType::OWNER;
246     } else if (roleType == KvStoreRoleType::VISITOR) {
247         options.createIfMissing = false;
248         options.role = RoleType::VISITOR;
249     } else {
250         MEDIA_ERR_LOG("GetKvStoreOption invalid role");
251         return false;
252     }
253     options.group.groupDir = baseDir;
254     options.encrypt = false;
255     options.backup = false;
256     options.autoSync = false;
257     options.securityLevel = SecurityLevel::S3;
258     options.kvStoreType = KvStoreType::LOCAL_ONLY;
259     return true;
260 }
261 
RebuildKvStore(const KvStoreValueType & valueType,const std::string & baseDir)262 int32_t MediaLibraryKvStore::RebuildKvStore(const KvStoreValueType &valueType, const std::string &baseDir)
263 {
264     MEDIA_INFO_LOG("Start RebuildKvStore, type %{public}d", valueType);
265     MediaLibraryTracer tracer;
266     tracer.Start("MediaLibraryKvStore::RebuildKvStore");
267     Status status;
268     tracer.Start("DeleteKvStore");
269     if (valueType == KvStoreValueType::MONTH_ASTC) {
270         status = dataManager_.DeleteKvStore(KVSTORE_APPID, KVSTORE_MONTH_STOREID, baseDir);
271     } else if (valueType == KvStoreValueType::YEAR_ASTC) {
272         status = dataManager_.DeleteKvStore(KVSTORE_APPID, KVSTORE_YEAR_STOREID, baseDir);
273     } else {
274         MEDIA_ERR_LOG("Invalid value type: %{public}d", valueType);
275         return E_ERR;
276     }
277     tracer.Finish();
278 
279     if (status != Status::SUCCESS) {
280         MEDIA_ERR_LOG("Delete kvstore failed, type %{public}d, status %{public}d", valueType, status);
281         return static_cast<int32_t>(status);
282     }
283 
284     int32_t err = Init(KvStoreRoleType::OWNER, valueType, baseDir);
285     if (err != E_OK) {
286         MEDIA_ERR_LOG("Rebuild kvstore failed, type %{public}d, status %{public}d", valueType, err);
287         return err;
288     }
289 
290     if (!Close()) {
291         return E_ERR;
292     }
293     MEDIA_INFO_LOG("RebuildKvStore finish, type %{public}d", valueType);
294     return E_OK;
295 }
296 
BatchInsert(const std::vector<DistributedKv::Entry> & entries)297 int32_t MediaLibraryKvStore::BatchInsert(const std::vector<DistributedKv::Entry> &entries)
298 {
299     if (kvStorePtr_ == nullptr) {
300         MEDIA_ERR_LOG("KvStorePtr is nullptr");
301         return E_HAS_DB_ERROR;
302     }
303     if (entries.empty()) {
304         MEDIA_ERR_LOG("Entries is empty");
305         return E_ERR;
306     }
307 
308     MediaLibraryTracer tracer;
309     tracer.Start("MediaLibraryKvStore::BatchInsert");
310     Status status = kvStorePtr_->PutBatch(entries);
311     if (status != Status::SUCCESS) {
312         MEDIA_ERR_LOG("Batch insert failed, status %{public}d", status);
313         return static_cast<int32_t>(status);
314     }
315     return E_OK;
316 }
317 
InitSingleKvstore(const KvStoreRoleType & roleType,const std::string & storeId,const std::string & baseDir)318 int32_t MediaLibraryKvStore::InitSingleKvstore(const KvStoreRoleType &roleType,
319     const std::string &storeId, const std::string &baseDir)
320 {
321     MediaLibraryTracer tracer;
322     tracer.Start("MediaLibraryKvStore::InitKvStore");
323     Options options;
324     if (roleType == KvStoreRoleType::OWNER) {
325         options.createIfMissing = true;
326         options.role = RoleType::OWNER;
327     } else if (roleType == KvStoreRoleType::VISITOR) {
328         options.createIfMissing = false;
329         options.role = RoleType::VISITOR;
330     } else {
331         MEDIA_ERR_LOG("GetKvStoreOption invalid role");
332         return E_ERR;
333     }
334     options.group.groupDir = baseDir;
335     options.encrypt = false;
336     options.backup = false;
337     options.autoSync = false;
338     options.securityLevel = SecurityLevel::S3;
339     options.kvStoreType = KvStoreType::LOCAL_ONLY;
340 
341     MEDIA_INFO_LOG("InitKvStore baseDir %{public}s", options.group.groupDir.c_str());
342     Status status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, {storeId}, kvStorePtr_);
343     if (status != Status::SUCCESS) {
344         MEDIA_ERR_LOG("Init kvstore failed, status:%{public}d", status);
345         return static_cast<int32_t>(status);
346     }
347     return E_OK;
348 }
349 
PutAllValueToNewKvStore(std::shared_ptr<MediaLibraryKvStore> & newKvstore)350 int32_t MediaLibraryKvStore::PutAllValueToNewKvStore(std::shared_ptr<MediaLibraryKvStore> &newKvstore)
351 {
352     if (kvStorePtr_ == nullptr) {
353         MEDIA_ERR_LOG("KvStorePtr is nullptr");
354         return E_HAS_DB_ERROR;
355     }
356 
357     MediaLibraryTracer tracer;
358     tracer.Start("MediaLibraryKvStore::PutAllValueToNewKvStore");
359     MEDIA_INFO_LOG("Start PutAllValueToNewKvStore");
360     DataQuery dataQuery;
361     dataQuery.Between("", "Z");
362     std::shared_ptr<KvStoreResultSet> resultSet;
363     Status status = kvStorePtr_->GetResultSet(dataQuery, resultSet);
364     if (status != Status::SUCCESS || resultSet == nullptr) {
365         MEDIA_ERR_LOG("GetResultSet error occur, status: %{public}d", status);
366         return static_cast<int32_t>(status);
367     }
368 
369     std::vector<Entry> entryList;
370     while (resultSet->MoveToNext()) {
371         Entry entry;
372         status = resultSet->GetEntry(entry);
373         if (status != Status::SUCCESS) {
374             MEDIA_ERR_LOG("GetEntry error occur, status: %{public}d", status);
375             return static_cast<int32_t>(status);
376         }
377 
378         entryList.emplace_back(std::move(entry));
379         if (entryList.size() >= KVSTORE_MAX_NUMBER_BATCH_INSERT) {
380             newKvstore->BatchInsert(entryList);
381             entryList.clear();
382         }
383     }
384     if (!entryList.empty()) {
385         newKvstore->BatchInsert(entryList);
386     }
387     status = kvStorePtr_->CloseResultSet(resultSet);
388     MEDIA_INFO_LOG("End PutAllValueToNewKvStore");
389     return static_cast<int32_t>(status);
390 }
391 } // namespace OHOS::Media
392