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