• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "account_data_storage.h"
16 #include <memory>
17 #include <thread>
18 #include <unistd.h>
19 #include "account_log_wrapper.h"
20 #include "hisysevent_adapter.h"
21 
22 namespace OHOS {
23 namespace AccountSA {
24 const int32_t MAX_TIMES = 10;
25 const int32_t SLEEP_INTERVAL = 100 * 1000;
26 const std::string KVSTORE_BASE_DIR = "/data/service/el1/public/database/";
27 
AccountDataStorage(const std::string & appId,const std::string & storeId,const bool & autoSync)28 AccountDataStorage::AccountDataStorage(const std::string &appId, const std::string &storeId, const bool &autoSync)
29 {
30     appId_.appId = appId;
31     storeId_.storeId = storeId;
32     autoSync_ = autoSync;
33 }
34 
~AccountDataStorage()35 AccountDataStorage::~AccountDataStorage()
36 {
37     if (kvStorePtr_ != nullptr) {
38         dataManager_.CloseKvStore(appId_, kvStorePtr_);
39     }
40 }
41 
TryTwice(const std::function<DistributedKv::Status ()> & func) const42 void AccountDataStorage::TryTwice(const std::function<DistributedKv::Status()> &func) const
43 {
44     OHOS::DistributedKv::Status status = func();
45     if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
46         status = func();
47         ACCOUNT_LOGE("distribute database ipc error and try again, status = %{public}d", status);
48     }
49 }
50 
GetKvStore()51 OHOS::DistributedKv::Status AccountDataStorage::GetKvStore()
52 {
53     OHOS::DistributedKv::Options options = {
54         .createIfMissing = true,
55         .encrypt = false,
56         .autoSync = autoSync_,
57         .syncable = autoSync_,
58         .area = OHOS::DistributedKv::EL1,
59         .kvStoreType = OHOS::DistributedKv::KvStoreType::SINGLE_VERSION,
60         .baseDir = KVSTORE_BASE_DIR + appId_.appId,
61     };
62 
63     OHOS::DistributedKv::Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
64     if (status != OHOS::DistributedKv::Status::SUCCESS || kvStorePtr_ == nullptr) {
65         ACCOUNT_LOGE("GetSingleKvStore failed! status %{public}d, kvStorePtr_ is nullptr", status);
66         return status;
67     }
68     return status;
69 }
70 
CheckKvStore()71 bool AccountDataStorage::CheckKvStore()
72 {
73     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
74 
75     if (kvStorePtr_ != nullptr) {
76         return true;
77     }
78     int32_t tryTimes = MAX_TIMES;
79     OHOS::DistributedKv::Status status = OHOS::DistributedKv::Status::SUCCESS;
80     while (tryTimes > 0) {
81         status = GetKvStore();
82         if (status == OHOS::DistributedKv::Status::SUCCESS && kvStorePtr_ != nullptr) {
83             break;
84         }
85 
86         usleep(SLEEP_INTERVAL);
87         tryTimes--;
88     }
89 
90     if (kvStorePtr_ == nullptr) {
91         return false;
92     }
93 
94     return true;
95 }
96 
LoadAllData(std::map<std::string,std::shared_ptr<IAccountInfo>> & infos)97 ErrCode AccountDataStorage::LoadAllData(std::map<std::string, std::shared_ptr<IAccountInfo>> &infos)
98 {
99     if (!CheckKvStore()) {
100         ACCOUNT_LOGE("kvStore is nullptr");
101         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
102     }
103 
104     OHOS::DistributedKv::Status status = DistributedKv::Status::SUCCESS;
105     std::vector<OHOS::DistributedKv::Entry> allEntries;
106     TryTwice([this, &status, &allEntries] {
107         status = GetEntries("", allEntries);
108         return status;
109     });
110 
111     if (status != OHOS::DistributedKv::Status::SUCCESS) {
112         ACCOUNT_LOGE("get entries error: %{public}d", status);
113         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
114     }
115     infos.clear();
116     SaveEntries(allEntries, infos);
117     return ERR_OK;
118 }
119 
AddAccountInfo(const IAccountInfo & iAccountInfo)120 ErrCode AccountDataStorage::AddAccountInfo(const IAccountInfo &iAccountInfo)
121 {
122     if (IsKeyExists(iAccountInfo.GetPrimeKey())) {
123         ACCOUNT_LOGE("the key already exists.");
124         return ERR_OSACCOUNT_SERVICE_DATA_STORAGE_KEY_EXISTED_ERROR;
125     }
126 
127     std::string accountInfoStr = iAccountInfo.ToString();
128     if (accountInfoStr.empty()) {
129         ACCOUNT_LOGE("account info str is empty!");
130         return ERR_OSACCOUNT_SERVICE_ACCOUNT_INFO_EMPTY_ERROR;
131     }
132     return PutValueToKvStore(iAccountInfo.GetPrimeKey(), accountInfoStr);
133 }
134 
SaveAccountInfo(const IAccountInfo & iAccountInfo)135 ErrCode AccountDataStorage::SaveAccountInfo(const IAccountInfo &iAccountInfo)
136 {
137     if (!IsKeyExists(iAccountInfo.GetPrimeKey())) {
138         ACCOUNT_LOGE("the key does not exist");
139         return ERR_OSACCOUNT_SERVICE_DATA_STORAGE_KEY_NOT_EXISTS_ERROR;
140     }
141 
142     std::string accountInfoStr = iAccountInfo.ToString();
143     if (accountInfoStr.empty()) {
144         ACCOUNT_LOGE("account info str is empty!");
145         return ERR_OSACCOUNT_SERVICE_ACCOUNT_INFO_EMPTY_ERROR;
146     }
147     return PutValueToKvStore(iAccountInfo.GetPrimeKey(), accountInfoStr);
148 }
149 
RemoveValueFromKvStore(const std::string & keyStr)150 ErrCode AccountDataStorage::RemoveValueFromKvStore(const std::string &keyStr)
151 {
152     if (!CheckKvStore()) {
153         ACCOUNT_LOGE("kvStore is nullptr");
154         return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
155     }
156 
157     OHOS::DistributedKv::Key key(keyStr);
158     OHOS::DistributedKv::Status status;
159     OHOS::DistributedKv::Value value;
160     {
161         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
162         // check exist
163         status = kvStorePtr_->Get(key, value);
164         if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
165             ACCOUNT_LOGE("kvstore ipc error and try again, status = %{public}d", status);
166             status = kvStorePtr_->Get(key, value);
167         }
168         if (status != OHOS::DistributedKv::Status::SUCCESS) {
169             ACCOUNT_LOGI("key does not exist in kvStore.");
170             return ERR_OK;
171         }
172 
173         // delete
174         status = kvStorePtr_->Delete(key);
175         if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
176             status = kvStorePtr_->Delete(key);
177             ACCOUNT_LOGE("kvstore ipc error and try to call again, status = %{public}d", status);
178         }
179     }
180 
181     if (status != OHOS::DistributedKv::Status::SUCCESS) {
182         ACCOUNT_LOGE("delete key from kvstore failed, status %{public}d.", status);
183         return ERR_ACCOUNT_COMMON_DELETE_KEY_FROM_KVSTORE_ERROR;
184     }
185 
186     ACCOUNT_LOGD("delete key from kvStore succeed!");
187     return ERR_OK;
188 }
189 
GetEntries(std::string subId,std::vector<OHOS::DistributedKv::Entry> & allEntries) const190 OHOS::DistributedKv::Status AccountDataStorage::GetEntries(
191     std::string subId, std::vector<OHOS::DistributedKv::Entry> &allEntries) const
192 {
193     OHOS::DistributedKv::Key allEntryKeyPrefix(subId);
194     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
195     OHOS::DistributedKv::Status status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
196 
197     return status;
198 }
199 
DeleteKvStore()200 ErrCode AccountDataStorage::DeleteKvStore()
201 {
202     if (!CheckKvStore()) {
203         ACCOUNT_LOGE("kvStore is nullptr");
204         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
205     }
206 
207     OHOS::DistributedKv::Status status;
208     {
209         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
210         dataManager_.CloseKvStore(this->appId_, this->storeId_);
211         kvStorePtr_ = nullptr;
212         std::string baseDir = KVSTORE_BASE_DIR + this->appId_.appId;
213         status = dataManager_.DeleteKvStore(this->appId_, this->storeId_, baseDir);
214     }
215     if (status != OHOS::DistributedKv::Status::SUCCESS) {
216         ACCOUNT_LOGE("error, status = %{public}d", status);
217         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
218     }
219 
220     return ERR_OK;
221 }
222 
GetAccountInfoById(const std::string id,IAccountInfo & iAccountInfo)223 ErrCode AccountDataStorage::GetAccountInfoById(const std::string id, IAccountInfo &iAccountInfo)
224 {
225     std::string valueStr;
226     ErrCode ret = GetValueFromKvStore(id, valueStr);
227     if (ret != ERR_OK) {
228         ACCOUNT_LOGE("get value from kvstore failed! id %{public}s.", id.c_str());
229         return ret;
230     }
231 
232     nlohmann::json jsonObject = nlohmann::json::parse(valueStr, nullptr, false);
233     if (!jsonObject.is_structured()) {  // check format
234         ACCOUNT_LOGE("bad format of value from kvstore! id %{public}s.", id.c_str());
235         return ERR_ACCOUNT_COMMON_BAD_JSON_FORMAT_ERROR;
236     }
237     iAccountInfo.FromJson(jsonObject);
238     return ERR_OK;
239 }
240 
LoadDataByLocalFuzzyQuery(std::string subId,std::map<std::string,std::shared_ptr<IAccountInfo>> & infos)241 ErrCode AccountDataStorage::LoadDataByLocalFuzzyQuery(
242     std::string subId, std::map<std::string, std::shared_ptr<IAccountInfo>> &infos)
243 {
244     if (!CheckKvStore()) {
245         ACCOUNT_LOGE("kvStore is nullptr");
246         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
247     }
248 
249     OHOS::DistributedKv::Status status = OHOS::DistributedKv::Status::SUCCESS;
250     std::vector<OHOS::DistributedKv::Entry> allEntries;
251     TryTwice([this, &status, &allEntries, subId] {
252         status = GetEntries(subId, allEntries);
253         return status;
254     });
255 
256     if (status != OHOS::DistributedKv::Status::SUCCESS) {
257         ACCOUNT_LOGE("get entries error: %{public}d", status);
258         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
259     }
260     infos.clear();
261     SaveEntries(allEntries, infos);
262     return ERR_OK;
263 }
264 
PutValueToKvStore(const std::string & keyStr,const std::string & valueStr)265 ErrCode AccountDataStorage::PutValueToKvStore(const std::string &keyStr, const std::string &valueStr)
266 {
267     if (!CheckKvStore()) {
268         ACCOUNT_LOGE("kvStore is nullptr");
269         return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
270     }
271 
272     OHOS::DistributedKv::Key key(keyStr);
273     OHOS::DistributedKv::Value value(valueStr);
274     OHOS::DistributedKv::Status status;
275 
276     {
277         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
278         status = kvStorePtr_->Put(key, value);
279         if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
280             status = kvStorePtr_->Put(key, value);
281         }
282     }
283 
284     if (status != OHOS::DistributedKv::Status::SUCCESS) {
285         ACCOUNT_LOGE("put value to kvStore error, status = %{public}d", status);
286         return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
287     }
288 
289     return ERR_OK;
290 }
291 
GetValueFromKvStore(const std::string & keyStr,std::string & valueStr)292 ErrCode AccountDataStorage::GetValueFromKvStore(const std::string &keyStr, std::string &valueStr)
293 {
294     if (!CheckKvStore()) {
295         ACCOUNT_LOGE("kvStore is nullptr");
296         return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
297     }
298 
299     OHOS::DistributedKv::Key key(keyStr);
300     OHOS::DistributedKv::Value value;
301     OHOS::DistributedKv::Status status;
302 
303     {
304         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
305         status = kvStorePtr_->Get(key, value);
306         if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
307             ACCOUNT_LOGE("kvstore ipc error and try again, status = %{public}d", status);
308             status = kvStorePtr_->Get(key, value);
309         }
310     }
311 
312     if (status != OHOS::DistributedKv::Status::SUCCESS) {
313         ACCOUNT_LOGE("get value from kvstore error, status %{public}d.", status);
314         return ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
315     }
316 
317     valueStr = value.ToString();
318     return ERR_OK;
319 }
320 
IsKeyExists(const std::string keyStr)321 bool AccountDataStorage::IsKeyExists(const std::string keyStr)
322 {
323     std::string valueStr;
324     if (GetValueFromKvStore(keyStr, valueStr) != ERR_OK) {
325         return false;
326     }
327     return true;
328 }
329 }  // namespace AccountSA
330 }  // namespace OHOS
331