• 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 <vector>
19 
20 #include "anonymous_string.h"
21 #include "capability_info.h"
22 #include "capability_info_manager.h"
23 #include "capability_utils.h"
24 #include "constants.h"
25 #include "dh_context.h"
26 #include "distributed_hardware_errno.h"
27 #include "distributed_hardware_log.h"
28 #include "event_handler.h"
29 #include "version_info_manager.h"
30 
31 namespace OHOS {
32 namespace DistributedHardware {
33 #undef DH_LOG_TAG
34 #define DH_LOG_TAG "DBAdapter"
35 
36 namespace {
37     constexpr int32_t MAX_INIT_RETRY_TIMES = 20;
38     constexpr int32_t INIT_RETRY_SLEEP_INTERVAL = 200 * 1000; // 200ms
39     constexpr int32_t DIED_CHECK_MAX_TIMES = 300;
40     constexpr int32_t DIED_CHECK_INTERVAL = 100 * 1000; // 100ms
41     const std::string DATABASE_DIR = "/data/service/el1/public/database/";
42 }
43 
DBAdapter(const std::string & appId,const std::string & storeId,const std::shared_ptr<DistributedKv::KvStoreObserver> & changeListener)44 DBAdapter::DBAdapter(const std::string &appId, const std::string &storeId,
45                      const std::shared_ptr<DistributedKv::KvStoreObserver> &changeListener)
46 {
47     this->appId_.appId = appId;
48     this->storeId_.storeId = storeId;
49     this->dataChangeListener_ = changeListener;
50     DHLOGI("DBAdapter Constructor Success, appId: %s, storeId: %s", appId.c_str(), storeId.c_str());
51 }
52 
~DBAdapter()53 DBAdapter::~DBAdapter()
54 {
55     DHLOGI("DBAdapter Destruction");
56 }
57 
GetKvStorePtr()58 DistributedKv::Status DBAdapter::GetKvStorePtr()
59 {
60     DistributedKv::Options options = {
61         .createIfMissing = true,
62         .encrypt = false,
63         .autoSync = true,
64         .securityLevel = DistributedKv::SecurityLevel::S1,
65         .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
66         .area = DistributedKv::EL1,
67         .baseDir = DATABASE_DIR + appId_.appId
68     };
69     DistributedKv::SyncPolicy syncPolicyOnline {
70         .type = DistributedKv::IMMEDIATE_SYNC_ON_ONLINE
71     };
72     options.policies.emplace_back(syncPolicyOnline);
73     return kvDataMgr_.GetSingleKvStore(options, appId_, storeId_, kvStoragePtr_);
74 }
75 
Init()76 int32_t DBAdapter::Init()
77 {
78     DHLOGI("Init DB, storeId: %s", storeId_.storeId.c_str());
79     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
80     int32_t tryTimes = MAX_INIT_RETRY_TIMES;
81     while (tryTimes > 0) {
82         DistributedKv::Status status = GetKvStorePtr();
83         if (status == DistributedKv::Status::SUCCESS && kvStoragePtr_) {
84             DHLOGI("Init KvStorePtr Success");
85             RegisterChangeListener();
86             RegisterKvStoreDeathListener();
87             return DH_FWK_SUCCESS;
88         }
89         DHLOGD("CheckKvStore, left times: %d", tryTimes);
90         usleep(INIT_RETRY_SLEEP_INTERVAL);
91         tryTimes--;
92     }
93     if (kvStoragePtr_ == nullptr) {
94         DHLOGE("Init KvStorePtr failed");
95         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
96     }
97     return DH_FWK_SUCCESS;
98 }
99 
UnInit()100 void DBAdapter::UnInit()
101 {
102     DHLOGI("DBAdapter UnInit");
103     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
104     if (kvStoragePtr_ == nullptr) {
105         DHLOGE("kvStoragePtr_ is null");
106         return;
107     }
108     UnRegisterKvStoreDeathListener();
109     UnRegisterChangeListener();
110     kvStoragePtr_.reset();
111 }
112 
ReInit()113 int32_t DBAdapter::ReInit()
114 {
115     DHLOGI("ReInit DB, storeId: %s", storeId_.storeId.c_str());
116     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
117     if (kvStoragePtr_ == nullptr) {
118         DHLOGE("kvStoragePtr_ is null");
119         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
120     }
121     kvStoragePtr_.reset();
122     DistributedKv::Status status = GetKvStorePtr();
123     if (status != DistributedKv::Status::SUCCESS || !kvStoragePtr_) {
124         DHLOGW("Get kvStoragePtr_ failed, status: %d", status);
125         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
126     }
127     RegisterKvStoreDeathListener();
128     return DH_FWK_SUCCESS;
129 }
130 
GetDataByKey(const std::string & key,std::string & data)131 int32_t DBAdapter::GetDataByKey(const std::string &key, std::string &data)
132 {
133     DHLOGI("Get data by key: %s", GetAnonyString(key).c_str());
134     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
135     if (kvStoragePtr_ == nullptr) {
136         DHLOGE("kvStoragePtr_ is null");
137         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
138     }
139     DistributedKv::Key kvKey(key);
140     DistributedKv::Value kvValue;
141     DistributedKv::Status status = kvStoragePtr_->Get(kvKey, kvValue);
142     if (status != DistributedKv::Status::SUCCESS) {
143         DHLOGE("Query from db failed, key: %s", GetAnonyString(key).c_str());
144         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
145     }
146     data = kvValue.ToString();
147     return DH_FWK_SUCCESS;
148 }
149 
GetDataByKeyPrefix(const std::string & keyPrefix,std::vector<std::string> & values)150 int32_t DBAdapter::GetDataByKeyPrefix(const std::string &keyPrefix, std::vector<std::string> &values)
151 {
152     DHLOGI("Get data by key prefix: %s", GetAnonyString(keyPrefix).c_str());
153     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
154     if (kvStoragePtr_ == nullptr) {
155         DHLOGE("kvStoragePtr_ is null");
156         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
157     }
158 
159     // if prefix is empty, get all entries.
160     DistributedKv::Key allEntryKeyPrefix(keyPrefix);
161     std::vector<DistributedKv::Entry> allEntries;
162     DistributedKv::Status status = kvStoragePtr_->GetEntries(allEntryKeyPrefix, allEntries);
163     if (status != DistributedKv::Status::SUCCESS) {
164         DHLOGE("Query data by keyPrefix failed, prefix: %s",
165             GetAnonyString(keyPrefix).c_str());
166         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
167     }
168     if (allEntries.size() == 0 || allEntries.size() > MAX_DB_RECORD_SIZE) {
169         DHLOGE("AllEntries size is invalid!");
170         return ERR_DH_FWK_PARA_INVALID;
171     }
172     for (const auto& item : allEntries) {
173         values.push_back(item.value.ToString());
174     }
175     return DH_FWK_SUCCESS;
176 }
177 
PutData(const std::string & key,const std::string & value)178 int32_t DBAdapter::PutData(const std::string &key, const std::string &value)
179 {
180     if (key.empty() || key.size() > MAX_MESSAGE_LEN || value.empty() || value.size() > MAX_MESSAGE_LEN) {
181         DHLOGI("Param is invalid!");
182         return ERR_DH_FWK_PARA_INVALID;
183     }
184     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
185     if (kvStoragePtr_ == nullptr) {
186         DHLOGE("kvStoragePtr_ is null");
187         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
188     }
189     DistributedKv::Key kvKey(key);
190     DistributedKv::Value kvValue(value);
191     DistributedKv::Status status = kvStoragePtr_->Put(kvKey, kvValue);
192     if (status == DistributedKv::Status::IPC_ERROR) {
193         DHLOGE("Put kv to db failed, ret: %d", status);
194         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
195     }
196     return DH_FWK_SUCCESS;
197 }
198 
PutDataBatch(const std::vector<std::string> & keys,const std::vector<std::string> & values)199 int32_t DBAdapter::PutDataBatch(const std::vector<std::string> &keys, const std::vector<std::string> &values)
200 {
201     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
202     if (kvStoragePtr_ == nullptr) {
203         DHLOGE("kvStoragePtr_ is null");
204         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
205     }
206     if (keys.size() != values.size() || keys.empty() || values.empty()) {
207         DHLOGE("Param is invalid!");
208         return ERR_DH_FWK_PARA_INVALID;
209     }
210     std::vector<DistributedKv::Entry> entries;
211     for (unsigned long i = 0; i < keys.size(); i++) {
212         DistributedKv::Entry entry;
213         entry.key = keys[i];
214         entry.value = values[i];
215         entries.push_back(entry);
216     }
217     DistributedKv::Status status = kvStoragePtr_->PutBatch(entries);
218     if (status != DistributedKv::Status::SUCCESS) {
219         DHLOGE("Put kv batch to db failed, ret: %d", status);
220         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
221     }
222     DHLOGI("Put kv batch to db success");
223     return DH_FWK_SUCCESS;
224 }
225 
SyncDBForRecover()226 void DBAdapter::SyncDBForRecover()
227 {
228     DHLOGI("Sync store id: %s after db recover", storeId_.storeId.c_str());
229     if (storeId_.storeId == GLOBAL_CAPABILITY_ID) {
230         AppExecFwk::InnerEvent::Pointer msgEvent = AppExecFwk::InnerEvent::Get(EVENT_CAPABILITY_INFO_DB_RECOVER);
231         CapabilityInfoManager::GetInstance()->GetEventHandler()->SendEvent(msgEvent,
232             0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
233     }
234 
235     if (storeId_.storeId == GLOBAL_VERSION_ID) {
236         AppExecFwk::InnerEvent::Pointer msgEvent = AppExecFwk::InnerEvent::Get(EVENT_VERSION_INFO_DB_RECOVER);
237         VersionInfoManager::GetInstance()->GetEventHandler()->SendEvent(msgEvent,
238             0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
239     }
240 }
241 
RegisterChangeListener()242 int32_t DBAdapter::RegisterChangeListener()
243 {
244     DHLOGI("Register db data change listener");
245     if (kvStoragePtr_ == nullptr) {
246         DHLOGE("kvStoragePtr_ is null");
247         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
248     }
249     DistributedKv::Status status = kvStoragePtr_->SubscribeKvStore(DistributedKv::SubscribeType::SUBSCRIBE_TYPE_REMOTE,
250         dataChangeListener_);
251     if (status == DistributedKv::Status::IPC_ERROR) {
252         DHLOGE("Register db data change listener failed, ret: %d", status);
253         return ERR_DH_FWK_RESOURCE_REGISTER_DB_FAILED;
254     }
255     return DH_FWK_SUCCESS;
256 }
257 
UnRegisterChangeListener()258 int32_t DBAdapter::UnRegisterChangeListener()
259 {
260     DHLOGI("UnRegister db data change listener");
261     if (kvStoragePtr_ == nullptr) {
262         DHLOGE("kvStoragePtr_ is null");
263         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
264     }
265     DistributedKv::Status status = kvStoragePtr_->UnSubscribeKvStore(
266         DistributedKv::SubscribeType::SUBSCRIBE_TYPE_REMOTE, dataChangeListener_);
267     if (status == DistributedKv::Status::IPC_ERROR) {
268         DHLOGE("UnRegister db data change listener failed, ret: %d", status);
269         return ERR_DH_FWK_RESOURCE_UNREGISTER_DB_FAILED;
270     }
271     return DH_FWK_SUCCESS;
272 }
273 
RegisterKvStoreDeathListener()274 void DBAdapter::RegisterKvStoreDeathListener()
275 {
276     DHLOGI("Register kvStore death listener");
277     kvDataMgr_.RegisterKvStoreServiceDeathRecipient(shared_from_this());
278 }
279 
UnRegisterKvStoreDeathListener()280 void DBAdapter::UnRegisterKvStoreDeathListener()
281 {
282     DHLOGI("UnRegister kvStore death listener");
283     kvDataMgr_.UnRegisterKvStoreServiceDeathRecipient(shared_from_this());
284 }
285 
OnRemoteDied()286 void DBAdapter::OnRemoteDied()
287 {
288     DHLOGI("OnRemoteDied, recover db begin");
289     auto reInitTask = [this] {
290         int32_t times = 0;
291         while (times < DIED_CHECK_MAX_TIMES) {
292             // init kvStore.
293             if (this->ReInit() == DH_FWK_SUCCESS) {
294                 // register data change listener again.
295                 this->RegisterChangeListener();
296                 this->SyncDBForRecover();
297                 DHLOGE("Current times is %d", times);
298                 break;
299             }
300             times++;
301             usleep(DIED_CHECK_INTERVAL);
302         }
303     };
304     DHContext::GetInstance().GetEventHandler()->PostTask(reInitTask, "reInitTask", 0);
305     DHLOGI("OnRemoteDied, recover db end");
306 }
307 
DeleteKvStore()308 void DBAdapter::DeleteKvStore()
309 {
310     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
311     DistributedKv::Status status = kvDataMgr_.DeleteKvStore(appId_, storeId_);
312     if (status != DistributedKv::Status::SUCCESS) {
313         DHLOGE("DeleteKvStore error, appId: %s, storeId: %s, status: %d",
314             appId_.appId.c_str(), storeId_.storeId.c_str(), status);
315         return;
316     }
317     DHLOGI("DeleteKvStore success appId: %s", appId_.appId.c_str());
318 }
319 
RemoveDeviceData(const std::string & deviceId)320 int32_t DBAdapter::RemoveDeviceData(const std::string &deviceId)
321 {
322     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
323     if (kvStoragePtr_ == nullptr) {
324         DHLOGE("kvStoragePtr_ is null");
325         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
326     }
327     DistributedKv::Status status = kvStoragePtr_->RemoveDeviceData(deviceId);
328     if (status != DistributedKv::Status::SUCCESS) {
329         DHLOGE("Remove device data failed, deviceId: %s", GetAnonyString(deviceId).c_str());
330         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
331     }
332     DHLOGD("Remove device data success, deviceId: %s", GetAnonyString(deviceId).c_str());
333     return DH_FWK_SUCCESS;
334 }
335 
RemoveDataByKey(const std::string & key)336 int32_t DBAdapter::RemoveDataByKey(const std::string &key)
337 {
338     std::lock_guard<std::mutex> lock(dbAdapterMutex_);
339     if (kvStoragePtr_ == nullptr) {
340         DHLOGE("kvStoragePtr_ is null");
341         return ERR_DH_FWK_RESOURCE_KV_STORAGE_POINTER_NULL;
342     }
343     DistributedKv::Key kvKey(key);
344     DistributedKv::Status status = kvStoragePtr_->Delete(kvKey);
345     if (status != DistributedKv::Status::SUCCESS) {
346         DHLOGE("Remove data by key failed");
347         return ERR_DH_FWK_RESOURCE_KV_STORAGE_OPERATION_FAIL;
348     }
349     DHLOGD("Remove data by key success");
350     return DH_FWK_SUCCESS;
351 }
352 } // namespace DistributedHardware
353 } // namespace OHOS
354