Пример #1
1
// DeleteKeys will remove a group of keys in bulk
func (r *RedisClusterStorageManager) DeleteScanMatch(pattern string) bool {

	if GetRelevantClusterReference(r.IsCache) == nil {
		log.Info("Connection dropped, connecting..")
		r.Connect()
		return r.DeleteScanMatch(pattern)
	}

	log.Debug("Deleting: ", pattern)

	// here we'll store our iterator value
	iter := "0"

	// this will store the keys of each iteration
	var keys []string
	for {
		// we scan with our iter offset, starting at 0
		arr, err := redis.MultiBulk(GetRelevantClusterReference(r.IsCache).Do("SCAN", iter, "MATCH", pattern))
		if err != nil {
			log.Error("SCAN Token Get Failure: ", err)
			return false
		}
		// now we get the iter and the keys from the multi-bulk reply
		iter, _ = redis.String(arr[0], nil)
		theseKeys, _ := redis.Strings(arr[1], nil)
		keys = append(keys, theseKeys...)

		// check if we need to stop...
		if iter == "0" {
			break
		}
	}

	if len(keys) > 0 {
		for _, v := range keys {
			name := "" + v
			log.Info("Deleting: ", name)
			_, err := GetRelevantClusterReference(r.IsCache).Do("DEL", name)
			if err != nil {
				log.Error("Error trying to delete key: ", v, " - ", err)

			}
		}
		log.Info("Deleted: ", len(keys), " records")
	} else {
		log.Debug("RedisClusterStorageManager called DEL - Nothing to delete")
	}

	return true
}
Пример #2
0
func TestHashM(t *testing.T) {
	startTestApp()

	c := getTestConn()
	defer c.Close()

	key := []byte("b")
	if ok, err := redis.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 {
		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 {
		t.Fatal(err)
	} else {
		if err := testHashArray(v, 1, 2, 3, 0); err != nil {
			t.Fatal(err)
		}
	}

	if n, err := redis.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 {
		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 {
		t.Fatal(err)
	} else {
		if err := testHashArray(v, 0, 0, 0, 0); err != nil {
			t.Fatal(err)
		}
	}

	if n, err := redis.Int(c.Do("hlen", key)); err != nil {
		t.Fatal(err)
	} else if n != 0 {
		t.Fatal(n)
	}
}
Пример #3
0
func TestHashGetAll(t *testing.T) {
	startTestApp()

	c := getTestConn()
	defer c.Close()

	key := []byte("d")

	if ok, err := redis.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 {
		t.Fatal(err)
	} else {
		if err := testHashArray(v, 1, 1, 2, 2, 3, 3); err != nil {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("hkeys", key)); err != nil {
		t.Fatal(err)
	} else {
		if err := testHashArray(v, 1, 2, 3); err != nil {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("hvals", key)); err != nil {
		t.Fatal(err)
	} else {
		if err := testHashArray(v, 1, 2, 3); err != nil {
			t.Fatal(err)
		}
	}

	if n, err := redis.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 {
		t.Fatal(err)
	} else if n != 0 {
		t.Fatal(n)
	}
}
Пример #4
0
func TestKVM(t *testing.T) {
	c := getTestConn()
	defer c.Close()

	if ok, err := redis.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 {
		t.Fatal(err)
	} else if len(v) != 3 {
		t.Fatal(len(v))
	} else {
		if vv, ok := v[0].([]byte); !ok || string(vv) != "1" {
			t.Fatal("not 1")
		}

		if vv, ok := v[1].([]byte); !ok || string(vv) != "2" {
			t.Fatal("not 2")
		}

		if v[2] != nil {
			t.Fatal("must nil")
		}
	}
}
Пример #5
0
func testListRange(key []byte, start int64, stop int64, checkValues ...int) error {
	c := getTestConn()
	defer c.Close()

	vs, err := redis.MultiBulk(c.Do("lrange", key, start, stop))
	if err != nil {
		return err
	}

	if len(vs) != len(checkValues) {
		return fmt.Errorf("invalid return number %d != %d", len(vs), len(checkValues))
	}

	var n int
	for i, v := range vs {
		if d, ok := v.([]byte); ok {
			n, err = strconv.Atoi(string(d))
			if err != nil {
				return err
			} else if n != checkValues[i] {
				return fmt.Errorf("invalid data %d: %d != %d", i, n, checkValues[i])
			}
		} else {
			return fmt.Errorf("invalid data %v %T", v, v)
		}
	}

	return nil
}
Пример #6
0
func popMessage(conn redis.Conn, key string) (*Message, error) {
	reply, err := redis.MultiBulk(conn.Do("BLPOP", key, DEFAULTTIMEOUT))
	if err != nil {
		return nil, err
	}
	return parseMessage(reply)
}
Пример #7
0
func (this *RedisClient) GetFields(PK interface{}, fields []string) (map[string]string, error) {
	key := fmt.Sprintf("PK:%v", PK)
	//var value string
	var comm []interface{}
	comm = append(comm, key)
	for _, v := range fields {
		comm = append(comm, v)
	}
	//fmt.Printf("Comm : %v \n",comm)

	conn := this.pool.Get()
	defer conn.Close()
	reply, err := redis.MultiBulk(conn.Do("HMGET", comm...))
	if err != nil {
		return nil, err
	}
	//var list = make([]string, 0)
	var res = make(map[string]string)
	for index, v := range reply {
		s, err := redis.String(v, nil)
		if err != nil {
			return nil, err
		}
		s = strings.Trim(s, "\"")
		res[fields[index]] = s
		// list = append(list, s)
	}
	//fmt.Printf("\n ALL REDIS RESULT :: %v\n", res)
	return res, nil

}
Пример #8
0
// return: success_count, remain_count, error
// slotsmgrt host port timeout slotnum count
func (m *migrater) sendRedisMigrateCmd(c redis.Conn, slotId int, toAddr string) (bool, error) {
	addrParts := strings.Split(toAddr, ":")
	if len(addrParts) != 2 {
		return false, ErrInvalidAddr
	}

	//use scan and migrate
	reply, err := redis.MultiBulk(c.Do("scan", 0))
	if err != nil {
		return false, err
	}

	var next string
	var keys []interface{}

	if _, err := redis.Scan(reply, &next, &keys); err != nil {
		return false, err
	}

	for _, key := range keys {
		if _, err := c.Do("migrate", addrParts[0], addrParts[1], key, slotId, MIGRATE_TIMEOUT); err != nil {
			//todo, try del if key exists
			return false, err
		}
	}

	return next != "0", nil
}
Пример #9
0
func (j *Job) Start() error {
	Debugf("Starting job: %d", j.Id)

	client := j.client
	// Send job arguments
	if len(j.Args) > 0 {
		args := append([]interface{}{fmt.Sprintf("%s/args", j.key())}, asInterfaceSlice(j.Args)...)
		if _, err := client.send("RPUSH", args...); err != nil {
			return err
		}
	}

	// Send environment vars
	if len(j.Env) > 0 {
		env := append([]interface{}{fmt.Sprintf("%s/env", j.key())}, asInterfaceSlice(splitEnv(j.Env))...)
		if _, err := client.send("HMSET", env...); err != nil {
			return err
		}
	}

	j.exitFailure, j.exitSuccess = make(chan bool), make(chan bool)
	// Start waiting for exit
	go func() {
		Debugf("Waiting for job: %d", j.Id)

		reply, err := redis.MultiBulk(client.send("BLPOP", fmt.Sprintf("%s/wait", j.key()), DEFAULTTIMEOUT))
		Debugf("Job complete: %d", j.Id)
		if err != nil {
			j.exitError = err
			j.exitFailure <- true
			return
		}

		status := reply[1].([]byte)
		// Status will be empty for success
		if len(status) == 0 {
			j.exitSuccess <- true
			return
		}

		buffer := bytes.NewBuffer(status)
		code, err := strconv.Atoi(buffer.String())
		if err != nil {
			j.exitError = err
			j.exitFailure <- true
			return
		}
		j.ExitStatus = code
		j.exitFailure <- true
	}()

	// Send start job
	if _, err := client.send("RPUSH", fmt.Sprintf("/jobs/start"), j.Id); err != nil {
		return err
	}

	return nil
}
Пример #10
0
func GetDistribution(distribution string) ([]interface{}, error) {
	rdb := redisServer.GetConnection()

	rdb.Send("MULTI")
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_T"))
	rdb.Send("ZRANGE", distribution, 0, -1, "WITHSCORES")
	data, err := redis.MultiBulk(rdb.Do("EXEC"))
	return data, err
}
Пример #11
0
func GetNMostProbable(distribution string, N int) ([]interface{}, error) {
	rdb := redisServer.GetConnection()

	rdb.Send("MULTI")
	rdb.Send("ZREVRANGEBYSCORE", distribution, "+INF", "-INF", "WITHSCORES", "LIMIT", 0, N)
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_Z"))
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_T"))
	data, err := redis.MultiBulk(rdb.Do("EXEC"))
	return data, err
}
Пример #12
0
func GetField(distribution, field string) ([]interface{}, error) {
	rdb := redisServer.GetConnection()

	rdb.Send("MULTI")
	rdb.Send("ZSCORE", distribution, field)
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_Z"))
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_T"))
	data, err := redis.MultiBulk(rdb.Do("EXEC"))
	return data, err
}
Пример #13
0
func (this *RedisClient) GetFields(PK interface{}, fields []string) (map[string]string, error) {
	key := fmt.Sprintf("PK:%v", PK)
	//var value string
	var comm []interface{}
	comm = append(comm, key)
	for _, v := range fields {
		comm = append(comm, v)
	}
	//fmt.Printf("Comm : %v \n",comm)

	conn := this.pool.Get()
	defer conn.Close()
	reply, err := redis.MultiBulk(conn.Do("HMGET", comm...))
	if err != nil {
		return nil, err
	}
	//var list = make([]string, 0)
	var res = make(map[string]string)
	for index, v := range reply {
		s, err := redis.String(v, nil)
		if err != nil {
			return nil, err
		}
		s = strings.Trim(s, "\"")
		res[fields[index]] = s
		// list = append(list, s)
	}
	//fmt.Printf("\n ALL REDIS RESULT :: %v\n", res)
	return res, nil

	/*
			res, err := redis.Values(conn.Do("HMGET", comm...))
			if err != nil {
				this.logger.Error("REDIS ERROR : %v ", err)
				return nil,err
			}

			fmt.Printf("\n ALL REDIS RESULT :: %v\n", res)
			values :=make([]string,len(fields))
			if _, err := redis.Scan(res, values...); err != nil {
		    	// handle error
				return nil,err
			}
			fmt.Printf("REDISE STRING :: ")
			for _,v:=range values{
				fmt.Printf(" %v ",v)
			}
			fmt.Printf("\n")
	*/

	return nil, err
}
Пример #14
0
func Scan(cursor int) (results ScanResults, err error) {
	client := pool.Get()
	data, err := redis.MultiBulk(client.Do("SCAN", cursor, "COUNT", "1000"))

	if err != nil {
		return results, err
	}

	results.Iterator, _ = redis.Int(data[0], nil)
	results.Keys, _ = redis.Strings(data[1], nil)

	return results, err
}
Пример #15
0
func GetField(distribution string, fields ...string) ([]interface{}, error) {
	rdb := redisServer.GetConnection()
	defer rdb.Close()

	rdb.Send("MULTI")
	for _, field := range fields {
		rdb.Send("ZSCORE", distribution, field)
	}
	rdb.Send("ZCARD", distribution)
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_Z"))
	rdb.Send("GET", fmt.Sprintf("%s.%s", distribution, "_T"))
	data, err := redis.MultiBulk(rdb.Do("EXEC"))
	return data, err
}
Пример #16
0
func TestRedisCluster(t *testing.T) {
	N := 500

	group1 := NewRedisShardGroup(1, NewRedisShard(1, "127.0.0.1", 6379), NewRedisShard(2, "127.0.0.1", 6379))
	group2 := NewRedisShardGroup(2, NewRedisShard(3, "127.0.0.1", 6379), NewRedisShard(4, "127.0.0.1", 6379))
	group3 := NewRedisShardGroup(3, NewRedisShard(5, "127.0.0.1", 6379), NewRedisShard(6, "127.0.0.1", 6379))
	group4 := NewRedisShardGroup(4, NewRedisShard(8, "127.0.0.1", 6379), NewRedisShard(7, "127.0.0.1", 6379))

	rc := NewRedisCluster(group1, group2, group3, group4)

	if rc == nil {
		t.Fatalf("Could not create redis cluster")
	}

	if rc.Status != CLUSTER_READY {
		t.Fatalf("Could not connect to servers")
	}

	for i := 0; i < N; i++ {
		log.Printf("Setting element %d", i)
		_, err := rc.Do(MessageFromString(fmt.Sprintf("SET TEST_%d %d", i, i)))
		if err != nil {
			t.Fatalf("Could not set value TEST_%d: %s", i, err)
		}
	}

	pipeline := rc.Pipeline()
	for i := 0; i < N; i++ {
		_, err := pipeline.Send(MessageFromString(fmt.Sprintf("GET TEST_%d", i)))
		if err != nil {
			t.Fatalf("Could not send to pipeline: %s: %s", fmt.Sprintf("TEST_%d", i), err)
		}
	}
	result, err := pipeline.Execute()
	mb, err := redis.MultiBulk(result.Bytes(), nil)
	for i, value := range mb {
		if err != nil || value != i {
			t.Fatalf("Did not get proper result back for TEST_%d: %d: %s", i, value, err)
		}
	}

	for i := 0; i < N; i++ {
		_, err := rc.Do(MessageFromString(fmt.Sprintf("DEL TEST_%d", i)))
		if err != nil {
			t.Fatalf("Could not delete key TEST_%d: %s", i, err)
		}
	}
}
Пример #17
0
func (d *Distribution) addMultiBulkCounts(data interface{}) error {
	distData, _ := redis.MultiBulk(data, nil)
	for i := 0; i < len(distData); i += 2 {
		k, err := redis.String(distData[i], nil)
		if err != nil || k == "" {
			log.Printf("Could not read %s from distribution %s: %s", distData[i], d.Name, err)
		}
		v, err := redis.Int(distData[i+1], nil)
		if err != nil {
			log.Printf("Could not read %s from distribution %s: %s", distData[i+1], d.Name, err)
		}
		d.Data[k] = &Value{Count: v}
	}

	return nil
}
Пример #18
0
func readLog() {
	c, err := redis.Dial("tcp", ":6379")
	if err != nil {
		log.Println("Redis Connect Error : ", err)
		return
	}
	defer c.Close()
	c.Do("SELECT", 10)
	for {
		result, _ := redis.MultiBulk(c.Do("BRPOP", "IRC_HISTORY", 0))

		if result != nil {
			msg <- string(result[1].([]byte))
		}
	}
}
Пример #19
0
// Flush deletes all cached data.
func (r *RedisCache) Flush() (err error) {
	if r.occupyMode {
		_, err = r.do("FLUSHDB")
		return
	}

	keys, err := redigo.MultiBulk(r.do("HKEYS", r.key(GC_HASH_KEY)))
	if err != nil {
		return
	}

	fmt.Println(keys)

	conn := r.pool.Get()
	defer conn.Close()

	_, err = conn.Do("DEL", keys...)

	return
}
Пример #20
0
func (c Client) Next() *Job {
	log.Println("Fetching job from", c.spec.Queue)

	multiBulk, _ := redis.MultiBulk((*c.conn).Do("BLPOP", c.spec.Queue, 0))
	for len(multiBulk) > 0 {
		var jobData []byte
		multiBulk, _ = redis.Scan(multiBulk, &jobData)
		// The first element returned is the queue name.
		if string(jobData) == c.spec.Queue {
			continue
		}

		job := new(Job)
		log.Println("job", string(jobData))
		json.Unmarshal(jobData, &job)

		return job
	}
	return nil
}
Пример #21
0
func (this *HashMap) GetStringList(k []string) ([]string, error) {
	args := []interface{}{}
	args = append(args, this.Name)
	for _, v := range k {
		args = append(args, v)
	}
	reply, err := redis.MultiBulk(Do("HMGET", args...))
	if err != nil {
		return nil, err
	}
	var list = make([]string, 0)
	for _, v := range reply {
		s, err := redis.String(v, nil)
		if err != nil {
			break
		}
		s = strings.Trim(s, "\"")
		list = append(list, s)
	}
	return list, err
}
Пример #22
0
func (this *SortedSet) GetStringsRev(start, limit int) ([]string, error) {
	a, err := Do("ZREVRANGE", this.Name, start, start+limit)
	if err != nil {
		return nil, err
	}
	b, err := redis.MultiBulk(a, err)
	if err != nil {
		return nil, err
	}

	var list = make([]string, 0)
	for _, v := range b {
		s, err := redis.String(v, nil)
		if err != nil {
			break
		}
		s = strings.Trim(s, "\"")
		list = append(list, s)
	}
	return list, err
}
Пример #23
0
func (s *Streamer) start() {
	s.errs = make(chan error, 1024)
	go func() {
		s.group.Add(1)
		defer s.group.Done()

		conn := s.pool.Get()
		defer conn.Close()

		Debugf("Reading from: %s", s.OutKey)
		for {
			reply, err := redis.MultiBulk(conn.Do("BLPOP", s.OutKey, DEFAULTTIMEOUT))
			if err != nil {
				s.errs <- err
				continue
			}
			b := reply[1].([]byte)

			parts := bytes.SplitN(b, []byte(":"), 2)
			if len(parts) < 2 {
				s.errs <- ErrInvalidResposeType
				continue
			}
			name := string(parts[0])
			msg := parts[1]
			if len(msg) == 0 {
				s.mutex.Lock()
				if c, ok := s.consumers[name]; ok {
					close(c)
					delete(s.consumers, name)
				}
				if len(s.consumers) == 0 {
					s.mutex.Unlock()
					break
				}
				s.mutex.Unlock()
				continue
			}
			c, ok := s.consumers[name]
			if !ok {
				s.mutex.Lock()
				c = make(chan []byte, 1024)
				s.consumers[name] = c

				go newListener(s, name, c)
				s.mutex.Unlock()
			}
			c <- msg
		}
		for _, c := range s.consumers {
			close(c)
		}
		s.isReadsClosed = true
		s.group.Done()
	}()

	go func() {
		s.group.Add(1)
		defer s.group.Done()

		conn := s.pool.Get()
		defer conn.Close()

		Debugf("Writing to: %s", s.InKey)
		for msg := range s.producer {
			if _, err := conn.Do("RPUSH", s.InKey, msg); err != nil {
				s.errs <- err
			}
		}
	}()
}
Пример #24
0
func TestZSetRange(t *testing.T) {
	startTestApp()

	c := getTestConn()
	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 {
		t.Fatal(err)
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("zrange", key, -2, -1, "withscores")); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "c", 3, "d", 4); err != nil {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "d", 4, "c", 3, "b", 2, "a", 1); err != nil {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("zrevrange", key, 2, 3, "withscores")); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "b", 2, "a", 1); err != nil {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("zrevrange", key, -2, -1, "withscores")); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "b", 2, "a", 1); err != nil {
			t.Fatal(err)
		}
	}

	if n, err := redis.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 {
		t.Fatal(err)
	} else if n != 2 {
		t.Fatal(n)
	}

	if v, err := redis.MultiBulk(c.Do("zrange", key, 0, 4)); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "a", "b"); err != nil {
			t.Fatal(err)
		}
	}

	if n, err := redis.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 {
		t.Fatal(err)
	} else if n != 0 {
		t.Fatal(n)
	}

}
Пример #25
0
func TestZSetRangeScore(t *testing.T) {
	startTestApp()

	c := getTestConn()
	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 {
		t.Fatal(err)
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, "(1", "(4")); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "b", "c"); err != nil {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.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 {
			t.Fatal(err)
		}
	}

	if v, err := redis.MultiBulk(c.Do("zrevrangebyscore", key, "(1", "(4")); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "c", "b"); err != nil {
			t.Fatal(err)
		}
	}

	if n, err := redis.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 {
		t.Fatal(err)
	} else if n != 2 {
		t.Fatal(n)
	}

	if v, err := redis.MultiBulk(c.Do("zrangebyscore", key, 1, 4)); err != nil {
		t.Fatal(err)
	} else {
		if err := testZSetRange(v, "a", "d"); err != nil {
			t.Fatal(err)
		}
	}
}