• 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 "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