1 /*
2 * Copyright (c) 2023-2024 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
16 #include <cinttypes>
17 #include <mutex>
18
19 #include "datetime_ex.h"
20 #include "string_ex.h"
21
22 #include "distributed_device_profile_constants.h"
23 #include "distributed_device_profile_errors.h"
24 #include "distributed_device_profile_log.h"
25 #include "kv_adapter.h"
26 #include "profile_utils.h"
27
28 namespace OHOS {
29 namespace DistributedDeviceProfile {
30 using namespace OHOS::DistributedKv;
31 namespace {
32 constexpr int32_t MAX_INIT_RETRY_TIMES = 30;
33 constexpr int32_t INIT_RETRY_SLEEP_INTERVAL = 500 * 1000; // 500ms
34 const std::string DATABASE_DIR = "/data/service/el1/public/database/distributed_device_profile_service";
35 const std::string TAG = "KVAdapter";
36 }
37
KVAdapter(const std::string & appId,const std::string & storeId,const std::shared_ptr<DistributedKv::KvStoreObserver> & dataChangeListener,const std::shared_ptr<DistributedKv::KvStoreSyncCallback> & syncCompletedListener,const std::shared_ptr<DistributedKv::KvStoreDeathRecipient> & deathListener)38 KVAdapter::KVAdapter(const std::string &appId, const std::string &storeId,
39 const std::shared_ptr<DistributedKv::KvStoreObserver> &dataChangeListener,
40 const std::shared_ptr<DistributedKv::KvStoreSyncCallback> &syncCompletedListener,
41 const std::shared_ptr<DistributedKv::KvStoreDeathRecipient> &deathListener)
42 {
43 this->appId_.appId = appId;
44 this->storeId_.storeId = storeId;
45 this->dataChangeListener_ = dataChangeListener;
46 this->syncCompletedListener_= syncCompletedListener;
47 this->deathRecipient_ = deathListener;
48 HILOGI("KVAdapter Constructor Success, appId: %{public}s, storeId: %{public}s", appId.c_str(), storeId.c_str());
49 }
50
~KVAdapter()51 KVAdapter::~KVAdapter()
52 {
53 HILOGI("KVAdapter Destruction!");
54 }
55
Init()56 int32_t KVAdapter::Init()
57 {
58 HILOGI("Init kvAdapter, storeId: %{public}s", storeId_.storeId.c_str());
59 int32_t tryTimes = MAX_INIT_RETRY_TIMES;
60 int64_t beginTime = GetTickCount();
61 while (tryTimes > 0) {
62 DistributedKv::Status status = GetKvStorePtr();
63 if (kvStorePtr_ && status == DistributedKv::Status::SUCCESS) {
64 int64_t endTime = GetTickCount();
65 HILOGI("Init KvStorePtr Success, spend %{public}" PRId64 " ms", endTime - beginTime);
66 RegisterSyncCompletedListener();
67 RegisterDataChangeListener();
68 RegisterDeathListener();
69 return DP_SUCCESS;
70 }
71 HILOGI("CheckKvStore, left times: %{public}d, status: %{public}d", tryTimes, status);
72 if (status == DistributedKv::Status::SECURITY_LEVEL_ERROR) {
73 DeleteKvStore();
74 }
75 usleep(INIT_RETRY_SLEEP_INTERVAL);
76 tryTimes--;
77 }
78 return DP_KV_DB_INIT_FAIL;
79 }
80
UnInit()81 int32_t KVAdapter::UnInit()
82 {
83 HILOGI("DBAdapter UnInit");
84 UnRegisterSyncCompletedListener();
85 UnRegisterDataChangeListener();
86 UnRegisterDeathListener();
87 DeleteSyncCompletedListener();
88 DeleteDataChangeListener();
89 DeleteDeathListener();
90 DeleteKvStorePtr();
91 return DP_SUCCESS;
92 }
93
Put(const std::string & key,const std::string & value)94 int32_t KVAdapter::Put(const std::string& key, const std::string& value)
95 {
96 if (key.empty() || key.size() > MAX_STRING_LEN || value.empty() || value.size() > MAX_STRING_LEN) {
97 HILOGE("Param is invalid!");
98 return DP_INVALID_PARAMS;
99 }
100 DistributedKv::Status status;
101 {
102 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
103 if (kvStorePtr_ == nullptr) {
104 HILOGE("kvDBPtr is null!");
105 return DP_KV_DB_PTR_NULL;
106 }
107
108 DistributedKv::Key kvKey(key);
109 DistributedKv::Value oldV;
110 if (kvStorePtr_->Get(kvKey, oldV) == DistributedKv::Status::SUCCESS && oldV.ToString() == value) {
111 HILOGD("The key-value pair already exists. key=%{public}s,value=%{public}s",
112 ProfileUtils::GetAnonyString(key).c_str(),
113 ProfileUtils::GetAnonyString(value).c_str());
114 return DP_SUCCESS;
115 }
116
117 DistributedKv::Value kvValue(value);
118 status = kvStorePtr_->Put(kvKey, kvValue);
119 }
120 if (status != DistributedKv::Status::SUCCESS) {
121 HILOGE("Put kv to db failed, ret: %{public}d", status);
122 return DP_PUT_KV_DB_FAIL;
123 }
124 return DP_SUCCESS;
125 }
126
PutBatch(const std::map<std::string,std::string> & values)127 int32_t KVAdapter::PutBatch(const std::map<std::string, std::string>& values)
128 {
129 if (values.empty() || values.size() > MAX_PROFILE_SIZE) {
130 HILOGE("Param is invalid!");
131 return DP_INVALID_PARAMS;
132 }
133 DistributedKv::Status status;
134 {
135 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
136 if (kvStorePtr_ == nullptr) {
137 HILOGE("kvDBPtr is null!");
138 return DP_KV_DB_PTR_NULL;
139 }
140 std::vector<DistributedKv::Entry> entries;
141 DistributedKv::Value oldV;
142 DistributedKv::Key kvKey;
143 for (auto item : values) {
144 kvKey = item.first;
145 if (kvStorePtr_->Get(kvKey, oldV) == DistributedKv::Status::SUCCESS && oldV.ToString() == item.second) {
146 HILOGD("The key-value pair already exists. key=%{public}s,value=%{public}s",
147 ProfileUtils::GetAnonyString(item.first).c_str(),
148 ProfileUtils::GetAnonyString(item.second).c_str());
149 continue;
150 }
151
152 Entry entry;
153 entry.key = kvKey;
154 entry.value = item.second;
155 entries.emplace_back(entry);
156 }
157 if (entries.empty()) {
158 HILOGD("All key-value pair already exists.");
159 return DP_SUCCESS;
160 }
161 status = kvStorePtr_->PutBatch(entries);
162 }
163 if (status != DistributedKv::Status::SUCCESS) {
164 HILOGE("PutBatch kv to db failed, ret: %{public}d", status);
165 return DP_PUT_KV_DB_FAIL;
166 }
167 return DP_SUCCESS;
168 }
169
Delete(const std::string & key)170 int32_t KVAdapter::Delete(const std::string& key)
171 {
172 DistributedKv::Status status;
173 {
174 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
175 if (kvStorePtr_ == nullptr) {
176 HILOGE("kvDBPtr is null!");
177 return DP_KV_DB_PTR_NULL;
178 }
179 DistributedKv::Key kvKey(key);
180 status = kvStorePtr_->Delete(kvKey);
181 }
182 if (status != DistributedKv::Status::SUCCESS) {
183 HILOGE("Delete kv by key failed!");
184 return DP_DEL_KV_DB_FAIL;
185 }
186 HILOGI("Delete kv by key success!");
187 return DP_SUCCESS;
188 }
189
Get(const std::string & key,std::string & value)190 int32_t KVAdapter::Get(const std::string& key, std::string& value)
191 {
192 HILOGI("Get data by key: %{public}s", ProfileUtils::GetAnonyString(key).c_str());
193 DistributedKv::Key kvKey(key);
194 DistributedKv::Value kvValue;
195 DistributedKv::Status status;
196 {
197 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
198 if (kvStorePtr_ == nullptr) {
199 HILOGE("kvStoragePtr_ is null");
200 return DP_KV_DB_PTR_NULL;
201 }
202 status = kvStorePtr_->Get(kvKey, kvValue);
203 }
204 if (status != DistributedKv::Status::SUCCESS) {
205 HILOGE("Get data from kv failed, key: %{public}s", ProfileUtils::GetAnonyString(key).c_str());
206 return DP_GET_KV_DB_FAIL;
207 }
208 value = kvValue.ToString();
209 return DP_SUCCESS;
210 }
211
GetByPrefix(const std::string & keyPrefix,std::map<std::string,std::string> & values)212 int32_t KVAdapter::GetByPrefix(const std::string& keyPrefix, std::map<std::string, std::string>& values)
213 {
214 HILOGI("Get data by key prefix: %{public}s", ProfileUtils::GetAnonyString(keyPrefix).c_str());
215 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
216 if (kvStorePtr_ == nullptr) {
217 HILOGE("kvStoragePtr_ is null");
218 return DP_KV_DB_PTR_NULL;
219 }
220 // if prefix is empty, get all entries.
221 DistributedKv::Key allEntryKeyPrefix(keyPrefix);
222 std::vector<DistributedKv::Entry> allEntries;
223 DistributedKv::Status status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
224 if (status != DistributedKv::Status::SUCCESS) {
225 HILOGE("Query data by keyPrefix failed, prefix: %{public}s", ProfileUtils::GetAnonyString(keyPrefix).c_str());
226 return DP_GET_KV_DB_FAIL;
227 }
228 if (allEntries.size() == 0 || allEntries.size() > MAX_DB_SIZE) {
229 HILOGE("AllEntries size is invalid!");
230 return DP_INVALID_PARAMS;
231 }
232 for (const auto& item : allEntries) {
233 values[item.key.ToString()] = item.value.ToString();
234 }
235 return DP_SUCCESS;
236 }
237
DeleteByPrefix(const std::string & keyPrefix)238 int32_t KVAdapter::DeleteByPrefix(const std::string& keyPrefix)
239 {
240 HILOGI("call");
241 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
242 if (kvStorePtr_ == nullptr) {
243 HILOGE("kvStoragePtr_ is null");
244 return DP_KV_DB_PTR_NULL;
245 }
246 // if prefix is empty, get all entries.
247 DistributedKv::Key allEntryKeyPrefix(keyPrefix);
248 std::vector<DistributedKv::Entry> allEntries;
249 DistributedKv::Status status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
250 if (status != DistributedKv::Status::SUCCESS) {
251 return DP_DEL_KV_DB_FAIL;
252 }
253 std::vector<DistributedKv::Key> keys;
254 for (auto item : allEntries) {
255 keys.push_back(item.key);
256 }
257 status = kvStorePtr_->DeleteBatch(keys);
258 if (status != DistributedKv::Status::SUCCESS) {
259 return DP_DEL_KV_DB_FAIL;
260 }
261 return DP_SUCCESS;
262 }
263
GetKvStorePtr()264 DistributedKv::Status KVAdapter::GetKvStorePtr()
265 {
266 HILOGI("called");
267 DistributedKv::Options options = {
268 .createIfMissing = true,
269 .encrypt = false,
270 .autoSync = true,
271 .isPublic = true,
272 .securityLevel = DistributedKv::SecurityLevel::S1,
273 .area = 1,
274 .kvStoreType = KvStoreType::SINGLE_VERSION,
275 .baseDir = DATABASE_DIR
276 };
277 SyncPolicy syncPolicyOnline {
278 .type = PolicyType::IMMEDIATE_SYNC_ON_ONLINE
279 };
280 options.policies.emplace_back(syncPolicyOnline);
281 DistributedKv::Status status;
282 {
283 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
284 status = kvDataMgr_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
285 }
286 return status;
287 }
288
DeleteKvStorePtr()289 int32_t KVAdapter::DeleteKvStorePtr()
290 {
291 HILOGI("Delete KvStore Ptr!");
292 {
293 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
294 kvStorePtr_ = nullptr;
295 }
296 return DP_SUCCESS;
297 }
298
Sync(const std::vector<std::string> & deviceList,SyncMode syncMode)299 int32_t KVAdapter::Sync(const std::vector<std::string>& deviceList, SyncMode syncMode)
300 {
301 HILOGI("Sync!");
302 {
303 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
304 if (kvStorePtr_ == nullptr) {
305 HILOGE("kvStorePtr is nullptr!");
306 return DP_KV_DB_PTR_NULL;
307 }
308 if (deviceList.empty() || deviceList.size() > MAX_DEVICE_SIZE) {
309 HILOGE("deviceList is invalid!");
310 return DP_INVALID_PARAMS;
311 }
312 if (syncMode <= SyncMode::MIN || syncMode >= SyncMode::MAX) {
313 HILOGE("syncMode is invalid!");
314 return DP_INVALID_PARAMS;
315 }
316 DistributedKv::Status status = kvStorePtr_->Sync(deviceList, static_cast<DistributedKv::SyncMode>(syncMode));
317 if (status != DistributedKv::Status::SUCCESS) {
318 HILOGE("Sync fail!");
319 return DP_KV_SYNC_FAIL;
320 }
321 }
322 return DP_SUCCESS;
323 }
324
RegisterDataChangeListener()325 int32_t KVAdapter::RegisterDataChangeListener()
326 {
327 HILOGI("Register db data change listener");
328 {
329 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
330 if (kvStorePtr_ == nullptr) {
331 HILOGE("kvStoragePtr_ is null");
332 return DP_INVALID_PARAMS;
333 }
334 DistributedKv::Status status =
335 kvStorePtr_->SubscribeKvStore(DistributedKv::SubscribeType::SUBSCRIBE_TYPE_ALL, dataChangeListener_);
336 if (status != DistributedKv::Status::SUCCESS) {
337 HILOGE("Register db data change listener failed, ret: %{public}d", status);
338 return DP_REGISTER_KV_DATA_LISTENER_FAILED;
339 }
340 }
341 return DP_SUCCESS;
342 }
343
UnRegisterDataChangeListener()344 int32_t KVAdapter::UnRegisterDataChangeListener()
345 {
346 HILOGI("UnRegister db data change listener");
347 {
348 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
349 if (kvStorePtr_ == nullptr) {
350 HILOGE("kvStoragePtr_ is null");
351 return DP_KV_DB_PTR_NULL;
352 }
353 DistributedKv::Status status =
354 kvStorePtr_->UnSubscribeKvStore(DistributedKv::SubscribeType::SUBSCRIBE_TYPE_ALL, dataChangeListener_);
355 if (status != DistributedKv::Status::SUCCESS) {
356 HILOGE("UnRegister db data change listener failed, ret: %{public}d", status);
357 return DP_UNREGISTER_KV_DATA_LISTENER_FAILED;
358 }
359 }
360 return DP_SUCCESS;
361 }
362
DeleteDataChangeListener()363 int32_t KVAdapter::DeleteDataChangeListener()
364 {
365 HILOGI("Delete DataChangeListener!");
366 {
367 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
368 dataChangeListener_ = nullptr;
369 }
370 return DP_SUCCESS;
371 }
372
RegisterSyncCompletedListener()373 int32_t KVAdapter::RegisterSyncCompletedListener()
374 {
375 HILOGI("Register syncCompleted listener");
376 {
377 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
378 if (kvStorePtr_ == nullptr) {
379 HILOGE("kvStoragePtr_ is null");
380 return DP_KV_DB_PTR_NULL;
381 }
382 DistributedKv::Status status = kvStorePtr_->RegisterSyncCallback(syncCompletedListener_);
383 if (status != DistributedKv::Status::SUCCESS) {
384 HILOGE("Register syncCompleted listener failed, ret: %{public}d", status);
385 return DP_REGISTER_KV_SYNC_LISTENER_FAILED;
386 }
387 }
388 return DP_SUCCESS;
389 }
390
UnRegisterSyncCompletedListener()391 int32_t KVAdapter::UnRegisterSyncCompletedListener()
392 {
393 HILOGI("UnRegister syncCompleted listener");
394 {
395 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
396 if (kvStorePtr_ == nullptr) {
397 HILOGE("kvStoragePtr_ is null");
398 return DP_KV_DB_PTR_NULL;
399 }
400 DistributedKv::Status status = kvStorePtr_->UnRegisterSyncCallback();
401 if (status != DistributedKv::Status::SUCCESS) {
402 HILOGE("UnRegister db data change listener failed, ret: %{public}d", status);
403 return DP_UNREGISTER_KV_SYNC_LISTENER_FAILED;
404 }
405 }
406 return DP_SUCCESS;
407 }
408
DeleteSyncCompletedListener()409 int32_t KVAdapter::DeleteSyncCompletedListener()
410 {
411 HILOGI("Delete SyncCompletedListener!");
412 {
413 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
414 syncCompletedListener_ = nullptr;
415 }
416 return DP_SUCCESS;
417 }
418
RegisterDeathListener()419 int32_t KVAdapter::RegisterDeathListener()
420 {
421 HILOGI("Register syncCompleted listener");
422 {
423 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
424 kvDataMgr_.RegisterKvStoreServiceDeathRecipient(deathRecipient_);
425 }
426 return DP_SUCCESS;
427 }
428
UnRegisterDeathListener()429 int32_t KVAdapter::UnRegisterDeathListener()
430 {
431 HILOGI("UnRegister syncCompleted listener");
432 {
433 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
434 kvDataMgr_.UnRegisterKvStoreServiceDeathRecipient(deathRecipient_);
435 }
436 return DP_SUCCESS;
437 }
438
DeleteDeathListener()439 int32_t KVAdapter::DeleteDeathListener()
440 {
441 HILOGI("Delete DeathListener!");
442 {
443 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
444 deathRecipient_ = nullptr;
445 }
446 return DP_SUCCESS;
447 }
448
DeleteKvStore()449 int32_t KVAdapter::DeleteKvStore()
450 {
451 HILOGI("Delete KvStore!");
452 {
453 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
454 kvDataMgr_.CloseKvStore(appId_, storeId_);
455 kvDataMgr_.DeleteKvStore(appId_, storeId_, DATABASE_DIR);
456 }
457 return DP_SUCCESS;
458 }
459
GetByPrefix(const std::string & udid,const std::string & keyPrefix,std::map<std::string,std::string> & values)460 int32_t KVAdapter::GetByPrefix(const std::string& udid, const std::string& keyPrefix,
461 std::map<std::string, std::string>& values)
462 {
463 if (udid.empty() || keyPrefix.empty()) {
464 HILOGE("udid or keyPrefix is invalid");
465 return DP_INVALID_PARAMS;
466 }
467 HILOGI("Get data by key prefix: %{public}s", ProfileUtils::GetAnonyString(keyPrefix).c_str());
468 DistributedKv::Status status;
469 std::vector<DistributedKv::Entry> allEntries;
470 {
471 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
472 if (kvStorePtr_ == nullptr) {
473 HILOGE("kvStoragePtr_ is null");
474 return DP_KV_DB_PTR_NULL;
475 }
476 // if prefix is empty, get all entries.
477 DistributedKv::Key allEntryKeyPrefix(keyPrefix);
478 status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
479 HILOGI("Get data status: %{public}d", status);
480 }
481 // if data does not exist, GetEntries return SUCCESS, allEntries size is 0.
482 if (status != DistributedKv::Status::SUCCESS) {
483 HILOGE("Query data by keyPrefix failed, prefix: %{public}s", ProfileUtils::GetAnonyString(keyPrefix).c_str());
484 return DP_GET_KV_DB_FAIL;
485 }
486 // data to be queried must exist, if not, try to sync.
487 if (allEntries.size() == 0) {
488 HILOGE("AllEntries is empty!");
489 SyncDeviceProfile(udid);
490 return DP_INVALID_PARAMS;
491 }
492 if (allEntries.size() > MAX_DB_SIZE) {
493 HILOGE("AllEntries size is invalid!");
494 return DP_INVALID_PARAMS;
495 }
496 for (const auto& item : allEntries) {
497 values[item.key.ToString()] = item.value.ToString();
498 }
499 return DP_SUCCESS;
500 }
501
Get(const std::string & udid,const std::string & key,std::string & value)502 int32_t KVAdapter::Get(const std::string& udid, const std::string& key, std::string& value)
503 {
504 if (udid.empty() || key.empty()) {
505 HILOGE("udid or key is invalid");
506 return DP_INVALID_PARAMS;
507 }
508 HILOGI("Get data by key: %{public}s", ProfileUtils::GetAnonyString(key).c_str());
509 DistributedKv::Key kvKey(key);
510 DistributedKv::Value kvValue;
511 DistributedKv::Status status;
512 {
513 std::lock_guard<std::mutex> lock(kvAdapterMutex_);
514 if (kvStorePtr_ == nullptr) {
515 HILOGE("kvStoragePtr_ is null");
516 return DP_KV_DB_PTR_NULL;
517 }
518 status = kvStorePtr_->Get(kvKey, kvValue);
519 }
520 if (status == DistributedKv::Status::NOT_FOUND) {
521 SyncDeviceProfile(udid);
522 return DP_GET_KV_DB_FAIL;
523 }
524 if (status != DistributedKv::Status::SUCCESS) {
525 HILOGE("Get data from kv failed, key: %{public}s", ProfileUtils::GetAnonyString(key).c_str());
526 return DP_GET_KV_DB_FAIL;
527 }
528 value = kvValue.ToString();
529 return DP_SUCCESS;
530 }
531
SyncDeviceProfile(const std::string & udid)532 void KVAdapter::SyncDeviceProfile(const std::string& udid)
533 {
534 HILOGI("call!");
535 if (udid.empty()) {
536 HILOGE("udid is invalid.");
537 return;
538 }
539 std::vector<std::string> device;
540 device.push_back(udid);
541 SyncMode syncMode{ SyncMode::PUSH_PULL };
542 int32_t syncResult = Sync(device, syncMode);
543 HILOGI("SyncDeviceProfile res: %{public}d!", syncResult);
544 }
545 } // namespace DeviceProfile
546 } // namespace OHOS
547