• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "adapter/ohos/capability/distributed/storage/distributed_storage.h"
17 
18 #include "distributed_object.h"
19 #include "distributed_objectstore.h"
20 #include "objectstore_errors.h"
21 
22 #include "base/log/log.h"
23 #include "base/utils/utils.h"
24 #include "core/common/ace_application_info.h"
25 
26 namespace OHOS::Ace {
27 
28 class DistributedObjectWatcher final : public OHOS::ObjectStore::ObjectWatcher {
29 public:
DistributedObjectWatcher(OnDataChangeCallback && onChange)30     explicit DistributedObjectWatcher(OnDataChangeCallback&& onChange)
31     {
32         onChange_ = std::move(onChange);
33     }
34 
OnChanged(const std::string & sessionid,const std::vector<std::string> & changedData)35     void OnChanged(const std::string& sessionid, const std::vector<std::string>& changedData) override
36     {
37         CHECK_NULL_VOID_NOLOG(onChange_);
38         onChange_(sessionid, changedData);
39     }
40 
41 private:
42     OnDataChangeCallback onChange_;
43 };
44 
45 class DistributedObjectStatusNotifier final : public OHOS::ObjectStore::StatusNotifier {
46 public:
DistributedObjectStatusNotifier(ObjectStatusNotifyCallback && onNotify)47     explicit DistributedObjectStatusNotifier(ObjectStatusNotifyCallback&& onNotify)
48     {
49         onNotify_ = std::move(onNotify);
50     }
OnChanged(const std::string & sessionId,const std::string & networkId,const std::string & onlineStatus)51     void OnChanged(const std::string& sessionId, const std::string& networkId, const std::string& onlineStatus) override
52     {
53         LOGI("DistributedObjectStatusNotifier [%{public}s-%{public}s]", sessionId.c_str(), onlineStatus.c_str());
54         CHECK_NULL_VOID_NOLOG(onNotify_);
55         onNotify_(sessionId, onlineStatus);
56     }
57 
58 private:
59     ObjectStatusNotifyCallback onNotify_;
60 };
61 
DistributedObjectPtr(const std::string & sessionId,OnDataChangeCallback && onChange)62 DistributedObjectPtr::DistributedObjectPtr(const std::string& sessionId, OnDataChangeCallback&& onChange)
63 {
64     std::string bundleName = AceApplicationInfo::GetInstance().GetProcessName();
65     if (bundleName.empty()) {
66         LOGE("DistributedObjectStore bundleName is empty!");
67         return;
68     }
69     OHOS::ObjectStore::DistributedObjectStore* store =
70         OHOS::ObjectStore::DistributedObjectStore::GetInstance(bundleName);
71     CHECK_NULL_VOID(store);
72     static std::once_flag onceFlag;
73     std::call_once(onceFlag, [store]() {
74         auto callback = [](const std::string& sessionId, const std::string& onlineStatus) {
75             DistributedStorage::OnStatusNotify(sessionId, onlineStatus);
76         };
77         store->SetStatusNotifier(std::make_shared<DistributedObjectStatusNotifier>(callback));
78     });
79 
80     uint32_t ret = store->Get(sessionId, &object_);
81     if (ret != OHOS::ObjectStore::SUCCESS) {
82         LOGW("DistributedObjectStore get object[%{private}s] failed, try to create", sessionId.c_str());
83         object_ = store->CreateObject(sessionId);
84         CHECK_NULL_VOID(object_);
85     }
86 
87     sessionId_ = sessionId;
88     watcher_ = std::make_shared<DistributedObjectWatcher>(std::move(onChange));
89     ret = store->Watch(object_, watcher_);
90     if (ret != OHOS::ObjectStore::SUCCESS) {
91         LOGE("DistributedObjectStore Watch failed!, err=[%{private}u", ret);
92     }
93     LOGI("DistributedObjectPtr init success[%{public}s]", sessionId_.c_str());
94     invalid_ = false;
95 }
96 
~DistributedObjectPtr()97 DistributedObjectPtr::~DistributedObjectPtr()
98 {
99     if (object_ != nullptr) {
100         std::string bundleName = AceApplicationInfo::GetInstance().GetProcessName();
101         OHOS::ObjectStore::DistributedObjectStore* store =
102             OHOS::ObjectStore::DistributedObjectStore::GetInstance(bundleName);
103         CHECK_NULL_VOID(store);
104         uint32_t ret = store->UnWatch(object_);
105         if (ret != OHOS::ObjectStore::SUCCESS) {
106             LOGE("DistributedObjectStore UnWatch failed!, err=[%{private}u]", ret);
107         }
108         ret = store->DeleteObject(sessionId_);
109         if (ret != OHOS::ObjectStore::SUCCESS) {
110             LOGE("DistributedObjectStore DeleteObject failed!, err=[%{private}u]", ret);
111         }
112     }
113     DistributedStorage::DeleteStorage(sessionId_);
114 }
115 
GetRawPtr()116 OHOS::ObjectStore::DistributedObject* DistributedObjectPtr::GetRawPtr()
117 {
118     return object_;
119 }
120 
121 std::map<std::string, RefPtr<DistributedStorage>> DistributedStorage::storageMap_;
122 
AddStorage(const std::string & sessionId,RefPtr<DistributedStorage> storage)123 void DistributedStorage::AddStorage(const std::string& sessionId, RefPtr<DistributedStorage> storage)
124 {
125     storageMap_.try_emplace(sessionId, storage);
126 }
127 
DeleteStorage(const std::string & sessionId)128 void DistributedStorage::DeleteStorage(const std::string& sessionId)
129 {
130     storageMap_.erase(sessionId);
131 }
132 
OnStatusNotify(const std::string & sessionId,const std::string & status)133 void DistributedStorage::OnStatusNotify(const std::string& sessionId, const std::string& status)
134 {
135     auto storage = storageMap_.find(sessionId);
136     if (storage != storageMap_.end()) {
137         storage->second->NotifyStatus(status);
138     }
139 }
140 
Init(std::function<void (const std::string &)> && notifyCallback)141 bool DistributedStorage::Init(std::function<void(const std::string&)>&& notifyCallback)
142 {
143     notifyCallback_ = std::move(notifyCallback);
144     auto onChangeCallback = [weak = WeakClaim(this)](
145                                 const std::string& sessionid, const std::vector<std::string>& changedData) {
146         auto storage = weak.Upgrade();
147         for (auto& key : changedData) {
148             storage->OnDataChange(key);
149         }
150     };
151     objectPtr_ = std::make_unique<DistributedObjectPtr>(sessionId_, std::move(onChangeCallback));
152 
153     return true;
154 }
155 
SetString(const std::string & key,const std::string & value)156 void DistributedStorage::SetString(const std::string& key, const std::string& value)
157 {
158     if (objectPtr_->IsInvalid()) {
159         LOGE("Set string failed, distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
160             sessionId_.c_str(), key.c_str());
161         return;
162     }
163 
164     auto ret = objectPtr_->GetRawPtr()->PutString(key, value);
165     if (ret != OHOS::ObjectStore::SUCCESS) {
166         LOGE("Set string failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
167             key.c_str(), ret);
168     }
169 }
170 
GetString(const std::string & key)171 std::string DistributedStorage::GetString(const std::string& key)
172 {
173     if (objectPtr_->IsInvalid()) {
174         LOGE("Get string failed, distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
175             sessionId_.c_str(), key.c_str());
176         return "";
177     }
178     std::string value;
179     auto ret = objectPtr_->GetRawPtr()->GetString(key, value);
180     if (ret != OHOS::ObjectStore::SUCCESS) {
181         LOGE("Get string failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
182             key.c_str(), ret);
183     }
184     return value;
185 }
186 
SetDouble(const std::string & key,const double value)187 void DistributedStorage::SetDouble(const std::string& key, const double value)
188 {
189     if (objectPtr_->IsInvalid()) {
190         LOGE("Set double failed, distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
191             sessionId_.c_str(), key.c_str());
192         return;
193     }
194     auto ret = objectPtr_->GetRawPtr()->PutDouble(key, value);
195     if (ret != OHOS::ObjectStore::SUCCESS) {
196         LOGE("Set double failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
197             key.c_str(), ret);
198     }
199 }
200 
GetDouble(const std::string & key,double & value)201 bool DistributedStorage::GetDouble(const std::string& key, double& value)
202 {
203     if (objectPtr_->IsInvalid()) {
204         LOGE("Get double failed, distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
205             sessionId_.c_str(), key.c_str());
206         return false;
207     }
208     auto ret = objectPtr_->GetRawPtr()->GetDouble(key, value);
209     if (ret != OHOS::ObjectStore::SUCCESS) {
210         LOGE("Get double failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
211             key.c_str(), ret);
212         return false;
213     }
214     return true;
215 }
216 
SetBoolean(const std::string & key,const bool value)217 void DistributedStorage::SetBoolean(const std::string& key, const bool value)
218 {
219     if (objectPtr_->IsInvalid()) {
220         LOGE("Set boolean failed, distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
221             sessionId_.c_str(), key.c_str());
222         return;
223     }
224     auto ret = objectPtr_->GetRawPtr()->PutBoolean(key, value);
225     if (ret != OHOS::ObjectStore::SUCCESS) {
226         LOGE("Set boolean failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
227             key.c_str(), ret);
228     }
229 }
230 
GetBoolean(const std::string & key,bool & value)231 bool DistributedStorage::GetBoolean(const std::string& key, bool& value)
232 {
233     if (objectPtr_->IsInvalid()) {
234         LOGE("Get boolean failed, distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
235             sessionId_.c_str(), key.c_str());
236         return false;
237     }
238     auto ret = objectPtr_->GetRawPtr()->GetBoolean(key, value);
239     if (ret != OHOS::ObjectStore::SUCCESS) {
240         LOGE("Get boolean failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
241             key.c_str(), ret);
242         return false;
243     }
244     return true;
245 }
246 
GetDataType(const std::string & key)247 Storage::DataType DistributedStorage::GetDataType(const std::string& key)
248 {
249     if (objectPtr_->IsInvalid()) {
250         LOGE("Get type failed! distributed object is invalid! sessionId=[%{private}s], key=[%{private}s]",
251             sessionId_.c_str(), key.c_str());
252         return Storage::DataType::NONE;
253     }
254     OHOS::ObjectStore::Type type = OHOS::ObjectStore::Type::TYPE_STRING;
255     auto ret = objectPtr_->GetRawPtr()->GetType(key, type);
256 
257     if (ret != OHOS::ObjectStore::SUCCESS) {
258         LOGE("Get type failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u]", sessionId_.c_str(),
259             key.c_str(), ret);
260         return Storage::DataType::NONE;
261     }
262 
263     Storage::DataType dataType = Storage::DataType::NONE;
264     switch (type) {
265         case OHOS::ObjectStore::Type::TYPE_STRING:
266             dataType = Storage::DataType::STRING;
267             break;
268         case OHOS::ObjectStore::Type::TYPE_BOOLEAN:
269             dataType = Storage::DataType::BOOLEAN;
270             break;
271         case OHOS::ObjectStore::Type::TYPE_DOUBLE:
272             dataType = Storage::DataType::DOUBLE;
273             break;
274         default:
275             break;
276     }
277     return dataType;
278 }
279 
NotifyStatus(const std::string & status)280 void DistributedStorage::NotifyStatus(const std::string& status)
281 {
282     CHECK_NULL_VOID_NOLOG(taskExecutor_);
283     LOGI("DistributedStorage::NotifyStatus [%{public}s-%{public}s]", sessionId_.c_str(), status.c_str());
284     taskExecutor_->PostTask(
285         [weak = WeakClaim(this), status] {
286             auto storage = weak.Upgrade();
287             if (storage && storage->notifyCallback_) {
288                 storage->notifyCallback_(status);
289             }
290         },
291         TaskExecutor::TaskType::JS);
292 }
293 
294 } // namespace OHOS::Ace