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