add send and receive interface for client

This commit is contained in:
siddontang 2014-10-23 13:34:03 +08:00
parent 041a1737c8
commit d442a3b185
2 changed files with 86 additions and 15 deletions

View File

@ -19,23 +19,24 @@ type Config struct {
type Client struct { type Client struct {
sync.Mutex sync.Mutex
cfg *Config cfg *Config
proto string
conns *list.List conns *list.List
} }
func getProto(addr string) string {
if strings.Contains(addr, "/") {
return "unix"
} else {
return "tcp"
}
}
func NewClient(cfg *Config) *Client { func NewClient(cfg *Config) *Client {
c := new(Client) c := new(Client)
c.cfg = cfg c.cfg = cfg
if strings.Contains(cfg.Addr, "/") {
c.proto = "unix"
} else {
c.proto = "tcp"
}
c.conns = list.New() c.conns = list.New()
return c return c
@ -71,7 +72,7 @@ func (c *Client) get() *Conn {
if c.conns.Len() == 0 { if c.conns.Len() == 0 {
c.Unlock() c.Unlock()
return c.newConn() return c.newConn(c.cfg.Addr)
} else { } else {
e := c.conns.Front() e := c.conns.Front()
co := e.Value.(*Conn) co := e.Value.(*Conn)

View File

@ -19,6 +19,8 @@ func (err Error) Error() string { return string(err) }
type Conn struct { type Conn struct {
client *Client client *Client
addr string
c net.Conn c net.Conn
br *bufio.Reader br *bufio.Reader
bw *bufio.Writer bw *bufio.Writer
@ -33,25 +35,47 @@ type Conn struct {
numScratch [40]byte numScratch [40]byte
} }
func NewConn(addr string) *Conn {
co := new(Conn)
co.addr = addr
return co
}
func (c *Conn) Close() { func (c *Conn) Close() {
c.client.put(c) if c.client != nil {
c.client.put(c)
} else {
c.finalize()
}
} }
func (c *Conn) Do(cmd string, args ...interface{}) (interface{}, error) { func (c *Conn) Do(cmd string, args ...interface{}) (interface{}, error) {
if err := c.connect(); err != nil { if err := c.Send(cmd, args...); err != nil {
return nil, err return nil, err
} }
return c.Receive()
}
func (c *Conn) Send(cmd string, args ...interface{}) error {
if err := c.connect(); err != nil {
return err
}
if err := c.writeCommand(cmd, args); err != nil { if err := c.writeCommand(cmd, args); err != nil {
c.finalize() c.finalize()
return nil, err return err
} }
if err := c.bw.Flush(); err != nil { if err := c.bw.Flush(); err != nil {
c.finalize() c.finalize()
return nil, err return err
} }
return nil
}
func (c *Conn) Receive() (interface{}, error) {
if reply, err := c.readReply(); err != nil { if reply, err := c.readReply(); err != nil {
c.finalize() c.finalize()
return nil, err return nil, err
@ -64,6 +88,16 @@ func (c *Conn) Do(cmd string, args ...interface{}) (interface{}, error) {
} }
} }
func (c *Conn) ReceiveBulkTo(w io.Writer) error {
err := c.readBulkReplyTo(w)
if err != nil {
if _, ok := err.(Error); !ok {
c.finalize()
}
}
return err
}
func (c *Conn) finalize() { func (c *Conn) finalize() {
if c.c != nil { if c.c != nil {
c.c.Close() c.c.Close()
@ -77,7 +111,7 @@ func (c *Conn) connect() error {
} }
var err error var err error
c.c, err = net.Dial(c.client.proto, c.client.cfg.Addr) c.c, err = net.Dial(getProto(c.addr), c.addr)
if err != nil { if err != nil {
return err return err
} }
@ -244,6 +278,41 @@ var (
pongReply interface{} = "PONG" pongReply interface{} = "PONG"
) )
func (c *Conn) readBulkReplyTo(w io.Writer) error {
line, err := c.readLine()
if err != nil {
return err
}
if len(line) == 0 {
return errors.New("ledis: short response line")
}
switch line[0] {
case '-':
return Error(string(line[1:]))
case '$':
n, err := parseLen(line[1:])
if n < 0 || err != nil {
return err
}
var nn int64
if nn, err = io.CopyN(w, c.br, int64(n)); err != nil {
return err
} else if nn != int64(n) {
return io.ErrShortWrite
}
if line, err := c.readLine(); err != nil {
return err
} else if len(line) != 0 {
return errors.New("ledis: bad bulk string format")
}
return nil
default:
return fmt.Errorf("ledis: not invalid bulk string type, but %c", line[0])
}
}
func (c *Conn) readReply() (interface{}, error) { func (c *Conn) readReply() (interface{}, error) {
line, err := c.readLine() line, err := c.readLine()
if err != nil { if err != nil {
@ -301,9 +370,10 @@ func (c *Conn) readReply() (interface{}, error) {
return nil, errors.New("ledis: unexpected response line") return nil, errors.New("ledis: unexpected response line")
} }
func (c *Client) newConn() *Conn { func (c *Client) newConn(addr string) *Conn {
co := new(Conn) co := new(Conn)
co.client = c co.client = c
co.addr = addr
return co return co
} }