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