From 594f6a5d0df8ad54ec926fe0352aac463144ee1a Mon Sep 17 00:00:00 2001 From: siddontang Date: Sun, 22 Jun 2014 10:39:23 +0800 Subject: [PATCH] use ledis client --- client/go/redis/commandinfo.go | 45 --- client/go/redis/conn.go | 418 --------------------------- client/go/redis/doc.go | 167 ----------- client/go/redis/log.go | 117 -------- client/go/redis/pool.go | 358 ----------------------- client/go/redis/pubsub.go | 129 --------- client/go/redis/redis.go | 44 --- client/go/redis/reply.go | 271 ----------------- client/go/redis/scan.go | 513 --------------------------------- client/go/redis/script.go | 86 ------ cmd/ledis-benchmark/main.go | 18 +- server/app_test.go | 26 +- server/cmd_hash_test.go | 52 ++-- server/cmd_kv_test.go | 38 +-- server/cmd_list_test.go | 40 +-- server/cmd_ttl_test.go | 16 +- server/cmd_zset.go | 2 +- server/cmd_zset_test.go | 114 ++++---- 18 files changed, 147 insertions(+), 2307 deletions(-) delete mode 100644 client/go/redis/commandinfo.go delete mode 100644 client/go/redis/conn.go delete mode 100644 client/go/redis/doc.go delete mode 100644 client/go/redis/log.go delete mode 100644 client/go/redis/pool.go delete mode 100644 client/go/redis/pubsub.go delete mode 100644 client/go/redis/redis.go delete mode 100644 client/go/redis/reply.go delete mode 100644 client/go/redis/scan.go delete mode 100644 client/go/redis/script.go diff --git a/client/go/redis/commandinfo.go b/client/go/redis/commandinfo.go deleted file mode 100644 index 014115d..0000000 --- a/client/go/redis/commandinfo.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "strings" -) - -const ( - watchState = 1 << iota - multiState - subscribeState - monitorState -) - -type commandInfo struct { - set, clear int -} - -var commandInfos = map[string]commandInfo{ - "WATCH": commandInfo{set: watchState}, - "UNWATCH": commandInfo{clear: watchState}, - "MULTI": commandInfo{set: multiState}, - "EXEC": commandInfo{clear: watchState | multiState}, - "DISCARD": commandInfo{clear: watchState | multiState}, - "PSUBSCRIBE": commandInfo{set: subscribeState}, - "SUBSCRIBE": commandInfo{set: subscribeState}, - "MONITOR": commandInfo{set: monitorState}, -} - -func lookupCommandInfo(commandName string) commandInfo { - return commandInfos[strings.ToUpper(commandName)] -} diff --git a/client/go/redis/conn.go b/client/go/redis/conn.go deleted file mode 100644 index 331d3c6..0000000 --- a/client/go/redis/conn.go +++ /dev/null @@ -1,418 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "net" - "strconv" - "sync" - "time" -) - -// conn is the low-level implementation of Conn -type conn struct { - - // Shared - mu sync.Mutex - pending int - err error - conn net.Conn - - // Read - readTimeout time.Duration - br *bufio.Reader - - // Write - writeTimeout time.Duration - bw *bufio.Writer - - // Scratch space for formatting argument length. - // '*' or '$', length, "\r\n" - lenScratch [32]byte - - // Scratch space for formatting integers and floats. - numScratch [40]byte -} - -// Dial connects to the Redis server at the given network and address. -func Dial(network, address string) (Conn, error) { - c, err := net.Dial(network, address) - if err != nil { - return nil, err - } - return NewConn(c, 0, 0), nil -} - -// DialTimeout acts like Dial but takes timeouts for establishing the -// connection to the server, writing a command and reading a reply. -func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) { - var c net.Conn - var err error - if connectTimeout > 0 { - c, err = net.DialTimeout(network, address, connectTimeout) - } else { - c, err = net.Dial(network, address) - } - if err != nil { - return nil, err - } - return NewConn(c, readTimeout, writeTimeout), nil -} - -// NewConn returns a new Redigo connection for the given net connection. -func NewConn(netConn net.Conn, readTimeout, writeTimeout time.Duration) Conn { - return &conn{ - conn: netConn, - bw: bufio.NewWriter(netConn), - br: bufio.NewReader(netConn), - readTimeout: readTimeout, - writeTimeout: writeTimeout, - } -} - -func (c *conn) Close() error { - c.mu.Lock() - err := c.err - if c.err == nil { - c.err = errors.New("redigo: closed") - err = c.conn.Close() - } - c.mu.Unlock() - return err -} - -func (c *conn) fatal(err error) error { - c.mu.Lock() - if c.err == nil { - c.err = err - // Close connection to force errors on subsequent calls and to unblock - // other reader or writer. - c.conn.Close() - } - c.mu.Unlock() - return err -} - -func (c *conn) Err() error { - c.mu.Lock() - err := c.err - c.mu.Unlock() - return err -} - -func (c *conn) writeLen(prefix byte, n int) error { - c.lenScratch[len(c.lenScratch)-1] = '\n' - c.lenScratch[len(c.lenScratch)-2] = '\r' - i := len(c.lenScratch) - 3 - for { - c.lenScratch[i] = byte('0' + n%10) - i -= 1 - n = n / 10 - if n == 0 { - break - } - } - c.lenScratch[i] = prefix - _, err := c.bw.Write(c.lenScratch[i:]) - return err -} - -func (c *conn) writeString(s string) error { - c.writeLen('$', len(s)) - c.bw.WriteString(s) - _, err := c.bw.WriteString("\r\n") - return err -} - -func (c *conn) writeBytes(p []byte) error { - c.writeLen('$', len(p)) - c.bw.Write(p) - _, err := c.bw.WriteString("\r\n") - return err -} - -func (c *conn) writeInt64(n int64) error { - return c.writeBytes(strconv.AppendInt(c.numScratch[:0], n, 10)) -} - -func (c *conn) writeFloat64(n float64) error { - return c.writeBytes(strconv.AppendFloat(c.numScratch[:0], n, 'g', -1, 64)) -} - -func (c *conn) writeCommand(cmd string, args []interface{}) (err error) { - c.writeLen('*', 1+len(args)) - err = c.writeString(cmd) - for _, arg := range args { - if err != nil { - break - } - switch arg := arg.(type) { - case string: - err = c.writeString(arg) - case []byte: - err = c.writeBytes(arg) - case int: - err = c.writeInt64(int64(arg)) - case int64: - err = c.writeInt64(arg) - case float64: - err = c.writeFloat64(arg) - case bool: - if arg { - err = c.writeString("1") - } else { - err = c.writeString("0") - } - case nil: - err = c.writeString("") - default: - var buf bytes.Buffer - fmt.Fprint(&buf, arg) - err = c.writeBytes(buf.Bytes()) - } - } - return err -} - -func (c *conn) readLine() ([]byte, error) { - p, err := c.br.ReadSlice('\n') - if err == bufio.ErrBufferFull { - return nil, errors.New("redigo: long response line") - } - if err != nil { - return nil, err - } - i := len(p) - 2 - if i < 0 || p[i] != '\r' { - return nil, errors.New("redigo: bad response line terminator") - } - return p[:i], nil -} - -// parseLen parses bulk string and array lengths. -func parseLen(p []byte) (int, error) { - if len(p) == 0 { - return -1, errors.New("redigo: malformed length") - } - - if p[0] == '-' && len(p) == 2 && p[1] == '1' { - // handle $-1 and $-1 null replies. - return -1, nil - } - - var n int - for _, b := range p { - n *= 10 - if b < '0' || b > '9' { - return -1, errors.New("redigo: illegal bytes in length") - } - n += int(b - '0') - } - - return n, nil -} - -// parseInt parses an integer reply. -func parseInt(p []byte) (interface{}, error) { - if len(p) == 0 { - return 0, errors.New("redigo: malformed integer") - } - - var negate bool - if p[0] == '-' { - negate = true - p = p[1:] - if len(p) == 0 { - return 0, errors.New("redigo: malformed integer") - } - } - - var n int64 - for _, b := range p { - n *= 10 - if b < '0' || b > '9' { - return 0, errors.New("redigo: illegal bytes in length") - } - n += int64(b - '0') - } - - if negate { - n = -n - } - return n, nil -} - -var ( - okReply interface{} = "OK" - pongReply interface{} = "PONG" -) - -func (c *conn) readReply() (interface{}, error) { - line, err := c.readLine() - if err != nil { - return nil, err - } - if len(line) == 0 { - return nil, errors.New("redigo: short response line") - } - switch line[0] { - case '+': - switch { - case len(line) == 3 && line[1] == 'O' && line[2] == 'K': - // Avoid allocation for frequent "+OK" response. - return okReply, nil - case len(line) == 5 && line[1] == 'P' && line[2] == 'O' && line[3] == 'N' && line[4] == 'G': - // Avoid allocation in PING command benchmarks :) - return pongReply, nil - default: - return string(line[1:]), nil - } - case '-': - return Error(string(line[1:])), nil - case ':': - return parseInt(line[1:]) - case '$': - n, err := parseLen(line[1:]) - if n < 0 || err != nil { - return nil, err - } - p := make([]byte, n) - _, err = io.ReadFull(c.br, p) - if err != nil { - return nil, err - } - if line, err := c.readLine(); err != nil { - return nil, err - } else if len(line) != 0 { - return nil, errors.New("redigo: bad bulk string format") - } - return p, nil - case '*': - n, err := parseLen(line[1:]) - if n < 0 || err != nil { - return nil, err - } - r := make([]interface{}, n) - for i := range r { - r[i], err = c.readReply() - if err != nil { - return nil, err - } - } - return r, nil - } - return nil, errors.New("redigo: unexpected response line") -} - -func (c *conn) Send(cmd string, args ...interface{}) error { - c.mu.Lock() - c.pending += 1 - c.mu.Unlock() - if c.writeTimeout != 0 { - c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)) - } - if err := c.writeCommand(cmd, args); err != nil { - return c.fatal(err) - } - return nil -} - -func (c *conn) Flush() error { - if c.writeTimeout != 0 { - c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)) - } - if err := c.bw.Flush(); err != nil { - return c.fatal(err) - } - return nil -} - -func (c *conn) Receive() (reply interface{}, err error) { - c.mu.Lock() - // There can be more receives than sends when using pub/sub. To allow - // normal use of the connection after unsubscribe from all channels, do not - // decrement pending to a negative value. - if c.pending > 0 { - c.pending -= 1 - } - c.mu.Unlock() - if c.readTimeout != 0 { - c.conn.SetReadDeadline(time.Now().Add(c.readTimeout)) - } - if reply, err = c.readReply(); err != nil { - return nil, c.fatal(err) - } - if err, ok := reply.(Error); ok { - return nil, err - } - return -} - -func (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) { - c.mu.Lock() - pending := c.pending - c.pending = 0 - c.mu.Unlock() - - if cmd == "" && pending == 0 { - return nil, nil - } - - if c.writeTimeout != 0 { - c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)) - } - - if cmd != "" { - c.writeCommand(cmd, args) - } - - if err := c.bw.Flush(); err != nil { - return nil, c.fatal(err) - } - - if c.readTimeout != 0 { - c.conn.SetReadDeadline(time.Now().Add(c.readTimeout)) - } - - if cmd == "" { - reply := make([]interface{}, pending) - for i := range reply { - r, e := c.readReply() - if e != nil { - return nil, c.fatal(e) - } - reply[i] = r - } - return reply, nil - } - - var err error - var reply interface{} - for i := 0; i <= pending; i++ { - var e error - if reply, e = c.readReply(); e != nil { - return nil, c.fatal(e) - } - if e, ok := reply.(Error); ok && err == nil { - err = e - } - } - return reply, err -} diff --git a/client/go/redis/doc.go b/client/go/redis/doc.go deleted file mode 100644 index 63e6ffe..0000000 --- a/client/go/redis/doc.go +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -// Package redis is a client for the Redis database. -// -// The Redigo FAQ (https://github.com/garyburd/redigo/wiki/FAQ) contains more -// documentation about this package. -// -// Connections -// -// The Conn interface is the primary interface for working with Redis. -// Applications create connections by calling the Dial, DialWithTimeout or -// NewConn functions. In the future, functions will be added for creating -// sharded and other types of connections. -// -// The application must call the connection Close method when the application -// is done with the connection. -// -// Executing Commands -// -// The Conn interface has a generic method for executing Redis commands: -// -// Do(commandName string, args ...interface{}) (reply interface{}, err error) -// -// The Redis command reference (http://redis.io/commands) lists the available -// commands. An example of using the Redis APPEND command is: -// -// n, err := conn.Do("APPEND", "key", "value") -// -// The Do method converts command arguments to binary strings for transmission -// to the server as follows: -// -// Go Type Conversion -// []byte Sent as is -// string Sent as is -// int, int64 strconv.FormatInt(v) -// float64 strconv.FormatFloat(v, 'g', -1, 64) -// bool true -> "1", false -> "0" -// nil "" -// all other types fmt.Print(v) -// -// Redis command reply types are represented using the following Go types: -// -// Redis type Go type -// error redis.Error -// integer int64 -// simple string string -// bulk string []byte or nil if value not present. -// array []interface{} or nil if value not present. -// -// Use type assertions or the reply helper functions to convert from -// interface{} to the specific Go type for the command result. -// -// Pipelining -// -// Connections support pipelining using the Send, Flush and Receive methods. -// -// Send(commandName string, args ...interface{}) error -// Flush() error -// Receive() (reply interface{}, err error) -// -// Send writes the command to the connection's output buffer. Flush flushes the -// connection's output buffer to the server. Receive reads a single reply from -// the server. The following example shows a simple pipeline. -// -// c.Send("SET", "foo", "bar") -// c.Send("GET", "foo") -// c.Flush() -// c.Receive() // reply from SET -// v, err = c.Receive() // reply from GET -// -// The Do method combines the functionality of the Send, Flush and Receive -// methods. The Do method starts by writing the command and flushing the output -// buffer. Next, the Do method receives all pending replies including the reply -// for the command just sent by Do. If any of the received replies is an error, -// then Do returns the error. If there are no errors, then Do returns the last -// reply. If the command argument to the Do method is "", then the Do method -// will flush the output buffer and receive pending replies without sending a -// command. -// -// Use the Send and Do methods to implement pipelined transactions. -// -// c.Send("MULTI") -// c.Send("INCR", "foo") -// c.Send("INCR", "bar") -// r, err := c.Do("EXEC") -// fmt.Println(r) // prints [1, 1] -// -// Concurrency -// -// Connections support a single concurrent caller to the write methods (Send, -// Flush) and a single concurrent caller to the read method (Receive). Because -// Do method combines the functionality of Send, Flush and Receive, the Do -// method cannot be called concurrently with the other methods. -// -// For full concurrent access to Redis, use the thread-safe Pool to get and -// release connections from within a goroutine. -// -// Publish and Subscribe -// -// Use the Send, Flush and Receive methods to implement Pub/Sub subscribers. -// -// c.Send("SUBSCRIBE", "example") -// c.Flush() -// for { -// reply, err := c.Receive() -// if err != nil { -// return err -// } -// // process pushed message -// } -// -// The PubSubConn type wraps a Conn with convenience methods for implementing -// subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods -// send and flush a subscription management command. The receive method -// converts a pushed message to convenient types for use in a type switch. -// -// psc := PubSubConn{c} -// psc.Subscribe("example") -// for { -// switch v := psc.Receive().(type) { -// case redis.Message: -// fmt.Printf("%s: message: %s\n", v.Channel, v.Data) -// case redis.Subscription: -// fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count) -// case error: -// return v -// } -// } -// -// Reply Helpers -// -// The Bool, Int, Bytes, String, Strings and Values functions convert a reply -// to a value of a specific type. To allow convenient wrapping of calls to the -// connection Do and Receive methods, the functions take a second argument of -// type error. If the error is non-nil, then the helper function returns the -// error. If the error is nil, the function converts the reply to the specified -// type: -// -// exists, err := redis.Bool(c.Do("EXISTS", "foo")) -// if err != nil { -// // handle error return from c.Do or type conversion error. -// } -// -// The Scan function converts elements of a array reply to Go types: -// -// var value1 int -// var value2 string -// reply, err := redis.Values(c.Do("MGET", "key1", "key2")) -// if err != nil { -// // handle error -// } -// if _, err := redis.Scan(reply, &value1, &value2); err != nil { -// // handle error -// } -package redis diff --git a/client/go/redis/log.go b/client/go/redis/log.go deleted file mode 100644 index 129b86d..0000000 --- a/client/go/redis/log.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "bytes" - "fmt" - "log" -) - -// NewLoggingConn returns a logging wrapper around a connection. -func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn { - if prefix != "" { - prefix = prefix + "." - } - return &loggingConn{conn, logger, prefix} -} - -type loggingConn struct { - Conn - logger *log.Logger - prefix string -} - -func (c *loggingConn) Close() error { - err := c.Conn.Close() - var buf bytes.Buffer - fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err) - c.logger.Output(2, buf.String()) - return err -} - -func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) { - const chop = 32 - switch v := v.(type) { - case []byte: - if len(v) > chop { - fmt.Fprintf(buf, "%q...", v[:chop]) - } else { - fmt.Fprintf(buf, "%q", v) - } - case string: - if len(v) > chop { - fmt.Fprintf(buf, "%q...", v[:chop]) - } else { - fmt.Fprintf(buf, "%q", v) - } - case []interface{}: - if len(v) == 0 { - buf.WriteString("[]") - } else { - sep := "[" - fin := "]" - if len(v) > chop { - v = v[:chop] - fin = "...]" - } - for _, vv := range v { - buf.WriteString(sep) - c.printValue(buf, vv) - sep = ", " - } - buf.WriteString(fin) - } - default: - fmt.Fprint(buf, v) - } -} - -func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) { - var buf bytes.Buffer - fmt.Fprintf(&buf, "%s%s(", c.prefix, method) - if method != "Receive" { - buf.WriteString(commandName) - for _, arg := range args { - buf.WriteString(", ") - c.printValue(&buf, arg) - } - } - buf.WriteString(") -> (") - if method != "Send" { - c.printValue(&buf, reply) - buf.WriteString(", ") - } - fmt.Fprintf(&buf, "%v)", err) - c.logger.Output(3, buf.String()) -} - -func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) { - reply, err := c.Conn.Do(commandName, args...) - c.print("Do", commandName, args, reply, err) - return reply, err -} - -func (c *loggingConn) Send(commandName string, args ...interface{}) error { - err := c.Conn.Send(commandName, args...) - c.print("Send", commandName, args, nil, err) - return err -} - -func (c *loggingConn) Receive() (interface{}, error) { - reply, err := c.Conn.Receive() - c.print("Receive", "", nil, reply, err) - return reply, err -} diff --git a/client/go/redis/pool.go b/client/go/redis/pool.go deleted file mode 100644 index 2e2dac9..0000000 --- a/client/go/redis/pool.go +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "bytes" - "container/list" - "crypto/rand" - "crypto/sha1" - "errors" - "io" - "strconv" - "sync" - "time" -) - -var nowFunc = time.Now // for testing - -// ErrPoolExhausted is returned from a pool connection method (Do, Send, -// Receive, Flush, Err) when the maximum number of database connections in the -// pool has been reached. -var ErrPoolExhausted = errors.New("redigo: connection pool exhausted") - -var errPoolClosed = errors.New("redigo: connection pool closed") - -// Pool maintains a pool of connections. The application calls the Get method -// to get a connection from the pool and the connection's Close method to -// return the connection's resources to the pool. -// -// The following example shows how to use a pool in a web application. The -// application creates a pool at application startup and makes it available to -// request handlers using a global variable. -// -// func newPool(server, password string) *redis.Pool { -// return &redis.Pool{ -// MaxIdle: 3, -// IdleTimeout: 240 * time.Second, -// Dial: func () (redis.Conn, error) { -// c, err := redis.Dial("tcp", server) -// if err != nil { -// return nil, err -// } -// if _, err := c.Do("AUTH", password); err != nil { -// c.Close() -// return nil, err -// } -// return c, err -// }, -// TestOnBorrow: func(c redis.Conn, t time.Time) error { -// _, err := c.Do("PING") -// return err -// }, -// } -// } -// -// var ( -// pool *redis.Pool -// redisServer = flag.String("redisServer", ":6379", "") -// redisPassword = flag.String("redisPassword", "", "") -// ) -// -// func main() { -// flag.Parse() -// pool = newPool(*redisServer, *redisPassword) -// ... -// } -// -// A request handler gets a connection from the pool and closes the connection -// when the handler is done: -// -// func serveHome(w http.ResponseWriter, r *http.Request) { -// conn := pool.Get() -// defer conn.Close() -// .... -// } -// -type Pool struct { - - // Dial is an application supplied function for creating new connections. - Dial func() (Conn, error) - - // TestOnBorrow is an optional application supplied function for checking - // the health of an idle connection before the connection is used again by - // the application. Argument t is the time that the connection was returned - // to the pool. If the function returns an error, then the connection is - // closed. - TestOnBorrow func(c Conn, t time.Time) error - - // Maximum number of idle connections in the pool. - MaxIdle int - - // Maximum number of connections allocated by the pool at a given time. - // When zero, there is no limit on the number of connections in the pool. - MaxActive int - - // Close connections after remaining idle for this duration. If the value - // is zero, then idle connections are not closed. Applications should set - // the timeout to a value less than the server's timeout. - IdleTimeout time.Duration - - // mu protects fields defined below. - mu sync.Mutex - closed bool - active int - - // Stack of idleConn with most recently used at the front. - idle list.List -} - -type idleConn struct { - c Conn - t time.Time -} - -// NewPool is a convenience function for initializing a pool. -func NewPool(newFn func() (Conn, error), maxIdle int) *Pool { - return &Pool{Dial: newFn, MaxIdle: maxIdle} -} - -// Get gets a connection. The application must close the returned connection. -// The connection acquires an underlying connection on the first call to the -// connection Do, Send, Receive, Flush or Err methods. An application can force -// the connection to acquire an underlying connection without executing a Redis -// command by calling the Err method. -func (p *Pool) Get() Conn { - return &pooledConnection{p: p} -} - -// ActiveCount returns the number of active connections in the pool. -func (p *Pool) ActiveCount() int { - p.mu.Lock() - active := p.active - p.mu.Unlock() - return active -} - -// Close releases the resources used by the pool. -func (p *Pool) Close() error { - p.mu.Lock() - idle := p.idle - p.idle.Init() - p.closed = true - p.active -= idle.Len() - p.mu.Unlock() - for e := idle.Front(); e != nil; e = e.Next() { - e.Value.(idleConn).c.Close() - } - return nil -} - -// get prunes stale connections and returns a connection from the idle list or -// creates a new connection. -func (p *Pool) get() (Conn, error) { - p.mu.Lock() - - if p.closed { - p.mu.Unlock() - return nil, errors.New("redigo: get on closed pool") - } - - // Prune stale connections. - - if timeout := p.IdleTimeout; timeout > 0 { - for i, n := 0, p.idle.Len(); i < n; i++ { - e := p.idle.Back() - if e == nil { - break - } - ic := e.Value.(idleConn) - if ic.t.Add(timeout).After(nowFunc()) { - break - } - p.idle.Remove(e) - p.active -= 1 - p.mu.Unlock() - ic.c.Close() - p.mu.Lock() - } - } - - // Get idle connection. - - for i, n := 0, p.idle.Len(); i < n; i++ { - e := p.idle.Front() - if e == nil { - break - } - ic := e.Value.(idleConn) - p.idle.Remove(e) - test := p.TestOnBorrow - p.mu.Unlock() - if test == nil || test(ic.c, ic.t) == nil { - return ic.c, nil - } - ic.c.Close() - p.mu.Lock() - p.active -= 1 - } - - if p.MaxActive > 0 && p.active >= p.MaxActive { - p.mu.Unlock() - return nil, ErrPoolExhausted - } - - // No idle connection, create new. - - dial := p.Dial - p.active += 1 - p.mu.Unlock() - c, err := dial() - if err != nil { - p.mu.Lock() - p.active -= 1 - p.mu.Unlock() - c = nil - } - return c, err -} - -func (p *Pool) put(c Conn, forceClose bool) error { - if c.Err() == nil && !forceClose { - p.mu.Lock() - if !p.closed { - p.idle.PushFront(idleConn{t: nowFunc(), c: c}) - if p.idle.Len() > p.MaxIdle { - c = p.idle.Remove(p.idle.Back()).(idleConn).c - } else { - c = nil - } - } - p.mu.Unlock() - } - if c != nil { - p.mu.Lock() - p.active -= 1 - p.mu.Unlock() - return c.Close() - } - return nil -} - -type pooledConnection struct { - c Conn - err error - p *Pool - state int -} - -func (c *pooledConnection) get() error { - if c.err == nil && c.c == nil { - c.c, c.err = c.p.get() - } - return c.err -} - -var ( - sentinel []byte - sentinelOnce sync.Once -) - -func initSentinel() { - p := make([]byte, 64) - if _, err := rand.Read(p); err == nil { - sentinel = p - } else { - h := sha1.New() - io.WriteString(h, "Oops, rand failed. Use time instead.") - io.WriteString(h, strconv.FormatInt(time.Now().UnixNano(), 10)) - sentinel = h.Sum(nil) - } -} - -func (c *pooledConnection) Close() (err error) { - if c.c != nil { - if c.state&multiState != 0 { - c.c.Send("DISCARD") - c.state &^= (multiState | watchState) - } else if c.state&watchState != 0 { - c.c.Send("UNWATCH") - c.state &^= watchState - } - if c.state&subscribeState != 0 { - c.c.Send("UNSUBSCRIBE") - c.c.Send("PUNSUBSCRIBE") - // To detect the end of the message stream, ask the server to echo - // a sentinel value and read until we see that value. - sentinelOnce.Do(initSentinel) - c.c.Send("ECHO", sentinel) - c.c.Flush() - for { - p, err := c.c.Receive() - if err != nil { - break - } - if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) { - c.state &^= subscribeState - break - } - } - } - c.c.Do("") - c.p.put(c.c, c.state != 0) - c.c = nil - c.err = errPoolClosed - } - return err -} - -func (c *pooledConnection) Err() error { - if err := c.get(); err != nil { - return err - } - return c.c.Err() -} - -func (c *pooledConnection) Do(commandName string, args ...interface{}) (reply interface{}, err error) { - if err := c.get(); err != nil { - return nil, err - } - ci := lookupCommandInfo(commandName) - c.state = (c.state | ci.set) &^ ci.clear - return c.c.Do(commandName, args...) -} - -func (c *pooledConnection) Send(commandName string, args ...interface{}) error { - if err := c.get(); err != nil { - return err - } - ci := lookupCommandInfo(commandName) - c.state = (c.state | ci.set) &^ ci.clear - return c.c.Send(commandName, args...) -} - -func (c *pooledConnection) Flush() error { - if err := c.get(); err != nil { - return err - } - return c.c.Flush() -} - -func (c *pooledConnection) Receive() (reply interface{}, err error) { - if err := c.get(); err != nil { - return nil, err - } - return c.c.Receive() -} diff --git a/client/go/redis/pubsub.go b/client/go/redis/pubsub.go deleted file mode 100644 index f079042..0000000 --- a/client/go/redis/pubsub.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "errors" -) - -// Subscription represents a subscribe or unsubscribe notification. -type Subscription struct { - - // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe" - Kind string - - // The channel that was changed. - Channel string - - // The current number of subscriptions for connection. - Count int -} - -// Message represents a message notification. -type Message struct { - - // The originating channel. - Channel string - - // The message data. - Data []byte -} - -// PMessage represents a pmessage notification. -type PMessage struct { - - // The matched pattern. - Pattern string - - // The originating channel. - Channel string - - // The message data. - Data []byte -} - -// PubSubConn wraps a Conn with convenience methods for subscribers. -type PubSubConn struct { - Conn Conn -} - -// Close closes the connection. -func (c PubSubConn) Close() error { - return c.Conn.Close() -} - -// Subscribe subscribes the connection to the specified channels. -func (c PubSubConn) Subscribe(channel ...interface{}) error { - c.Conn.Send("SUBSCRIBE", channel...) - return c.Conn.Flush() -} - -// PSubscribe subscribes the connection to the given patterns. -func (c PubSubConn) PSubscribe(channel ...interface{}) error { - c.Conn.Send("PSUBSCRIBE", channel...) - return c.Conn.Flush() -} - -// Unsubscribe unsubscribes the connection from the given channels, or from all -// of them if none is given. -func (c PubSubConn) Unsubscribe(channel ...interface{}) error { - c.Conn.Send("UNSUBSCRIBE", channel...) - return c.Conn.Flush() -} - -// PUnsubscribe unsubscribes the connection from the given patterns, or from all -// of them if none is given. -func (c PubSubConn) PUnsubscribe(channel ...interface{}) error { - c.Conn.Send("PUNSUBSCRIBE", channel...) - return c.Conn.Flush() -} - -// Receive returns a pushed message as a Subscription, Message, PMessage or -// error. The return value is intended to be used directly in a type switch as -// illustrated in the PubSubConn example. -func (c PubSubConn) Receive() interface{} { - reply, err := Values(c.Conn.Receive()) - if err != nil { - return err - } - - var kind string - reply, err = Scan(reply, &kind) - if err != nil { - return err - } - - switch kind { - case "message": - var m Message - if _, err := Scan(reply, &m.Channel, &m.Data); err != nil { - return err - } - return m - case "pmessage": - var pm PMessage - if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil { - return err - } - return pm - case "subscribe", "psubscribe", "unsubscribe", "punsubscribe": - s := Subscription{Kind: kind} - if _, err := Scan(reply, &s.Channel, &s.Count); err != nil { - return err - } - return s - } - return errors.New("redigo: unknown pubsub notification") -} diff --git a/client/go/redis/redis.go b/client/go/redis/redis.go deleted file mode 100644 index c90a48e..0000000 --- a/client/go/redis/redis.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -// Error represents an error returned in a command reply. -type Error string - -func (err Error) Error() string { return string(err) } - -// Conn represents a connection to a Redis server. -type Conn interface { - // Close closes the connection. - Close() error - - // Err returns a non-nil value if the connection is broken. The returned - // value is either the first non-nil value returned from the underlying - // network connection or a protocol parsing error. Applications should - // close broken connections. - Err() error - - // Do sends a command to the server and returns the received reply. - Do(commandName string, args ...interface{}) (reply interface{}, err error) - - // Send writes the command to the client's output buffer. - Send(commandName string, args ...interface{}) error - - // Flush flushes the output buffer to the Redis server. - Flush() error - - // Receive receives a single reply from the Redis server - Receive() (reply interface{}, err error) -} diff --git a/client/go/redis/reply.go b/client/go/redis/reply.go deleted file mode 100644 index 161a147..0000000 --- a/client/go/redis/reply.go +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "errors" - "fmt" - "strconv" -) - -// ErrNil indicates that a reply value is nil. -var ErrNil = errors.New("redigo: nil returned") - -// Int is a helper that converts a command reply to an integer. If err is not -// equal to nil, then Int returns 0, err. Otherwise, Int converts the -// reply to an int as follows: -// -// Reply type Result -// integer int(reply), nil -// bulk string parsed reply, nil -// nil 0, ErrNil -// other 0, error -func Int(reply interface{}, err error) (int, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case int64: - x := int(reply) - if int64(x) != reply { - return 0, strconv.ErrRange - } - return x, nil - case []byte: - n, err := strconv.ParseInt(string(reply), 10, 0) - return int(n), err - case nil: - return 0, ErrNil - case Error: - return 0, reply - } - return 0, fmt.Errorf("redigo: unexpected type for Int, got type %T", reply) -} - -// Int64 is a helper that converts a command reply to 64 bit integer. If err is -// not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the -// reply to an int64 as follows: -// -// Reply type Result -// integer reply, nil -// bulk string parsed reply, nil -// nil 0, ErrNil -// other 0, error -func Int64(reply interface{}, err error) (int64, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case int64: - return reply, nil - case []byte: - n, err := strconv.ParseInt(string(reply), 10, 64) - return n, err - case nil: - return 0, ErrNil - case Error: - return 0, reply - } - return 0, fmt.Errorf("redigo: unexpected type for Int64, got type %T", reply) -} - -var errNegativeInt = errors.New("redigo: unexpected value for Uint64") - -// Uint64 is a helper that converts a command reply to 64 bit integer. If err is -// not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the -// reply to an int64 as follows: -// -// Reply type Result -// integer reply, nil -// bulk string parsed reply, nil -// nil 0, ErrNil -// other 0, error -func Uint64(reply interface{}, err error) (uint64, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case int64: - if reply < 0 { - return 0, errNegativeInt - } - return uint64(reply), nil - case []byte: - n, err := strconv.ParseUint(string(reply), 10, 64) - return n, err - case nil: - return 0, ErrNil - case Error: - return 0, reply - } - return 0, fmt.Errorf("redigo: unexpected type for Uint64, got type %T", reply) -} - -// Float64 is a helper that converts a command reply to 64 bit float. If err is -// not equal to nil, then Float64 returns 0, err. Otherwise, Float64 converts -// the reply to an int as follows: -// -// Reply type Result -// bulk string parsed reply, nil -// nil 0, ErrNil -// other 0, error -func Float64(reply interface{}, err error) (float64, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case []byte: - n, err := strconv.ParseFloat(string(reply), 64) - return n, err - case nil: - return 0, ErrNil - case Error: - return 0, reply - } - return 0, fmt.Errorf("redigo: unexpected type for Float64, got type %T", reply) -} - -// String is a helper that converts a command reply to a string. If err is not -// equal to nil, then String returns "", err. Otherwise String converts the -// reply to a string as follows: -// -// Reply type Result -// bulk string string(reply), nil -// simple string reply, nil -// nil "", ErrNil -// other "", error -func String(reply interface{}, err error) (string, error) { - if err != nil { - return "", err - } - switch reply := reply.(type) { - case []byte: - return string(reply), nil - case string: - return reply, nil - case nil: - return "", ErrNil - case Error: - return "", reply - } - return "", fmt.Errorf("redigo: unexpected type for String, got type %T", reply) -} - -// Bytes is a helper that converts a command reply to a slice of bytes. If err -// is not equal to nil, then Bytes returns nil, err. Otherwise Bytes converts -// the reply to a slice of bytes as follows: -// -// Reply type Result -// bulk string reply, nil -// simple string []byte(reply), nil -// nil nil, ErrNil -// other nil, error -func Bytes(reply interface{}, err error) ([]byte, error) { - if err != nil { - return nil, err - } - switch reply := reply.(type) { - case []byte: - return reply, nil - case string: - return []byte(reply), nil - case nil: - return nil, ErrNil - case Error: - return nil, reply - } - return nil, fmt.Errorf("redigo: unexpected type for Bytes, got type %T", reply) -} - -// Bool is a helper that converts a command reply to a boolean. If err is not -// equal to nil, then Bool returns false, err. Otherwise Bool converts the -// reply to boolean as follows: -// -// Reply type Result -// integer value != 0, nil -// bulk string strconv.ParseBool(reply) -// nil false, ErrNil -// other false, error -func Bool(reply interface{}, err error) (bool, error) { - if err != nil { - return false, err - } - switch reply := reply.(type) { - case int64: - return reply != 0, nil - case []byte: - return strconv.ParseBool(string(reply)) - case nil: - return false, ErrNil - case Error: - return false, reply - } - return false, fmt.Errorf("redigo: unexpected type for Bool, got type %T", reply) -} - -// MultiBulk is deprecated. Use Values. -func MultiBulk(reply interface{}, err error) ([]interface{}, error) { return Values(reply, err) } - -// Values is a helper that converts an array command reply to a []interface{}. -// If err is not equal to nil, then Values returns nil, err. Otherwise, Values -// converts the reply as follows: -// -// Reply type Result -// array reply, nil -// nil nil, ErrNil -// other nil, error -func Values(reply interface{}, err error) ([]interface{}, error) { - if err != nil { - return nil, err - } - switch reply := reply.(type) { - case []interface{}: - return reply, nil - case nil: - return nil, ErrNil - case Error: - return nil, reply - } - return nil, fmt.Errorf("redigo: unexpected type for Values, got type %T", reply) -} - -// Strings is a helper that converts an array command reply to a []string. If -// err is not equal to nil, then Strings returns nil, err. If one of the array -// items is not a bulk string or nil, then Strings returns an error. -func Strings(reply interface{}, err error) ([]string, error) { - if err != nil { - return nil, err - } - switch reply := reply.(type) { - case []interface{}: - result := make([]string, len(reply)) - for i := range reply { - if reply[i] == nil { - continue - } - p, ok := reply[i].([]byte) - if !ok { - return nil, fmt.Errorf("redigo: unexpected element type for Strings, got type %T", reply[i]) - } - result[i] = string(p) - } - return result, nil - case nil: - return nil, ErrNil - case Error: - return nil, reply - } - return nil, fmt.Errorf("redigo: unexpected type for Strings, got type %T", reply) -} diff --git a/client/go/redis/scan.go b/client/go/redis/scan.go deleted file mode 100644 index 8c9cfa1..0000000 --- a/client/go/redis/scan.go +++ /dev/null @@ -1,513 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "errors" - "fmt" - "reflect" - "strconv" - "strings" - "sync" -) - -func ensureLen(d reflect.Value, n int) { - if n > d.Cap() { - d.Set(reflect.MakeSlice(d.Type(), n, n)) - } else { - d.SetLen(n) - } -} - -func cannotConvert(d reflect.Value, s interface{}) error { - return fmt.Errorf("redigo: Scan cannot convert from %s to %s", - reflect.TypeOf(s), d.Type()) -} - -func convertAssignBytes(d reflect.Value, s []byte) (err error) { - switch d.Type().Kind() { - case reflect.Float32, reflect.Float64: - var x float64 - x, err = strconv.ParseFloat(string(s), d.Type().Bits()) - d.SetFloat(x) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - var x int64 - x, err = strconv.ParseInt(string(s), 10, d.Type().Bits()) - d.SetInt(x) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - var x uint64 - x, err = strconv.ParseUint(string(s), 10, d.Type().Bits()) - d.SetUint(x) - case reflect.Bool: - var x bool - x, err = strconv.ParseBool(string(s)) - d.SetBool(x) - case reflect.String: - d.SetString(string(s)) - case reflect.Slice: - if d.Type().Elem().Kind() != reflect.Uint8 { - err = cannotConvert(d, s) - } else { - d.SetBytes(s) - } - default: - err = cannotConvert(d, s) - } - return -} - -func convertAssignInt(d reflect.Value, s int64) (err error) { - switch d.Type().Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - d.SetInt(s) - if d.Int() != s { - err = strconv.ErrRange - d.SetInt(0) - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - if s < 0 { - err = strconv.ErrRange - } else { - x := uint64(s) - d.SetUint(x) - if d.Uint() != x { - err = strconv.ErrRange - d.SetUint(0) - } - } - case reflect.Bool: - d.SetBool(s != 0) - default: - err = cannotConvert(d, s) - } - return -} - -func convertAssignValue(d reflect.Value, s interface{}) (err error) { - switch s := s.(type) { - case []byte: - err = convertAssignBytes(d, s) - case int64: - err = convertAssignInt(d, s) - default: - err = cannotConvert(d, s) - } - return err -} - -func convertAssignValues(d reflect.Value, s []interface{}) error { - if d.Type().Kind() != reflect.Slice { - return cannotConvert(d, s) - } - ensureLen(d, len(s)) - for i := 0; i < len(s); i++ { - if err := convertAssignValue(d.Index(i), s[i]); err != nil { - return err - } - } - return nil -} - -func convertAssign(d interface{}, s interface{}) (err error) { - // Handle the most common destination types using type switches and - // fall back to reflection for all other types. - switch s := s.(type) { - case nil: - // ingore - case []byte: - switch d := d.(type) { - case *string: - *d = string(s) - case *int: - *d, err = strconv.Atoi(string(s)) - case *bool: - *d, err = strconv.ParseBool(string(s)) - case *[]byte: - *d = s - case *interface{}: - *d = s - case nil: - // skip value - default: - if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr { - err = cannotConvert(d, s) - } else { - err = convertAssignBytes(d.Elem(), s) - } - } - case int64: - switch d := d.(type) { - case *int: - x := int(s) - if int64(x) != s { - err = strconv.ErrRange - x = 0 - } - *d = x - case *bool: - *d = s != 0 - case *interface{}: - *d = s - case nil: - // skip value - default: - if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr { - err = cannotConvert(d, s) - } else { - err = convertAssignInt(d.Elem(), s) - } - } - case []interface{}: - switch d := d.(type) { - case *[]interface{}: - *d = s - case *interface{}: - *d = s - case nil: - // skip value - default: - if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr { - err = cannotConvert(d, s) - } else { - err = convertAssignValues(d.Elem(), s) - } - } - case Error: - err = s - default: - err = cannotConvert(reflect.ValueOf(d), s) - } - return -} - -// Scan copies from src to the values pointed at by dest. -// -// The values pointed at by dest must be an integer, float, boolean, string, -// []byte, interface{} or slices of these types. Scan uses the standard strconv -// package to convert bulk strings to numeric and boolean types. -// -// If a dest value is nil, then the corresponding src value is skipped. -// -// If a src element is nil, then the corresponding dest value is not modified. -// -// To enable easy use of Scan in a loop, Scan returns the slice of src -// following the copied values. -func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) { - if len(src) < len(dest) { - return nil, errors.New("redigo: Scan array short") - } - var err error - for i, d := range dest { - err = convertAssign(d, src[i]) - if err != nil { - break - } - } - return src[len(dest):], err -} - -type fieldSpec struct { - name string - index []int - //omitEmpty bool -} - -type structSpec struct { - m map[string]*fieldSpec - l []*fieldSpec -} - -func (ss *structSpec) fieldSpec(name []byte) *fieldSpec { - return ss.m[string(name)] -} - -func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec) { - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - switch { - case f.PkgPath != "": - // Ignore unexported fields. - case f.Anonymous: - // TODO: Handle pointers. Requires change to decoder and - // protection against infinite recursion. - if f.Type.Kind() == reflect.Struct { - compileStructSpec(f.Type, depth, append(index, i), ss) - } - default: - fs := &fieldSpec{name: f.Name} - tag := f.Tag.Get("redis") - p := strings.Split(tag, ",") - if len(p) > 0 { - if p[0] == "-" { - continue - } - if len(p[0]) > 0 { - fs.name = p[0] - } - for _, s := range p[1:] { - switch s { - //case "omitempty": - // fs.omitempty = true - default: - panic(errors.New("redigo: unknown field flag " + s + " for type " + t.Name())) - } - } - } - d, found := depth[fs.name] - if !found { - d = 1 << 30 - } - switch { - case len(index) == d: - // At same depth, remove from result. - delete(ss.m, fs.name) - j := 0 - for i := 0; i < len(ss.l); i++ { - if fs.name != ss.l[i].name { - ss.l[j] = ss.l[i] - j += 1 - } - } - ss.l = ss.l[:j] - case len(index) < d: - fs.index = make([]int, len(index)+1) - copy(fs.index, index) - fs.index[len(index)] = i - depth[fs.name] = len(index) - ss.m[fs.name] = fs - ss.l = append(ss.l, fs) - } - } - } -} - -var ( - structSpecMutex sync.RWMutex - structSpecCache = make(map[reflect.Type]*structSpec) - defaultFieldSpec = &fieldSpec{} -) - -func structSpecForType(t reflect.Type) *structSpec { - - structSpecMutex.RLock() - ss, found := structSpecCache[t] - structSpecMutex.RUnlock() - if found { - return ss - } - - structSpecMutex.Lock() - defer structSpecMutex.Unlock() - ss, found = structSpecCache[t] - if found { - return ss - } - - ss = &structSpec{m: make(map[string]*fieldSpec)} - compileStructSpec(t, make(map[string]int), nil, ss) - structSpecCache[t] = ss - return ss -} - -var errScanStructValue = errors.New("redigo: ScanStruct value must be non-nil pointer to a struct") - -// ScanStruct scans alternating names and values from src to a struct. The -// HGETALL and CONFIG GET commands return replies in this format. -// -// ScanStruct uses exported field names to match values in the response. Use -// 'redis' field tag to override the name: -// -// Field int `redis:"myName"` -// -// Fields with the tag redis:"-" are ignored. -// -// Integer, float, boolean, string and []byte fields are supported. Scan uses the -// standard strconv package to convert bulk string values to numeric and -// boolean types. -// -// If a src element is nil, then the corresponding field is not modified. -func ScanStruct(src []interface{}, dest interface{}) error { - d := reflect.ValueOf(dest) - if d.Kind() != reflect.Ptr || d.IsNil() { - return errScanStructValue - } - d = d.Elem() - if d.Kind() != reflect.Struct { - return errScanStructValue - } - ss := structSpecForType(d.Type()) - - if len(src)%2 != 0 { - return errors.New("redigo: ScanStruct expects even number of values in values") - } - - for i := 0; i < len(src); i += 2 { - s := src[i+1] - if s == nil { - continue - } - name, ok := src[i].([]byte) - if !ok { - return errors.New("redigo: ScanStruct key not a bulk string value") - } - fs := ss.fieldSpec(name) - if fs == nil { - continue - } - if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil { - return err - } - } - return nil -} - -var ( - errScanSliceValue = errors.New("redigo: ScanSlice dest must be non-nil pointer to a struct") -) - -// ScanSlice scans src to the slice pointed to by dest. The elements the dest -// slice must be integer, float, boolean, string, struct or pointer to struct -// values. -// -// Struct fields must be integer, float, boolean or string values. All struct -// fields are used unless a subset is specified using fieldNames. -func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error { - d := reflect.ValueOf(dest) - if d.Kind() != reflect.Ptr || d.IsNil() { - return errScanSliceValue - } - d = d.Elem() - if d.Kind() != reflect.Slice { - return errScanSliceValue - } - - isPtr := false - t := d.Type().Elem() - if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct { - isPtr = true - t = t.Elem() - } - - if t.Kind() != reflect.Struct { - ensureLen(d, len(src)) - for i, s := range src { - if s == nil { - continue - } - if err := convertAssignValue(d.Index(i), s); err != nil { - return err - } - } - return nil - } - - ss := structSpecForType(t) - fss := ss.l - if len(fieldNames) > 0 { - fss = make([]*fieldSpec, len(fieldNames)) - for i, name := range fieldNames { - fss[i] = ss.m[name] - if fss[i] == nil { - return errors.New("redigo: ScanSlice bad field name " + name) - } - } - } - - if len(fss) == 0 { - return errors.New("redigo: ScanSlice no struct fields") - } - - n := len(src) / len(fss) - if n*len(fss) != len(src) { - return errors.New("redigo: ScanSlice length not a multiple of struct field count") - } - - ensureLen(d, n) - for i := 0; i < n; i++ { - d := d.Index(i) - if isPtr { - if d.IsNil() { - d.Set(reflect.New(t)) - } - d = d.Elem() - } - for j, fs := range fss { - s := src[i*len(fss)+j] - if s == nil { - continue - } - if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil { - return err - } - } - } - return nil -} - -// Args is a helper for constructing command arguments from structured values. -type Args []interface{} - -// Add returns the result of appending value to args. -func (args Args) Add(value ...interface{}) Args { - return append(args, value...) -} - -// AddFlat returns the result of appending the flattened value of v to args. -// -// Maps are flattened by appending the alternating keys and map values to args. -// -// Slices are flattened by appending the slice elements to args. -// -// Structs are flattened by appending the alternating names and values of -// exported fields to args. If v is a nil struct pointer, then nothing is -// appended. The 'redis' field tag overrides struct field names. See ScanStruct -// for more information on the use of the 'redis' field tag. -// -// Other types are appended to args as is. -func (args Args) AddFlat(v interface{}) Args { - rv := reflect.ValueOf(v) - switch rv.Kind() { - case reflect.Struct: - args = flattenStruct(args, rv) - case reflect.Slice: - for i := 0; i < rv.Len(); i++ { - args = append(args, rv.Index(i).Interface()) - } - case reflect.Map: - for _, k := range rv.MapKeys() { - args = append(args, k.Interface(), rv.MapIndex(k).Interface()) - } - case reflect.Ptr: - if rv.Type().Elem().Kind() == reflect.Struct { - if !rv.IsNil() { - args = flattenStruct(args, rv.Elem()) - } - } else { - args = append(args, v) - } - default: - args = append(args, v) - } - return args -} - -func flattenStruct(args Args, v reflect.Value) Args { - ss := structSpecForType(v.Type()) - for _, fs := range ss.l { - fv := v.FieldByIndex(fs.index) - args = append(args, fs.name, fv.Interface()) - } - return args -} diff --git a/client/go/redis/script.go b/client/go/redis/script.go deleted file mode 100644 index 2417753..0000000 --- a/client/go/redis/script.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "crypto/sha1" - "encoding/hex" - "io" - "strings" -) - -// Script encapsulates the source, hash and key count for a Lua script. See -// http://redis.io/commands/eval for information on scripts in Redis. -type Script struct { - keyCount int - src string - hash string -} - -// NewScript returns a new script object. If keyCount is greater than or equal -// to zero, then the count is automatically inserted in the EVAL command -// argument list. If keyCount is less than zero, then the application supplies -// the count as the first value in the keysAndArgs argument to the Do, Send and -// SendHash methods. -func NewScript(keyCount int, src string) *Script { - h := sha1.New() - io.WriteString(h, src) - return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))} -} - -func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} { - var args []interface{} - if s.keyCount < 0 { - args = make([]interface{}, 1+len(keysAndArgs)) - args[0] = spec - copy(args[1:], keysAndArgs) - } else { - args = make([]interface{}, 2+len(keysAndArgs)) - args[0] = spec - args[1] = s.keyCount - copy(args[2:], keysAndArgs) - } - return args -} - -// Do evalutes the script. Under the covers, Do optimistically evaluates the -// script using the EVALSHA command. If the command fails because the script is -// not loaded, then Do evaluates the script using the EVAL command (thus -// causing the script to load). -func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) { - v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...) - if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") { - v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...) - } - return v, err -} - -// SendHash evaluates the script without waiting for the reply. The script is -// evaluated with the EVALSHA command. The application must ensure that the -// script is loaded by a previous call to Send, Do or Load methods. -func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error { - return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...) -} - -// Send evaluates the script without waiting for the reply. -func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error { - return c.Send("EVAL", s.args(s.src, keysAndArgs)...) -} - -// Load loads the script without evaluating it. -func (s *Script) Load(c Conn) error { - _, err := c.Do("SCRIPT", "LOAD", s.src) - return err -} diff --git a/cmd/ledis-benchmark/main.go b/cmd/ledis-benchmark/main.go index 9209dd7..4f01242 100644 --- a/cmd/ledis-benchmark/main.go +++ b/cmd/ledis-benchmark/main.go @@ -3,7 +3,7 @@ package main import ( "flag" "fmt" - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "math/rand" "sync" "time" @@ -16,14 +16,14 @@ var clients = flag.Int("c", 50, "number of clients") var wg sync.WaitGroup -var pool *redis.Pool +var client *ledis.Client var loop int = 0 func waitBench(cmd string, args ...interface{}) { defer wg.Done() - c := pool.Get() + c := client.Get() defer c.Close() for i := 0; i < loop; i++ { @@ -234,15 +234,9 @@ func main() { addr := fmt.Sprintf("%s:%d", *ip, *port) - f := func() (redis.Conn, error) { - c, err := redis.Dial("tcp", addr) - if err != nil { - return nil, err - } - - return c, nil - } - pool = redis.NewPool(f, *clients) + cfg := new(ledis.Config) + cfg.Addr = addr + client = ledis.NewClient(cfg) benchSet() benchIncr() diff --git a/server/app_test.go b/server/app_test.go index 6ae909a..b4db346 100644 --- a/server/app_test.go +++ b/server/app_test.go @@ -1,7 +1,7 @@ package server import ( - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "os" "sync" "testing" @@ -10,29 +10,23 @@ import ( var testAppOnce sync.Once var testApp *App -var testPool *redis.Pool +var testLedisClient *ledis.Client -func newTestRedisPool() { - f := func() (redis.Conn, error) { - c, err := redis.Dial("tcp", "127.0.0.1:16380") - if err != nil { - return nil, err - } - - return c, nil - } - - testPool = redis.NewPool(f, 4) +func newTestLedisClient() { + cfg := new(ledis.Config) + cfg.Addr = "127.0.0.1:16380" + cfg.MaxIdleConns = 4 + testLedisClient = ledis.NewClient(cfg) } -func getTestConn() redis.Conn { +func getTestConn() *ledis.Conn { startTestApp() - return testPool.Get() + return testLedisClient.Get() } func startTestApp() { f := func() { - newTestRedisPool() + newTestLedisClient() os.RemoveAll("/tmp/testdb") diff --git a/server/cmd_hash_test.go b/server/cmd_hash_test.go index 3894386..6b3cae3 100644 --- a/server/cmd_hash_test.go +++ b/server/cmd_hash_test.go @@ -2,7 +2,7 @@ package server import ( "fmt" - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "strconv" "testing" ) @@ -12,43 +12,43 @@ func TestHash(t *testing.T) { defer c.Close() key := []byte("a") - if n, err := redis.Int(c.Do("hset", key, 1, 0)); err != nil { + if n, err := ledis.Int(c.Do("hset", key, 1, 0)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hexists", key, 1)); err != nil { + if n, err := ledis.Int(c.Do("hexists", key, 1)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hexists", key, -1)); err != nil { + if n, err := ledis.Int(c.Do("hexists", key, -1)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hget", key, 1)); err != nil { + if n, err := ledis.Int(c.Do("hget", key, 1)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hset", key, 1, 1)); err != nil { + if n, err := ledis.Int(c.Do("hset", key, 1, 1)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hget", key, 1)); err != nil { + if n, err := ledis.Int(c.Do("hget", key, 1)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) @@ -84,19 +84,19 @@ func TestHashM(t *testing.T) { defer c.Close() key := []byte("b") - if ok, err := redis.String(c.Do("hmset", key, 1, 1, 2, 2, 3, 3)); err != nil { + if ok, err := ledis.String(c.Do("hmset", key, 1, 1, 2, 2, 3, 3)); err != nil { t.Fatal(err) } else if ok != OK { t.Fatal(ok) } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if v, err := redis.MultiBulk(c.Do("hmget", key, 1, 2, 3, 4)); err != nil { + if v, err := ledis.MultiBulk(c.Do("hmget", key, 1, 2, 3, 4)); err != nil { t.Fatal(err) } else { if err := testHashArray(v, 1, 2, 3, 0); err != nil { @@ -104,19 +104,19 @@ func TestHashM(t *testing.T) { } } - if n, err := redis.Int(c.Do("hdel", key, 1, 2, 3, 4)); err != nil { + if n, err := ledis.Int(c.Do("hdel", key, 1, 2, 3, 4)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if v, err := redis.MultiBulk(c.Do("hmget", key, 1, 2, 3, 4)); err != nil { + if v, err := ledis.MultiBulk(c.Do("hmget", key, 1, 2, 3, 4)); err != nil { t.Fatal(err) } else { if err := testHashArray(v, 0, 0, 0, 0); err != nil { @@ -124,7 +124,7 @@ func TestHashM(t *testing.T) { } } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) @@ -136,31 +136,31 @@ func TestHashIncr(t *testing.T) { defer c.Close() key := []byte("c") - if n, err := redis.Int(c.Do("hincrby", key, 1, 1)); err != nil { + if n, err := ledis.Int(c.Do("hincrby", key, 1, 1)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(err) } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hincrby", key, 1, 10)); err != nil { + if n, err := ledis.Int(c.Do("hincrby", key, 1, 10)); err != nil { t.Fatal(err) } else if n != 11 { t.Fatal(err) } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hincrby", key, 1, -11)); err != nil { + if n, err := ledis.Int(c.Do("hincrby", key, 1, -11)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(err) @@ -174,13 +174,13 @@ func TestHashGetAll(t *testing.T) { key := []byte("d") - if ok, err := redis.String(c.Do("hmset", key, 1, 1, 2, 2, 3, 3)); err != nil { + if ok, err := ledis.String(c.Do("hmset", key, 1, 1, 2, 2, 3, 3)); err != nil { t.Fatal(err) } else if ok != OK { t.Fatal(ok) } - if v, err := redis.MultiBulk(c.Do("hgetall", key)); err != nil { + if v, err := ledis.MultiBulk(c.Do("hgetall", key)); err != nil { t.Fatal(err) } else { if err := testHashArray(v, 1, 1, 2, 2, 3, 3); err != nil { @@ -188,7 +188,7 @@ func TestHashGetAll(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("hkeys", key)); err != nil { + if v, err := ledis.MultiBulk(c.Do("hkeys", key)); err != nil { t.Fatal(err) } else { if err := testHashArray(v, 1, 2, 3); err != nil { @@ -196,7 +196,7 @@ func TestHashGetAll(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("hvals", key)); err != nil { + if v, err := ledis.MultiBulk(c.Do("hvals", key)); err != nil { t.Fatal(err) } else { if err := testHashArray(v, 1, 2, 3); err != nil { @@ -204,13 +204,13 @@ func TestHashGetAll(t *testing.T) { } } - if n, err := redis.Int(c.Do("hclear", key)); err != nil { + if n, err := ledis.Int(c.Do("hclear", key)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if n, err := redis.Int(c.Do("hlen", key)); err != nil { + if n, err := ledis.Int(c.Do("hlen", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) diff --git a/server/cmd_kv_test.go b/server/cmd_kv_test.go index 91e0126..4f3cf23 100644 --- a/server/cmd_kv_test.go +++ b/server/cmd_kv_test.go @@ -1,7 +1,7 @@ package server import ( - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "testing" ) @@ -9,65 +9,65 @@ func TestKV(t *testing.T) { c := getTestConn() defer c.Close() - if ok, err := redis.String(c.Do("set", "a", "1234")); err != nil { + if ok, err := ledis.String(c.Do("set", "a", "1234")); err != nil { t.Fatal(err) } else if ok != OK { t.Fatal(ok) } - if n, err := redis.Int(c.Do("setnx", "a", "123")); err != nil { + if n, err := ledis.Int(c.Do("setnx", "a", "123")); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("setnx", "b", "123")); err != nil { + if n, err := ledis.Int(c.Do("setnx", "b", "123")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if v, err := redis.String(c.Do("get", "a")); err != nil { + if v, err := ledis.String(c.Do("get", "a")); err != nil { t.Fatal(err) } else if v != "1234" { t.Fatal(v) } - if v, err := redis.String(c.Do("getset", "a", "123")); err != nil { + if v, err := ledis.String(c.Do("getset", "a", "123")); err != nil { t.Fatal(err) } else if v != "1234" { t.Fatal(v) } - if v, err := redis.String(c.Do("get", "a")); err != nil { + if v, err := ledis.String(c.Do("get", "a")); err != nil { t.Fatal(err) } else if v != "123" { t.Fatal(v) } - if n, err := redis.Int(c.Do("exists", "a")); err != nil { + if n, err := ledis.Int(c.Do("exists", "a")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("exists", "empty_key_test")); err != nil { + if n, err := ledis.Int(c.Do("exists", "empty_key_test")); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if _, err := redis.Int(c.Do("del", "a", "b")); err != nil { + if _, err := ledis.Int(c.Do("del", "a", "b")); err != nil { t.Fatal(err) } - if n, err := redis.Int(c.Do("exists", "a")); err != nil { + if n, err := ledis.Int(c.Do("exists", "a")); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("exists", "b")); err != nil { + if n, err := ledis.Int(c.Do("exists", "b")); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) @@ -78,13 +78,13 @@ func TestKVM(t *testing.T) { c := getTestConn() defer c.Close() - if ok, err := redis.String(c.Do("mset", "a", "1", "b", "2")); err != nil { + if ok, err := ledis.String(c.Do("mset", "a", "1", "b", "2")); err != nil { t.Fatal(err) } else if ok != OK { t.Fatal(ok) } - if v, err := redis.MultiBulk(c.Do("mget", "a", "b", "c")); err != nil { + if v, err := ledis.MultiBulk(c.Do("mget", "a", "b", "c")); err != nil { t.Fatal(err) } else if len(v) != 3 { t.Fatal(len(v)) @@ -107,31 +107,31 @@ func TestKVIncrDecr(t *testing.T) { c := getTestConn() defer c.Close() - if n, err := redis.Int64(c.Do("incr", "n")); err != nil { + if n, err := ledis.Int64(c.Do("incr", "n")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int64(c.Do("incr", "n")); err != nil { + if n, err := ledis.Int64(c.Do("incr", "n")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int64(c.Do("decr", "n")); err != nil { + if n, err := ledis.Int64(c.Do("decr", "n")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int64(c.Do("incrby", "n", 10)); err != nil { + if n, err := ledis.Int64(c.Do("incrby", "n", 10)); err != nil { t.Fatal(err) } else if n != 11 { t.Fatal(n) } - if n, err := redis.Int64(c.Do("decrby", "n", 10)); err != nil { + if n, err := ledis.Int64(c.Do("decrby", "n", 10)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) diff --git a/server/cmd_list_test.go b/server/cmd_list_test.go index c970052..a319f7b 100644 --- a/server/cmd_list_test.go +++ b/server/cmd_list_test.go @@ -2,7 +2,7 @@ package server import ( "fmt" - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "strconv" "testing" ) @@ -11,10 +11,10 @@ func testListIndex(key []byte, index int64, v int) error { c := getTestConn() defer c.Close() - n, err := redis.Int(c.Do("lindex", key, index)) - if err == redis.ErrNil && v != 0 { + n, err := ledis.Int(c.Do("lindex", key, index)) + if err == ledis.ErrNil && v != 0 { return fmt.Errorf("must nil") - } else if err != nil && err != redis.ErrNil { + } else if err != nil && err != ledis.ErrNil { return err } else if n != v { return fmt.Errorf("index err number %d != %d", n, v) @@ -27,7 +27,7 @@ func testListRange(key []byte, start int64, stop int64, checkValues ...int) erro c := getTestConn() defer c.Close() - vs, err := redis.MultiBulk(c.Do("lrange", key, start, stop)) + vs, err := ledis.MultiBulk(c.Do("lrange", key, start, stop)) if err != nil { return err } @@ -59,31 +59,31 @@ func TestList(t *testing.T) { key := []byte("a") - if n, err := redis.Int(c.Do("lpush", key, 1)); err != nil { + if n, err := ledis.Int(c.Do("lpush", key, 1)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("rpush", key, 2)); err != nil { + if n, err := ledis.Int(c.Do("rpush", key, 2)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("rpush", key, 3)); err != nil { + if n, err := ledis.Int(c.Do("rpush", key, 3)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if n, err := redis.Int(c.Do("llen", key)); err != nil { + if n, err := ledis.Int(c.Do("llen", key)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - //for redis-cli a 1 2 3 + //for ledis-cli a 1 2 3 // 127.0.0.1:6379> lrange a 0 0 // 1) "1" if err := testListRange(key, 0, 0, 1); err != nil { @@ -201,7 +201,7 @@ func TestListMPush(t *testing.T) { defer c.Close() key := []byte("b") - if n, err := redis.Int(c.Do("rpush", key, 1, 2, 3)); err != nil { + if n, err := ledis.Int(c.Do("rpush", key, 1, 2, 3)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) @@ -211,7 +211,7 @@ func TestListMPush(t *testing.T) { t.Fatal(err) } - if n, err := redis.Int(c.Do("lpush", key, 1, 2, 3)); err != nil { + if n, err := ledis.Int(c.Do("lpush", key, 1, 2, 3)); err != nil { t.Fatal(err) } else if n != 6 { t.Fatal(n) @@ -227,25 +227,25 @@ func TestPop(t *testing.T) { defer c.Close() key := []byte("c") - if n, err := redis.Int(c.Do("rpush", key, 1, 2, 3, 4, 5, 6)); err != nil { + if n, err := ledis.Int(c.Do("rpush", key, 1, 2, 3, 4, 5, 6)); err != nil { t.Fatal(err) } else if n != 6 { t.Fatal(n) } - if v, err := redis.Int(c.Do("lpop", key)); err != nil { + if v, err := ledis.Int(c.Do("lpop", key)); err != nil { t.Fatal(err) } else if v != 1 { t.Fatal(v) } - if v, err := redis.Int(c.Do("rpop", key)); err != nil { + if v, err := ledis.Int(c.Do("rpop", key)); err != nil { t.Fatal(err) } else if v != 6 { t.Fatal(v) } - if n, err := redis.Int(c.Do("lpush", key, 1)); err != nil { + if n, err := ledis.Int(c.Do("lpush", key, 1)); err != nil { t.Fatal(err) } else if n != 5 { t.Fatal(n) @@ -256,14 +256,14 @@ func TestPop(t *testing.T) { } for i := 1; i <= 5; i++ { - if v, err := redis.Int(c.Do("lpop", key)); err != nil { + if v, err := ledis.Int(c.Do("lpop", key)); err != nil { t.Fatal(err) } else if v != i { t.Fatal(v) } } - if n, err := redis.Int(c.Do("llen", key)); err != nil { + if n, err := ledis.Int(c.Do("llen", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) @@ -271,13 +271,13 @@ func TestPop(t *testing.T) { c.Do("rpush", key, 1, 2, 3, 4, 5) - if n, err := redis.Int(c.Do("lclear", key)); err != nil { + if n, err := ledis.Int(c.Do("lclear", key)); err != nil { t.Fatal(err) } else if n != 5 { t.Fatal(n) } - if n, err := redis.Int(c.Do("llen", key)); err != nil { + if n, err := ledis.Int(c.Do("llen", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) diff --git a/server/cmd_ttl_test.go b/server/cmd_ttl_test.go index 7a1f1f4..c312ba7 100644 --- a/server/cmd_ttl_test.go +++ b/server/cmd_ttl_test.go @@ -1,7 +1,7 @@ package server import ( - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "testing" "time" ) @@ -19,13 +19,13 @@ func TestKVExpire(t *testing.T) { // expire + ttl exp := int64(10) - if n, err := redis.Int(c.Do("expire", k, exp)); err != nil { + if n, err := ledis.Int(c.Do("expire", k, exp)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if ttl, err := redis.Int64(c.Do("ttl", k)); err != nil { + if ttl, err := ledis.Int64(c.Do("ttl", k)); err != nil { t.Fatal(err) } else if ttl != exp { t.Fatal(ttl) @@ -33,13 +33,13 @@ func TestKVExpire(t *testing.T) { // expireat + ttl tm := now() + 3 - if n, err := redis.Int(c.Do("expireat", k, tm)); err != nil { + if n, err := ledis.Int(c.Do("expireat", k, tm)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if ttl, err := redis.Int64(c.Do("ttl", k)); err != nil { + if ttl, err := ledis.Int64(c.Do("ttl", k)); err != nil { t.Fatal(err) } else if ttl != 3 { t.Fatal(ttl) @@ -48,15 +48,15 @@ func TestKVExpire(t *testing.T) { kErr := "not_exist_ttl" // err - expire, expireat - if n, err := redis.Int(c.Do("expire", kErr, tm)); err != nil || n != 0 { + if n, err := ledis.Int(c.Do("expire", kErr, tm)); err != nil || n != 0 { t.Fatal(false) } - if n, err := redis.Int(c.Do("expireat", kErr, tm)); err != nil || n != 0 { + if n, err := ledis.Int(c.Do("expireat", kErr, tm)); err != nil || n != 0 { t.Fatal(false) } - if n, err := redis.Int(c.Do("ttl", kErr)); err != nil || n != -1 { + if n, err := ledis.Int(c.Do("ttl", kErr)); err != nil || n != -1 { t.Fatal(false) } diff --git a/server/cmd_zset.go b/server/cmd_zset.go index dfc24f8..4004134 100644 --- a/server/cmd_zset.go +++ b/server/cmd_zset.go @@ -377,7 +377,7 @@ func zrangebyscoreGeneric(c *client, reverse bool) error { } if offset < 0 { - //for redis, if offset < 0, a empty will return + //for ledis, if offset < 0, a empty will return //so here we directly return a empty array c.writeArray([]interface{}{}) return nil diff --git a/server/cmd_zset_test.go b/server/cmd_zset_test.go index fc5b9e0..69664cf 100644 --- a/server/cmd_zset_test.go +++ b/server/cmd_zset_test.go @@ -2,7 +2,7 @@ package server import ( "fmt" - "github.com/siddontang/ledisdb/client/go/redis" + "github.com/siddontang/ledisdb/client/go/ledis" "strconv" "testing" ) @@ -12,91 +12,91 @@ func TestZSet(t *testing.T) { defer c.Close() key := []byte("myzset") - if n, err := redis.Int(c.Do("zadd", key, 3, "a", 4, "b")); err != nil { + if n, err := ledis.Int(c.Do("zadd", key, 3, "a", 4, "b")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(n) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zadd", key, 1, "a", 2, "b")); err != nil { + if n, err := ledis.Int(c.Do("zadd", key, 1, "a", 2, "b")); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(n) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zadd", key, 3, "c", 4, "d")); err != nil { + if n, err := ledis.Int(c.Do("zadd", key, 3, "c", 4, "d")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 4 { t.Fatal(n) } - if s, err := redis.Int(c.Do("zscore", key, "c")); err != nil { + if s, err := ledis.Int(c.Do("zscore", key, "c")); err != nil { t.Fatal(err) } else if s != 3 { t.Fatal(s) } - if n, err := redis.Int(c.Do("zrem", key, "d", "e")); err != nil { + if n, err := ledis.Int(c.Do("zrem", key, "d", "e")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zincrby", key, 4, "c")); err != nil { + if n, err := ledis.Int(c.Do("zincrby", key, 4, "c")); err != nil { t.Fatal(err) } else if n != 7 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zincrby", key, -4, "c")); err != nil { + if n, err := ledis.Int(c.Do("zincrby", key, -4, "c")); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zincrby", key, 4, "d")); err != nil { + if n, err := ledis.Int(c.Do("zincrby", key, 4, "d")); err != nil { t.Fatal(err) } else if n != 4 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 4 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zrem", key, "a", "b", "c", "d")); err != nil { + if n, err := ledis.Int(c.Do("zrem", key, "a", "b", "c", "d")); err != nil { t.Fatal(err) } else if n != 4 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) @@ -109,47 +109,47 @@ func TestZSetCount(t *testing.T) { defer c.Close() key := []byte("myzset") - if _, err := redis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { + if _, err := ledis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { t.Fatal(err) } - if n, err := redis.Int(c.Do("zcount", key, 2, 4)); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, 2, 4)); err != nil { t.Fatal(err) } else if n != 3 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcount", key, 4, 4)); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, 4, 4)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcount", key, 4, 3)); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, 4, 3)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcount", key, "(2", 4)); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, "(2", 4)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcount", key, "2", "(4")); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, "2", "(4")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcount", key, "(2", "(4")); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, "(2", "(4")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcount", key, "-inf", "+inf")); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, "-inf", "+inf")); err != nil { t.Fatal(err) } else if n != 4 { t.Fatal(n) @@ -157,7 +157,7 @@ func TestZSetCount(t *testing.T) { c.Do("zadd", key, 3, "e") - if n, err := redis.Int(c.Do("zcount", key, "(2", "(4")); err != nil { + if n, err := ledis.Int(c.Do("zcount", key, "(2", "(4")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) @@ -171,27 +171,27 @@ func TestZSetRank(t *testing.T) { defer c.Close() key := []byte("myzset") - if _, err := redis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { + if _, err := ledis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { t.Fatal(err) } - if n, err := redis.Int(c.Do("zrank", key, "c")); err != nil { + if n, err := ledis.Int(c.Do("zrank", key, "c")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if _, err := redis.Int(c.Do("zrank", key, "e")); err != redis.ErrNil { + if _, err := ledis.Int(c.Do("zrank", key, "e")); err != ledis.ErrNil { t.Fatal(err) } - if n, err := redis.Int(c.Do("zrevrank", key, "c")); err != nil { + if n, err := ledis.Int(c.Do("zrevrank", key, "c")); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } - if _, err := redis.Int(c.Do("zrevrank", key, "e")); err != redis.ErrNil { + if _, err := ledis.Int(c.Do("zrevrank", key, "e")); err != ledis.ErrNil { t.Fatal(err) } } @@ -228,11 +228,11 @@ func TestZSetRangeScore(t *testing.T) { defer c.Close() key := []byte("myzset_range") - if _, err := redis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { + if _, err := ledis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { t.Fatal(err) } - if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, 1, 4, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrangebyscore", key, 1, 4, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "a", 1, "b", 2, "c", 3, "d", 4); err != nil { @@ -240,7 +240,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, 1, 4, "withscores", "limit", 1, 2)); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrangebyscore", key, 1, 4, "withscores", "limit", 1, 2)); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "b", 2, "c", 3); err != nil { @@ -248,7 +248,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, "-inf", "+inf", "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrangebyscore", key, "-inf", "+inf", "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "a", 1, "b", 2, "c", 3, "d", 4); err != nil { @@ -256,7 +256,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, "(1", "(4")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrangebyscore", key, "(1", "(4")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "b", "c"); err != nil { @@ -264,7 +264,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrangebyscore", key, 1, 4, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrangebyscore", key, 1, 4, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "d", 4, "c", 3, "b", 2, "a", 1); err != nil { @@ -272,7 +272,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrangebyscore", key, 1, 4, "withscores", "limit", 1, 2)); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrangebyscore", key, 1, 4, "withscores", "limit", 1, 2)); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "c", 3, "b", 2); err != nil { @@ -280,7 +280,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrangebyscore", key, "-inf", "+inf", "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrangebyscore", key, "-inf", "+inf", "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "d", 4, "c", 3, "b", 2, "a", 1); err != nil { @@ -288,7 +288,7 @@ func TestZSetRangeScore(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrangebyscore", key, "(1", "(4")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrangebyscore", key, "(1", "(4")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "c", "b"); err != nil { @@ -296,19 +296,19 @@ func TestZSetRangeScore(t *testing.T) { } } - if n, err := redis.Int(c.Do("zremrangebyscore", key, 2, 3)); err != nil { + if n, err := ledis.Int(c.Do("zremrangebyscore", key, 2, 3)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, 1, 4)); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrangebyscore", key, 1, 4)); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "a", "d"); err != nil { @@ -322,11 +322,11 @@ func TestZSetRange(t *testing.T) { defer c.Close() key := []byte("myzset_range_rank") - if _, err := redis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { + if _, err := ledis.Int(c.Do("zadd", key, 1, "a", 2, "b", 3, "c", 4, "d")); err != nil { t.Fatal(err) } - if v, err := redis.MultiBulk(c.Do("zrange", key, 0, 3, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrange", key, 0, 3, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "a", 1, "b", 2, "c", 3, "d", 4); err != nil { @@ -334,7 +334,7 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrange", key, 1, 4, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrange", key, 1, 4, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "b", 2, "c", 3, "d", 4); err != nil { @@ -342,7 +342,7 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrange", key, -2, -1, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrange", key, -2, -1, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "c", 3, "d", 4); err != nil { @@ -350,7 +350,7 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrange", key, 0, -1, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrange", key, 0, -1, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "a", 1, "b", 2, "c", 3, "d", 4); err != nil { @@ -358,13 +358,13 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrange", key, -1, -2, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrange", key, -1, -2, "withscores")); err != nil { t.Fatal(err) } else if len(v) != 0 { t.Fatal(len(v)) } - if v, err := redis.MultiBulk(c.Do("zrevrange", key, 0, 4, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrange", key, 0, 4, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "d", 4, "c", 3, "b", 2, "a", 1); err != nil { @@ -372,7 +372,7 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrange", key, 0, -1, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrange", key, 0, -1, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "d", 4, "c", 3, "b", 2, "a", 1); err != nil { @@ -380,7 +380,7 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrange", key, 2, 3, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrange", key, 2, 3, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "b", 2, "a", 1); err != nil { @@ -388,7 +388,7 @@ func TestZSetRange(t *testing.T) { } } - if v, err := redis.MultiBulk(c.Do("zrevrange", key, -2, -1, "withscores")); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrevrange", key, -2, -1, "withscores")); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "b", 2, "a", 1); err != nil { @@ -396,19 +396,19 @@ func TestZSetRange(t *testing.T) { } } - if n, err := redis.Int(c.Do("zremrangebyrank", key, 2, 3)); err != nil { + if n, err := ledis.Int(c.Do("zremrangebyrank", key, 2, 3)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if v, err := redis.MultiBulk(c.Do("zrange", key, 0, 4)); err != nil { + if v, err := ledis.MultiBulk(c.Do("zrange", key, 0, 4)); err != nil { t.Fatal(err) } else { if err := testZSetRange(v, "a", "b"); err != nil { @@ -416,13 +416,13 @@ func TestZSetRange(t *testing.T) { } } - if n, err := redis.Int(c.Do("zclear", key)); err != nil { + if n, err := ledis.Int(c.Do("zclear", key)); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } - if n, err := redis.Int(c.Do("zcard", key)); err != nil { + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(err) } else if n != 0 { t.Fatal(n)