• 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 #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 &param)
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