forked from simonklee/godis
/
connection.go
115 lines (91 loc) · 2.32 KB
/
connection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package redis
import (
"github.com/simonz05/godis/bufin"
"net"
)
var ConnSum = 0
type Connection interface {
Write(args ...interface{}) error
Read() (*Reply, error)
Close() error
Sock() net.Conn
}
// Conn implements the Connection interface.
type Conn struct {
rbuf *bufin.Reader
c net.Conn
}
// NewConn expects a network address and protocol.
//
// NewConn("127.0.0.1:6379", "tcp")
//
// or for a unix domain socket
//
// NewConn("/path/to/redis.sock", "unix")
//
// NewConn then returns a Conn struct which implements the Connection
// interface. It's easy to use this interface to create your own
// redis client or to simply talk to the redis database.
func NewConn(addr, proto string, db int, password string) (*Conn, error) {
conn, err := net.Dial(proto, addr)
if err != nil {
return nil, err
}
ConnSum++
c := &Conn{bufin.NewReader(conn), conn}
if password != "" {
e := c.Write("AUTH", password)
if e != nil {
return nil, e
}
_, e = c.Read()
if e != nil {
return nil, e
}
}
if db != 0 {
e := c.Write("SELECT", db)
if e != nil {
return nil, e
}
_, e = c.Read()
if e != nil {
return nil, e
}
}
return c, nil
}
// Read reads one reply of the socket connection. If there is no reply waiting
// this method will block.
// Returns either an error or a pointer to a Reply object.
func (c *Conn) Read() (*Reply, error) {
reply := Parse(c.rbuf)
if reply.Err != nil {
return nil, reply.Err
}
return reply, nil
}
// Write accepts any redis command and arbitrary list of arguments.
//
// Write("SET", "counter", 1)
// Write("INCR", "counter")
//
// Write might return a net.Conn.Write error
func (c *Conn) Write(args ...interface{}) error {
_, e := c.c.Write(format(args...))
if e != nil {
return e
}
return nil
}
// Close is a simple helper method to close socket connection.
func (c *Conn) Close() error {
return c.c.Close()
}
// Sock returns the underlying net.Conn. You can use this connection as you
// wish. An example could be to set a r/w deadline on the connection.
//
// Sock().SetDeadline(t)
func (c *Conn) Sock() net.Conn {
return c.c
}