1fc223305Sopenharmony_ci/*
2fc223305Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3fc223305Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fc223305Sopenharmony_ci * you may not use this file except in compliance with the License.
5fc223305Sopenharmony_ci * You may obtain a copy of the License at
6fc223305Sopenharmony_ci *
7fc223305Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8fc223305Sopenharmony_ci *
9fc223305Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fc223305Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fc223305Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fc223305Sopenharmony_ci * See the License for the specific language governing permissions and
13fc223305Sopenharmony_ci * limitations under the License.
14fc223305Sopenharmony_ci */
15fc223305Sopenharmony_ci
16fc223305Sopenharmony_ci#include "preferences_enhance_impl.h"
17fc223305Sopenharmony_ci
18fc223305Sopenharmony_ci#include <cinttypes>
19fc223305Sopenharmony_ci#include <climits>
20fc223305Sopenharmony_ci#include <cstdint>
21fc223305Sopenharmony_ci#include <cstdlib>
22fc223305Sopenharmony_ci#include <functional>
23fc223305Sopenharmony_ci#include <sstream>
24fc223305Sopenharmony_ci#include <thread>
25fc223305Sopenharmony_ci
26fc223305Sopenharmony_ci#include "executor_pool.h"
27fc223305Sopenharmony_ci#include "preferences_file_operation.h"
28fc223305Sopenharmony_ci#include "log_print.h"
29fc223305Sopenharmony_ci#include "preferences_observer_stub.h"
30fc223305Sopenharmony_ci#include "preferences_value.h"
31fc223305Sopenharmony_ci#include "preferences_value_parcel.h"
32fc223305Sopenharmony_ci
33fc223305Sopenharmony_cinamespace OHOS {
34fc223305Sopenharmony_cinamespace NativePreferences {
35fc223305Sopenharmony_ci
36fc223305Sopenharmony_ciconstexpr int32_t CACHED_THRESHOLDS = 512 * 1024; // we will cached big obj(len >= 512k)
37fc223305Sopenharmony_ci
38fc223305Sopenharmony_ciPreferencesEnhanceImpl::PreferencesEnhanceImpl(const Options &options): PreferencesBase(options)
39fc223305Sopenharmony_ci{
40fc223305Sopenharmony_ci}
41fc223305Sopenharmony_ci
42fc223305Sopenharmony_ciPreferencesEnhanceImpl::~PreferencesEnhanceImpl()
43fc223305Sopenharmony_ci{
44fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
45fc223305Sopenharmony_ci    db_ = nullptr;
46fc223305Sopenharmony_ci}
47fc223305Sopenharmony_ci
48fc223305Sopenharmony_ciint PreferencesEnhanceImpl::Init()
49fc223305Sopenharmony_ci{
50fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
51fc223305Sopenharmony_ci    db_ = std::make_shared<PreferencesDb>();
52fc223305Sopenharmony_ci    cachedDataVersion_ = 0;
53fc223305Sopenharmony_ci    int errCode = db_->Init(options_.filePath, options_.bundleName);
54fc223305Sopenharmony_ci    if (errCode != E_OK) {
55fc223305Sopenharmony_ci        db_ = nullptr;
56fc223305Sopenharmony_ci    }
57fc223305Sopenharmony_ci    return errCode;
58fc223305Sopenharmony_ci}
59fc223305Sopenharmony_ci
60fc223305Sopenharmony_ciPreferencesValue PreferencesEnhanceImpl::Get(const std::string &key, const PreferencesValue &defValue)
61fc223305Sopenharmony_ci{
62fc223305Sopenharmony_ci    if (CheckKey(key) != E_OK) {
63fc223305Sopenharmony_ci        return defValue;
64fc223305Sopenharmony_ci    }
65fc223305Sopenharmony_ci    // write lock here, get not support concurrence
66fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
67fc223305Sopenharmony_ci    if (db_ == nullptr) {
68fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Get failed, db has been closed.");
69fc223305Sopenharmony_ci        return defValue;
70fc223305Sopenharmony_ci    }
71fc223305Sopenharmony_ci
72fc223305Sopenharmony_ci    int64_t kernelDataVersion = 0;
73fc223305Sopenharmony_ci    if (db_->GetKernelDataVersion(kernelDataVersion) != E_OK) {
74fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Get failed, get kernel data version failed.");
75fc223305Sopenharmony_ci        return defValue;
76fc223305Sopenharmony_ci    }
77fc223305Sopenharmony_ci    if (kernelDataVersion == cachedDataVersion_) {
78fc223305Sopenharmony_ci        auto it = largeCachedData_.find(key);
79fc223305Sopenharmony_ci        if (it != largeCachedData_.end()) {
80fc223305Sopenharmony_ci            return it->second;
81fc223305Sopenharmony_ci        }
82fc223305Sopenharmony_ci    }
83fc223305Sopenharmony_ci
84fc223305Sopenharmony_ci    std::vector<uint8_t> oriKey(key.begin(), key.end());
85fc223305Sopenharmony_ci    std::vector<uint8_t> oriValue;
86fc223305Sopenharmony_ci    int errCode = db_->Get(oriKey, oriValue);
87fc223305Sopenharmony_ci    if (errCode != E_OK) {
88fc223305Sopenharmony_ci        LOG_ERROR("get key failed, errCode=%{public}d", errCode);
89fc223305Sopenharmony_ci        return defValue;
90fc223305Sopenharmony_ci    }
91fc223305Sopenharmony_ci    auto item = PreferencesValueParcel::UnmarshallingPreferenceValue(oriValue);
92fc223305Sopenharmony_ci    if (item.first != E_OK) {
93fc223305Sopenharmony_ci        LOG_ERROR("get key failed, errCode=%{public}d", item.first);
94fc223305Sopenharmony_ci        return defValue;
95fc223305Sopenharmony_ci    }
96fc223305Sopenharmony_ci    if (oriValue.size() >= CACHED_THRESHOLDS) {
97fc223305Sopenharmony_ci        largeCachedData_.insert_or_assign(key, item.second);
98fc223305Sopenharmony_ci        cachedDataVersion_ = kernelDataVersion;
99fc223305Sopenharmony_ci    }
100fc223305Sopenharmony_ci    return item.second;
101fc223305Sopenharmony_ci}
102fc223305Sopenharmony_ci
103fc223305Sopenharmony_cibool PreferencesEnhanceImpl::HasKey(const std::string &key)
104fc223305Sopenharmony_ci{
105fc223305Sopenharmony_ci    if (CheckKey(key) != E_OK) {
106fc223305Sopenharmony_ci        return false;
107fc223305Sopenharmony_ci    }
108fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
109fc223305Sopenharmony_ci    if (db_ == nullptr) {
110fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:HasKey failed, db has been closed.");
111fc223305Sopenharmony_ci        return false;
112fc223305Sopenharmony_ci    }
113fc223305Sopenharmony_ci
114fc223305Sopenharmony_ci    int64_t kernelDataVersion = 0;
115fc223305Sopenharmony_ci    if (db_->GetKernelDataVersion(kernelDataVersion) != E_OK) {
116fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:HasKey failed, get kernel data version failed.");
117fc223305Sopenharmony_ci        return false;
118fc223305Sopenharmony_ci    }
119fc223305Sopenharmony_ci    if (kernelDataVersion == cachedDataVersion_) {
120fc223305Sopenharmony_ci        auto it = largeCachedData_.find(key);
121fc223305Sopenharmony_ci        if (it != largeCachedData_.end()) {
122fc223305Sopenharmony_ci            return true;
123fc223305Sopenharmony_ci        }
124fc223305Sopenharmony_ci    }
125fc223305Sopenharmony_ci
126fc223305Sopenharmony_ci    std::vector<uint8_t> oriKey(key.begin(), key.end());
127fc223305Sopenharmony_ci    std::vector<uint8_t> oriValue;
128fc223305Sopenharmony_ci    int errCode = db_->Get(oriKey, oriValue);
129fc223305Sopenharmony_ci    if (errCode != E_OK) {
130fc223305Sopenharmony_ci        LOG_ERROR("get key failed, errCode=%{public}d", errCode);
131fc223305Sopenharmony_ci        return false;
132fc223305Sopenharmony_ci    }
133fc223305Sopenharmony_ci    if (oriValue.size() >= CACHED_THRESHOLDS) {
134fc223305Sopenharmony_ci        auto item = PreferencesValueParcel::UnmarshallingPreferenceValue(oriValue);
135fc223305Sopenharmony_ci        if (item.first != E_OK) {
136fc223305Sopenharmony_ci            LOG_WARN("haskey unmarshall failed, haskey return true, errCode=%{public}d", item.first);
137fc223305Sopenharmony_ci            return true;
138fc223305Sopenharmony_ci        }
139fc223305Sopenharmony_ci        largeCachedData_.insert_or_assign(key, item.second);
140fc223305Sopenharmony_ci        cachedDataVersion_ = kernelDataVersion;
141fc223305Sopenharmony_ci    }
142fc223305Sopenharmony_ci    return true;
143fc223305Sopenharmony_ci}
144fc223305Sopenharmony_ci
145fc223305Sopenharmony_ciint PreferencesEnhanceImpl::Put(const std::string &key, const PreferencesValue &value)
146fc223305Sopenharmony_ci{
147fc223305Sopenharmony_ci    int errCode = CheckKey(key);
148fc223305Sopenharmony_ci    if (errCode != E_OK) {
149fc223305Sopenharmony_ci        return errCode;
150fc223305Sopenharmony_ci    }
151fc223305Sopenharmony_ci    errCode = CheckValue(value);
152fc223305Sopenharmony_ci    if (errCode != E_OK) {
153fc223305Sopenharmony_ci        return errCode;
154fc223305Sopenharmony_ci    }
155fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
156fc223305Sopenharmony_ci    if (db_ == nullptr) {
157fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Put failed, db has been closed.");
158fc223305Sopenharmony_ci        return E_ERROR;
159fc223305Sopenharmony_ci    }
160fc223305Sopenharmony_ci
161fc223305Sopenharmony_ci    std::vector<uint8_t> oriValue;
162fc223305Sopenharmony_ci    uint32_t oriValueLen = PreferencesValueParcel::CalSize(value);
163fc223305Sopenharmony_ci    oriValue.resize(oriValueLen);
164fc223305Sopenharmony_ci    errCode = PreferencesValueParcel::MarshallingPreferenceValue(value, oriValue);
165fc223305Sopenharmony_ci    if (errCode != E_OK) {
166fc223305Sopenharmony_ci        LOG_ERROR("marshalling value failed, errCode=%{public}d", errCode);
167fc223305Sopenharmony_ci        return errCode;
168fc223305Sopenharmony_ci    }
169fc223305Sopenharmony_ci    std::vector<uint8_t> oriKey(key.begin(), key.end());
170fc223305Sopenharmony_ci    errCode = db_->Put(oriKey, oriValue);
171fc223305Sopenharmony_ci    if (errCode != E_OK) {
172fc223305Sopenharmony_ci        LOG_ERROR("put data failed, errCode=%{public}d", errCode);
173fc223305Sopenharmony_ci        return errCode;
174fc223305Sopenharmony_ci    }
175fc223305Sopenharmony_ci
176fc223305Sopenharmony_ci    // update cached and version
177fc223305Sopenharmony_ci    if (oriValueLen >= CACHED_THRESHOLDS) {
178fc223305Sopenharmony_ci        largeCachedData_.insert_or_assign(key, value);
179fc223305Sopenharmony_ci        cachedDataVersion_ = cachedDataVersion_ == INT64_MAX ? 0 : cachedDataVersion_ + 1;
180fc223305Sopenharmony_ci    } else {
181fc223305Sopenharmony_ci        auto pos = largeCachedData_.find(key);
182fc223305Sopenharmony_ci        if (pos != largeCachedData_.end()) {
183fc223305Sopenharmony_ci            largeCachedData_.erase(pos);
184fc223305Sopenharmony_ci        }
185fc223305Sopenharmony_ci    }
186fc223305Sopenharmony_ci
187fc223305Sopenharmony_ci    ExecutorPool::Task task = [pref = shared_from_this(), key, value] {
188fc223305Sopenharmony_ci        PreferencesEnhanceImpl::NotifyPreferencesObserver(pref, key, value);
189fc223305Sopenharmony_ci    };
190fc223305Sopenharmony_ci    executorPool_.Execute(std::move(task));
191fc223305Sopenharmony_ci    return E_OK;
192fc223305Sopenharmony_ci}
193fc223305Sopenharmony_ci
194fc223305Sopenharmony_ciint PreferencesEnhanceImpl::Delete(const std::string &key)
195fc223305Sopenharmony_ci{
196fc223305Sopenharmony_ci    int errCode = CheckKey(key);
197fc223305Sopenharmony_ci    if (errCode != E_OK) {
198fc223305Sopenharmony_ci        return errCode;
199fc223305Sopenharmony_ci    }
200fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
201fc223305Sopenharmony_ci    if (db_ == nullptr) {
202fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Delete failed, db has been closed.");
203fc223305Sopenharmony_ci        return E_ERROR;
204fc223305Sopenharmony_ci    }
205fc223305Sopenharmony_ci
206fc223305Sopenharmony_ci    std::vector<uint8_t> oriKey(key.begin(), key.end());
207fc223305Sopenharmony_ci    errCode = db_->Delete(oriKey);
208fc223305Sopenharmony_ci    if (errCode != E_OK) {
209fc223305Sopenharmony_ci        LOG_ERROR("delete data failed, errCode=%{public}d", errCode);
210fc223305Sopenharmony_ci        return errCode;
211fc223305Sopenharmony_ci    }
212fc223305Sopenharmony_ci
213fc223305Sopenharmony_ci    // update cached and version
214fc223305Sopenharmony_ci    auto it = largeCachedData_.find(key);
215fc223305Sopenharmony_ci    if (it != largeCachedData_.end()) {
216fc223305Sopenharmony_ci        largeCachedData_.erase(it);
217fc223305Sopenharmony_ci        cachedDataVersion_ = cachedDataVersion_ == INT64_MAX ? 0 : cachedDataVersion_ + 1;
218fc223305Sopenharmony_ci    }
219fc223305Sopenharmony_ci
220fc223305Sopenharmony_ci    PreferencesValue value;
221fc223305Sopenharmony_ci    ExecutorPool::Task task = [pref = shared_from_this(), key, value] {
222fc223305Sopenharmony_ci        PreferencesEnhanceImpl::NotifyPreferencesObserver(pref, key, value);
223fc223305Sopenharmony_ci    };
224fc223305Sopenharmony_ci    executorPool_.Execute(std::move(task));
225fc223305Sopenharmony_ci    return E_OK;
226fc223305Sopenharmony_ci}
227fc223305Sopenharmony_ci
228fc223305Sopenharmony_cistd::pair<int, std::map<std::string, PreferencesValue>> PreferencesEnhanceImpl::GetAllInner()
229fc223305Sopenharmony_ci{
230fc223305Sopenharmony_ci    std::map<std::string, PreferencesValue> map;
231fc223305Sopenharmony_ci    if (db_ == nullptr) {
232fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:GetAll failed, db has been closed.");
233fc223305Sopenharmony_ci        return std::make_pair(E_ALREADY_CLOSED, map);
234fc223305Sopenharmony_ci    }
235fc223305Sopenharmony_ci
236fc223305Sopenharmony_ci    int64_t kernelDataVersion = 0;
237fc223305Sopenharmony_ci    if (db_->GetKernelDataVersion(kernelDataVersion) != E_OK) {
238fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:GetAll failed, get kernel data version failed.");
239fc223305Sopenharmony_ci        return std::make_pair(E_ERROR, map);
240fc223305Sopenharmony_ci    }
241fc223305Sopenharmony_ci
242fc223305Sopenharmony_ci    std::map<std::string, PreferencesValue> result;
243fc223305Sopenharmony_ci    std::list<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> data;
244fc223305Sopenharmony_ci    int errCode = db_->GetAll(data);
245fc223305Sopenharmony_ci    if (errCode != E_OK) {
246fc223305Sopenharmony_ci        LOG_ERROR("get all failed, errCode=%{public}d", errCode);
247fc223305Sopenharmony_ci        return std::make_pair(errCode, map);
248fc223305Sopenharmony_ci    }
249fc223305Sopenharmony_ci    for (auto it = data.begin(); it != data.end(); it++) {
250fc223305Sopenharmony_ci        std::string key(it->first.begin(), it->first.end());
251fc223305Sopenharmony_ci        auto item = PreferencesValueParcel::UnmarshallingPreferenceValue(it->second);
252fc223305Sopenharmony_ci        result.insert({key, item.second});
253fc223305Sopenharmony_ci        if (item.first != E_OK) {
254fc223305Sopenharmony_ci            LOG_ERROR("get key failed, errCode=%{public}d", errCode);
255fc223305Sopenharmony_ci            return std::make_pair(item.first, map);
256fc223305Sopenharmony_ci        }
257fc223305Sopenharmony_ci        if (it->second.size() >= CACHED_THRESHOLDS) {
258fc223305Sopenharmony_ci            largeCachedData_.insert_or_assign(key, item.second);
259fc223305Sopenharmony_ci        }
260fc223305Sopenharmony_ci    }
261fc223305Sopenharmony_ci    cachedDataVersion_ = kernelDataVersion;
262fc223305Sopenharmony_ci    return std::make_pair(E_OK, result);
263fc223305Sopenharmony_ci}
264fc223305Sopenharmony_ci
265fc223305Sopenharmony_cistd::map<std::string, PreferencesValue> PreferencesEnhanceImpl::GetAll()
266fc223305Sopenharmony_ci{
267fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
268fc223305Sopenharmony_ci    std::pair<int, std::map<std::string, PreferencesValue>> res = GetAllInner();
269fc223305Sopenharmony_ci    return res.second;
270fc223305Sopenharmony_ci}
271fc223305Sopenharmony_ci
272fc223305Sopenharmony_civoid PreferencesEnhanceImpl::NotifyPreferencesObserver(std::shared_ptr<PreferencesEnhanceImpl> pref,
273fc223305Sopenharmony_ci    const std::string &key, const PreferencesValue &value)
274fc223305Sopenharmony_ci{
275fc223305Sopenharmony_ci    std::shared_lock<std::shared_mutex> readLock(pref->obseverMetux_);
276fc223305Sopenharmony_ci    LOG_DEBUG("notify observer size:%{public}zu", pref->dataObserversMap_.size());
277fc223305Sopenharmony_ci    for (const auto &[weakPrt, keys] : pref->dataObserversMap_) {
278fc223305Sopenharmony_ci        auto itKey = keys.find(key);
279fc223305Sopenharmony_ci        if (itKey == keys.end()) {
280fc223305Sopenharmony_ci            continue;
281fc223305Sopenharmony_ci        }
282fc223305Sopenharmony_ci        std::map<std::string, PreferencesValue> records = {{key, value}};
283fc223305Sopenharmony_ci        if (std::shared_ptr<PreferencesObserver> sharedPtr = weakPrt.lock()) {
284fc223305Sopenharmony_ci            LOG_DEBUG("dataChange observer call, resultSize:%{public}zu", records.size());
285fc223305Sopenharmony_ci            sharedPtr->OnChange(records);
286fc223305Sopenharmony_ci        }
287fc223305Sopenharmony_ci    }
288fc223305Sopenharmony_ci    auto dataObsMgrClient = DataObsMgrClient::GetInstance();
289fc223305Sopenharmony_ci    for (auto it = pref->localObservers_.begin(); it != pref->localObservers_.end(); ++it) {
290fc223305Sopenharmony_ci        std::weak_ptr<PreferencesObserver> weakPreferencesObserver = *it;
291fc223305Sopenharmony_ci        if (std::shared_ptr<PreferencesObserver> sharedPreferencesObserver = weakPreferencesObserver.lock()) {
292fc223305Sopenharmony_ci            sharedPreferencesObserver->OnChange(key);
293fc223305Sopenharmony_ci        }
294fc223305Sopenharmony_ci    }
295fc223305Sopenharmony_ci    if (dataObsMgrClient != nullptr) {
296fc223305Sopenharmony_ci        dataObsMgrClient->NotifyChange(pref->MakeUri(key));
297fc223305Sopenharmony_ci    }
298fc223305Sopenharmony_ci}
299fc223305Sopenharmony_ci
300fc223305Sopenharmony_civoid PreferencesEnhanceImpl::NotifyPreferencesObserverBatchKeys(std::shared_ptr<PreferencesEnhanceImpl> pref,
301fc223305Sopenharmony_ci    const std::map<std::string, PreferencesValue> &data)
302fc223305Sopenharmony_ci{
303fc223305Sopenharmony_ci    for (const auto &[key, value] : data) {
304fc223305Sopenharmony_ci        NotifyPreferencesObserver(pref, key, value);
305fc223305Sopenharmony_ci    }
306fc223305Sopenharmony_ci}
307fc223305Sopenharmony_ci
308fc223305Sopenharmony_ciint PreferencesEnhanceImpl::Clear()
309fc223305Sopenharmony_ci{
310fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
311fc223305Sopenharmony_ci    LOG_INFO("Clear called, file: %{public}s", ExtractFileName(options_.filePath).c_str());
312fc223305Sopenharmony_ci    if (db_ == nullptr) {
313fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Clear failed, db has been closed.");
314fc223305Sopenharmony_ci        return E_ERROR;
315fc223305Sopenharmony_ci    }
316fc223305Sopenharmony_ci
317fc223305Sopenharmony_ci    std::pair<int, std::map<std::string, PreferencesValue>> res = GetAllInner();
318fc223305Sopenharmony_ci    if (res.first != E_OK) {
319fc223305Sopenharmony_ci        LOG_ERROR("get all failed when clear, errCode=%{public}d", res.first);
320fc223305Sopenharmony_ci        return res.first;
321fc223305Sopenharmony_ci    }
322fc223305Sopenharmony_ci
323fc223305Sopenharmony_ci    std::map<std::string, PreferencesValue> allData = res.second;
324fc223305Sopenharmony_ci
325fc223305Sopenharmony_ci    int errCode = db_->DropCollection();
326fc223305Sopenharmony_ci    if (errCode != E_OK) {
327fc223305Sopenharmony_ci        LOG_ERROR("drop collection failed when clear, errCode=%{public}d", errCode);
328fc223305Sopenharmony_ci        return errCode;
329fc223305Sopenharmony_ci    }
330fc223305Sopenharmony_ci
331fc223305Sopenharmony_ci    if (!allData.empty()) {
332fc223305Sopenharmony_ci        ExecutorPool::Task task = [pref = shared_from_this(), allData] {
333fc223305Sopenharmony_ci            PreferencesEnhanceImpl::NotifyPreferencesObserverBatchKeys(pref, allData);
334fc223305Sopenharmony_ci        };
335fc223305Sopenharmony_ci        executorPool_.Execute(std::move(task));
336fc223305Sopenharmony_ci    }
337fc223305Sopenharmony_ci
338fc223305Sopenharmony_ci    errCode = db_->CreateCollection();
339fc223305Sopenharmony_ci    if (errCode != E_OK) {
340fc223305Sopenharmony_ci        LOG_ERROR("create collection failed when clear, errCode=%{public}d", errCode);
341fc223305Sopenharmony_ci        return errCode;
342fc223305Sopenharmony_ci    }
343fc223305Sopenharmony_ci    largeCachedData_.clear();
344fc223305Sopenharmony_ci    cachedDataVersion_ = cachedDataVersion_ == INT64_MAX ? 0 : cachedDataVersion_ + 1;
345fc223305Sopenharmony_ci    return E_OK;
346fc223305Sopenharmony_ci}
347fc223305Sopenharmony_ci
348fc223305Sopenharmony_ciint PreferencesEnhanceImpl::CloseDb()
349fc223305Sopenharmony_ci{
350fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
351fc223305Sopenharmony_ci    if (db_ == nullptr) {
352fc223305Sopenharmony_ci        LOG_WARN("PreferencesEnhanceImpl:CloseDb failed, db has been closed, no need to close again.");
353fc223305Sopenharmony_ci        return E_OK;
354fc223305Sopenharmony_ci    }
355fc223305Sopenharmony_ci    int errCode = db_->CloseDb();
356fc223305Sopenharmony_ci    if (errCode != E_OK) {
357fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:CloseDb failed.");
358fc223305Sopenharmony_ci        return errCode;
359fc223305Sopenharmony_ci    }
360fc223305Sopenharmony_ci    largeCachedData_.clear();
361fc223305Sopenharmony_ci    db_ = nullptr;
362fc223305Sopenharmony_ci    return E_OK;
363fc223305Sopenharmony_ci}
364fc223305Sopenharmony_ci
365fc223305Sopenharmony_cistd::pair<int, PreferencesValue> PreferencesEnhanceImpl::GetValue(const std::string &key,
366fc223305Sopenharmony_ci    const PreferencesValue &defValue)
367fc223305Sopenharmony_ci{
368fc223305Sopenharmony_ci    int errCode = CheckKey(key);
369fc223305Sopenharmony_ci    if (errCode != E_OK) {
370fc223305Sopenharmony_ci        return std::make_pair(errCode, defValue);
371fc223305Sopenharmony_ci    }
372fc223305Sopenharmony_ci    // write lock here, get not support concurrence
373fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
374fc223305Sopenharmony_ci    if (db_ == nullptr) {
375fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Get failed, db has been closed.");
376fc223305Sopenharmony_ci        return std::make_pair(E_ALREADY_CLOSED, defValue);
377fc223305Sopenharmony_ci    }
378fc223305Sopenharmony_ci
379fc223305Sopenharmony_ci    int64_t kernelDataVersion = 0;
380fc223305Sopenharmony_ci    if (db_->GetKernelDataVersion(kernelDataVersion) != E_OK) {
381fc223305Sopenharmony_ci        LOG_ERROR("PreferencesEnhanceImpl:Get failed, get kernel data version failed.");
382fc223305Sopenharmony_ci        return std::make_pair(E_ERROR, defValue);
383fc223305Sopenharmony_ci    }
384fc223305Sopenharmony_ci    if (kernelDataVersion == cachedDataVersion_) {
385fc223305Sopenharmony_ci        auto it = largeCachedData_.find(key);
386fc223305Sopenharmony_ci        if (it != largeCachedData_.end()) {
387fc223305Sopenharmony_ci            return std::make_pair(E_OK, it->second);
388fc223305Sopenharmony_ci        }
389fc223305Sopenharmony_ci    }
390fc223305Sopenharmony_ci
391fc223305Sopenharmony_ci    std::vector<uint8_t> oriKey(key.begin(), key.end());
392fc223305Sopenharmony_ci    std::vector<uint8_t> oriValue;
393fc223305Sopenharmony_ci    errCode = db_->Get(oriKey, oriValue);
394fc223305Sopenharmony_ci    if (errCode != E_OK) {
395fc223305Sopenharmony_ci        LOG_ERROR("get key failed, errCode=%{public}d", errCode);
396fc223305Sopenharmony_ci        return std::make_pair(errCode, defValue);
397fc223305Sopenharmony_ci    }
398fc223305Sopenharmony_ci    auto item = PreferencesValueParcel::UnmarshallingPreferenceValue(oriValue);
399fc223305Sopenharmony_ci    if (item.first != E_OK) {
400fc223305Sopenharmony_ci        LOG_ERROR("get key failed, errCode=%{public}d", item.first);
401fc223305Sopenharmony_ci        return std::make_pair(item.first, defValue);
402fc223305Sopenharmony_ci    }
403fc223305Sopenharmony_ci    if (oriValue.size() >= CACHED_THRESHOLDS) {
404fc223305Sopenharmony_ci        largeCachedData_.insert_or_assign(key, item.second);
405fc223305Sopenharmony_ci        cachedDataVersion_ = kernelDataVersion;
406fc223305Sopenharmony_ci    }
407fc223305Sopenharmony_ci    return std::make_pair(E_OK, item.second);
408fc223305Sopenharmony_ci}
409fc223305Sopenharmony_ci
410fc223305Sopenharmony_cistd::pair<int, std::map<std::string, PreferencesValue>> PreferencesEnhanceImpl::GetAllData()
411fc223305Sopenharmony_ci{
412fc223305Sopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(dbMutex_);
413fc223305Sopenharmony_ci    return GetAllInner();
414fc223305Sopenharmony_ci}
415fc223305Sopenharmony_ci} // End of namespace NativePreferences
416fc223305Sopenharmony_ci} // End of namespace OHOS
417