• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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