github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/epoll.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package poller
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/weedge/lib/log"
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  const (
    14  	// man epoll_ctl  see EPOLL_EVENTS detail
    15  	//1 2 8 16 8192 2147483648
    16  	//EpollReadEvents = unix.EPOLLIN | unix.EPOLLPRI | unix.EPOLLERR | unix.EPOLLHUP | unix.EPOLLRDHUP | unix.EPOLLET
    17  	EpollReadEvents = unix.EPOLLIN | unix.EPOLLET
    18  	EpollPeerClose  = unix.EPOLLIN | unix.EPOLLRDHUP
    19  	EpollRead       = unix.EPOLLIN
    20  	EpollErr        = unix.EPOLLIN | unix.EPOLLERR
    21  	EpollReadErr    = unix.EPOLLIN | unix.EPOLLERR | unix.EPOLLHUP | unix.EPOLLRDHUP
    22  )
    23  
    24  func createPoller() (pollFD int, err error) {
    25  	pollFD, err = unix.EpollCreate1(unix.EPOLL_CLOEXEC)
    26  	if err != nil {
    27  		return
    28  	}
    29  	return
    30  }
    31  
    32  func addReadEventFD(pollFD, fd int) (err error) {
    33  	err = unix.EpollCtl(pollFD, unix.EPOLL_CTL_ADD, fd, &unix.EpollEvent{
    34  		Events: EpollReadEvents,
    35  		Fd:     int32(fd),
    36  	})
    37  
    38  	return
    39  }
    40  
    41  func delEventFD(pollFD, fd int) error {
    42  	err := unix.EpollCtl(pollFD, unix.EPOLL_CTL_DEL, fd, nil)
    43  	if err != nil {
    44  		return err
    45  	}
    46  
    47  	return nil
    48  }
    49  
    50  func getEvents(pollFD int) ([]eventInfo, error) {
    51  	epollEvents := make([]unix.EpollEvent, 100)
    52  	n, err := unix.EpollWait(pollFD, epollEvents, -1)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	events := make([]eventInfo, 0, len(epollEvents))
    58  	for i := 0; i < n; i++ {
    59  		event := eventInfo{
    60  			fd: int(epollEvents[i].Fd),
    61  		}
    62  		if epollEvents[i].Events == EpollRead { // likely
    63  			event.etype = ETypeIn
    64  			events = append(events, event)
    65  		} else if epollEvents[i].Events == EpollPeerClose { // likely
    66  			event.etype = ETypeClose
    67  			events = append(events, event)
    68  		} else if epollEvents[i].Events == EpollErr { // unlikely
    69  			log.Errorf("epoll wait err event %v", epollEvents[i])
    70  			event.etype = ETypeClose
    71  			events = append(events, event)
    72  		} else if epollEvents[i].Events == EpollReadErr { // unlikely
    73  			log.Errorf("epoll wait read err event %v", epollEvents[i])
    74  			event.etype = ETypeClose
    75  			events = append(events, event)
    76  		} else { // unlikely
    77  			log.Errorf("epoll wait other event %v", epollEvents[i])
    78  		}
    79  	}
    80  	//sort.Slice(events, func(i, j int) bool { return events[i].etype < events[j].etype })
    81  
    82  	return events, nil
    83  }
    84  
    85  func setSockKeepAliveOptions(fd int, d time.Duration) (err error) {
    86  	err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1)
    87  	if err != nil {
    88  		return
    89  	}
    90  
    91  	secs := int(roundDurationUp(d, time.Second))
    92  	err = unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, secs)
    93  	if err != nil {
    94  		return
    95  	}
    96  
    97  	err = unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPIDLE, secs)
    98  	if err != nil {
    99  		return
   100  	}
   101  
   102  	return
   103  }