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 #define LOG_TAG "RdbManagerImpl"
16 #include "rdb_manager_impl.h"
17
18 #include <thread>
19
20 #include "global_resource.h"
21 #include "ipc_skeleton.h"
22 #include "irdb_service.h"
23 #include "iservice_registry.h"
24 #include "itypes_util.h"
25 #include "logger.h"
26 #include "rdb_errno.h"
27 #include "rdb_service_proxy.h"
28 #include "system_ability_definition.h"
29
30 namespace OHOS::DistributedRdb {
31 using namespace OHOS::Rdb;
32 using RdbServiceProxy = DistributedRdb::RdbServiceProxy;
33 using namespace OHOS::NativeRdb;
34 using namespace OHOS::DistributedRdb::RelationalStore;
35 constexpr int32_t MAX_RETRY = 100;
36 class DeathStub : public IRemoteBroker {
37 public:
38 DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedRdb.DeathStub");
39 };
40 class DeathStubImpl : public IRemoteStub<DeathStub> {};
GetDistributedDataManager(const std::string & bundleName)41 std::shared_ptr<RdbStoreDataServiceProxy> RdbManagerImpl::GetDistributedDataManager(const std::string &bundleName)
42 {
43 auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
44 if (manager == nullptr) {
45 LOG_ERROR("Get system ability manager failed.");
46 return nullptr;
47 }
48 auto dataMgr = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
49 if (dataMgr == nullptr) {
50 LOG_ERROR("Get distributed data manager failed.");
51 return nullptr;
52 }
53 sptr<RdbStoreDataServiceProxy> dataService = new (std::nothrow) RdbStoreDataServiceProxy(dataMgr);
54 if (dataService == nullptr) {
55 LOG_ERROR("New RdbStoreDataServiceProxy failed.");
56 return nullptr;
57 }
58
59 sptr<IRemoteObject> observer = new (std::nothrow) DeathStubImpl();
60 dataService->RegisterDeathObserver(bundleName, observer);
61 return std::shared_ptr<RdbStoreDataServiceProxy>(dataService.GetRefPtr(), [dataService](const auto *) {});
62 }
63
LinkToDeath(const sptr<IRemoteObject> & remote)64 sptr<IRemoteObject::DeathRecipient> RdbManagerImpl::LinkToDeath(const sptr<IRemoteObject> &remote)
65 {
66 auto &manager = RdbManagerImpl::GetInstance();
67 sptr<RdbManagerImpl::ServiceDeathRecipient> deathRecipient = new (std::nothrow)
68 RdbManagerImpl::ServiceDeathRecipient(&manager);
69 if (deathRecipient == nullptr) {
70 LOG_ERROR("New ServiceDeathRecipient failed.");
71 return nullptr;
72 }
73 if (!remote->AddDeathRecipient(deathRecipient)) {
74 LOG_ERROR("Add death recipient failed.");
75 }
76 return deathRecipient;
77 }
78
RdbManagerImpl()79 RdbManagerImpl::RdbManagerImpl()
80 {
81 }
82
~RdbManagerImpl()83 RdbManagerImpl::~RdbManagerImpl()
84 {
85 LOG_INFO("Destroy.");
86 }
87
GetInstance()88 RdbManagerImpl &RdbManagerImpl::GetInstance()
89 {
90 static RdbManagerImpl manager;
91 return manager;
92 }
93
GetRdbService(const RdbSyncerParam & param)94 std::pair<int32_t, std::shared_ptr<RdbService>> RdbManagerImpl::GetRdbService(const RdbSyncerParam ¶m)
95 {
96 if (param.bundleName_.empty()) {
97 return { E_INVALID_ARGS, nullptr };
98 }
99
100 std::lock_guard<std::mutex> lock(mutex_);
101 if (rdbService_ != nullptr) {
102 return { E_OK, rdbService_ };
103 }
104
105 if (distributedDataMgr_ == nullptr) {
106 distributedDataMgr_ = GetDistributedDataManager(param.bundleName_);
107 }
108 if (distributedDataMgr_ == nullptr) {
109 LOG_ERROR("Get distributed data manager failed.");
110 return { E_SERVICE_NOT_FOUND, nullptr };
111 }
112
113 auto remote = distributedDataMgr_->GetFeatureInterface(DistributedRdb::RdbService::SERVICE_NAME);
114 if (remote == nullptr) {
115 LOG_ERROR("Get rdb service failed.");
116 return { E_NOT_SUPPORT, nullptr };
117 }
118
119 if (!remote->IsProxyObject()) {
120 return { E_NOT_SUPPORT, nullptr };
121 }
122
123 sptr<RdbServiceProxy> rdbService = iface_cast<RdbServiceProxy>(remote);
124 if (rdbService == nullptr) {
125 rdbService = new (std::nothrow) RdbServiceProxy(remote);
126 }
127
128 if (rdbService == nullptr || rdbService->InitNotifier(param) != RDB_OK) {
129 LOG_ERROR("Init notifier failed.");
130 return { E_ERROR, nullptr };
131 }
132
133 sptr<IRdbService> serviceBase = rdbService;
134 auto deathRecipient = LinkToDeath(serviceBase->AsObject());
135 // the rdbService is not null, so rdbService.GetRefPtr() is not null;
136 rdbService_ = std::shared_ptr<RdbService>(rdbService.GetRefPtr(), [rdbService, deathRecipient](const auto *) {
137 sptr<IRdbService> serviceBase = rdbService;
138 serviceBase->AsObject()->RemoveDeathRecipient(deathRecipient);
139 });
140 param_ = param;
141 GlobalResource::RegisterClean(GlobalResource::IPC, []() {
142 return RdbManagerImpl::GetInstance().CleanUp();
143 });
144 return { E_OK, rdbService_ };
145 }
146
OnRemoteDied()147 void RdbManagerImpl::OnRemoteDied()
148 {
149 LOG_INFO("Rdb service has dead!");
150 if (rdbService_ == nullptr) {
151 ResetServiceHandle();
152 return;
153 }
154 auto proxy = std::static_pointer_cast<RdbServiceProxy>(rdbService_);
155 if (proxy == nullptr) {
156 return;
157 }
158 auto observers = proxy->ExportObservers();
159 auto syncObservers = proxy->ExportSyncObservers();
160 proxy->OnRemoteDeadSyncComplete();
161 ResetServiceHandle();
162
163 std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME));
164 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param_);
165 if (errCode != E_OK) {
166 return;
167 }
168 proxy = std::static_pointer_cast<RdbServiceProxy>(service);
169 if (proxy == nullptr) {
170 return;
171 }
172 proxy->ImportObservers(observers);
173 proxy->ImportSyncObservers(syncObservers);
174 }
175
ResetServiceHandle()176 void RdbManagerImpl::ResetServiceHandle()
177 {
178 std::lock_guard<std::mutex> lock(mutex_);
179 distributedDataMgr_ = nullptr;
180 rdbService_ = nullptr;
181 }
182
CleanUp()183 int32_t RdbManagerImpl::CleanUp()
184 {
185 std::lock_guard<std::mutex> lock(mutex_);
186 if (distributedDataMgr_ != nullptr) {
187 auto code = distributedDataMgr_->Exit();
188 if (code != E_OK) {
189 LOG_ERROR("Exit failed.code:%{public}d!", code);
190 return code;
191 }
192 }
193 distributedDataMgr_ = nullptr;
194 if (rdbService_.use_count() > 1) {
195 LOG_WARN("RdbService has other in use:%{public}ld!", rdbService_.use_count());
196 return E_ERROR;
197 }
198 rdbService_ = nullptr;
199 return E_OK;
200 }
201
RdbStoreDataServiceProxy(const sptr<IRemoteObject> & impl)202 RdbStoreDataServiceProxy::RdbStoreDataServiceProxy(const sptr<IRemoteObject> &impl)
203 : IRemoteProxy<DistributedRdb::IKvStoreDataService>(impl)
204 {
205 }
206
GetFeatureInterface(const std::string & name)207 sptr<IRemoteObject> RdbStoreDataServiceProxy::GetFeatureInterface(const std::string &name)
208 {
209 LOG_DEBUG("%{public}s", name.c_str());
210 MessageParcel data;
211 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
212 LOG_ERROR("Write descriptor failed.");
213 return nullptr;
214 }
215
216 if (!ITypesUtil::Marshal(data, name)) {
217 LOG_ERROR("Write descriptor failed.");
218 return nullptr;
219 }
220
221 MessageParcel reply;
222 MessageOption mo{ MessageOption::TF_SYNC };
223 int32_t error =
224 Remote()->SendRequest(static_cast<uint32_t>(KvStoreInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo);
225 if (error != 0) {
226 LOG_ERROR("SendRequest returned %{public}d", error);
227 return nullptr;
228 }
229
230 sptr<IRemoteObject> remoteObject;
231 if (!ITypesUtil::Unmarshal(reply, remoteObject)) {
232 LOG_ERROR("Remote object is nullptr.");
233 return nullptr;
234 }
235 return remoteObject;
236 }
237
RegisterDeathObserver(const std::string & bundleName,sptr<IRemoteObject> observer,const std::string & featureName)238 int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(
239 const std::string &bundleName, sptr<IRemoteObject> observer, const std::string &featureName)
240 {
241 MessageParcel data;
242 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
243 LOG_ERROR("Write descriptor failed.");
244 return E_ERROR;
245 }
246
247 if (!ITypesUtil::Marshal(data, bundleName, observer, featureName)) {
248 LOG_ERROR("Write descriptor failed.");
249 return E_ERROR;
250 }
251
252 MessageParcel reply;
253 MessageOption mo{ MessageOption::TF_SYNC };
254 int32_t error =
255 Remote()->SendRequest(static_cast<uint32_t>(KvStoreInterfaceCode::REGISTER_DEATH_OBSERVER), data, reply, mo);
256 if (error != 0) {
257 LOG_ERROR("SendRequest returned %{public}d", error);
258 return E_ERROR;
259 }
260
261 int32_t status = E_ERROR;
262 ITypesUtil::Unmarshal(reply, status);
263 if (status == E_OK) {
264 clientDeathObserver_ = observer;
265 }
266 return status;
267 }
268
Exit(const std::string & featureName)269 int32_t RdbStoreDataServiceProxy::Exit(const std::string &featureName)
270 {
271 MessageParcel data;
272 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
273 LOG_ERROR("Write descriptor failed.");
274 return E_ERROR;
275 }
276
277 if (!ITypesUtil::Marshal(data, featureName)) {
278 LOG_ERROR("Write descriptor failed.");
279 return E_ERROR;
280 }
281
282 MessageParcel reply;
283 MessageOption mo{ MessageOption::TF_SYNC };
284 int32_t error = Remote()->SendRequest(static_cast<uint32_t>(KvStoreInterfaceCode::FEATURE_EXIT), data, reply, mo);
285 if (error != 0) {
286 LOG_ERROR("SendRequest returned %{public}d", error);
287 return E_ERROR;
288 }
289
290 int32_t status = E_ERROR;
291 ITypesUtil::Unmarshal(reply, status);
292 if (status == E_OK) {
293 int32_t retry = 0;
294 while (clientDeathObserver_ != nullptr && clientDeathObserver_->GetSptrRefCount() > 1 && retry < MAX_RETRY) {
295 retry++;
296 std::this_thread::sleep_for(std::chrono::milliseconds(1));
297 }
298 if (clientDeathObserver_ != nullptr && clientDeathObserver_->GetSptrRefCount() > 1) {
299 LOG_WARN("observer still in use! count:%{public}d", clientDeathObserver_->GetSptrRefCount());
300 return E_ERROR;
301 }
302 }
303 return status;
304 }
305 } // namespace OHOS::DistributedRdb
306