mirror of https://github.com/tidwall/evio.git
Added Wake to connection
This commit is contained in:
parent
3db0020933
commit
3a190d6d20
2
evio.go
2
evio.go
|
@ -60,6 +60,8 @@ type Conn interface {
|
||||||
LocalAddr() net.Addr
|
LocalAddr() net.Addr
|
||||||
// RemoteAddr is the connection's remote peer address.
|
// RemoteAddr is the connection's remote peer address.
|
||||||
RemoteAddr() net.Addr
|
RemoteAddr() net.Addr
|
||||||
|
// Wake triggers a Data event for this connection.
|
||||||
|
Wake()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadBalance sets the load balancing method.
|
// LoadBalance sets the load balancing method.
|
||||||
|
|
11
evio_std.go
11
evio_std.go
|
@ -40,6 +40,7 @@ func (c *stdudpconn) SetContext(ctx interface{}) {}
|
||||||
func (c *stdudpconn) AddrIndex() int { return c.addrIndex }
|
func (c *stdudpconn) AddrIndex() int { return c.addrIndex }
|
||||||
func (c *stdudpconn) LocalAddr() net.Addr { return c.localAddr }
|
func (c *stdudpconn) LocalAddr() net.Addr { return c.localAddr }
|
||||||
func (c *stdudpconn) RemoteAddr() net.Addr { return c.remoteAddr }
|
func (c *stdudpconn) RemoteAddr() net.Addr { return c.remoteAddr }
|
||||||
|
func (c *stdudpconn) Wake() {}
|
||||||
|
|
||||||
type stdloop struct {
|
type stdloop struct {
|
||||||
idx int // loop index
|
idx int // loop index
|
||||||
|
@ -59,16 +60,22 @@ type stdconn struct {
|
||||||
done int32 // 0: attached, 1: closed, 2: detached
|
done int32 // 0: attached, 1: closed, 2: detached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type wakeReq struct {
|
||||||
|
c *stdconn
|
||||||
|
}
|
||||||
|
|
||||||
func (c *stdconn) Context() interface{} { return c.ctx }
|
func (c *stdconn) Context() interface{} { return c.ctx }
|
||||||
func (c *stdconn) SetContext(ctx interface{}) { c.ctx = ctx }
|
func (c *stdconn) SetContext(ctx interface{}) { c.ctx = ctx }
|
||||||
func (c *stdconn) AddrIndex() int { return c.addrIndex }
|
func (c *stdconn) AddrIndex() int { return c.addrIndex }
|
||||||
func (c *stdconn) LocalAddr() net.Addr { return c.localAddr }
|
func (c *stdconn) LocalAddr() net.Addr { return c.localAddr }
|
||||||
func (c *stdconn) RemoteAddr() net.Addr { return c.remoteAddr }
|
func (c *stdconn) RemoteAddr() net.Addr { return c.remoteAddr }
|
||||||
|
func (c *stdconn) Wake() { c.loop.ch <- wakeReq{c} }
|
||||||
|
|
||||||
type stdin struct {
|
type stdin struct {
|
||||||
c *stdconn
|
c *stdconn
|
||||||
in []byte
|
in []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type stderr struct {
|
type stderr struct {
|
||||||
c *stdconn
|
c *stdconn
|
||||||
err error
|
err error
|
||||||
|
@ -267,6 +274,8 @@ func stdloopRun(s *stdserver, l *stdloop) {
|
||||||
err = stdloopReadUDP(s, l, v)
|
err = stdloopReadUDP(s, l, v)
|
||||||
case *stderr:
|
case *stderr:
|
||||||
err = stdloopError(s, l, v.c, v.err)
|
err = stdloopError(s, l, v.c, v.err)
|
||||||
|
case wakeReq:
|
||||||
|
err = stdloopRead(s, l, v.c, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -360,6 +369,8 @@ func (c *stddetachedConn) Close() error {
|
||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *stddetachedConn) Wake() {}
|
||||||
|
|
||||||
func stdloopRead(s *stdserver, l *stdloop, c *stdconn, in []byte) error {
|
func stdloopRead(s *stdserver, l *stdloop, c *stdconn, in []byte) error {
|
||||||
if atomic.LoadInt32(&c.done) == 2 {
|
if atomic.LoadInt32(&c.done) == 2 {
|
||||||
// should not ignore reads for detached connections
|
// should not ignore reads for detached connections
|
||||||
|
|
39
evio_unix.go
39
evio_unix.go
|
@ -22,16 +22,16 @@ import (
|
||||||
type conn struct {
|
type conn struct {
|
||||||
fd int // file descriptor
|
fd int // file descriptor
|
||||||
lnidx int // listener index in the server lns list
|
lnidx int // listener index in the server lns list
|
||||||
loopidx int // owner loop
|
|
||||||
out []byte // write buffer
|
out []byte // write buffer
|
||||||
sa syscall.Sockaddr // remote socket address
|
sa syscall.Sockaddr // remote socket address
|
||||||
reuse bool // should reuse input buffer
|
reuse bool // should reuse input buffer
|
||||||
opened bool // connection opened event fired
|
opened bool // connection opened event fired
|
||||||
action Action // next user action
|
action Action // next user action
|
||||||
ctx interface{} // user-defined context
|
ctx interface{} // user-defined context
|
||||||
addrIndex int
|
addrIndex int // index of listening address
|
||||||
localAddr net.Addr
|
localAddr net.Addr // local addre
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr // remote addr
|
||||||
|
loop *loop // connected loop
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) Context() interface{} { return c.ctx }
|
func (c *conn) Context() interface{} { return c.ctx }
|
||||||
|
@ -39,6 +39,11 @@ func (c *conn) SetContext(ctx interface{}) { c.ctx = ctx }
|
||||||
func (c *conn) AddrIndex() int { return c.addrIndex }
|
func (c *conn) AddrIndex() int { return c.addrIndex }
|
||||||
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
|
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
|
||||||
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
|
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
|
||||||
|
func (c *conn) Wake() {
|
||||||
|
if c.loop != nil {
|
||||||
|
c.loop.poll.Trigger(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
events Events // user events
|
events Events // user events
|
||||||
|
@ -198,6 +203,12 @@ func loopNote(s *server, l *loop, note interface{}) error {
|
||||||
s.tch <- delay
|
s.tch <- delay
|
||||||
case error: // shutdown
|
case error: // shutdown
|
||||||
err = v
|
err = v
|
||||||
|
case *conn:
|
||||||
|
// Wake called for connection
|
||||||
|
if l.fdconns[v.fd] != v {
|
||||||
|
return nil // ignore stale wakes
|
||||||
|
}
|
||||||
|
return loopWake(s, l, v)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -258,7 +269,8 @@ func loopAccept(s *server, l *loop, fd int) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case RoundRobin:
|
case RoundRobin:
|
||||||
if int(atomic.LoadUintptr(&s.accepted))%len(s.loops) != l.idx {
|
idx := int(atomic.LoadUintptr(&s.accepted)) % len(s.loops)
|
||||||
|
if idx != l.idx {
|
||||||
return nil // do not accept
|
return nil // do not accept
|
||||||
}
|
}
|
||||||
atomic.AddUintptr(&s.accepted, 1)
|
atomic.AddUintptr(&s.accepted, 1)
|
||||||
|
@ -277,7 +289,7 @@ func loopAccept(s *server, l *loop, fd int) error {
|
||||||
if err := syscall.SetNonblock(nfd, true); err != nil {
|
if err := syscall.SetNonblock(nfd, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c := &conn{fd: nfd, sa: sa, lnidx: i}
|
c := &conn{fd: nfd, sa: sa, lnidx: i, loop: l}
|
||||||
l.fdconns[c.fd] = c
|
l.fdconns[c.fd] = c
|
||||||
l.poll.AddReadWrite(c.fd)
|
l.poll.AddReadWrite(c.fd)
|
||||||
atomic.AddInt32(&l.count, 1)
|
atomic.AddInt32(&l.count, 1)
|
||||||
|
@ -391,6 +403,21 @@ func loopAction(s *server, l *loop, c *conn) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loopWake(s *server, l *loop, c *conn) error {
|
||||||
|
if s.events.Data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out, action := s.events.Data(c, nil)
|
||||||
|
c.action = action
|
||||||
|
if len(out) > 0 {
|
||||||
|
c.out = append([]byte{}, out...)
|
||||||
|
}
|
||||||
|
if len(c.out) != 0 || c.action != None {
|
||||||
|
l.poll.ModReadWrite(c.fd)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func loopRead(s *server, l *loop, c *conn) error {
|
func loopRead(s *server, l *loop, c *conn) error {
|
||||||
var in []byte
|
var in []byte
|
||||||
n, err := syscall.Read(c.fd, l.packet)
|
n, err := syscall.Read(c.fd, l.packet)
|
||||||
|
|
|
@ -58,13 +58,20 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
events.Opened = func(ec evio.Conn) (out []byte, opts evio.Options, action evio.Action) {
|
events.Opened = func(ec evio.Conn) (out []byte, opts evio.Options, action evio.Action) {
|
||||||
|
//fmt.Printf("opened: %v\n", ec.RemoteAddr())
|
||||||
ec.SetContext(&conn{})
|
ec.SetContext(&conn{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
events.Closed = func(ec evio.Conn, err error) (action evio.Action) {
|
events.Closed = func(ec evio.Conn, err error) (action evio.Action) {
|
||||||
|
// fmt.Printf("closed: %v\n", ec.RemoteAddr())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
events.Data = func(ec evio.Conn, in []byte) (out []byte, action evio.Action) {
|
events.Data = func(ec evio.Conn, in []byte) (out []byte, action evio.Action) {
|
||||||
|
if in == nil {
|
||||||
|
log.Printf("wake from %s\n", ec.RemoteAddr())
|
||||||
|
return nil, evio.Close
|
||||||
|
}
|
||||||
c := ec.Context().(*conn)
|
c := ec.Context().(*conn)
|
||||||
data := c.is.Begin(in)
|
data := c.is.Begin(in)
|
||||||
var n int
|
var n int
|
||||||
|
@ -94,6 +101,9 @@ func main() {
|
||||||
} else {
|
} else {
|
||||||
out = redcon.AppendString(out, "PONG")
|
out = redcon.AppendString(out, "PONG")
|
||||||
}
|
}
|
||||||
|
case "WAKE":
|
||||||
|
go ec.Wake()
|
||||||
|
out = redcon.AppendString(out, "OK")
|
||||||
case "ECHO":
|
case "ECHO":
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
out = redcon.AppendError(out, "ERR wrong number of arguments for '"+string(args[0])+"' command")
|
out = redcon.AppendError(out, "ERR wrong number of arguments for '"+string(args[0])+"' command")
|
||||||
|
|
Loading…
Reference in New Issue