• 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 <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