• 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 const string KVDB_PATH = "/data/service/el1/public/database/DistributedSchedule";
39 constexpr int32_t RETRY_TIMES_WAIT_KV_DATA = 30;
40 constexpr int32_t RETRY_TIMES_GET_KVSTORE = 5;
41 }
42 
DistributedDataStorage()43 DistributedDataStorage::DistributedDataStorage()
44 {
45     appId_.appId = APP_ID;
46     storeId_.storeId = STORE_ID;
47 }
48 
Init()49 bool DistributedDataStorage::Init()
50 {
51     HILOGD("begin.");
52     if (kvStoreDeathRecipient_ == nullptr) {
53         kvStoreDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new KvStoreDeathRecipient());
54     }
55     if (dmsDataStorageHandler_ == nullptr) {
56         shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("dmsDataStorageHandler");
57         dmsDataStorageHandler_ = make_shared<AppExecFwk::EventHandler>(runner);
58     }
59     int32_t 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         .area = 1,
147         .baseDir = KVDB_PATH
148     };
149     Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
150     if (status != Status::SUCCESS) {
151         HILOGE("GetSingleKvStore failed, status = %{public}d.", status);
152     }
153     HILOGI("GetSingleKvStore success!");
154     return status;
155 }
156 
SubscribeDistributedDataStorage()157 void DistributedDataStorage::SubscribeDistributedDataStorage()
158 {
159     int64_t begin = GetTickCount();
160     shared_lock<shared_mutex> readLock(initLock_);
161     if (kvStorePtr_ == nullptr) {
162         HILOGW("kvStorePtr is null!");
163         return;
164     }
165     SubscribeType subscribeType = SubscribeType::SUBSCRIBE_TYPE_REMOTE;
166     if (distributedDataChangeListener_ != nullptr) {
167         HILOGD("SubscribeKvStore start.");
168         Status status = kvStorePtr_->SubscribeKvStore(subscribeType, move(distributedDataChangeListener_));
169         HILOGI("[PerformanceTest] SubscribeKvStore spend %{public}" PRId64 " ms", GetTickCount() - begin);
170         if (status != Status::SUCCESS) {
171             HILOGE("SubscribeKvStore failed! status = %{public}d.", status);
172             return;
173         }
174     }
175 }
176 
NotifyRemoteDied(const wptr<IRemoteObject> & remote)177 void DistributedDataStorage::NotifyRemoteDied(const wptr<IRemoteObject>& remote)
178 {
179     HILOGD("begin.");
180     if (kvStoreDeathRecipient_ != nullptr) {
181         remote->RemoveDeathRecipient(kvStoreDeathRecipient_);
182     }
183 }
184 
Stop()185 bool DistributedDataStorage::Stop()
186 {
187     HILOGD("begin.");
188     dmsDataStorageHandler_ = nullptr;
189     bool ret = UninitDistributedDataStorage();
190     if (!ret) {
191         HILOGE("UninitDistributedDataStorage failed!");
192         return false;
193     }
194     HILOGD("Stop success!");
195     return true;
196 }
197 
UninitDistributedDataStorage()198 bool DistributedDataStorage::UninitDistributedDataStorage()
199 {
200     int64_t begin = GetTickCount();
201     Status status;
202     if (distributedDataChangeListener_ != nullptr && kvStorePtr_ != nullptr) {
203         SubscribeType subscribeType = SubscribeType::SUBSCRIBE_TYPE_REMOTE;
204         status = kvStorePtr_->UnSubscribeKvStore(subscribeType, move(distributedDataChangeListener_));
205         HILOGI("[PerformanceTest] UnSubscribeKvStore spend %{public}" PRId64 " ms", GetTickCount() - begin);
206         if (status != Status::SUCCESS) {
207             HILOGE("UnSubscribeKvStore failed! status = %{public}d.", status);
208             return false;
209         }
210         distributedDataChangeListener_ = nullptr;
211     }
212     if (kvStorePtr_ != nullptr) {
213         status = dataManager_.CloseKvStore(appId_, storeId_);
214         if (status != Status::SUCCESS) {
215             HILOGE("CloseKvStore failed! status = %{public}d.", status);
216             return false;
217         }
218         kvStorePtr_ = nullptr;
219     }
220     status = dataManager_.DeleteKvStore(appId_, storeId_, KVDB_PATH);
221     if (status != Status::SUCCESS) {
222         HILOGE("DeleteKvStore failed! status = %{public}d.", status);
223         return false;
224     }
225     return true;
226 }
227 
Insert(const string & networkId,int32_t missionId,const uint8_t * byteStream,size_t len)228 bool DistributedDataStorage::Insert(const string& networkId, int32_t missionId,
229     const uint8_t* byteStream, size_t len)
230 {
231     if (networkId.empty()) {
232         HILOGW("networkId is empty!");
233         return false;
234     }
235     if (missionId < 0) {
236         HILOGW("missionId is invalid!");
237         return false;
238     }
239     string uuid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUuidByNetworkId(networkId);
240     if (uuid.empty()) {
241         HILOGW("uuid is empty!");
242         return false;
243     }
244     {
245         unique_lock<shared_mutex> writeLock(initLock_);
246         bool ret = InsertInnerLocked(uuid, missionId, byteStream, len);
247         if (!ret) {
248             HILOGE("Insert uuid = %{public}s + missionId = %{public}d failed!",
249                 DnetworkAdapter::AnonymizeNetworkId(uuid).c_str(), missionId);
250             return false;
251         }
252     }
253     HILOGI("Insert uuid = %{public}s + missionId = %{public}d successful!",
254         DnetworkAdapter::AnonymizeNetworkId(uuid).c_str(), missionId);
255     return true;
256 }
257 
InsertInnerLocked(const string & uuid,int32_t missionId,const uint8_t * byteStream,size_t len)258 bool DistributedDataStorage::InsertInnerLocked(const string& uuid, int32_t missionId,
259     const uint8_t* byteStream, size_t len)
260 {
261     HILOGD("called.");
262     int64_t begin = GetTickCount();
263     if (kvStorePtr_ == nullptr) {
264         HILOGW("kvStorePtr is null!");
265         return false;
266     }
267     Key key;
268     Value value;
269     GenerateKey(uuid, missionId, key);
270     GenerateValue(byteStream, len, value);
271     auto status = kvStorePtr_->Put(key, value);
272     HILOGI("[PerformanceTest] Put Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
273     if (status != Status::SUCCESS) {
274         HILOGE("kvStorePtr Put failed! status = %{public}d.", status);
275         return false;
276     }
277     return true;
278 }
279 
Delete(const string & networkId,int32_t missionId)280 bool DistributedDataStorage::Delete(const string& networkId, int32_t missionId)
281 {
282     if (networkId.empty()) {
283         HILOGW("networkId is empty!");
284         return false;
285     }
286     if (missionId < 0) {
287         HILOGW("missionId is invalid!");
288         return false;
289     }
290     string uuid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUuidByNetworkId(networkId);
291     if (uuid.empty()) {
292         HILOGW("uuid is empty!");
293         return false;
294     }
295     {
296         unique_lock<shared_mutex> writeLock(initLock_);
297         bool ret = DeleteInnerLocked(uuid, missionId);
298         if (!ret) {
299             HILOGE("Delete uuid = %{public}s + missionId = %{public}d failed!",
300                 DnetworkAdapter::AnonymizeNetworkId(uuid).c_str(), missionId);
301             return false;
302         }
303     }
304     HILOGI("Delete uuid = %{public}s + missionId = %{public}d successful!",
305         DnetworkAdapter::AnonymizeNetworkId(uuid).c_str(), missionId);
306     return true;
307 }
308 
DeleteInnerLocked(const string & uuid,int32_t missionId)309 bool DistributedDataStorage::DeleteInnerLocked(const string& uuid, int32_t missionId)
310 {
311     HILOGD("called.");
312     int64_t begin = GetTickCount();
313     if (kvStorePtr_ == nullptr) {
314         HILOGW("kvStorePtr is null!");
315         return false;
316     }
317     Key key;
318     GenerateKey(uuid, missionId, key);
319     auto status = kvStorePtr_->Delete(key);
320     HILOGI("[PerformanceTest] Delete Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
321     if (status != Status::SUCCESS) {
322         HILOGE("kvStorePtr Delete failed! status = %{public}d.", status);
323         return false;
324     }
325     return true;
326 }
327 
FuzzyDelete(const string & networkId)328 bool DistributedDataStorage::FuzzyDelete(const string& networkId)
329 {
330     if (networkId.empty()) {
331         HILOGW("networkId is empty!");
332         return false;
333     }
334     {
335         unique_lock<shared_mutex> writeLock(initLock_);
336         bool ret = FuzzyDeleteInnerLocked(networkId);
337         if (!ret) {
338             HILOGW("FuzzyDelete networkId = %{public}s failed!",
339                 DnetworkAdapter::AnonymizeNetworkId(networkId).c_str());
340             return false;
341         }
342     }
343     HILOGI("FuzzyDelete networkId = %{public}s successful!", DnetworkAdapter::AnonymizeNetworkId(networkId).c_str());
344     return true;
345 }
346 
FuzzyDeleteInnerLocked(const string & networkId)347 bool DistributedDataStorage::FuzzyDeleteInnerLocked(const string& networkId)
348 {
349     HILOGD("called.");
350     int64_t begin = GetTickCount();
351     if (kvStorePtr_ == nullptr) {
352         HILOGW("kvStorePtr is null!");
353         return false;
354     }
355     auto status = kvStorePtr_->RemoveDeviceData(networkId);
356     HILOGI("[PerformanceTest] RemoveDeviceData Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
357     if (status != Status::SUCCESS) {
358         HILOGE("kvStorePtr RemoveDeviceData failed! status = %{public}d.", status);
359         return false;
360     }
361     return true;
362 }
363 
Query(const string & networkId,int32_t missionId,Value & value) const364 bool DistributedDataStorage::Query(const string& networkId, int32_t missionId, Value& value) const
365 {
366     if (networkId.empty()) {
367         HILOGW("networkId is empty!");
368         return false;
369     }
370     if (missionId < 0) {
371         HILOGW("missionId is invalid!");
372         return false;
373     }
374     string uuid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUuidByNetworkId(networkId);
375     if (uuid.empty()) {
376         HILOGW("uuid is empty!");
377         return false;
378     }
379     {
380         shared_lock<shared_mutex> readLock(initLock_);
381         bool ret = QueryInnerLocked(uuid, missionId, value);
382         if (!ret) {
383             HILOGE("Query uuid = %{public}s + missionId = %{public}d failed!",
384                 DnetworkAdapter::AnonymizeNetworkId(uuid).c_str(), missionId);
385             return false;
386         }
387     }
388     HILOGI("Query uuid = %{public}s + missionId = %{public}d successful!",
389         DnetworkAdapter::AnonymizeNetworkId(uuid).c_str(), missionId);
390     return true;
391 }
392 
QueryInnerLocked(const string & uuid,int32_t missionId,Value & value) const393 bool DistributedDataStorage::QueryInnerLocked(const string& uuid, int32_t missionId, Value& value) const
394 {
395     HILOGD("called.");
396     int64_t begin = GetTickCount();
397     if (kvStorePtr_ == nullptr) {
398         HILOGW("kvStorePtr is null!");
399         return false;
400     }
401     Key key;
402     GenerateKey(uuid, missionId, key);
403     auto status = kvStorePtr_->Get(key, value);
404     HILOGI("[PerformanceTest] Get Snapshot spend %{public}" PRId64 " ms", GetTickCount() - begin);
405     if (status != Status::SUCCESS) {
406         HILOGE("kvStorePtr Get failed! status = %{public}d.", status);
407         return false;
408     }
409     return true;
410 }
411 
GenerateKey(const string & uuid,int32_t missionId,Key & key)412 void DistributedDataStorage::GenerateKey(const string& uuid, int32_t missionId, Key& key)
413 {
414     string keyString;
415     keyString.append(uuid).append("_").append(to_string(missionId));
416     key = keyString;
417 }
418 
GenerateValue(const uint8_t * byteStream,size_t len,Value & value)419 void DistributedDataStorage::GenerateValue(const uint8_t* byteStream, size_t len, Value& value)
420 {
421     Value valueString((char *)byteStream, len);
422     value = valueString;
423 }
424 } // DistributedSchedule
425 } // namespace OHOS