minor optimizations

This commit is contained in:
Josh Baker 2016-08-20 08:19:08 -07:00
parent 142cd0b96f
commit 55f1a9cf23
1 changed files with 88 additions and 83 deletions

111
redcon.go
View File

@ -42,32 +42,40 @@ func ListenAndServe(
return err return err
} }
defer ln.Close() defer ln.Close()
if handler == nil {
handler = func(conn Conn, cmds [][]string) {}
}
var mu sync.Mutex var mu sync.Mutex
for { for {
conn, err := ln.Accept() nc, err := ln.Accept()
if err != nil { if err != nil {
return err return err
} }
wr := newWriter(conn) tcpc := nc.(*net.TCPConn)
wrc := &connWriter{wr, conn.RemoteAddr().String()} c := &conn{tcpc, newWriter(tcpc), tcpc.RemoteAddr().String()}
if accept != nil && !accept(wrc) { if accept != nil && !accept(c) {
conn.Close() c.Close()
continue continue
} }
go func() { go handle(c, &mu, handler, closed)
}
}
func handle(c *conn, mu *sync.Mutex,
handler func(conn Conn, cmds [][]string),
closed func(conn Conn, err error)) {
var err error var err error
defer func() { defer func() {
conn.Close() c.conn.Close()
if closed != nil { if closed != nil {
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
if err == io.EOF { if err == io.EOF {
err = nil err = nil
} }
closed(wrc, err) closed(c, err)
} }
}() }()
rd := newReader(conn) rd := newReader(c.conn)
err = func() error { err = func() error {
for { for {
cmds, err := rd.ReadCommands() cmds, err := rd.ReadCommands()
@ -75,70 +83,67 @@ func ListenAndServe(
if err, ok := err.(*errProtocol); ok { if err, ok := err.(*errProtocol); ok {
// All protocol errors should attempt a response to // All protocol errors should attempt a response to
// the client. Ignore errors. // the client. Ignore errors.
wr.WriteError("ERR " + err.Error()) c.wr.WriteError("ERR " + err.Error())
wr.Flush() c.wr.Flush()
} }
return err return err
} }
if len(cmds) > 0 { if len(cmds) > 0 {
if handler != nil { handler(c, cmds)
handler(wrc, cmds)
} }
} if c.wr.err != nil {
if wr.err != nil { if c.wr.err == errClosed {
if wr.err == errClosed {
return nil return nil
} }
return wr.err return c.wr.err
} }
if err := wr.Flush(); err != nil { if err := c.wr.Flush(); err != nil {
return err return err
} }
} }
}() }()
}()
}
} }
type connWriter struct { type conn struct {
wr *respWriter conn *net.TCPConn
wr *writer
addr string addr string
} }
func (wrc *connWriter) Close() error { func (c *conn) Close() error {
return wrc.wr.Close() return c.wr.Close()
} }
func (wrc *connWriter) WriteString(str string) { func (c *conn) WriteString(str string) {
wrc.wr.WriteString(str) c.wr.WriteString(str)
} }
func (wrc *connWriter) WriteBulk(bulk string) { func (c *conn) WriteBulk(bulk string) {
wrc.wr.WriteBulk(bulk) c.wr.WriteBulk(bulk)
} }
func (wrc *connWriter) WriteInt(num int) { func (c *conn) WriteInt(num int) {
wrc.wr.WriteInt(num) c.wr.WriteInt(num)
} }
func (wrc *connWriter) WriteError(msg string) { func (c *conn) WriteError(msg string) {
wrc.wr.WriteError(msg) c.wr.WriteError(msg)
} }
func (wrc *connWriter) WriteArray(count int) { func (c *conn) WriteArray(count int) {
wrc.wr.WriteMultiBulkStart(count) c.wr.WriteMultiBulkStart(count)
} }
func (wrc *connWriter) WriteNull() { func (c *conn) WriteNull() {
wrc.wr.WriteNull() c.wr.WriteNull()
} }
func (wrc *connWriter) RemoteAddr() string { func (c *conn) RemoteAddr() string {
return wrc.addr return c.addr
} }
// Reader represents a RESP command reader. // Reader represents a RESP command reader.
type respReader struct { type respReader struct {
r io.Reader // base reader r *net.TCPConn // base reader
b []byte // unprocessed bytes b []byte // unprocessed bytes
a []byte // static read buffer a []byte // static read buffer
} }
// NewReader returns a RESP command reader. // NewReader returns a RESP command reader.
func newReader(r io.Reader) *respReader { func newReader(r *net.TCPConn) *respReader {
return &respReader{ return &respReader{
r: r, r: r,
a: make([]byte, 8192), a: make([]byte, 8192),
@ -316,24 +321,24 @@ func (r *respReader) ReadCommands() ([][]string, error) {
var errClosed = errors.New("closed") var errClosed = errors.New("closed")
type respWriter struct { type writer struct {
w io.Writer w *net.TCPConn
b []byte b []byte
err error err error
} }
func newWriter(w io.Writer) *respWriter { func newWriter(w *net.TCPConn) *writer {
return &respWriter{w: w, b: make([]byte, 0, 256)} return &writer{w: w, b: make([]byte, 0, 256)}
} }
func (w *respWriter) WriteNull() error { func (w *writer) WriteNull() error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
w.b = append(w.b, '$', '-', '1', '\r', '\n') w.b = append(w.b, '$', '-', '1', '\r', '\n')
return nil return nil
} }
func (w *respWriter) WriteMultiBulkStart(count int) error { func (w *writer) WriteMultiBulkStart(count int) error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
@ -343,7 +348,7 @@ func (w *respWriter) WriteMultiBulkStart(count int) error {
return nil return nil
} }
func (w *respWriter) WriteBulk(bulk string) error { func (w *writer) WriteBulk(bulk string) error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
@ -355,7 +360,7 @@ func (w *respWriter) WriteBulk(bulk string) error {
return nil return nil
} }
func (w *respWriter) Flush() error { func (w *writer) Flush() error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
@ -370,7 +375,7 @@ func (w *respWriter) Flush() error {
return nil return nil
} }
func (w *respWriter) WriteMultiBulk(bulks []string) error { func (w *writer) WriteMultiBulk(bulks []string) error {
if err := w.WriteMultiBulkStart(len(bulks)); err != nil { if err := w.WriteMultiBulkStart(len(bulks)); err != nil {
return err return err
} }
@ -382,7 +387,7 @@ func (w *respWriter) WriteMultiBulk(bulks []string) error {
return nil return nil
} }
func (w *respWriter) WriteError(msg string) error { func (w *writer) WriteError(msg string) error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
@ -392,7 +397,7 @@ func (w *respWriter) WriteError(msg string) error {
return nil return nil
} }
func (w *respWriter) WriteString(msg string) error { func (w *writer) WriteString(msg string) error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
@ -402,7 +407,7 @@ func (w *respWriter) WriteString(msg string) error {
return nil return nil
} }
func (w *respWriter) WriteInt(num int) error { func (w *writer) WriteInt(num int) error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }
@ -412,7 +417,7 @@ func (w *respWriter) WriteInt(num int) error {
return nil return nil
} }
func (w *respWriter) Close() error { func (w *writer) Close() error {
if w.err != nil { if w.err != nil {
return w.err return w.err
} }