ledisdb/cmd/vendor/github.com/siddontang/goredis/client.go

220 lines
3.0 KiB
Go
Raw Normal View History

2015-03-11 06:54:02 +03:00
package goredis
2014-06-21 18:12:37 +04:00
import (
"container/list"
"net"
2014-06-21 18:12:37 +04:00
"strings"
"sync"
2015-03-18 06:54:27 +03:00
"time"
2014-06-21 18:12:37 +04:00
)
2015-03-11 06:54:02 +03:00
type PoolConn struct {
*Conn
c *Client
}
func (c *PoolConn) Close() {
if c.Conn.isClosed() {
2015-03-16 06:35:59 +03:00
return
}
2015-03-11 06:54:02 +03:00
c.c.put(c.Conn)
2014-06-21 18:12:37 +04:00
}
2015-03-23 14:50:37 +03:00
// force close inner connection and not put it into pool
func (c *PoolConn) Finalize() {
c.Conn.Close()
}
2014-06-21 18:12:37 +04:00
type Client struct {
sync.Mutex
2015-03-11 06:54:02 +03:00
addr string
maxIdleConns int
readBufferSize int
writeBufferSize int
password string
2014-06-21 18:12:37 +04:00
conns *list.List
2015-03-18 06:54:27 +03:00
quit chan struct{}
wg sync.WaitGroup
2014-06-21 18:12:37 +04:00
}
func getProto(addr string) string {
if strings.Contains(addr, "/") {
return "unix"
} else {
return "tcp"
}
}
2015-03-11 06:54:02 +03:00
func NewClient(addr string, password string) *Client {
2014-06-21 18:12:37 +04:00
c := new(Client)
2015-03-11 06:54:02 +03:00
c.addr = addr
c.maxIdleConns = 4
c.readBufferSize = 1024
c.writeBufferSize = 1024
c.password = password
2014-06-21 18:12:37 +04:00
c.conns = list.New()
2015-03-18 06:54:27 +03:00
c.quit = make(chan struct{})
c.wg.Add(1)
go c.onCheck()
2014-06-21 18:12:37 +04:00
return c
}
2015-03-11 06:54:02 +03:00
func (c *Client) SetPassword(pass string) {
c.password = pass
}
func (c *Client) SetReadBufferSize(s int) {
c.readBufferSize = s
}
func (c *Client) SetWriteBufferSize(s int) {
c.writeBufferSize = s
}
func (c *Client) SetMaxIdleConns(n int) {
c.maxIdleConns = n
}
2014-06-21 18:12:37 +04:00
func (c *Client) Do(cmd string, args ...interface{}) (interface{}, error) {
var co *Conn
var err error
var r interface{}
for i := 0; i < 2; i++ {
co, err = c.get()
if err != nil {
return nil, err
}
r, err = co.Do(cmd, args...)
if err != nil {
2015-03-11 06:54:02 +03:00
co.Close()
if e, ok := err.(*net.OpError); ok && strings.Contains(e.Error(), "use of closed network connection") {
//send to a closed connection, try again
continue
}
return nil, err
} else {
c.put(co)
}
return r, nil
}
2014-06-21 18:12:37 +04:00
return nil, err
2014-06-21 18:12:37 +04:00
}
func (c *Client) Close() {
c.Lock()
defer c.Unlock()
2015-03-18 06:54:27 +03:00
close(c.quit)
c.wg.Wait()
2014-06-21 18:12:37 +04:00
for c.conns.Len() > 0 {
e := c.conns.Front()
co := e.Value.(*Conn)
c.conns.Remove(e)
2015-03-11 06:54:02 +03:00
co.Close()
2014-06-21 18:12:37 +04:00
}
}
2015-03-11 06:54:02 +03:00
func (c *Client) Get() (*PoolConn, error) {
co, err := c.get()
if err != nil {
return nil, err
}
return &PoolConn{co, c}, err
2014-06-21 18:12:37 +04:00
}
2015-03-11 06:54:02 +03:00
func (c *Client) get() (co *Conn, err error) {
2014-06-21 18:12:37 +04:00
c.Lock()
if c.conns.Len() == 0 {
c.Unlock()
2015-03-11 06:54:02 +03:00
co, err = c.newConn(c.addr, c.password)
2014-06-21 18:12:37 +04:00
} else {
e := c.conns.Front()
2015-03-11 06:54:02 +03:00
co = e.Value.(*Conn)
2014-06-21 18:12:37 +04:00
c.conns.Remove(e)
c.Unlock()
}
2015-03-11 06:54:02 +03:00
return
2014-06-21 18:12:37 +04:00
}
func (c *Client) put(conn *Conn) {
c.Lock()
2015-03-18 06:54:27 +03:00
defer c.Unlock()
for c.conns.Len() >= c.maxIdleConns {
// remove back
e := c.conns.Back()
co := e.Value.(*Conn)
c.conns.Remove(e)
co.Close()
}
c.conns.PushFront(conn)
}
func (c *Client) getIdle() *Conn {
c.Lock()
defer c.Unlock()
if c.conns.Len() == 0 {
return nil
2014-06-21 18:12:37 +04:00
} else {
2015-03-18 06:54:27 +03:00
e := c.conns.Back()
co := e.Value.(*Conn)
c.conns.Remove(e)
return co
}
}
func (c *Client) checkIdle() {
co := c.getIdle()
if co == nil {
return
}
_, err := co.Do("PING")
if err != nil {
co.Close()
} else {
c.put(co)
}
}
func (c *Client) onCheck() {
t := time.NewTicker(3 * time.Second)
defer func() {
t.Stop()
c.wg.Done()
}()
for {
select {
case <-t.C:
c.checkIdle()
case <-c.quit:
return
}
2014-06-21 18:12:37 +04:00
}
}