mirror of
https://gitee.com/openharmony/msdp_device_status
synced 2024-11-27 17:51:04 +00:00
refactor epoll manager
Signed-off-by: blueyouh <bailiang18@huawei.com> Change-Id: Id3451546e448d28a1973bf6f84605b3ade81e5cb Signed-off-by: blueyouh <bailiang18@huawei.com>
This commit is contained in:
parent
b4dc5b32cb
commit
47e7a00896
35
common/epoll/BUILD.gn
Executable file
35
common/epoll/BUILD.gn
Executable file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("../../device_status.gni")
|
||||
|
||||
config("devicestatus_epoll_public_config") {
|
||||
include_dirs = [ "include" ]
|
||||
}
|
||||
|
||||
ohos_source_set("devicestatus_epoll") {
|
||||
include_dirs = [ "include" ]
|
||||
|
||||
sources = [ "src/epoll_manager.cpp" ]
|
||||
|
||||
public_configs = [ ":devicestatus_epoll_public_config" ]
|
||||
|
||||
deps = [ "${device_status_utils_path}:devicestatus_util" ]
|
||||
|
||||
public_deps = [ "${device_status_root_path}/data:devicestatus_data" ]
|
||||
|
||||
external_deps = [ "hilog:libhilog" ]
|
||||
|
||||
subsystem_name = "${device_status_subsystem_name}"
|
||||
part_name = "${device_status_part_name}"
|
||||
}
|
62
common/epoll/include/epoll_manager.h
Normal file
62
common/epoll/include/epoll_manager.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef EPOLL_MANAGER_H
|
||||
#define EPOLL_MANAGER_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "nocopyable.h"
|
||||
|
||||
#include "i_epoll_event_source.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Msdp {
|
||||
namespace DeviceStatus {
|
||||
class EpollManager final : public IEpollEventSource {
|
||||
public:
|
||||
EpollManager() = default;
|
||||
~EpollManager();
|
||||
DISALLOW_COPY_AND_MOVE(EpollManager);
|
||||
|
||||
int32_t Open();
|
||||
void Close();
|
||||
|
||||
int32_t Add(IEpollEventSource &source);
|
||||
void Remove(IEpollEventSource &source);
|
||||
int32_t Update(IEpollEventSource &source);
|
||||
int32_t Wait(struct epoll_event *events, int32_t maxevents);
|
||||
int32_t WaitTimeout(struct epoll_event *events, int32_t maxevents, int32_t timeout);
|
||||
|
||||
int32_t GetFd() const override;
|
||||
void Dispatch(const struct epoll_event &ev) override;
|
||||
|
||||
private:
|
||||
void DispatchOne(const struct epoll_event &ev);
|
||||
|
||||
private:
|
||||
int32_t epollFd_ { -1 };
|
||||
};
|
||||
|
||||
inline int32_t EpollManager::GetFd() const
|
||||
{
|
||||
return epollFd_;
|
||||
}
|
||||
} // namespace DeviceStatus
|
||||
} // namespace Msdp
|
||||
} // namespace OHOS
|
||||
#endif // EPOLL_MANAGER_H
|
137
common/epoll/src/epoll_manager.cpp
Normal file
137
common/epoll/src/epoll_manager.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "epoll_manager.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "devicestatus_define.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Msdp {
|
||||
namespace DeviceStatus {
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "EpollManager" };
|
||||
constexpr int32_t MAX_N_EVENTS { 64 };
|
||||
} // namespace
|
||||
|
||||
EpollManager::~EpollManager()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
int32_t EpollManager::Open()
|
||||
{
|
||||
epollFd_ = ::epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollFd_ == -1) {
|
||||
FI_HILOGE("epoll_create1 failed: %{public}s", ::strerror(errno));
|
||||
return RET_ERR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void EpollManager::Close()
|
||||
{
|
||||
if (epollFd_ != -1) {
|
||||
if (::close(epollFd_) != 0) {
|
||||
FI_HILOGE("close(%{public}d) failed:%{public}s", epollFd_, ::strerror(errno));
|
||||
}
|
||||
epollFd_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t EpollManager::Add(IEpollEventSource &source)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
struct epoll_event ev {};
|
||||
ev.events = source.GetEvents();
|
||||
ev.data.ptr = &source;
|
||||
|
||||
int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_ADD, source.GetFd(), &ev);
|
||||
if (ret != 0) {
|
||||
FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
|
||||
return RET_ERR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void EpollManager::Remove(IEpollEventSource &source)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_DEL, source.GetFd(), nullptr);
|
||||
if (ret != 0) {
|
||||
FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int32_t EpollManager::Update(IEpollEventSource &source)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
struct epoll_event ev {};
|
||||
ev.events = source.GetEvents();
|
||||
ev.data.ptr = &source;
|
||||
|
||||
int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_MOD, source.GetFd(), &ev);
|
||||
if (ret != 0) {
|
||||
FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
|
||||
return RET_ERR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32_t EpollManager::Wait(struct epoll_event *events, int32_t maxevents)
|
||||
{
|
||||
return WaitTimeout(events, maxevents, -1);
|
||||
}
|
||||
|
||||
int32_t EpollManager::WaitTimeout(struct epoll_event *events, int32_t maxevents, int32_t timeout)
|
||||
{
|
||||
int32_t ret = ::epoll_wait(epollFd_, events, maxevents, timeout);
|
||||
if (ret < 0) {
|
||||
FI_HILOGE("epoll_wait failed:%{public}s", ::strerror(errno));
|
||||
} else if (ret == 0) {
|
||||
FI_HILOGE("epoll_wait timeout");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EpollManager::Dispatch(const struct epoll_event &ev)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
if ((ev.events & EPOLLIN) == EPOLLIN) {
|
||||
DispatchOne(ev);
|
||||
} else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
|
||||
FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void EpollManager::DispatchOne(const struct epoll_event &ev)
|
||||
{
|
||||
struct epoll_event evs[MAX_N_EVENTS];
|
||||
int32_t cnt = WaitTimeout(evs, MAX_N_EVENTS, 0);
|
||||
|
||||
for (int32_t index = 0; index < cnt; ++index) {
|
||||
IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
|
||||
CHKPC(source);
|
||||
if ((evs[index].events & EPOLLIN) == EPOLLIN) {
|
||||
source->Dispatch(evs[index]);
|
||||
} else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
|
||||
FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace DeviceStatus
|
||||
} // namespace Msdp
|
||||
} // namespace OHOS
|
29
data/BUILD.gn
Executable file
29
data/BUILD.gn
Executable file
@ -0,0 +1,29 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("../device_status.gni")
|
||||
|
||||
config("devicestatus_data_public_config") {
|
||||
include_dirs = [ "include" ]
|
||||
}
|
||||
|
||||
ohos_source_set("devicestatus_data") {
|
||||
include_dirs = [ "include" ]
|
||||
|
||||
sources = []
|
||||
|
||||
public_configs = [ ":devicestatus_data_public_config" ]
|
||||
|
||||
subsystem_name = "${device_status_subsystem_name}"
|
||||
part_name = "${device_status_part_name}"
|
||||
}
|
@ -26,9 +26,15 @@ public:
|
||||
IEpollEventSource() = default;
|
||||
virtual ~IEpollEventSource() = default;
|
||||
|
||||
virtual uint32_t GetEvents() const;
|
||||
virtual int32_t GetFd() const = 0;
|
||||
virtual void Dispatch(const struct epoll_event &ev) = 0;
|
||||
};
|
||||
|
||||
inline uint32_t IEpollEventSource::GetEvents() const
|
||||
{
|
||||
return (EPOLLIN | EPOLLHUP | EPOLLERR);
|
||||
}
|
||||
} // namespace DeviceStatus
|
||||
} // namespace Msdp
|
||||
} // namespace OHOS
|
@ -102,6 +102,8 @@ ohos_shared_library("devicestatus_service") {
|
||||
deps += [ "interaction/coordination:coordination" ]
|
||||
}
|
||||
|
||||
public_deps = [ "${device_status_root_path}/common/epoll:devicestatus_epoll" ]
|
||||
|
||||
external_deps = external_deps_set
|
||||
if (fusion_interaction_coordination) {
|
||||
external_deps += [
|
||||
@ -140,6 +142,8 @@ ohos_static_library("devicestatus_static_service") {
|
||||
deps += [ "interaction/coordination:coordination" ]
|
||||
}
|
||||
|
||||
public_deps = [ "${device_status_root_path}/common/epoll:devicestatus_epoll" ]
|
||||
|
||||
external_deps = external_deps_set
|
||||
if (fusion_interaction_coordination) {
|
||||
external_deps += [
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "enumerator.h"
|
||||
#include "i_context.h"
|
||||
#include "i_device_mgr.h"
|
||||
#include "i_epoll_event_source.h"
|
||||
#include "epoll_manager.h"
|
||||
#include "monitor.h"
|
||||
|
||||
namespace OHOS {
|
||||
@ -67,17 +67,13 @@ private:
|
||||
int32_t OnInit(IContext *context);
|
||||
int32_t OnEnable();
|
||||
int32_t OnDisable();
|
||||
int32_t OnEpollDispatch();
|
||||
int32_t OnEpollDispatch(uint32_t events);
|
||||
int32_t ParseDeviceId(const std::string &devNode);
|
||||
void OnDeviceAdded(std::shared_ptr<IDevice> dev);
|
||||
void OnDeviceRemoved(std::shared_ptr<IDevice> dev);
|
||||
int32_t OnAddDeviceObserver(std::weak_ptr<IDeviceObserver> observer);
|
||||
int32_t OnRemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer);
|
||||
int32_t OnRetriggerHotplug(std::weak_ptr<IDeviceObserver> observer);
|
||||
int32_t EpollCreate();
|
||||
int32_t EpollAdd(IEpollEventSource *source);
|
||||
void EpollDel(IEpollEventSource *source);
|
||||
void EpollClose();
|
||||
int32_t RunGetDevice(std::packaged_task<std::shared_ptr<IDevice>(int32_t)> &task, int32_t id) const;
|
||||
std::shared_ptr<IDevice> OnGetDevice(int32_t id) const;
|
||||
std::shared_ptr<IDevice> AddDevice(const std::string &devNode);
|
||||
@ -86,17 +82,17 @@ private:
|
||||
|
||||
private:
|
||||
IContext *context_ { nullptr };
|
||||
int32_t epollFd_ { -1 };
|
||||
Enumerator enumerator_;
|
||||
Monitor monitor_;
|
||||
HotplugHandler hotplug_;
|
||||
std::shared_ptr<EpollManager> epollMgr_ { nullptr };
|
||||
std::set<std::weak_ptr<IDeviceObserver>> observers_;
|
||||
std::unordered_map<int32_t, std::shared_ptr<IDevice>> devices_;
|
||||
};
|
||||
|
||||
inline int32_t DeviceManager::GetFd() const
|
||||
{
|
||||
return epollFd_;
|
||||
return (epollMgr_ != nullptr ? epollMgr_->GetFd() : -1);
|
||||
}
|
||||
} // namespace DeviceStatus
|
||||
} // namespace Msdp
|
||||
|
@ -36,7 +36,6 @@ namespace Msdp {
|
||||
namespace DeviceStatus {
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceManager" };
|
||||
constexpr int32_t MAX_N_EVENTS { 64 };
|
||||
constexpr size_t EXPECTED_N_SUBMATCHES { 2 };
|
||||
constexpr size_t EXPECTED_SUBMATCH { 1 };
|
||||
} // namespace
|
||||
@ -96,19 +95,17 @@ int32_t DeviceManager::Enable()
|
||||
int32_t DeviceManager::OnEnable()
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
int32_t ret = EpollCreate();
|
||||
epollMgr_ = std::make_shared<EpollManager>();
|
||||
int32_t ret = epollMgr_->Open();
|
||||
if (ret != RET_OK) {
|
||||
FI_HILOGE("EpollCreate failed");
|
||||
return ret;
|
||||
}
|
||||
ret = monitor_.Enable();
|
||||
if (ret != RET_OK) {
|
||||
FI_HILOGE("Failed to enable monitor");
|
||||
goto CLOSE_EPOLL;
|
||||
}
|
||||
ret = EpollAdd(&monitor_);
|
||||
ret = epollMgr_->Add(monitor_);
|
||||
if (ret != RET_OK) {
|
||||
FI_HILOGE("EpollAdd failed");
|
||||
goto DISABLE_MONITOR;
|
||||
}
|
||||
enumerator_.ScanDevices();
|
||||
@ -118,7 +115,7 @@ DISABLE_MONITOR:
|
||||
monitor_.Disable();
|
||||
|
||||
CLOSE_EPOLL:
|
||||
EpollClose();
|
||||
epollMgr_.reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -136,9 +133,10 @@ int32_t DeviceManager::Disable()
|
||||
|
||||
int32_t DeviceManager::OnDisable()
|
||||
{
|
||||
EpollDel(&monitor_);
|
||||
CHKPR(epollMgr_, RET_ERR);
|
||||
epollMgr_->Remove(monitor_);
|
||||
monitor_.Disable();
|
||||
EpollClose();
|
||||
epollMgr_.reset();
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
@ -266,85 +264,25 @@ void DeviceManager::OnDeviceRemoved(std::shared_ptr<IDevice> dev)
|
||||
}
|
||||
}
|
||||
|
||||
int32_t DeviceManager::EpollCreate()
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
epollFd_ = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollFd_ < 0) {
|
||||
FI_HILOGE("epoll_create1 failed");
|
||||
return RET_ERR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32_t DeviceManager::EpollAdd(IEpollEventSource *source)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
CHKPR(source, RET_ERR);
|
||||
struct epoll_event ev {};
|
||||
ev.events = EPOLLIN | EPOLLHUP | EPOLLERR;
|
||||
ev.data.ptr = source;
|
||||
int32_t ret = epoll_ctl(epollFd_, EPOLL_CTL_ADD, source->GetFd(), &ev);
|
||||
if (ret != 0) {
|
||||
FI_HILOGE("epoll_ctl failed:%{public}s", strerror(errno));
|
||||
return RET_ERR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void DeviceManager::EpollDel(IEpollEventSource *source)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
CHKPV(source);
|
||||
int32_t ret = epoll_ctl(epollFd_, EPOLL_CTL_DEL, source->GetFd(), nullptr);
|
||||
if (ret != 0) {
|
||||
FI_HILOGE("epoll_ctl failed:%{public}s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::EpollClose()
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
if (epollFd_ >= 0) {
|
||||
if (close(epollFd_) < 0) {
|
||||
FI_HILOGE("Close epoll fd failed, error:%{public}s, epollFd_:%{public}d", strerror(errno), epollFd_);
|
||||
}
|
||||
epollFd_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::Dispatch(const struct epoll_event &ev)
|
||||
{
|
||||
CALL_DEBUG_ENTER;
|
||||
if ((ev.events & EPOLLIN) == EPOLLIN) {
|
||||
CHKPV(context_);
|
||||
int32_t ret = context_->GetDelegateTasks().PostAsyncTask(
|
||||
std::bind(&DeviceManager::OnEpollDispatch, this));
|
||||
if (ret != RET_OK) {
|
||||
FI_HILOGE("PostAsyncTask failed");
|
||||
}
|
||||
} else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
|
||||
FI_HILOGE("Epoll hangup:%{public}s", strerror(errno));
|
||||
CHKPV(context_);
|
||||
int32_t ret = context_->GetDelegateTasks().PostAsyncTask(
|
||||
std::bind(&DeviceManager::OnEpollDispatch, this, ev.events));
|
||||
if (ret != RET_OK) {
|
||||
FI_HILOGE("PostAsyncTask failed");
|
||||
}
|
||||
}
|
||||
|
||||
int32_t DeviceManager::OnEpollDispatch()
|
||||
int32_t DeviceManager::OnEpollDispatch(uint32_t events)
|
||||
{
|
||||
struct epoll_event evs[MAX_N_EVENTS];
|
||||
int32_t cnt = epoll_wait(epollFd_, evs, MAX_N_EVENTS, 0);
|
||||
if (cnt < 0) {
|
||||
FI_HILOGE("epoll_wait failed");
|
||||
return RET_ERR;
|
||||
}
|
||||
for (int32_t index = 0; index < cnt; ++index) {
|
||||
IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
|
||||
CHKPC(source);
|
||||
if ((evs[index].events & EPOLLIN) == EPOLLIN) {
|
||||
source->Dispatch(evs[index]);
|
||||
} else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
|
||||
FI_HILOGE("Epoll hangup:%{public}s", strerror(errno));
|
||||
}
|
||||
}
|
||||
struct epoll_event ev {};
|
||||
ev.events = events;
|
||||
ev.data.ptr = epollMgr_.get();
|
||||
|
||||
CHKPR(epollMgr_, RET_ERR);
|
||||
epollMgr_->Dispatch(ev);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user