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