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 "mission/distributed_data_storage.h"
17
18 #include <thread>
19 #include <unistd.h>
20 #include "datetime_ex.h"
21 #include "dtbschedmgr_device_info_storage.h"
22 #include "dtbschedmgr_log.h"
23 #include "ipc_object_proxy.h"
24 #include "ipc_skeleton.h"
25 #include "iservice_registry.h"
26 #include "mission/distributed_sched_mission_manager.h"
27 #include "system_ability_definition.h"
28
29 using namespace std;
30 using namespace OHOS::DistributedKv;
31
32 namespace OHOS {
33 namespace DistributedSchedule {
34 namespace {
35 const string TAG = "DistributedDataStorage";
36 const string APP_ID = "DistributedSchedule";
37 const string STORE_ID = "SnapshotInfoDataStorage";
38 constexpr int32_t RETRY_TIMES_WAIT_KV_DATA = 30;
39 constexpr int32_t RETRY_TIMES_GET_KVSTORE = 5;
40 }
41
DistributedDataStorage()42 DistributedDataStorage::DistributedDataStorage()
43 {
44 appId_.appId = APP_ID;
45 storeId_.storeId = STORE_ID;
46 }
47
Init()48 bool DistributedDataStorage::Init()
49 {
50 HILOGD("begin.");
51 if (kvStoreDeathRecipient_ == nullptr) {
52 kvStoreDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new KvStoreDeathRecipient());
53 }
54 bool ret = InitHandler();
55 if (!ret) {
56 HILOGE("InitHandler failed!");
57 return false;
58 }
59 ret = InitKvDataService();
60 if (!ret) {
61 HILOGE("InitKvDataService failed!");
62 return false;
63 }
64 return true;
65 }
66
InitKvDataService()67 bool DistributedDataStorage::InitKvDataService()
68 {
69 auto waitTask = [this]() {
70 if (!WaitKvDataService()) {
71 HILOGE("get kvDataService failed!");
72 return;
73 }
74 InitDistributedDataStorage();
75 distributedDataChangeListener_ = make_unique<DistributedDataChangeListener>();
76 SubscribeDistributedDataStorage();
77 };
78 if (!dmsDataStorageHandler_->PostTask(waitTask)) {
79 HILOGE("post task failed!");
80 return false;
81 }
82 return true;
83 }
84
WaitKvDataService()85 bool DistributedDataStorage::WaitKvDataService()
86 {
87 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
88 if (samgrProxy == nullptr) {
89 HILOGE("get samgrProxy failed!");
90 return false;
91 }
92 int32_t retryTimes = RETRY_TIMES_WAIT_KV_DATA;
93 do {
94 auto kvDataSvr = samgrProxy->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
95 if (kvDataSvr != nullptr) {
96 IPCObjectProxy* proxy = reinterpret_cast<IPCObjectProxy*>(kvDataSvr.GetRefPtr());
97 if (proxy != nullptr && !proxy->IsObjectDead()) {
98 HILOGI("get service success!");
99 proxy->AddDeathRecipient(kvStoreDeathRecipient_);
100 return true;
101 }
102 }
103 HILOGD("waiting for service...");
104 this_thread::sleep_for(1s);
105 if (--retryTimes <= 0) {
106 HILOGE("waiting service timeout(30)s.");
107 return false;
108 }
109 } while (true);
110 return false;
111 }
112
InitDistributedDataStorage()113 void DistributedDataStorage::InitDistributedDataStorage()
114 {
115 int64_t begin = GetTickCount();
116 unique_lock<shared_mutex> writeLock(initLock_);
117 bool result = TryGetKvStore();
118 int64_t end = GetTickCount();
119 HILOGI("TryGetKvStore %{public}s, spend %{public}" PRId64 " ms", result ? "success" : "failed", end - begin);
120 }
121
TryGetKvStore()122 bool DistributedDataStorage::TryGetKvStore()
123 {
124 int32_t retryTimes = 0;
125 while (retryTimes < RETRY_TIMES_GET_KVSTORE) {
126 if (GetKvStore() == Status::SUCCESS && kvStorePtr_ != nullptr) {
127 return true;
128 }
129 HILOGD("retry get kvstore...");
130 this_thread::sleep_for(500ms);
131 retryTimes++;
132 }
133 if (kvStorePtr_ == nullptr) {
134 return false;
135 }
136 return true;
137 }
138
GetKvStore()139 Status DistributedDataStorage::GetKvStore()
140 {
141 Options options = {
142 .createIfMissing = true,
143 .encrypt = false,
144 .autoSync = true,
145 .kvStoreType = KvStoreType::SINGLE_VERSION,
146 };
147 Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
148 if (status != Status::SUCCESS) {
149 HILOGE("GetSingleKvStore failed, status = %{public}d.", status);
150 }
151 HILOGI("GetSingleKvStore success!");
152 return status;
153 }
154
SubscribeDistributedDataStorage()155 void DistributedDataStorage::SubscribeDistributedDataStorage()
156 {
157 int64_t begin = GetTickCount();
158 shared_lock<shared_mutex> readLock(initLock_);
159 if (kvStorePtr_ == nullptr) {
160 HILOGW("kvStorePtr is null!");
161 return;
162 }
163 SubscribeType subscribeType = SubscribeType::DEFAULT;
164 if (distributedDataChangeListener_ != nullptr) {
165 HILOGD("SubscribeKvStore start.");
166 Status status = kvStorePtr_->SubscribeKvStore(subscribeType, move(distributedDataChangeListener_));
167 HILOGI("[PerformanceTest] SubscribeKvStore spend %{public}" PRId64 " ms", GetTickCount() - begin);
168 if (status != Status::SUCCESS) {
169 HILOGE("SubscribeKvStore failed! status = %{public}d.", status);
170 return;
171 }
172 }
173 }
174
InitHandler()175 bool DistributedDataStorage::InitHandler()
176 {
177 if (dmsDataStorageHandler_ == nullptr) {
178 shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("dmsDataStorageHandler");
179 dmsDataStorageHandler_ = make_shared<AppExecFwk::EventHandler>(runner);
180 }
181 if (dmsDataStorageHandler_ == nullptr) {
182 HILOGW("dmsDataStorageHandler_ is null!");
183 return false;
184 }
185 return true;
186 }
187
NotifyRemoteDied(const wptr<IRemoteObject> & remote)188 void DistributedDataStorage::NotifyRemoteDied(const wptr<IRemoteObject>& remote)
189 {
190 HILOGD("begin.");
191 if (kvStoreDeathRecipient_ != nullptr) {
192 remote->RemoveDeathRecipient(kvStoreDeathRecipient_);
193 }
194 }
195
Stop()196 bool DistributedDataStorage::Stop()
197 {
198 HILOGD("begin.");
199 dmsDataStorageHandler_ = nullptr;
200 bool ret = UninitDistributedDataStorage();
201 if (!ret) {
202 HILOGE("UninitDistributedDataStorage failed!");
203 return false;
204 }
205 HILOGD("Stop success!");
206 return true;
207 }
208
UninitDistributedDataStorage()209 bool DistributedDataStorage::UninitDistributedDataStorage()
210 {
211 int64_t begin = GetTickCount();
212 Status status;
213 if (distributedDataChangeListener_ != nullptr && kvStorePtr_ != nullptr) {
214 SubscribeType subscribeType = SubscribeType::DEFAULT;
215 status = kvStorePtr_->UnSubscribeKvStore(subscribeType, move(distributedDataChangeListener_));
216 HILOGI("[PerformanceTest] UnSubscribeKvStore spend %{public}" PRId64 " ms", GetTickCount() - begin);
217 if (status != Status::SUCCESS) {
218 HILOGE("UnSubscribeKvStore failed! status = %{public}d.", status);
219 return false;
220 }
221 distributedDataChangeListener_ = nullptr;
222 }
223 if (kvStorePtr_ != nullptr) {
224 status = dataManager_.CloseKvStore(appId_, storeId_);
225 if (status != Status::SUCCESS) {
226 HILOGE("CloseKvStore failed! status = %{public}d.", status);
227 return false;
228 }
229 kvStorePtr_ = nullptr;
230 }
231 status = dataManager_.DeleteKvStore(appId_, storeId_);
232 if (status != Status::SUCCESS) {
233 HILOGE("DeleteKvStore failed! status = %{public}d.", status);
234 return false;
235 }
236 return true;
237 }
238
Insert(const string & networkId,int32_t missionId,const uint8_t * byteStream,size_t len)239 bool DistributedDataStorage::Insert(const string& networkId, int32_t missionId,
240 const uint8_t* byteStream, size_t len)
241 {
242 if (networkId.empty()) {
243 HILOGW("networkId is empty!");
244 return false;
245 }
246 if (missionId < 0) {
247 HILOGW("missionId is invalid!");
248 return false;
249 }
250 string uuid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUuidByNetworkId(networkId);
251 if (uuid.empty()) {
252 HILOGW("uuid is empty!");
253 return false;
254 }
255 {
256 unique_lock<shared_mutex> writeLock(initLock_);
257 bool ret = InsertInnerLocked(uuid, missionId, byteStream, len);
258 if (!ret) {
259 HILOGE("Insert uuid = %{public}s + missionId = %{public}d failed!",
260 DnetworkAdapter::AnonymizeDeviceId(uuid).c_str(), missionId);
261 return false;
262 }
263 }
264 HILOGI("Insert uuid = %{public}s + missionId = %{public}d successful!",
265 DnetworkAdapter::AnonymizeDeviceId(uuid).c_str(), missionId);
266 return true;
267 }
268
InsertInnerLocked(const string & uuid,int32_t missionId,const uint8_t * byteStream,size_t len)269 bool DistributedDataStorage::InsertInnerLocked(const string& uuid, int32_t missionId,
270 const uint8_t* byteStream, size_t len)
271 {
272 HILOGD("called.");
273 int64_t begin = GetTickCount();
274 if (kvStorePtr_ == nullptr) {
275 HILOGW("kvStorePtr is null!");
276 return false;
277 }
278 Key key;
279 Value value;
280 GenerateKey(uuid, missionId, key);
281 GenerateValue(byteStream, len, value);
282 auto status = kvStorePtr_->Put(key, value);
283 HILOGI("[PerformanceTest] Put Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
284 if (status != Status::SUCCESS) {
285 HILOGE("kvStorePtr Put failed! status = %{public}d.", status);
286 return false;
287 }
288 return true;
289 }
290
Delete(const string & networkId,int32_t missionId)291 bool DistributedDataStorage::Delete(const string& networkId, int32_t missionId)
292 {
293 if (networkId.empty()) {
294 HILOGW("networkId is empty!");
295 return false;
296 }
297 if (missionId < 0) {
298 HILOGW("missionId is invalid!");
299 return false;
300 }
301 string uuid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUuidByNetworkId(networkId);
302 if (uuid.empty()) {
303 HILOGW("uuid is empty!");
304 return false;
305 }
306 {
307 unique_lock<shared_mutex> writeLock(initLock_);
308 bool ret = DeleteInnerLocked(uuid, missionId);
309 if (!ret) {
310 HILOGE("Delete uuid = %{public}s + missionId = %{public}d failed!",
311 DnetworkAdapter::AnonymizeDeviceId(uuid).c_str(), missionId);
312 return false;
313 }
314 }
315 HILOGI("Delete uuid = %{public}s + missionId = %{public}d successful!",
316 DnetworkAdapter::AnonymizeDeviceId(uuid).c_str(), missionId);
317 return true;
318 }
319
DeleteInnerLocked(const string & uuid,int32_t missionId)320 bool DistributedDataStorage::DeleteInnerLocked(const string& uuid, int32_t missionId)
321 {
322 HILOGD("called.");
323 int64_t begin = GetTickCount();
324 if (kvStorePtr_ == nullptr) {
325 HILOGW("kvStorePtr is null!");
326 return false;
327 }
328 Key key;
329 GenerateKey(uuid, missionId, key);
330 auto status = kvStorePtr_->Delete(key);
331 HILOGI("[PerformanceTest] Delete Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
332 if (status != Status::SUCCESS) {
333 HILOGE("kvStorePtr Delete failed! status = %{public}d.", status);
334 return false;
335 }
336 return true;
337 }
338
FuzzyDelete(const string & networkId)339 bool DistributedDataStorage::FuzzyDelete(const string& networkId)
340 {
341 if (networkId.empty()) {
342 HILOGW("networkId is empty!");
343 return false;
344 }
345 {
346 unique_lock<shared_mutex> writeLock(initLock_);
347 bool ret = FuzzyDeleteInnerLocked(networkId);
348 if (!ret) {
349 HILOGW("FuzzyDelete networkId = %{public}s failed!", DnetworkAdapter::AnonymizeDeviceId(networkId).c_str());
350 return false;
351 }
352 }
353 HILOGI("FuzzyDelete networkId = %{public}s successful!", DnetworkAdapter::AnonymizeDeviceId(networkId).c_str());
354 return true;
355 }
356
FuzzyDeleteInnerLocked(const string & networkId)357 bool DistributedDataStorage::FuzzyDeleteInnerLocked(const string& networkId)
358 {
359 HILOGD("called.");
360 int64_t begin = GetTickCount();
361 if (kvStorePtr_ == nullptr) {
362 HILOGW("kvStorePtr is null!");
363 return false;
364 }
365 auto status = kvStorePtr_->RemoveDeviceData(networkId);
366 HILOGI("[PerformanceTest] RemoveDeviceData Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
367 if (status != Status::SUCCESS) {
368 HILOGE("kvStorePtr RemoveDeviceData failed! status = %{public}d.", status);
369 return false;
370 }
371 return true;
372 }
373
Query(const string & networkId,int32_t missionId,Value & value) const374 bool DistributedDataStorage::Query(const string& networkId, int32_t missionId, Value& value) const
375 {
376 if (networkId.empty()) {
377 HILOGW("networkId is empty!");
378 return false;
379 }
380 if (missionId < 0) {
381 HILOGW("missionId is invalid!");
382 return false;
383 }
384 string uuid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUuidByNetworkId(networkId);
385 if (uuid.empty()) {
386 HILOGW("uuid is empty!");
387 return false;
388 }
389 {
390 shared_lock<shared_mutex> readLock(initLock_);
391 bool ret = QueryInnerLocked(uuid, missionId, value);
392 if (!ret) {
393 HILOGE("Query uuid = %{public}s + missionId = %{public}d failed!",
394 DnetworkAdapter::AnonymizeDeviceId(uuid).c_str(), missionId);
395 return false;
396 }
397 }
398 HILOGI("Query uuid = %{public}s + missionId = %{public}d successful!",
399 DnetworkAdapter::AnonymizeDeviceId(uuid).c_str(), missionId);
400 return true;
401 }
402
QueryInnerLocked(const string & uuid,int32_t missionId,Value & value) const403 bool DistributedDataStorage::QueryInnerLocked(const string& uuid, int32_t missionId, Value& value) const
404 {
405 HILOGD("called.");
406 int64_t begin = GetTickCount();
407 if (kvStorePtr_ == nullptr) {
408 HILOGW("kvStorePtr is null!");
409 return false;
410 }
411 Key key;
412 GenerateKey(uuid, missionId, key);
413 auto status = kvStorePtr_->Get(key, value);
414 HILOGI("[PerformanceTest] Get Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
415 if (status != Status::SUCCESS) {
416 HILOGE("kvStorePtr Get failed! status = %{public}d.", status);
417 return false;
418 }
419 return true;
420 }
421
GenerateKey(const string & uuid,int32_t missionId,Key & key)422 void DistributedDataStorage::GenerateKey(const string& uuid, int32_t missionId, Key& key)
423 {
424 string keyString;
425 keyString.append(uuid).append("_").append(to_string(missionId));
426 key = keyString;
427 }
428
GenerateValue(const uint8_t * byteStream,size_t len,Value & value)429 void DistributedDataStorage::GenerateValue(const uint8_t* byteStream, size_t len, Value& value)
430 {
431 Value valueString((char *)byteStream, len);
432 value = valueString;
433 }
434 } // DistributedSchedule
435 } // namespace OHOS