• 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 
16 #include "db_adapter.h"
17 
18 #include "anonymous_string.h"
19 #include "capability_info.h"
20 #include "capability_info_manager.h"
21 #include "capability_utils.h"
22 #include "constants.h"
23 #include "dh_context.h"
24 #include "distributed_hardware_errno.h"
25 #include "distributed_hardware_log.h"
26 #include "event_bus.h"
27 #include "version_info_event.h"
28 
29 namespace OHOS {
30 namespace DistributedHardware {
31 #undef DH_LOG_TAG
32 #define DH_LOG_TAG "DBAdapter"
33 
34 namespace {
35 const std::string DATABASE_DIR = "/data/service/el1/public/database/";
36 }
37 
DBAdapter(const std::string & appId,const std::string & storeId,const std::shared_ptr<DistributedKv::KvStoreObserver> & changeListener)38 DBAdapter::DBAdapter(const std::string &appId, const std::string &storeId,
39                      const std::shared_ptr<DistributedKv::KvStoreObserver> &changeListener)
40 {
41     this->appId_.appId = appId;
42     this->storeId_.storeId = storeId;
43     this->dataChangeListener_ = changeListener;
44     DHLOGI("DBAdapter Constructor Success, appId: %s, storeId: %s", appId.c_str(), storeId.c_str());
45 }
46 
~DBAdapter()47 DBAdapter::~DBAdapter()
48 {
49     DHLOGI("DBAdapter Destruction");
50 }
51 
GetKvStorePtr()52 DistributedKv::Status DBAdapter::GetKvStorePtr()
53 {
54     DistributedKv::Options options = {
55         .createIfMissing = true,
56         .encrypt = false,
57         .autoSync = true,
58         .securityLevel = DistributedKv::SecurityLevel::S1,
59         .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
60         .area = DistributedKv::EL1,
61         .baseDir = DATABASE_DIR + appId_.appId
62     };
63     return kvDataMgr_.GetSingleKvStore(options, appId_, storeId_, kvStoragePtr_);
64 }
65 
Init()66 int32_t DBAdapter::Init()
67 {
68     DHLOGI("Init DB, storeId: %s", storeId_.storeId.c_str());
69     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
70     int32_t tryTimes = MAX_INIT_RETRY_TIMES;
71     while (tryTimes > 0) {
72         DistributedKv::Status status = GetKvStorePtr();
73         if (status == DistributedKv::Status::SUCCESS && kvStoragePtr_) {
74             DHLOGI("Init KvStorePtr Success");
75             RegisterManualSyncListener();
76             RegisterChangeListener();
77             RegisterKvStoreDeathListener();
78             return DH_FWK_SUCCESS;
79         }
80         DHLOGD("CheckKvStore, left times: %d", tryTimes);
81         usleep(INIT_RETRY_SLEEP_INTERVAL);
82         tryTimes--;
83     }
84     if (kvStoragePtr_ == nullptr) {
85         DHLOGE("Init KvStorePtr failed");
86         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
87     }
88     return DH_FWK_SUCCESS;
89 }
90 
UnInit()91 void DBAdapter::UnInit()
92 {
93     DHLOGI("DBAdapter UnInit");
94     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
95     if (kvStoragePtr_ == nullptr) {
96         DHLOGE("kvStoragePtr_ is null");
97         return;
98     }
99     UnRegisterKvStoreDeathListener();
100     UnRegisterChangeListener();
101     UnRegisterManualSyncListener();
102     kvStoragePtr_.reset();
103 }
104 
ReInit()105 int32_t DBAdapter::ReInit()
106 {
107     DHLOGI("ReInit DB, storeId: %s", storeId_.storeId.c_str());
108     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
109     if (kvStoragePtr_ == nullptr) {
110         DHLOGE("kvStoragePtr_ is null");
111         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
112     }
113     UnRegisterManualSyncListener();
114     kvStoragePtr_.reset();
115     DistributedKv::Status status = GetKvStorePtr();
116     if (status != DistributedKv::Status::SUCCESS || !kvStoragePtr_) {
117         DHLOGW("Get kvStoragePtr_ failed, status: %d", status);
118         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
119     }
120     RegisterManualSyncListener();
121     RegisterKvStoreDeathListener();
122     return DH_FWK_SUCCESS;
123 }
124 
SyncCompleted(const std::map<std::string,DistributedKv::Status> & results)125 void DBAdapter::SyncCompleted(const std::map<std::string, DistributedKv::Status> &results)
126 {
127     DHLOGI("DBAdapter SyncCompleted start");
128     if (results.size() == 0 || results.size() > MAX_DB_RECORD_SIZE) {
129         DHLOGE("Results size is invalid!");
130         return;
131     }
132     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
133     for (const auto &result : results) {
134         std::string deviceId = result.first;
135         DHLOGI("SyncCompleted, deviceId: %s", GetAnonyString(deviceId).c_str());
136         if (manualSyncCountMap_.count(deviceId) == 0) {
137             DHLOGE("SyncCompleted, error, ManualSyncCount is removed");
138             return;
139         }
140         DHLOGI("ManualSyncCallback::SyncCompleted, retryCount: %d", manualSyncCountMap_[deviceId]);
141         if (result.second == DistributedKv::Status::SUCCESS) {
142             manualSyncCountMap_[deviceId] = 0;
143         } else {
144             manualSyncCountMap_[deviceId]++;
145             if (manualSyncCountMap_[deviceId] >= MANUAL_SYNC_TIMES) {
146                 manualSyncCountMap_[deviceId] = 0;
147             } else {
148                 auto retryTask = [this, deviceId] {
149                     this->ManualSync(deviceId);
150                     usleep(MANUAL_SYNC_INTERVAL);
151                 };
152                 DHContext::GetInstance().GetEventBus()->PostTask(retryTask, "retryTask", 0);
153             }
154         }
155     }
156 }
157 
GetDataByKey(const std::string & key,std::string & data)158 int32_t DBAdapter::GetDataByKey(const std::string &key, std::string &data)
159 {
160     DHLOGI("Get data by key: %s", GetAnonyString(key).c_str());
161     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
162     if (kvStoragePtr_ == nullptr) {
163         DHLOGE("kvStoragePtr_ is null");
164         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
165     }
166     DistributedKv::Key kvKey(key);
167     DistributedKv::Value kvValue;
168     DistributedKv::Status status = kvStoragePtr_->Get(kvKey, kvValue);
169     if (status != DistributedKv::Status::SUCCESS) {
170         DHLOGE("Query from db failed, key: %s", GetAnonyString(key).c_str());
171         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
172     }
173     data = kvValue.ToString();
174     return DH_FWK_SUCCESS;
175 }
176 
GetDataByKeyPrefix(const std::string & keyPrefix,std::vector<std::string> & values)177 int32_t DBAdapter::GetDataByKeyPrefix(const std::string &keyPrefix, std::vector<std::string> &values)
178 {
179     DHLOGI("Get data by key prefix: %s", GetAnonyString(keyPrefix).c_str());
180     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
181     if (kvStoragePtr_ == nullptr) {
182         DHLOGE("kvStoragePtr_ is null");
183         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
184     }
185 
186     // if prefix is empty, get all entries.
187     DistributedKv::Key allEntryKeyPrefix(keyPrefix);
188     std::vector<DistributedKv::Entry> allEntries;
189     DistributedKv::Status status = kvStoragePtr_->GetEntries(allEntryKeyPrefix, allEntries);
190     if (status != DistributedKv::Status::SUCCESS) {
191         DHLOGE("Query data by keyPrefix failed, prefix: %s",
192             GetAnonyString(keyPrefix).c_str());
193         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
194     }
195     if (allEntries.size() == 0 || allEntries.size() > MAX_DB_RECORD_SIZE) {
196         DHLOGE("AllEntries size is invalid!");
197         return ERR_DH_FWK_PARA_INVALID;
198     }
199     for (const auto& item : allEntries) {
200         values.push_back(item.value.ToString());
201     }
202     return DH_FWK_SUCCESS;
203 }
204 
PutData(const std::string & key,const std::string & value)205 int32_t DBAdapter::PutData(const std::string &key, const std::string &value)
206 {
207     if (key.empty() || key.size() > MAX_MESSAGE_LEN || value.empty() || value.size() > MAX_MESSAGE_LEN) {
208         DHLOGI("Param is invalid!");
209         return ERR_DH_FWK_PARA_INVALID;
210     }
211     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
212     if (kvStoragePtr_ == nullptr) {
213         DHLOGE("kvStoragePtr_ is null");
214         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
215     }
216     DistributedKv::Key kvKey(key);
217     DistributedKv::Value kvValue(value);
218     DistributedKv::Status status = kvStoragePtr_->Put(kvKey, kvValue);
219     if (status == DistributedKv::Status::IPC_ERROR) {
220         DHLOGE("Put kv to db failed, ret: %d", status);
221         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
222     }
223     return DH_FWK_SUCCESS;
224 }
225 
PutDataBatch(const std::vector<std::string> & keys,const std::vector<std::string> & values)226 int32_t DBAdapter::PutDataBatch(const std::vector<std::string> &keys, const std::vector<std::string> &values)
227 {
228     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
229     if (kvStoragePtr_ == nullptr) {
230         DHLOGE("kvStoragePtr_ is null");
231         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
232     }
233     if (keys.size() != values.size() || keys.empty() || values.empty()) {
234         DHLOGE("Param is invalid!");
235         return ERR_DH_FWK_PARA_INVALID;
236     }
237     std::vector<DistributedKv::Entry> entries;
238     for (unsigned long i = 0; i < keys.size(); i++) {
239         DistributedKv::Entry entry;
240         entry.key = keys[i];
241         entry.value = values[i];
242         entries.push_back(entry);
243     }
244     DistributedKv::Status status = kvStoragePtr_->PutBatch(entries);
245     if (status != DistributedKv::Status::SUCCESS) {
246         DHLOGE("Put kv batch to db failed, ret: %d", status);
247         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
248     }
249     DHLOGI("Put kv batch to db success");
250     return DH_FWK_SUCCESS;
251 }
252 
CreateManualSyncCount(const std::string & deviceId)253 void DBAdapter::CreateManualSyncCount(const std::string &deviceId)
254 {
255     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
256     manualSyncCountMap_[deviceId] = 0;
257 }
258 
RemoveManualSyncCount(const std::string & deviceId)259 void DBAdapter::RemoveManualSyncCount(const std::string &deviceId)
260 {
261     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
262     manualSyncCountMap_.erase(deviceId);
263 }
264 
ManualSync(const std::string & networkId)265 int32_t DBAdapter::ManualSync(const std::string &networkId)
266 {
267     DHLOGI("Manual sync between networkId: %s", GetAnonyString(networkId).c_str());
268     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
269     if (kvStoragePtr_ == nullptr) {
270         DHLOGE("kvStoragePtr_ is null");
271         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
272     }
273     std::vector<std::string> devList = { networkId };
274     DistributedKv::Status status = kvStoragePtr_->Sync(devList, DistributedKv::SyncMode::PULL);
275     if (status != DistributedKv::Status::SUCCESS) {
276         DHLOGE("ManualSync Data failed, networkId: %s", GetAnonyString(networkId).c_str());
277         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
278     }
279     return DH_FWK_SUCCESS;
280 }
281 
SyncDBForRecover()282 void DBAdapter::SyncDBForRecover()
283 {
284     DHLOGI("Sync store id: %s after db recover", storeId_.storeId.c_str());
285     if (storeId_.storeId == GLOBAL_CAPABILITY_ID) {
286         CapabilityInfoEvent recoverEvent(*this, CapabilityInfoEvent::EventType::RECOVER);
287         DHContext::GetInstance().GetEventBus()->PostEvent<CapabilityInfoEvent>(recoverEvent);
288     }
289 
290     if (storeId_.storeId == GLOBAL_VERSION_ID) {
291         VersionInfoEvent recoverEvent(*this, VersionInfoEvent::EventType::RECOVER);
292         DHContext::GetInstance().GetEventBus()->PostEvent<VersionInfoEvent>(recoverEvent);
293     }
294 }
295 
RegisterChangeListener()296 int32_t DBAdapter::RegisterChangeListener()
297 {
298     DHLOGI("Register db data change listener");
299     if (kvStoragePtr_ == nullptr) {
300         DHLOGE("kvStoragePtr_ is null");
301         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
302     }
303     DistributedKv::Status status = kvStoragePtr_->SubscribeKvStore(DistributedKv::SubscribeType::SUBSCRIBE_TYPE_REMOTE,
304         dataChangeListener_);
305     if (status == DistributedKv::Status::IPC_ERROR) {
306         DHLOGE("Register db data change listener failed, ret: %d", status);
307         return ERR_DH_FWK_RESOURCE_REGISTER_DB_FAILED;
308     }
309     return DH_FWK_SUCCESS;
310 }
311 
UnRegisterChangeListener()312 int32_t DBAdapter::UnRegisterChangeListener()
313 {
314     DHLOGI("UnRegister db data change listener");
315     if (kvStoragePtr_ == nullptr) {
316         DHLOGE("kvStoragePtr_ is null");
317         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
318     }
319     DistributedKv::Status status = kvStoragePtr_->UnSubscribeKvStore(
320         DistributedKv::SubscribeType::SUBSCRIBE_TYPE_REMOTE, dataChangeListener_);
321     if (status == DistributedKv::Status::IPC_ERROR) {
322         DHLOGE("UnRegister db data change listener failed, ret: %d", status);
323         return ERR_DH_FWK_RESOURCE_UNREGISTER_DB_FAILED;
324     }
325     return DH_FWK_SUCCESS;
326 }
327 
RegisterKvStoreDeathListener()328 void DBAdapter::RegisterKvStoreDeathListener()
329 {
330     DHLOGI("Register kvStore death listener");
331     kvDataMgr_.RegisterKvStoreServiceDeathRecipient(shared_from_this());
332 }
333 
UnRegisterKvStoreDeathListener()334 void DBAdapter::UnRegisterKvStoreDeathListener()
335 {
336     DHLOGI("UnRegister kvStore death listener");
337     kvDataMgr_.UnRegisterKvStoreServiceDeathRecipient(shared_from_this());
338 }
339 
RegisterManualSyncListener()340 void DBAdapter::RegisterManualSyncListener()
341 {
342     DHLOGI("Register manualSyncCallback");
343     if (kvStoragePtr_ == nullptr) {
344         DHLOGE("kvStoragePtr_ is null");
345         return;
346     }
347     kvStoragePtr_->RegisterSyncCallback(shared_from_this());
348 }
349 
UnRegisterManualSyncListener()350 void DBAdapter::UnRegisterManualSyncListener()
351 {
352     DHLOGI("UnRegister manualSyncCallback");
353     if (kvStoragePtr_ == nullptr) {
354         DHLOGE("kvStoragePtr_ is null");
355         return;
356     }
357     kvStoragePtr_->UnRegisterSyncCallback();
358 }
359 
OnRemoteDied()360 void DBAdapter::OnRemoteDied()
361 {
362     DHLOGI("OnRemoteDied, recover db begin");
363     auto ReInitTask = [this] {
364         int32_t times = 0;
365         while (times < DIED_CHECK_MAX_TIMES) {
366             // init kvStore.
367             if (this->ReInit() == DH_FWK_SUCCESS) {
368                 // register data change listener again.
369                 this->RegisterChangeListener();
370                 this->SyncDBForRecover();
371                 DHLOGE("Current times is %d", times);
372                 break;
373             }
374             times++;
375             usleep(DIED_CHECK_INTERVAL);
376         }
377     };
378     DHContext::GetInstance().GetEventBus()->PostTask(ReInitTask, "ReInitTask", 0);
379     DHLOGI("OnRemoteDied, recover db end");
380 }
381 
DeleteKvStore()382 void DBAdapter::DeleteKvStore()
383 {
384     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
385     DistributedKv::Status status = kvDataMgr_.DeleteKvStore(appId_, storeId_);
386     if (status != DistributedKv::Status::SUCCESS) {
387         DHLOGE("DeleteKvStore error, appId: %s, storeId: %s, status: %d",
388             appId_.appId.c_str(), storeId_.storeId.c_str(), status);
389         return;
390     }
391     DHLOGI("DeleteKvStore success appId: %s", appId_.appId.c_str());
392 }
393 
RemoveDeviceData(const std::string & deviceId)394 int32_t DBAdapter::RemoveDeviceData(const std::string &deviceId)
395 {
396     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
397     if (kvStoragePtr_ == nullptr) {
398         DHLOGE("kvStoragePtr_ is null");
399         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
400     }
401     DistributedKv::Status status = kvStoragePtr_->RemoveDeviceData(deviceId);
402     if (status != DistributedKv::Status::SUCCESS) {
403         DHLOGE("Remove device data failed, deviceId: %s", GetAnonyString(deviceId).c_str());
404         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
405     }
406     DHLOGD("Remove device data success, deviceId: %s", GetAnonyString(deviceId).c_str());
407     return DH_FWK_SUCCESS;
408 }
409 
RemoveDataByKey(const std::string & key)410 int32_t DBAdapter::RemoveDataByKey(const std::string &key)
411 {
412     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
413     if (kvStoragePtr_ == nullptr) {
414         DHLOGE("kvStoragePtr_ is null");
415         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
416     }
417     DistributedKv::Key kvKey(key);
418     DistributedKv::Status status = kvStoragePtr_->Delete(kvKey);
419     if (status != DistributedKv::Status::SUCCESS) {
420         DHLOGE("Remove data by key failed");
421         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
422     }
423     DHLOGD("Remove data by key success");
424     return DH_FWK_SUCCESS;
425 }
426 } // namespace DistributedHardware
427 } // namespace OHOS
428