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