forked from mirror/ledisdb
abstract the read / write in server client
This commit is contained in:
parent
895613ca5b
commit
14767ecadb
|
@ -123,7 +123,7 @@ func (app *App) Run() {
|
|||
continue
|
||||
}
|
||||
|
||||
newClient(conn, app)
|
||||
newTcpClient(conn, app)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
259
server/client.go
259
server/client.go
|
@ -1,7 +1,6 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/siddontang/go-log/log"
|
||||
|
@ -9,7 +8,6 @@ import (
|
|||
"io"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -21,40 +19,56 @@ type client struct {
|
|||
ldb *ledis.Ledis
|
||||
|
||||
db *ledis.DB
|
||||
c net.Conn
|
||||
|
||||
rb *bufio.Reader
|
||||
wb *bufio.Writer
|
||||
ctx clientContext
|
||||
resp responseWriter
|
||||
req requestReader
|
||||
|
||||
cmd string
|
||||
args [][]byte
|
||||
|
||||
reqC chan error
|
||||
|
||||
syncBuf bytes.Buffer
|
||||
|
||||
compressBuf []byte
|
||||
|
||||
logBuf bytes.Buffer
|
||||
syncBuf bytes.Buffer
|
||||
logBuf bytes.Buffer
|
||||
}
|
||||
|
||||
func newClient(c net.Conn, app *App) {
|
||||
co := new(client)
|
||||
type clientContext interface {
|
||||
addr() string
|
||||
release()
|
||||
}
|
||||
|
||||
co.app = app
|
||||
co.ldb = app.ldb
|
||||
//use default db
|
||||
co.db, _ = app.ldb.Select(0)
|
||||
co.c = c
|
||||
type requestReader interface {
|
||||
// readLine func() ([]byte, error)
|
||||
read() ([][]byte, error)
|
||||
}
|
||||
|
||||
co.rb = bufio.NewReaderSize(c, 256)
|
||||
co.wb = bufio.NewWriterSize(c, 256)
|
||||
type responseWriter interface {
|
||||
writeError(error)
|
||||
writeStatus(string)
|
||||
writeInteger(int64)
|
||||
writeBulk([]byte)
|
||||
writeArray([]interface{})
|
||||
writeSliceArray([][]byte)
|
||||
writeFVPairArray([]ledis.FVPair)
|
||||
writeScorePairArray([]ledis.ScorePair, bool)
|
||||
writeBulkFrom(int64, io.Reader)
|
||||
flush()
|
||||
}
|
||||
|
||||
co.reqC = make(chan error, 1)
|
||||
func newClient(app *App) *client {
|
||||
c := new(client)
|
||||
|
||||
co.compressBuf = make([]byte, 256)
|
||||
c.app = app
|
||||
c.ldb = app.ldb
|
||||
c.db, _ = app.ldb.Select(0)
|
||||
|
||||
go co.run()
|
||||
c.reqC = make(chan error, 1)
|
||||
|
||||
c.compressBuf = make([]byte, 256)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *client) run() {
|
||||
|
@ -67,11 +81,11 @@ func (c *client) run() {
|
|||
log.Fatal("client run panic %s:%v", buf, e)
|
||||
}
|
||||
|
||||
c.c.Close()
|
||||
c.ctx.release()
|
||||
}()
|
||||
|
||||
for {
|
||||
req, err := c.readRequest()
|
||||
req, err := c.req.read()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -80,65 +94,6 @@ func (c *client) run() {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *client) readLine() ([]byte, error) {
|
||||
return ReadLine(c.rb)
|
||||
}
|
||||
|
||||
//A client sends to the Redis server a RESP Array consisting of just Bulk Strings.
|
||||
func (c *client) readRequest() ([][]byte, error) {
|
||||
l, err := c.readLine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(l) == 0 || l[0] != '*' {
|
||||
return nil, errReadRequest
|
||||
}
|
||||
|
||||
var nparams int
|
||||
if nparams, err = strconv.Atoi(ledis.String(l[1:])); err != nil {
|
||||
return nil, err
|
||||
} else if nparams <= 0 {
|
||||
return nil, errReadRequest
|
||||
}
|
||||
|
||||
req := make([][]byte, 0, nparams)
|
||||
var n int
|
||||
for i := 0; i < nparams; i++ {
|
||||
if l, err = c.readLine(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(l) == 0 {
|
||||
return nil, errReadRequest
|
||||
} else if l[0] == '$' {
|
||||
//handle resp string
|
||||
if n, err = strconv.Atoi(ledis.String(l[1:])); err != nil {
|
||||
return nil, err
|
||||
} else if n == -1 {
|
||||
req = append(req, nil)
|
||||
} else {
|
||||
buf := make([]byte, n)
|
||||
if _, err = io.ReadFull(c.rb, buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if l, err = c.readLine(); err != nil {
|
||||
return nil, err
|
||||
} else if len(l) != 0 {
|
||||
return nil, errors.New("bad bulk string format")
|
||||
}
|
||||
|
||||
req = append(req, buf)
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
return nil, errReadRequest
|
||||
}
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *client) handleRequest(req [][]byte) {
|
||||
var err error
|
||||
|
||||
|
@ -179,137 +134,27 @@ func (c *client) handleRequest(req [][]byte) {
|
|||
}
|
||||
}
|
||||
|
||||
c.app.access.Log(c.c.RemoteAddr().String(), duration.Nanoseconds()/1000000, c.logBuf.Bytes(), err)
|
||||
c.app.access.Log(c.ctx.addr(), duration.Nanoseconds()/1000000, c.logBuf.Bytes(), err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.writeError(err)
|
||||
c.resp.writeError(err)
|
||||
}
|
||||
|
||||
c.wb.Flush()
|
||||
c.resp.flush()
|
||||
}
|
||||
|
||||
func (c *client) writeError(err error) {
|
||||
c.wb.Write(ledis.Slice("-ERR"))
|
||||
if err != nil {
|
||||
c.wb.WriteByte(' ')
|
||||
c.wb.Write(ledis.Slice(err.Error()))
|
||||
}
|
||||
c.wb.Write(Delims)
|
||||
func newTcpClient(conn net.Conn, app *App) {
|
||||
c := newClient(app)
|
||||
|
||||
c.ctx = newTcpContext(conn)
|
||||
c.req = newTcpReader(conn)
|
||||
c.resp = newTcpWriter(conn)
|
||||
|
||||
go c.run()
|
||||
}
|
||||
|
||||
func (c *client) writeStatus(status string) {
|
||||
c.wb.WriteByte('+')
|
||||
c.wb.Write(ledis.Slice(status))
|
||||
c.wb.Write(Delims)
|
||||
}
|
||||
|
||||
func (c *client) writeInteger(n int64) {
|
||||
c.wb.WriteByte(':')
|
||||
c.wb.Write(ledis.StrPutInt64(n))
|
||||
c.wb.Write(Delims)
|
||||
}
|
||||
|
||||
func (c *client) writeBulk(b []byte) {
|
||||
c.wb.WriteByte('$')
|
||||
if b == nil {
|
||||
c.wb.Write(NullBulk)
|
||||
} else {
|
||||
c.wb.Write(ledis.Slice(strconv.Itoa(len(b))))
|
||||
c.wb.Write(Delims)
|
||||
c.wb.Write(b)
|
||||
}
|
||||
|
||||
c.wb.Write(Delims)
|
||||
}
|
||||
|
||||
func (c *client) writeArray(ay []interface{}) {
|
||||
c.wb.WriteByte('*')
|
||||
if ay == nil {
|
||||
c.wb.Write(NullArray)
|
||||
c.wb.Write(Delims)
|
||||
} else {
|
||||
c.wb.Write(ledis.Slice(strconv.Itoa(len(ay))))
|
||||
c.wb.Write(Delims)
|
||||
|
||||
for i := 0; i < len(ay); i++ {
|
||||
switch v := ay[i].(type) {
|
||||
case []interface{}:
|
||||
c.writeArray(v)
|
||||
case []byte:
|
||||
c.writeBulk(v)
|
||||
case nil:
|
||||
c.writeBulk(nil)
|
||||
case int64:
|
||||
c.writeInteger(v)
|
||||
default:
|
||||
panic("invalid array type")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) writeSliceArray(ay [][]byte) {
|
||||
c.wb.WriteByte('*')
|
||||
if ay == nil {
|
||||
c.wb.Write(NullArray)
|
||||
c.wb.Write(Delims)
|
||||
} else {
|
||||
c.wb.Write(ledis.Slice(strconv.Itoa(len(ay))))
|
||||
c.wb.Write(Delims)
|
||||
|
||||
for i := 0; i < len(ay); i++ {
|
||||
c.writeBulk(ay[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) writeFVPairArray(ay []ledis.FVPair) {
|
||||
c.wb.WriteByte('*')
|
||||
if ay == nil {
|
||||
c.wb.Write(NullArray)
|
||||
c.wb.Write(Delims)
|
||||
} else {
|
||||
c.wb.Write(ledis.Slice(strconv.Itoa(len(ay) * 2)))
|
||||
c.wb.Write(Delims)
|
||||
|
||||
for i := 0; i < len(ay); i++ {
|
||||
c.writeBulk(ay[i].Field)
|
||||
c.writeBulk(ay[i].Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) writeScorePairArray(ay []ledis.ScorePair, withScores bool) {
|
||||
c.wb.WriteByte('*')
|
||||
if ay == nil {
|
||||
c.wb.Write(NullArray)
|
||||
c.wb.Write(Delims)
|
||||
} else {
|
||||
if withScores {
|
||||
c.wb.Write(ledis.Slice(strconv.Itoa(len(ay) * 2)))
|
||||
c.wb.Write(Delims)
|
||||
} else {
|
||||
c.wb.Write(ledis.Slice(strconv.Itoa(len(ay))))
|
||||
c.wb.Write(Delims)
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < len(ay); i++ {
|
||||
c.writeBulk(ay[i].Member)
|
||||
|
||||
if withScores {
|
||||
c.writeBulk(ledis.StrPutInt64(ay[i].Score))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) writeBulkFrom(n int64, rb io.Reader) {
|
||||
c.wb.WriteByte('$')
|
||||
c.wb.Write(ledis.Slice(strconv.FormatInt(n, 10)))
|
||||
c.wb.Write(Delims)
|
||||
|
||||
io.Copy(c.wb, rb)
|
||||
c.wb.Write(Delims)
|
||||
}
|
||||
// func newHttpClient(w http.ResponseWriter, r *http.Request, app *App) {
|
||||
// c := newClient(app)
|
||||
// go c.run()
|
||||
// }
|
||||
|
|
|
@ -14,7 +14,7 @@ func bgetCommand(c *client) error {
|
|||
if v, err := c.db.BGet(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func bdeleteCommand(c *client) error {
|
|||
if n, err := c.db.BDelete(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func bsetbitCommand(c *client) error {
|
|||
if ori, err := c.db.BSetBit(args[0], offset, uint8(val)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(int64(ori))
|
||||
c.resp.writeInteger(int64(ori))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ func bgetbitCommand(c *client) error {
|
|||
if v, err := c.db.BGetBit(args[0], offset); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(int64(v))
|
||||
c.resp.writeInteger(int64(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ func bmsetbitCommand(c *client) error {
|
|||
if place, err := c.db.BMSetBit(key, pairs...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(place)
|
||||
c.resp.writeInteger(place)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ func bcountCommand(c *client) error {
|
|||
if cnt, err := c.db.BCount(args[0], start, end); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(int64(cnt))
|
||||
c.resp.writeInteger(int64(cnt))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ func boptCommand(c *client) error {
|
|||
if blen, err := c.db.BOperation(op, dstKey, srcKeys...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(int64(blen))
|
||||
c.resp.writeInteger(int64(blen))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ func bexpireCommand(c *client) error {
|
|||
if v, err := c.db.BExpire(args[0], duration); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -222,7 +222,7 @@ func bexpireatCommand(c *client) error {
|
|||
if v, err := c.db.BExpireAt(args[0], when); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -237,7 +237,7 @@ func bttlCommand(c *client) error {
|
|||
if v, err := c.db.BTTL(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -252,7 +252,7 @@ func bpersistCommand(c *client) error {
|
|||
if n, err := c.db.BPersist(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -13,7 +13,7 @@ func hsetCommand(c *client) error {
|
|||
if n, err := c.db.HSet(args[0], args[1], args[2]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -28,7 +28,7 @@ func hgetCommand(c *client) error {
|
|||
if v, err := c.db.HGet(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -48,7 +48,7 @@ func hexistsCommand(c *client) error {
|
|||
n = 0
|
||||
}
|
||||
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func hdelCommand(c *client) error {
|
|||
if n, err := c.db.HDel(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -77,7 +77,7 @@ func hlenCommand(c *client) error {
|
|||
if n, err := c.db.HLen(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -98,7 +98,7 @@ func hincrbyCommand(c *client) error {
|
|||
if n, err = c.db.HIncrBy(args[0], args[1], delta); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func hmsetCommand(c *client) error {
|
|||
if err := c.db.HMset(key, kvs...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeStatus(OK)
|
||||
c.resp.writeStatus(OK)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -141,7 +141,7 @@ func hmgetCommand(c *client) error {
|
|||
if v, err := c.db.HMget(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeSliceArray(v)
|
||||
c.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -156,7 +156,7 @@ func hgetallCommand(c *client) error {
|
|||
if v, err := c.db.HGetAll(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeFVPairArray(v)
|
||||
c.resp.writeFVPairArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -171,7 +171,7 @@ func hkeysCommand(c *client) error {
|
|||
if v, err := c.db.HKeys(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeSliceArray(v)
|
||||
c.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -186,7 +186,7 @@ func hvalsCommand(c *client) error {
|
|||
if v, err := c.db.HValues(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeSliceArray(v)
|
||||
c.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -201,7 +201,7 @@ func hclearCommand(c *client) error {
|
|||
if n, err := c.db.HClear(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -216,7 +216,7 @@ func hmclearCommand(c *client) error {
|
|||
if n, err := c.db.HMclear(args...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -236,7 +236,7 @@ func hexpireCommand(c *client) error {
|
|||
if v, err := c.db.HExpire(args[0], duration); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -256,7 +256,7 @@ func hexpireAtCommand(c *client) error {
|
|||
if v, err := c.db.HExpireAt(args[0], when); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -271,7 +271,7 @@ func httlCommand(c *client) error {
|
|||
if v, err := c.db.HTTL(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -286,7 +286,7 @@ func hpersistCommand(c *client) error {
|
|||
if n, err := c.db.HPersist(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -13,7 +13,7 @@ func getCommand(c *client) error {
|
|||
if v, err := c.db.Get(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func setCommand(c *client) error {
|
|||
if err := c.db.Set(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeStatus(OK)
|
||||
c.resp.writeStatus(OK)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -42,7 +42,7 @@ func getsetCommand(c *client) error {
|
|||
if v, err := c.db.GetSet(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -57,7 +57,7 @@ func setnxCommand(c *client) error {
|
|||
if n, err := c.db.SetNX(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -72,7 +72,7 @@ func existsCommand(c *client) error {
|
|||
if n, err := c.db.Exists(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -87,7 +87,7 @@ func incrCommand(c *client) error {
|
|||
if n, err := c.db.Incr(c.args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -102,7 +102,7 @@ func decrCommand(c *client) error {
|
|||
if n, err := c.db.Decr(c.args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -122,7 +122,7 @@ func incrbyCommand(c *client) error {
|
|||
if n, err := c.db.IncryBy(c.args[0], delta); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -142,7 +142,7 @@ func decrbyCommand(c *client) error {
|
|||
if n, err := c.db.DecrBy(c.args[0], delta); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -157,7 +157,7 @@ func delCommand(c *client) error {
|
|||
if n, err := c.db.Del(args...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -178,7 +178,7 @@ func msetCommand(c *client) error {
|
|||
if err := c.db.MSet(kvs...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeStatus(OK)
|
||||
c.resp.writeStatus(OK)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -197,7 +197,7 @@ func mgetCommand(c *client) error {
|
|||
if v, err := c.db.MGet(args...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeSliceArray(v)
|
||||
c.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -217,7 +217,7 @@ func expireCommand(c *client) error {
|
|||
if v, err := c.db.Expire(args[0], duration); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -237,7 +237,7 @@ func expireAtCommand(c *client) error {
|
|||
if v, err := c.db.ExpireAt(args[0], when); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -252,7 +252,7 @@ func ttlCommand(c *client) error {
|
|||
if v, err := c.db.TTL(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -267,7 +267,7 @@ func persistCommand(c *client) error {
|
|||
if n, err := c.db.Persist(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -13,7 +13,7 @@ func lpushCommand(c *client) error {
|
|||
if n, err := c.db.LPush(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -28,7 +28,7 @@ func rpushCommand(c *client) error {
|
|||
if n, err := c.db.RPush(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -43,7 +43,7 @@ func lpopCommand(c *client) error {
|
|||
if v, err := c.db.LPop(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -58,7 +58,7 @@ func rpopCommand(c *client) error {
|
|||
if v, err := c.db.RPop(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -73,7 +73,7 @@ func llenCommand(c *client) error {
|
|||
if n, err := c.db.LLen(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -93,7 +93,7 @@ func lindexCommand(c *client) error {
|
|||
if v, err := c.db.LIndex(args[0], int32(index)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(v)
|
||||
c.resp.writeBulk(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -122,7 +122,7 @@ func lrangeCommand(c *client) error {
|
|||
if v, err := c.db.LRange(args[0], int32(start), int32(stop)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeSliceArray(v)
|
||||
c.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -137,7 +137,7 @@ func lclearCommand(c *client) error {
|
|||
if n, err := c.db.LClear(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -152,7 +152,7 @@ func lmclearCommand(c *client) error {
|
|||
if n, err := c.db.LMclear(args...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -172,7 +172,7 @@ func lexpireCommand(c *client) error {
|
|||
if v, err := c.db.LExpire(args[0], duration); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -192,7 +192,7 @@ func lexpireAtCommand(c *client) error {
|
|||
if v, err := c.db.LExpireAt(args[0], when); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -207,7 +207,7 @@ func lttlCommand(c *client) error {
|
|||
if v, err := c.db.LTTL(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -222,7 +222,7 @@ func lpersistCommand(c *client) error {
|
|||
if n, err := c.db.LPersist(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -35,7 +35,7 @@ func slaveofCommand(c *client) error {
|
|||
return err
|
||||
}
|
||||
|
||||
c.writeStatus(OK)
|
||||
c.resp.writeStatus(OK)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func fullsyncCommand(c *client) error {
|
|||
|
||||
dumpFile.Seek(0, os.SEEK_SET)
|
||||
|
||||
c.writeBulkFrom(n, dumpFile)
|
||||
c.resp.writeBulkFrom(n, dumpFile)
|
||||
|
||||
name := dumpFile.Name()
|
||||
dumpFile.Close()
|
||||
|
@ -112,7 +112,7 @@ func syncCommand(c *client) error {
|
|||
return err
|
||||
}
|
||||
|
||||
c.writeBulk(buf)
|
||||
c.resp.writeBulk(buf)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -39,7 +39,7 @@ func zaddCommand(c *client) error {
|
|||
if n, err := c.db.ZAdd(key, params...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -54,7 +54,7 @@ func zcardCommand(c *client) error {
|
|||
if n, err := c.db.ZCard(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -68,12 +68,12 @@ func zscoreCommand(c *client) error {
|
|||
|
||||
if s, err := c.db.ZScore(args[0], args[1]); err != nil {
|
||||
if err == ledis.ErrScoreMiss {
|
||||
c.writeBulk(nil)
|
||||
c.resp.writeBulk(nil)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
c.writeBulk(ledis.StrPutInt64(s))
|
||||
c.resp.writeBulk(ledis.StrPutInt64(s))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -88,7 +88,7 @@ func zremCommand(c *client) error {
|
|||
if n, err := c.db.ZRem(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -110,7 +110,7 @@ func zincrbyCommand(c *client) error {
|
|||
if v, err := c.db.ZIncrBy(key, delta, args[2]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeBulk(ledis.StrPutInt64(v))
|
||||
c.resp.writeBulk(ledis.StrPutInt64(v))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -190,14 +190,14 @@ func zcountCommand(c *client) error {
|
|||
}
|
||||
|
||||
if min > max {
|
||||
c.writeInteger(0)
|
||||
c.resp.writeInteger(0)
|
||||
return nil
|
||||
}
|
||||
|
||||
if n, err := c.db.ZCount(args[0], min, max); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -212,9 +212,9 @@ func zrankCommand(c *client) error {
|
|||
if n, err := c.db.ZRank(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else if n == -1 {
|
||||
c.writeBulk(nil)
|
||||
c.resp.writeBulk(nil)
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -229,9 +229,9 @@ func zrevrankCommand(c *client) error {
|
|||
if n, err := c.db.ZRevRank(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else if n == -1 {
|
||||
c.writeBulk(nil)
|
||||
c.resp.writeBulk(nil)
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -253,7 +253,7 @@ func zremrangebyrankCommand(c *client) error {
|
|||
if n, err := c.db.ZRemRangeByRank(key, start, stop); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -274,7 +274,7 @@ func zremrangebyscoreCommand(c *client) error {
|
|||
if n, err := c.db.ZRemRangeByScore(key, min, max); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -315,7 +315,7 @@ func zrangeGeneric(c *client, reverse bool) error {
|
|||
if datas, err := c.db.ZRangeGeneric(key, start, stop, reverse); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeScorePairArray(datas, withScores)
|
||||
c.resp.writeScorePairArray(datas, withScores)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -383,14 +383,14 @@ func zrangebyscoreGeneric(c *client, reverse bool) error {
|
|||
if offset < 0 {
|
||||
//for ledis, if offset < 0, a empty will return
|
||||
//so here we directly return a empty array
|
||||
c.writeArray([]interface{}{})
|
||||
c.resp.writeArray([]interface{}{})
|
||||
return nil
|
||||
}
|
||||
|
||||
if datas, err := c.db.ZRangeByScoreGeneric(key, min, max, offset, count, reverse); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeScorePairArray(datas, withScores)
|
||||
c.resp.writeScorePairArray(datas, withScores)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -413,7 +413,7 @@ func zclearCommand(c *client) error {
|
|||
if n, err := c.db.ZClear(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -428,7 +428,7 @@ func zmclearCommand(c *client) error {
|
|||
if n, err := c.db.ZMclear(args...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -448,7 +448,7 @@ func zexpireCommand(c *client) error {
|
|||
if v, err := c.db.ZExpire(args[0], duration); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -468,7 +468,7 @@ func zexpireAtCommand(c *client) error {
|
|||
if v, err := c.db.ZExpireAt(args[0], when); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -483,7 +483,7 @@ func zttlCommand(c *client) error {
|
|||
if v, err := c.db.ZTTL(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(v)
|
||||
c.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -498,7 +498,7 @@ func zpersistCommand(c *client) error {
|
|||
if n, err := c.db.ZPersist(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.writeInteger(n)
|
||||
c.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -21,7 +21,7 @@ func register(name string, f CommandFunc) {
|
|||
}
|
||||
|
||||
func pingCommand(c *client) error {
|
||||
c.writeStatus(PONG)
|
||||
c.resp.writeStatus(PONG)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ func echoCommand(c *client) error {
|
|||
return ErrCmdParams
|
||||
}
|
||||
|
||||
c.writeBulk(c.args[0])
|
||||
c.resp.writeBulk(c.args[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ func selectCommand(c *client) error {
|
|||
return err
|
||||
} else {
|
||||
c.db = db
|
||||
c.writeStatus(OK)
|
||||
c.resp.writeStatus(OK)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/siddontang/ledisdb/ledis"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type httpContext struct {
|
||||
}
|
||||
|
||||
type httpReader struct {
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
type httpWriter struct {
|
||||
resp *http.ResponseWriter
|
||||
}
|
||||
|
||||
// http context
|
||||
|
||||
func newHttpContext() *httpContext {
|
||||
ctx := new(httpContext)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (ctx *httpContext) addr() string {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ctx *httpContext) release() {
|
||||
|
||||
}
|
||||
|
||||
// http reader
|
||||
|
||||
func newHttpReader(req *http.Request) *httpReader {
|
||||
r := new(httpReader)
|
||||
r.req = req
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *httpReader) read() ([][]byte, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// http writer
|
||||
|
||||
func newHttpWriter(resp *http.ResponseWriter) *httpWriter {
|
||||
w := new(httpWriter)
|
||||
w.resp = resp
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeError(err error) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeStatus(status string) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeInteger(n int64) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeBulk(b []byte) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeArray(lst []interface{}) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeSliceArray(lst [][]byte) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeFVPairArray(lst []ledis.FVPair) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeScorePairArray(lst []ledis.ScorePair, withScores bool) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) writeBulkFrom(n int64, rb io.Reader) {
|
||||
|
||||
}
|
||||
|
||||
func (w *httpWriter) flush() {
|
||||
|
||||
}
|
|
@ -72,8 +72,8 @@ func (m *MasterInfo) Load(filePath string) error {
|
|||
type master struct {
|
||||
sync.Mutex
|
||||
|
||||
c net.Conn
|
||||
rb *bufio.Reader
|
||||
conn net.Conn
|
||||
rb *bufio.Reader
|
||||
|
||||
app *App
|
||||
|
||||
|
@ -114,9 +114,9 @@ func (m *master) Close() {
|
|||
default:
|
||||
}
|
||||
|
||||
if m.c != nil {
|
||||
m.c.Close()
|
||||
m.c = nil
|
||||
if m.conn != nil {
|
||||
m.conn.Close()
|
||||
m.conn = nil
|
||||
}
|
||||
|
||||
m.wg.Wait()
|
||||
|
@ -135,17 +135,17 @@ func (m *master) connect() error {
|
|||
return fmt.Errorf("no assign master addr")
|
||||
}
|
||||
|
||||
if m.c != nil {
|
||||
m.c.Close()
|
||||
m.c = nil
|
||||
if m.conn != nil {
|
||||
m.conn.Close()
|
||||
m.conn = nil
|
||||
}
|
||||
|
||||
if c, err := net.Dial("tcp", m.info.Addr); err != nil {
|
||||
if conn, err := net.Dial("tcp", m.info.Addr); err != nil {
|
||||
return err
|
||||
} else {
|
||||
m.c = c
|
||||
m.conn = conn
|
||||
|
||||
m.rb = bufio.NewReaderSize(m.c, 4096)
|
||||
m.rb = bufio.NewReaderSize(m.conn, 4096)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ var (
|
|||
)
|
||||
|
||||
func (m *master) fullSync() error {
|
||||
if _, err := m.c.Write(fullSyncCmd); err != nil {
|
||||
if _, err := m.conn.Write(fullSyncCmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ func (m *master) sync() error {
|
|||
|
||||
cmd := ledis.Slice(fmt.Sprintf(syncCmdFormat, len(logIndexStr),
|
||||
logIndexStr, len(logPosStr), logPosStr))
|
||||
if _, err := m.c.Write(cmd); err != nil {
|
||||
if _, err := m.conn.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"github.com/siddontang/ledisdb/ledis"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type tcpContext struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
type tcpWriter struct {
|
||||
buff *bufio.Writer
|
||||
}
|
||||
|
||||
type tcpReader struct {
|
||||
buff *bufio.Reader
|
||||
}
|
||||
|
||||
// tcp context
|
||||
|
||||
func newTcpContext(conn net.Conn) *tcpContext {
|
||||
ctx := new(tcpContext)
|
||||
ctx.conn = conn
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (ctx *tcpContext) addr() string {
|
||||
return ctx.conn.RemoteAddr().String()
|
||||
}
|
||||
|
||||
func (ctx *tcpContext) release() {
|
||||
if ctx.conn != nil {
|
||||
ctx.conn.Close()
|
||||
ctx.conn = nil
|
||||
}
|
||||
}
|
||||
|
||||
// tcp reader
|
||||
|
||||
func newTcpReader(conn net.Conn) *tcpReader {
|
||||
r := new(tcpReader)
|
||||
r.buff = bufio.NewReaderSize(conn, 256)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *tcpReader) readLine() ([]byte, error) {
|
||||
return ReadLine(r.buff)
|
||||
}
|
||||
|
||||
//A client sends to the Redis server a RESP Array consisting of just Bulk Strings.
|
||||
func (r *tcpReader) read() ([][]byte, error) {
|
||||
l, err := r.readLine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(l) == 0 || l[0] != '*' {
|
||||
return nil, errReadRequest
|
||||
}
|
||||
|
||||
var nparams int
|
||||
if nparams, err = strconv.Atoi(ledis.String(l[1:])); err != nil {
|
||||
return nil, err
|
||||
} else if nparams <= 0 {
|
||||
return nil, errReadRequest
|
||||
}
|
||||
|
||||
reqData := make([][]byte, 0, nparams)
|
||||
var n int
|
||||
for i := 0; i < nparams; i++ {
|
||||
if l, err = r.readLine(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(l) == 0 {
|
||||
return nil, errReadRequest
|
||||
} else if l[0] == '$' {
|
||||
//handle resp string
|
||||
if n, err = strconv.Atoi(ledis.String(l[1:])); err != nil {
|
||||
return nil, err
|
||||
} else if n == -1 {
|
||||
reqData = append(reqData, nil)
|
||||
} else {
|
||||
buf := make([]byte, n)
|
||||
if _, err = io.ReadFull(r.buff, buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if l, err = r.readLine(); err != nil {
|
||||
return nil, err
|
||||
} else if len(l) != 0 {
|
||||
return nil, errors.New("bad bulk string format")
|
||||
}
|
||||
|
||||
reqData = append(reqData, buf)
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
return nil, errReadRequest
|
||||
}
|
||||
}
|
||||
|
||||
return reqData, nil
|
||||
}
|
||||
|
||||
// tcp writer
|
||||
|
||||
func newTcpWriter(conn net.Conn) *tcpWriter {
|
||||
w := new(tcpWriter)
|
||||
w.buff = bufio.NewWriterSize(conn, 256)
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeError(err error) {
|
||||
w.buff.Write(ledis.Slice("-ERR"))
|
||||
if err != nil {
|
||||
w.buff.WriteByte(' ')
|
||||
w.buff.Write(ledis.Slice(err.Error()))
|
||||
}
|
||||
w.buff.Write(Delims)
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeStatus(status string) {
|
||||
w.buff.WriteByte('+')
|
||||
w.buff.Write(ledis.Slice(status))
|
||||
w.buff.Write(Delims)
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeInteger(n int64) {
|
||||
w.buff.WriteByte(':')
|
||||
w.buff.Write(ledis.StrPutInt64(n))
|
||||
w.buff.Write(Delims)
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeBulk(b []byte) {
|
||||
w.buff.WriteByte('$')
|
||||
if b == nil {
|
||||
w.buff.Write(NullBulk)
|
||||
} else {
|
||||
w.buff.Write(ledis.Slice(strconv.Itoa(len(b))))
|
||||
w.buff.Write(Delims)
|
||||
w.buff.Write(b)
|
||||
}
|
||||
|
||||
w.buff.Write(Delims)
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeArray(lst []interface{}) {
|
||||
w.buff.WriteByte('*')
|
||||
if lst == nil {
|
||||
w.buff.Write(NullArray)
|
||||
w.buff.Write(Delims)
|
||||
} else {
|
||||
w.buff.Write(ledis.Slice(strconv.Itoa(len(lst))))
|
||||
w.buff.Write(Delims)
|
||||
|
||||
for i := 0; i < len(lst); i++ {
|
||||
switch v := lst[i].(type) {
|
||||
case []interface{}:
|
||||
w.writeArray(v)
|
||||
case []byte:
|
||||
w.writeBulk(v)
|
||||
case nil:
|
||||
w.writeBulk(nil)
|
||||
case int64:
|
||||
w.writeInteger(v)
|
||||
default:
|
||||
panic("invalid array type")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeSliceArray(lst [][]byte) {
|
||||
w.buff.WriteByte('*')
|
||||
if lst == nil {
|
||||
w.buff.Write(NullArray)
|
||||
w.buff.Write(Delims)
|
||||
} else {
|
||||
w.buff.Write(ledis.Slice(strconv.Itoa(len(lst))))
|
||||
w.buff.Write(Delims)
|
||||
|
||||
for i := 0; i < len(lst); i++ {
|
||||
w.writeBulk(lst[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeFVPairArray(lst []ledis.FVPair) {
|
||||
w.buff.WriteByte('*')
|
||||
if lst == nil {
|
||||
w.buff.Write(NullArray)
|
||||
w.buff.Write(Delims)
|
||||
} else {
|
||||
w.buff.Write(ledis.Slice(strconv.Itoa(len(lst) * 2)))
|
||||
w.buff.Write(Delims)
|
||||
|
||||
for i := 0; i < len(lst); i++ {
|
||||
w.writeBulk(lst[i].Field)
|
||||
w.writeBulk(lst[i].Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeScorePairArray(lst []ledis.ScorePair, withScores bool) {
|
||||
w.buff.WriteByte('*')
|
||||
if lst == nil {
|
||||
w.buff.Write(NullArray)
|
||||
w.buff.Write(Delims)
|
||||
} else {
|
||||
if withScores {
|
||||
w.buff.Write(ledis.Slice(strconv.Itoa(len(lst) * 2)))
|
||||
w.buff.Write(Delims)
|
||||
} else {
|
||||
w.buff.Write(ledis.Slice(strconv.Itoa(len(lst))))
|
||||
w.buff.Write(Delims)
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < len(lst); i++ {
|
||||
w.writeBulk(lst[i].Member)
|
||||
|
||||
if withScores {
|
||||
w.writeBulk(ledis.StrPutInt64(lst[i].Score))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *tcpWriter) writeBulkFrom(n int64, rb io.Reader) {
|
||||
w.buff.WriteByte('$')
|
||||
w.buff.Write(ledis.Slice(strconv.FormatInt(n, 10)))
|
||||
w.buff.Write(Delims)
|
||||
|
||||
io.Copy(w.buff, rb)
|
||||
w.buff.Write(Delims)
|
||||
}
|
||||
|
||||
func (w *tcpWriter) flush() {
|
||||
w.buff.Flush()
|
||||
}
|
Loading…
Reference in New Issue