Refactor epoll monitor for generic use
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
b6bf350a07
commit
97c3c3847a
10 changed files with 288 additions and 297 deletions
102
monitor/monitor_linux.go
Normal file
102
monitor/monitor_linux.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
package monitor
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/containerd/archutils"
|
||||
)
|
||||
|
||||
type Monitorable interface {
|
||||
FD() int
|
||||
}
|
||||
|
||||
type Flusher interface {
|
||||
Flush() error
|
||||
}
|
||||
|
||||
// New returns a new process monitor that emits events whenever the
|
||||
// state of the fd refering to a process changes
|
||||
func New() (*Monitor, error) {
|
||||
fd, err := archutils.EpollCreate1(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Monitor{
|
||||
epollFd: fd,
|
||||
receivers: make(map[int]Monitorable),
|
||||
events: make(chan Monitorable, 1024),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Monitor struct {
|
||||
m sync.Mutex
|
||||
receivers map[int]Monitorable
|
||||
events chan Monitorable
|
||||
epollFd int
|
||||
}
|
||||
|
||||
// Events returns a chan that receives a Monitorable when it's FD changes state
|
||||
func (m *Monitor) Events() chan Monitorable {
|
||||
return m.events
|
||||
}
|
||||
|
||||
// Add adds a process to the list of the one being monitored
|
||||
func (m *Monitor) Add(ma Monitorable) error {
|
||||
m.m.Lock()
|
||||
defer m.m.Unlock()
|
||||
fd := ma.FD()
|
||||
event := syscall.EpollEvent{
|
||||
Fd: int32(fd),
|
||||
Events: syscall.EPOLLHUP,
|
||||
}
|
||||
if err := archutils.EpollCtl(m.epollFd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
|
||||
return err
|
||||
}
|
||||
m.receivers[fd] = ma
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove deletes the Monitorable type from the monitor so that
|
||||
// no other events are generated
|
||||
func (m *Monitor) Remove(ma Monitorable) error {
|
||||
m.m.Lock()
|
||||
defer m.m.Unlock()
|
||||
fd := ma.FD()
|
||||
delete(m.receivers, fd)
|
||||
return syscall.EpollCtl(m.epollFd, syscall.EPOLL_CTL_DEL, fd, &syscall.EpollEvent{
|
||||
Events: syscall.EPOLLHUP,
|
||||
Fd: int32(fd),
|
||||
})
|
||||
}
|
||||
|
||||
// Close cleans up resources allocated to the Monitor
|
||||
func (m *Monitor) Close() error {
|
||||
return syscall.Close(m.epollFd)
|
||||
}
|
||||
|
||||
func (m *Monitor) Run() {
|
||||
var events [128]syscall.EpollEvent
|
||||
for {
|
||||
n, err := archutils.EpollWait(m.epollFd, events[:], -1)
|
||||
if err != nil {
|
||||
if err == syscall.EINTR {
|
||||
continue
|
||||
}
|
||||
logrus.WithField("error", err).Fatal("containerd: epoll wait")
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
fd := int(events[i].Fd)
|
||||
m.m.Lock()
|
||||
r := m.receivers[fd]
|
||||
m.m.Unlock()
|
||||
if f, ok := r.(Flusher); ok {
|
||||
if err := f.Flush(); err != nil {
|
||||
logrus.WithField("error", err).Fatal("containerd: flush event FD")
|
||||
}
|
||||
}
|
||||
m.events <- r
|
||||
}
|
||||
}
|
||||
}
|
29
monitor/monitor_solaris.go
Normal file
29
monitor/monitor_solaris.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package monitor
|
||||
|
||||
import "errors"
|
||||
|
||||
func New() (*Monitor, error) {
|
||||
return nil, errors.New("Monitor NewMonitor() not implemented on Solaris")
|
||||
}
|
||||
|
||||
type Monitor struct {
|
||||
}
|
||||
|
||||
func (m *Monitor) Events() chan Monitorable {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Add(Monitorable) error {
|
||||
return errors.New("Monitor Add() not implemented on Solaris")
|
||||
}
|
||||
|
||||
func (m *Monitor) Remove(Monitorable) error {
|
||||
return errors.New("Monitor Remove() not implemented on Solaris")
|
||||
}
|
||||
|
||||
func (m *Monitor) Close() error {
|
||||
return errors.New("Monitor Close() not implemented on Solaris")
|
||||
}
|
||||
|
||||
func (m *Monitor) Run() {
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue