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