1fc223305Sopenharmony_ci/*
2fc223305Sopenharmony_ci * Copyright (c) 2021 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_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#include <chrono>
26fc223305Sopenharmony_ci#include <cinttypes>
27fc223305Sopenharmony_ci
28fc223305Sopenharmony_ci#include "base64_helper.h"
29fc223305Sopenharmony_ci#include "executor_pool.h"
30fc223305Sopenharmony_ci#include "log_print.h"
31fc223305Sopenharmony_ci#include "preferences_observer_stub.h"
32fc223305Sopenharmony_ci#include "preferences_xml_utils.h"
33fc223305Sopenharmony_ci#include "preferences_file_operation.h"
34fc223305Sopenharmony_ci#include "preferences_anonymous.h"
35fc223305Sopenharmony_ci
36fc223305Sopenharmony_cinamespace OHOS {
37fc223305Sopenharmony_cinamespace NativePreferences {
38fc223305Sopenharmony_ci
39fc223305Sopenharmony_ciusing namespace std::chrono;
40fc223305Sopenharmony_ci
41fc223305Sopenharmony_ciconstexpr int32_t WAIT_TIME = 2;
42fc223305Sopenharmony_ciconstexpr int32_t TASK_EXEC_TIME = 100;
43fc223305Sopenharmony_ci
44fc223305Sopenharmony_citemplate<typename T>
45fc223305Sopenharmony_cistd::string GetTypeName()
46fc223305Sopenharmony_ci{
47fc223305Sopenharmony_ci    return "unknown";
48fc223305Sopenharmony_ci}
49fc223305Sopenharmony_ci
50fc223305Sopenharmony_citemplate<>
51fc223305Sopenharmony_cistd::string GetTypeName<int>()
52fc223305Sopenharmony_ci{
53fc223305Sopenharmony_ci    return "int";
54fc223305Sopenharmony_ci}
55fc223305Sopenharmony_ci
56fc223305Sopenharmony_citemplate<>
57fc223305Sopenharmony_cistd::string GetTypeName<bool>()
58fc223305Sopenharmony_ci{
59fc223305Sopenharmony_ci    return "bool";
60fc223305Sopenharmony_ci}
61fc223305Sopenharmony_ci
62fc223305Sopenharmony_citemplate<>
63fc223305Sopenharmony_cistd::string GetTypeName<int64_t>()
64fc223305Sopenharmony_ci{
65fc223305Sopenharmony_ci    return "long";
66fc223305Sopenharmony_ci}
67fc223305Sopenharmony_ci
68fc223305Sopenharmony_citemplate<>
69fc223305Sopenharmony_cistd::string GetTypeName<uint64_t>()
70fc223305Sopenharmony_ci{
71fc223305Sopenharmony_ci    return "uint64_t";
72fc223305Sopenharmony_ci}
73fc223305Sopenharmony_ci
74fc223305Sopenharmony_citemplate<>
75fc223305Sopenharmony_cistd::string GetTypeName<float>()
76fc223305Sopenharmony_ci{
77fc223305Sopenharmony_ci    return "float";
78fc223305Sopenharmony_ci}
79fc223305Sopenharmony_ci
80fc223305Sopenharmony_citemplate<>
81fc223305Sopenharmony_cistd::string GetTypeName<double>()
82fc223305Sopenharmony_ci{
83fc223305Sopenharmony_ci    return "double";
84fc223305Sopenharmony_ci}
85fc223305Sopenharmony_ci
86fc223305Sopenharmony_citemplate<>
87fc223305Sopenharmony_cistd::string GetTypeName<std::string>()
88fc223305Sopenharmony_ci{
89fc223305Sopenharmony_ci    return "string";
90fc223305Sopenharmony_ci}
91fc223305Sopenharmony_ci
92fc223305Sopenharmony_citemplate<>
93fc223305Sopenharmony_cistd::string GetTypeName<std::vector<std::string>>()
94fc223305Sopenharmony_ci{
95fc223305Sopenharmony_ci    return "stringArray";
96fc223305Sopenharmony_ci}
97fc223305Sopenharmony_ci
98fc223305Sopenharmony_citemplate<>
99fc223305Sopenharmony_cistd::string GetTypeName<std::vector<double>>()
100fc223305Sopenharmony_ci{
101fc223305Sopenharmony_ci    return "doubleArray";
102fc223305Sopenharmony_ci}
103fc223305Sopenharmony_ci
104fc223305Sopenharmony_citemplate<>
105fc223305Sopenharmony_cistd::string GetTypeName<std::vector<bool>>()
106fc223305Sopenharmony_ci{
107fc223305Sopenharmony_ci    return "boolArray";
108fc223305Sopenharmony_ci}
109fc223305Sopenharmony_ci
110fc223305Sopenharmony_citemplate<>
111fc223305Sopenharmony_cistd::string GetTypeName<std::vector<uint8_t>>()
112fc223305Sopenharmony_ci{
113fc223305Sopenharmony_ci    return "uint8Array";
114fc223305Sopenharmony_ci}
115fc223305Sopenharmony_ci
116fc223305Sopenharmony_citemplate<>
117fc223305Sopenharmony_cistd::string GetTypeName<Object>()
118fc223305Sopenharmony_ci{
119fc223305Sopenharmony_ci    return "object";
120fc223305Sopenharmony_ci}
121fc223305Sopenharmony_ci
122fc223305Sopenharmony_citemplate<>
123fc223305Sopenharmony_cistd::string GetTypeName<BigInt>()
124fc223305Sopenharmony_ci{
125fc223305Sopenharmony_ci    return "BigInt";
126fc223305Sopenharmony_ci}
127fc223305Sopenharmony_ci
128fc223305Sopenharmony_ciPreferencesImpl::PreferencesImpl(const Options &options) : PreferencesBase(options)
129fc223305Sopenharmony_ci{
130fc223305Sopenharmony_ci    loaded_.store(false);
131fc223305Sopenharmony_ci    currentMemoryStateGeneration_ = 0;
132fc223305Sopenharmony_ci    diskStateGeneration_ = 0;
133fc223305Sopenharmony_ci    queue_ = std::make_shared<SafeBlockQueue<uint64_t>>(1);
134fc223305Sopenharmony_ci}
135fc223305Sopenharmony_ci
136fc223305Sopenharmony_ciPreferencesImpl::~PreferencesImpl()
137fc223305Sopenharmony_ci{
138fc223305Sopenharmony_ci}
139fc223305Sopenharmony_ci
140fc223305Sopenharmony_ciint PreferencesImpl::Init()
141fc223305Sopenharmony_ci{
142fc223305Sopenharmony_ci    if (!StartLoadFromDisk()) {
143fc223305Sopenharmony_ci        return E_ERROR;
144fc223305Sopenharmony_ci    }
145fc223305Sopenharmony_ci    return E_OK;
146fc223305Sopenharmony_ci}
147fc223305Sopenharmony_ci
148fc223305Sopenharmony_cibool PreferencesImpl::StartLoadFromDisk()
149fc223305Sopenharmony_ci{
150fc223305Sopenharmony_ci    loaded_.store(false);
151fc223305Sopenharmony_ci
152fc223305Sopenharmony_ci    ExecutorPool::Task task = [pref = shared_from_this()] { PreferencesImpl::LoadFromDisk(pref); };
153fc223305Sopenharmony_ci    return (executorPool_.Execute(std::move(task)) == ExecutorPool::INVALID_TASK_ID) ? false : true;
154fc223305Sopenharmony_ci}
155fc223305Sopenharmony_ci
156fc223305Sopenharmony_ci/* static */
157fc223305Sopenharmony_civoid PreferencesImpl::LoadFromDisk(std::shared_ptr<PreferencesImpl> pref)
158fc223305Sopenharmony_ci{
159fc223305Sopenharmony_ci    if (pref->loaded_.load()) {
160fc223305Sopenharmony_ci        return;
161fc223305Sopenharmony_ci    }
162fc223305Sopenharmony_ci    std::lock_guard<std::mutex> lock(pref->mutex_);
163fc223305Sopenharmony_ci    if (!pref->loaded_.load()) {
164fc223305Sopenharmony_ci        bool loadResult = PreferencesImpl::ReadSettingXml(pref);
165fc223305Sopenharmony_ci        if (!loadResult) {
166fc223305Sopenharmony_ci            LOG_WARN("The settingXml %{public}s load failed.", ExtractFileName(pref->options_.filePath).c_str());
167fc223305Sopenharmony_ci        }
168fc223305Sopenharmony_ci        pref->loaded_.store(true);
169fc223305Sopenharmony_ci        pref->cond_.notify_all();
170fc223305Sopenharmony_ci    }
171fc223305Sopenharmony_ci}
172fc223305Sopenharmony_ci
173fc223305Sopenharmony_civoid PreferencesImpl::AwaitLoadFile()
174fc223305Sopenharmony_ci{
175fc223305Sopenharmony_ci    if (loaded_.load()) {
176fc223305Sopenharmony_ci        return;
177fc223305Sopenharmony_ci    }
178fc223305Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
179fc223305Sopenharmony_ci    if (!loaded_.load()) {
180fc223305Sopenharmony_ci        cond_.wait_for(lock, std::chrono::seconds(WAIT_TIME), [this] { return loaded_.load(); });
181fc223305Sopenharmony_ci    }
182fc223305Sopenharmony_ci
183fc223305Sopenharmony_ci    if (!loaded_.load()) {
184fc223305Sopenharmony_ci        LOG_ERROR("The settingXml %{public}s load timeout.", ExtractFileName(options_.filePath).c_str());
185fc223305Sopenharmony_ci    }
186fc223305Sopenharmony_ci}
187fc223305Sopenharmony_ci
188fc223305Sopenharmony_ciPreferencesValue PreferencesImpl::Get(const std::string &key, const PreferencesValue &defValue)
189fc223305Sopenharmony_ci{
190fc223305Sopenharmony_ci    if (CheckKey(key) != E_OK) {
191fc223305Sopenharmony_ci        return defValue;
192fc223305Sopenharmony_ci    }
193fc223305Sopenharmony_ci
194fc223305Sopenharmony_ci    AwaitLoadFile();
195fc223305Sopenharmony_ci
196fc223305Sopenharmony_ci    auto it = valuesCache_.Find(key);
197fc223305Sopenharmony_ci    if (it.first) {
198fc223305Sopenharmony_ci        return it.second;
199fc223305Sopenharmony_ci    }
200fc223305Sopenharmony_ci    return defValue;
201fc223305Sopenharmony_ci}
202fc223305Sopenharmony_ci
203fc223305Sopenharmony_cistd::map<std::string, PreferencesValue> PreferencesImpl::GetAll()
204fc223305Sopenharmony_ci{
205fc223305Sopenharmony_ci    AwaitLoadFile();
206fc223305Sopenharmony_ci    return valuesCache_.Clone();
207fc223305Sopenharmony_ci}
208fc223305Sopenharmony_ci
209fc223305Sopenharmony_citemplate<typename T>
210fc223305Sopenharmony_cistatic void Convert2PrefValue(const Element &element, T &value)
211fc223305Sopenharmony_ci{
212fc223305Sopenharmony_ci    if constexpr (std::is_same<T, bool>::value) {
213fc223305Sopenharmony_ci        value = (element.value_.compare("true") == 0) ? true : false;
214fc223305Sopenharmony_ci    } else if constexpr (std::is_same<T, std::string>::value) {
215fc223305Sopenharmony_ci        value = element.value_;
216fc223305Sopenharmony_ci    } else if constexpr (std::is_same<T, std::monostate>::value) {
217fc223305Sopenharmony_ci        value = std::monostate();
218fc223305Sopenharmony_ci    } else {
219fc223305Sopenharmony_ci        std::stringstream ss;
220fc223305Sopenharmony_ci        ss << element.value_;
221fc223305Sopenharmony_ci        ss >> value;
222fc223305Sopenharmony_ci    }
223fc223305Sopenharmony_ci}
224fc223305Sopenharmony_ci
225fc223305Sopenharmony_citemplate<typename T>
226fc223305Sopenharmony_cistatic void Convert2PrefValue(const Element &element, std::vector<T> &values)
227fc223305Sopenharmony_ci{
228fc223305Sopenharmony_ci    for (const auto &child : element.children_) {
229fc223305Sopenharmony_ci        T value;
230fc223305Sopenharmony_ci        Convert2PrefValue(child, value);
231fc223305Sopenharmony_ci        values.push_back(value);
232fc223305Sopenharmony_ci    }
233fc223305Sopenharmony_ci}
234fc223305Sopenharmony_ci
235fc223305Sopenharmony_cistatic void Convert2PrefValue(const Element &element, BigInt &value)
236fc223305Sopenharmony_ci{
237fc223305Sopenharmony_ci    for (const auto &child : element.children_) {
238fc223305Sopenharmony_ci        uint64_t val;
239fc223305Sopenharmony_ci        Convert2PrefValue(child, val);
240fc223305Sopenharmony_ci        value.words_.push_back(val);
241fc223305Sopenharmony_ci    }
242fc223305Sopenharmony_ci    value.sign_ = 0;
243fc223305Sopenharmony_ci    if (!value.words_.empty()) {
244fc223305Sopenharmony_ci        value.sign_ = static_cast<int>(value.words_[value.words_.size() - 1]);
245fc223305Sopenharmony_ci        value.words_.pop_back();
246fc223305Sopenharmony_ci    }
247fc223305Sopenharmony_ci}
248fc223305Sopenharmony_ci
249fc223305Sopenharmony_citemplate<typename T>
250fc223305Sopenharmony_cibool GetPrefValue(const Element &element, T &value)
251fc223305Sopenharmony_ci{
252fc223305Sopenharmony_ci    LOG_WARN("unknown element type. the key is %{public}s", Anonymous::ToBeAnonymous(element.key_).c_str());
253fc223305Sopenharmony_ci    return false;
254fc223305Sopenharmony_ci}
255fc223305Sopenharmony_ci
256fc223305Sopenharmony_cistatic void Convert2PrefValue(const Element &element, std::vector<uint8_t> &value)
257fc223305Sopenharmony_ci{
258fc223305Sopenharmony_ci    if (!Base64Helper::Decode(element.value_, value)) {
259fc223305Sopenharmony_ci        value.clear();
260fc223305Sopenharmony_ci    }
261fc223305Sopenharmony_ci}
262fc223305Sopenharmony_ci
263fc223305Sopenharmony_cistatic void Convert2PrefValue(const Element &element, Object &value)
264fc223305Sopenharmony_ci{
265fc223305Sopenharmony_ci    value.valueStr = element.value_;
266fc223305Sopenharmony_ci}
267fc223305Sopenharmony_ci
268fc223305Sopenharmony_citemplate<typename T, typename First, typename... Types>
269fc223305Sopenharmony_cibool GetPrefValue(const Element &element, T &value)
270fc223305Sopenharmony_ci{
271fc223305Sopenharmony_ci    if (element.tag_ == GetTypeName<First>()) {
272fc223305Sopenharmony_ci        First val;
273fc223305Sopenharmony_ci        Convert2PrefValue(element, val);
274fc223305Sopenharmony_ci        value = val;
275fc223305Sopenharmony_ci        return true;
276fc223305Sopenharmony_ci    }
277fc223305Sopenharmony_ci    return GetPrefValue<T, Types...>(element, value);
278fc223305Sopenharmony_ci}
279fc223305Sopenharmony_ci
280fc223305Sopenharmony_citemplate<typename... Types>
281fc223305Sopenharmony_cibool Convert2PrefValue(const Element &element, std::variant<Types...> &value)
282fc223305Sopenharmony_ci{
283fc223305Sopenharmony_ci    return GetPrefValue<decltype(value), Types...>(element, value);
284fc223305Sopenharmony_ci}
285fc223305Sopenharmony_ci
286fc223305Sopenharmony_civoid ReadXmlElement(const Element &element, std::map<std::string, PreferencesValue> &prefMap)
287fc223305Sopenharmony_ci{
288fc223305Sopenharmony_ci    PreferencesValue value(static_cast<int64_t>(0));
289fc223305Sopenharmony_ci    if (Convert2PrefValue(element, value.value_)) {
290fc223305Sopenharmony_ci        prefMap.insert(std::make_pair(element.key_, value));
291fc223305Sopenharmony_ci    }
292fc223305Sopenharmony_ci}
293fc223305Sopenharmony_ci
294fc223305Sopenharmony_cibool PreferencesImpl::ReadSettingXml(std::shared_ptr<PreferencesImpl> pref)
295fc223305Sopenharmony_ci{
296fc223305Sopenharmony_ci    std::vector<Element> settings;
297fc223305Sopenharmony_ci    if (!PreferencesXmlUtils::ReadSettingXml(pref->options_.filePath, pref->options_.bundleName,
298fc223305Sopenharmony_ci        pref->options_.dataGroupId, settings)) {
299fc223305Sopenharmony_ci        return false;
300fc223305Sopenharmony_ci    }
301fc223305Sopenharmony_ci
302fc223305Sopenharmony_ci    std::map<std::string, PreferencesValue> values;
303fc223305Sopenharmony_ci    for (const auto &element : settings) {
304fc223305Sopenharmony_ci        ReadXmlElement(element, values);
305fc223305Sopenharmony_ci    }
306fc223305Sopenharmony_ci    pref->valuesCache_ = std::move(values);
307fc223305Sopenharmony_ci    return true;
308fc223305Sopenharmony_ci}
309fc223305Sopenharmony_ci
310fc223305Sopenharmony_citemplate<typename T>
311fc223305Sopenharmony_civoid Convert2Element(Element &elem, const T &value)
312fc223305Sopenharmony_ci{
313fc223305Sopenharmony_ci    elem.tag_ = GetTypeName<T>();
314fc223305Sopenharmony_ci    if constexpr (std::is_same<T, bool>::value) {
315fc223305Sopenharmony_ci        elem.value_ = ((bool)value) ? "true" : "false";
316fc223305Sopenharmony_ci    } else if constexpr (std::is_same<T, std::string>::value) {
317fc223305Sopenharmony_ci        elem.value_ = value;
318fc223305Sopenharmony_ci    } else if constexpr (std::is_same<T, std::monostate>::value) {
319fc223305Sopenharmony_ci        elem.value_ = {};
320fc223305Sopenharmony_ci    } else {
321fc223305Sopenharmony_ci        elem.value_ = std::to_string(value);
322fc223305Sopenharmony_ci    }
323fc223305Sopenharmony_ci}
324fc223305Sopenharmony_ci
325fc223305Sopenharmony_citemplate<typename T>
326fc223305Sopenharmony_civoid Convert2Element(Element &elem, const std::vector<T> &value)
327fc223305Sopenharmony_ci{
328fc223305Sopenharmony_ci    elem.tag_ = GetTypeName<std::vector<T>>();
329fc223305Sopenharmony_ci    for (const T &val : value) {
330fc223305Sopenharmony_ci        Element element;
331fc223305Sopenharmony_ci        Convert2Element(element, val);
332fc223305Sopenharmony_ci        elem.children_.push_back(element);
333fc223305Sopenharmony_ci    }
334fc223305Sopenharmony_ci}
335fc223305Sopenharmony_ci
336fc223305Sopenharmony_civoid Convert2Element(Element &elem, const std::vector<uint8_t> &value)
337fc223305Sopenharmony_ci{
338fc223305Sopenharmony_ci    elem.tag_ = GetTypeName<std::vector<uint8_t>>();
339fc223305Sopenharmony_ci    elem.value_ = Base64Helper::Encode(value);
340fc223305Sopenharmony_ci}
341fc223305Sopenharmony_ci
342fc223305Sopenharmony_civoid Convert2Element(Element &elem, const Object &value)
343fc223305Sopenharmony_ci{
344fc223305Sopenharmony_ci    elem.tag_ = GetTypeName<Object>();
345fc223305Sopenharmony_ci    elem.value_ = value.valueStr;
346fc223305Sopenharmony_ci}
347fc223305Sopenharmony_ci
348fc223305Sopenharmony_civoid Convert2Element(Element &elem, const BigInt &value)
349fc223305Sopenharmony_ci{
350fc223305Sopenharmony_ci    elem.tag_ = GetTypeName<BigInt>();
351fc223305Sopenharmony_ci    for (const auto &val : value.words_) {
352fc223305Sopenharmony_ci        Element element;
353fc223305Sopenharmony_ci        Convert2Element(element, val);
354fc223305Sopenharmony_ci        elem.children_.push_back(element);
355fc223305Sopenharmony_ci    }
356fc223305Sopenharmony_ci    // place symbol at the end
357fc223305Sopenharmony_ci    Element symbolElement;
358fc223305Sopenharmony_ci    Convert2Element(symbolElement, static_cast<uint64_t>(value.sign_));
359fc223305Sopenharmony_ci    elem.children_.push_back(symbolElement);
360fc223305Sopenharmony_ci}
361fc223305Sopenharmony_ci
362fc223305Sopenharmony_citemplate<typename T> void GetElement(Element &elem, const T &value)
363fc223305Sopenharmony_ci{
364fc223305Sopenharmony_ci    LOG_WARN("unknown element type. the key is %{public}s", Anonymous::ToBeAnonymous(elem.key_).c_str());
365fc223305Sopenharmony_ci}
366fc223305Sopenharmony_ci
367fc223305Sopenharmony_citemplate<typename T, typename First, typename... Types> void GetElement(Element &elem, const T &value)
368fc223305Sopenharmony_ci{
369fc223305Sopenharmony_ci    auto *val = std::get_if<First>(&value);
370fc223305Sopenharmony_ci    if (val != nullptr) {
371fc223305Sopenharmony_ci        return Convert2Element(elem, *val);
372fc223305Sopenharmony_ci    }
373fc223305Sopenharmony_ci    return GetElement<T, Types...>(elem, value);
374fc223305Sopenharmony_ci}
375fc223305Sopenharmony_ci
376fc223305Sopenharmony_citemplate<typename... Types> void Convert2Element(Element &elem, const std::variant<Types...> &value)
377fc223305Sopenharmony_ci{
378fc223305Sopenharmony_ci    return GetElement<decltype(value), Types...>(elem, value);
379fc223305Sopenharmony_ci}
380fc223305Sopenharmony_ci
381fc223305Sopenharmony_civoid WriteXmlElement(Element &elem, const PreferencesValue &value)
382fc223305Sopenharmony_ci{
383fc223305Sopenharmony_ci    Convert2Element(elem, value.value_);
384fc223305Sopenharmony_ci}
385fc223305Sopenharmony_ci
386fc223305Sopenharmony_cibool PreferencesImpl::WriteSettingXml(
387fc223305Sopenharmony_ci    const Options &options, const std::map<std::string, PreferencesValue> &writeToDiskMap)
388fc223305Sopenharmony_ci{
389fc223305Sopenharmony_ci    std::vector<Element> settings;
390fc223305Sopenharmony_ci    for (auto it = writeToDiskMap.begin(); it != writeToDiskMap.end(); it++) {
391fc223305Sopenharmony_ci        Element elem;
392fc223305Sopenharmony_ci        elem.key_ = it->first;
393fc223305Sopenharmony_ci        PreferencesValue value = it->second;
394fc223305Sopenharmony_ci        WriteXmlElement(elem, value);
395fc223305Sopenharmony_ci        settings.push_back(elem);
396fc223305Sopenharmony_ci    }
397fc223305Sopenharmony_ci
398fc223305Sopenharmony_ci    return PreferencesXmlUtils::WriteSettingXml(options.filePath, options.bundleName, options.dataGroupId, settings);
399fc223305Sopenharmony_ci}
400fc223305Sopenharmony_ci
401fc223305Sopenharmony_ci
402fc223305Sopenharmony_cibool PreferencesImpl::HasKey(const std::string &key)
403fc223305Sopenharmony_ci{
404fc223305Sopenharmony_ci    if (CheckKey(key) != E_OK) {
405fc223305Sopenharmony_ci        return false;
406fc223305Sopenharmony_ci    }
407fc223305Sopenharmony_ci
408fc223305Sopenharmony_ci    AwaitLoadFile();
409fc223305Sopenharmony_ci    return valuesCache_.Contains(key);
410fc223305Sopenharmony_ci}
411fc223305Sopenharmony_ci
412fc223305Sopenharmony_ciint PreferencesImpl::Put(const std::string &key, const PreferencesValue &value)
413fc223305Sopenharmony_ci{
414fc223305Sopenharmony_ci    int errCode = CheckKey(key);
415fc223305Sopenharmony_ci    if (errCode != E_OK) {
416fc223305Sopenharmony_ci        return errCode;
417fc223305Sopenharmony_ci    }
418fc223305Sopenharmony_ci    errCode = CheckValue(value);
419fc223305Sopenharmony_ci    if (errCode != E_OK) {
420fc223305Sopenharmony_ci        return errCode;
421fc223305Sopenharmony_ci    }
422fc223305Sopenharmony_ci    AwaitLoadFile();
423fc223305Sopenharmony_ci
424fc223305Sopenharmony_ci    valuesCache_.Compute(key, [this, &value](auto &key, PreferencesValue &val) {
425fc223305Sopenharmony_ci        if (val == value) {
426fc223305Sopenharmony_ci            return true;
427fc223305Sopenharmony_ci        }
428fc223305Sopenharmony_ci        val = value;
429fc223305Sopenharmony_ci        modifiedKeys_.push_back(key);
430fc223305Sopenharmony_ci        return true;
431fc223305Sopenharmony_ci    });
432fc223305Sopenharmony_ci    return E_OK;
433fc223305Sopenharmony_ci}
434fc223305Sopenharmony_ci
435fc223305Sopenharmony_ciint PreferencesImpl::Delete(const std::string &key)
436fc223305Sopenharmony_ci{
437fc223305Sopenharmony_ci    int errCode = CheckKey(key);
438fc223305Sopenharmony_ci    if (errCode != E_OK) {
439fc223305Sopenharmony_ci        return errCode;
440fc223305Sopenharmony_ci    }
441fc223305Sopenharmony_ci    AwaitLoadFile();
442fc223305Sopenharmony_ci    valuesCache_.EraseIf(key, [this](auto &key, PreferencesValue &val) {
443fc223305Sopenharmony_ci        modifiedKeys_.push_back(key);
444fc223305Sopenharmony_ci        return true;
445fc223305Sopenharmony_ci    });
446fc223305Sopenharmony_ci    return E_OK;
447fc223305Sopenharmony_ci}
448fc223305Sopenharmony_ci
449fc223305Sopenharmony_ciint PreferencesImpl::Clear()
450fc223305Sopenharmony_ci{
451fc223305Sopenharmony_ci    AwaitLoadFile();
452fc223305Sopenharmony_ci    valuesCache_.EraseIf([this](auto &key, PreferencesValue &val) {
453fc223305Sopenharmony_ci        modifiedKeys_.push_back(key);
454fc223305Sopenharmony_ci        return true;
455fc223305Sopenharmony_ci    });
456fc223305Sopenharmony_ci    return E_OK;
457fc223305Sopenharmony_ci}
458fc223305Sopenharmony_ci
459fc223305Sopenharmony_ciint PreferencesImpl::WriteToDiskFile(std::shared_ptr<PreferencesImpl> pref)
460fc223305Sopenharmony_ci{
461fc223305Sopenharmony_ci    std::list<std::string> keysModified;
462fc223305Sopenharmony_ci    std::map<std::string, PreferencesValue> writeToDiskMap;
463fc223305Sopenharmony_ci    pref->valuesCache_.DoActionWhenClone(
464fc223305Sopenharmony_ci        [pref, &writeToDiskMap, &keysModified](const std::map<std::string, PreferencesValue> &map) {
465fc223305Sopenharmony_ci        if (!pref->modifiedKeys_.empty()) {
466fc223305Sopenharmony_ci            keysModified = std::move(pref->modifiedKeys_);
467fc223305Sopenharmony_ci        }
468fc223305Sopenharmony_ci        writeToDiskMap = std::move(map);
469fc223305Sopenharmony_ci    });
470fc223305Sopenharmony_ci
471fc223305Sopenharmony_ci    // Cache has not changed, Not need to write persistent files.
472fc223305Sopenharmony_ci    if (keysModified.empty()) {
473fc223305Sopenharmony_ci        LOG_INFO("No data to update persistent file");
474fc223305Sopenharmony_ci        return E_OK;
475fc223305Sopenharmony_ci    }
476fc223305Sopenharmony_ci    if (!pref->WriteSettingXml(pref->options_, writeToDiskMap)) {
477fc223305Sopenharmony_ci        return E_ERROR;
478fc223305Sopenharmony_ci    }
479fc223305Sopenharmony_ci    pref->NotifyPreferencesObserver(keysModified, writeToDiskMap);
480fc223305Sopenharmony_ci    return E_OK;
481fc223305Sopenharmony_ci}
482fc223305Sopenharmony_ci
483fc223305Sopenharmony_civoid PreferencesImpl::Flush()
484fc223305Sopenharmony_ci{
485fc223305Sopenharmony_ci    auto success = queue_->PushNoWait(1);
486fc223305Sopenharmony_ci    if (success) {
487fc223305Sopenharmony_ci        std::weak_ptr<SafeBlockQueue<uint64_t>> queue = queue_;
488fc223305Sopenharmony_ci        ExecutorPool::Task task = [queue, self = weak_from_this()] {
489fc223305Sopenharmony_ci            auto realQueue = queue.lock();
490fc223305Sopenharmony_ci            auto realThis = self.lock();
491fc223305Sopenharmony_ci            if (realQueue == nullptr || realThis == nullptr) {
492fc223305Sopenharmony_ci                return ;
493fc223305Sopenharmony_ci            }
494fc223305Sopenharmony_ci            uint64_t value = 0;
495fc223305Sopenharmony_ci            std::lock_guard<std::mutex> lock(realThis->mutex_);
496fc223305Sopenharmony_ci            auto has = realQueue->PopNotWait(value);
497fc223305Sopenharmony_ci            if (has && value == 1) {
498fc223305Sopenharmony_ci                PreferencesImpl::WriteToDiskFile(realThis);
499fc223305Sopenharmony_ci            }
500fc223305Sopenharmony_ci        };
501fc223305Sopenharmony_ci        executorPool_.Schedule(std::chrono::milliseconds(TASK_EXEC_TIME), std::move(task));
502fc223305Sopenharmony_ci    }
503fc223305Sopenharmony_ci}
504fc223305Sopenharmony_ci
505fc223305Sopenharmony_ciint PreferencesImpl::FlushSync()
506fc223305Sopenharmony_ci{
507fc223305Sopenharmony_ci    auto success = queue_->PushNoWait(1);
508fc223305Sopenharmony_ci    if (success) {
509fc223305Sopenharmony_ci        if (queue_ == nullptr) {
510fc223305Sopenharmony_ci            return E_ERROR;
511fc223305Sopenharmony_ci        }
512fc223305Sopenharmony_ci        uint64_t value = 0;
513fc223305Sopenharmony_ci        std::lock_guard<std::mutex> lock(mutex_);
514fc223305Sopenharmony_ci        auto has = queue_->PopNotWait(value);
515fc223305Sopenharmony_ci        if (has && value == 1) {
516fc223305Sopenharmony_ci            return PreferencesImpl::WriteToDiskFile(shared_from_this());
517fc223305Sopenharmony_ci        }
518fc223305Sopenharmony_ci    }
519fc223305Sopenharmony_ci    return E_OK;
520fc223305Sopenharmony_ci}
521fc223305Sopenharmony_ci
522fc223305Sopenharmony_cistd::pair<int, PreferencesValue> PreferencesImpl::GetValue(const std::string &key, const PreferencesValue &defValue)
523fc223305Sopenharmony_ci{
524fc223305Sopenharmony_ci    int errCode = CheckKey(key);
525fc223305Sopenharmony_ci    if (errCode != E_OK) {
526fc223305Sopenharmony_ci        return std::make_pair(errCode, defValue);
527fc223305Sopenharmony_ci    }
528fc223305Sopenharmony_ci
529fc223305Sopenharmony_ci    AwaitLoadFile();
530fc223305Sopenharmony_ci    auto iter = valuesCache_.Find(key);
531fc223305Sopenharmony_ci    if (iter.first) {
532fc223305Sopenharmony_ci        return std::make_pair(E_OK, iter.second);
533fc223305Sopenharmony_ci    }
534fc223305Sopenharmony_ci    return std::make_pair(E_NO_DATA, defValue);
535fc223305Sopenharmony_ci}
536fc223305Sopenharmony_ci
537fc223305Sopenharmony_cistd::pair<int, std::map<std::string, PreferencesValue>> PreferencesImpl::GetAllData()
538fc223305Sopenharmony_ci{
539fc223305Sopenharmony_ci    AwaitLoadFile();
540fc223305Sopenharmony_ci    return std::make_pair(E_OK, valuesCache_.Clone());
541fc223305Sopenharmony_ci}
542fc223305Sopenharmony_ci
543fc223305Sopenharmony_civoid PreferencesImpl::NotifyPreferencesObserver(const std::list<std::string> &keysModified,
544fc223305Sopenharmony_ci    const std::map<std::string, PreferencesValue> &writeToDiskMap)
545fc223305Sopenharmony_ci{
546fc223305Sopenharmony_ci    if (keysModified.empty()) {
547fc223305Sopenharmony_ci        return;
548fc223305Sopenharmony_ci    }
549fc223305Sopenharmony_ci    LOG_DEBUG("notify observer size:%{public}zu", dataObserversMap_.size());
550fc223305Sopenharmony_ci    std::shared_lock<std::shared_mutex> autoLock(obseverMetux_);
551fc223305Sopenharmony_ci    for (const auto &[weakPrt, keys] : dataObserversMap_) {
552fc223305Sopenharmony_ci        std::map<std::string, PreferencesValue> records;
553fc223305Sopenharmony_ci        for (auto key = keysModified.begin(); key != keysModified.end(); ++key) {
554fc223305Sopenharmony_ci            auto itKey = keys.find(*key);
555fc223305Sopenharmony_ci            if (itKey == keys.end()) {
556fc223305Sopenharmony_ci                continue;
557fc223305Sopenharmony_ci            }
558fc223305Sopenharmony_ci            PreferencesValue value;
559fc223305Sopenharmony_ci            auto dataIt = writeToDiskMap.find(*key);
560fc223305Sopenharmony_ci            if (dataIt != writeToDiskMap.end()) {
561fc223305Sopenharmony_ci                value = dataIt->second;
562fc223305Sopenharmony_ci            }
563fc223305Sopenharmony_ci            records.insert({*key, value});
564fc223305Sopenharmony_ci        }
565fc223305Sopenharmony_ci        if (records.empty()) {
566fc223305Sopenharmony_ci            continue;
567fc223305Sopenharmony_ci        }
568fc223305Sopenharmony_ci        if (std::shared_ptr<PreferencesObserver> sharedPtr = weakPrt.lock()) {
569fc223305Sopenharmony_ci            LOG_DEBUG("dataChange observer call, resultSize:%{public}zu", records.size());
570fc223305Sopenharmony_ci            sharedPtr->OnChange(records);
571fc223305Sopenharmony_ci        }
572fc223305Sopenharmony_ci    }
573fc223305Sopenharmony_ci
574fc223305Sopenharmony_ci    auto dataObsMgrClient = DataObsMgrClient::GetInstance();
575fc223305Sopenharmony_ci    for (auto key = keysModified.begin(); key != keysModified.end(); ++key) {
576fc223305Sopenharmony_ci        for (auto it = localObservers_.begin(); it != localObservers_.end(); ++it) {
577fc223305Sopenharmony_ci            std::weak_ptr<PreferencesObserver> weakPreferencesObserver = *it;
578fc223305Sopenharmony_ci            if (std::shared_ptr<PreferencesObserver> sharedPreferencesObserver = weakPreferencesObserver.lock()) {
579fc223305Sopenharmony_ci                sharedPreferencesObserver->OnChange(*key);
580fc223305Sopenharmony_ci            }
581fc223305Sopenharmony_ci        }
582fc223305Sopenharmony_ci
583fc223305Sopenharmony_ci        if (dataObsMgrClient == nullptr) {
584fc223305Sopenharmony_ci            continue;
585fc223305Sopenharmony_ci        }
586fc223305Sopenharmony_ci        LOG_INFO("The %{public}s is changed, the observer needs to be triggered.",
587fc223305Sopenharmony_ci            Anonymous::ToBeAnonymous(*key).c_str());
588fc223305Sopenharmony_ci        dataObsMgrClient->NotifyChange(MakeUri(*key));
589fc223305Sopenharmony_ci    }
590fc223305Sopenharmony_ci}
591fc223305Sopenharmony_ci} // End of namespace NativePreferences
592fc223305Sopenharmony_ci} // End of namespace OHOS
593