示例#1
0
文件: hash.go 项目: scozss/setdb
func Hincrby(args [][]byte, wb *levigo.WriteBatch) interface{} {
	mk := metaKey(args[0])
	length, err := hlen(mk, nil)
	if err != nil {
		return err
	}
	key := NewKeyBufferWithSuffix(HashKey, args[0], args[1]).Key()
	res, err := DB.Get(DefaultReadOptions, key)
	if err != nil {
		return err
	}

	var current int64
	if res != nil {
		current, err = bconv.ParseInt(res, 10, 64)
		if err != nil {
			return InvalidIntError
		}
	}
	increment, err := bconv.ParseInt(args[2], 10, 64)
	if err != nil {
		return InvalidIntError
	}
	result := strconv.AppendInt(nil, current+increment, 10)
	wb.Put(key, result)

	// if is a new key, increment the hash length
	if res == nil {
		setHlen(mk, length+1, wb)
	}
	return result
}
示例#2
0
文件: cluster.go 项目: scozss/setdb
func Restore(args [][]byte, wb *levigo.WriteBatch) interface{} {
	ttl, err := bconv.ParseInt(args[1], 10, 64)
	if err != nil {
		return InvalidIntError
	}
	err = rdb.DecodeDump(args[2], 0, args[0], ttl, &rdbDecoder{wb: wb})
	if err != nil {
		return err
	}
	return ReplyOK
}
示例#3
0
文件: commands.go 项目: scozss/setdb
func parseRange(args [][]byte, length int64) (int64, int64, error) {
	start, err := bconv.ParseInt(args[0], 10, 64)
	end, err2 := bconv.ParseInt(args[1], 10, 64)
	if err != nil || err2 != nil {
		return 0, 0, InvalidIntError
	}

	// if the index is negative, it is counting from the end,
	// so add it to the length to get the absolute index
	if start < 0 {
		start += length
	}
	if end < 0 {
		end += length
	}

	if end > length { // limit the end to the last member
		end = length - 1
	}

	return start, end, nil
}
示例#4
0
文件: cluster.go 项目: scozss/setdb
func Migrate(args [][]byte, wb *levigo.WriteBatch) interface{} {
	timeout, err := bconv.ParseInt(args[4], 10, 64)
	if err != nil {
		return InvalidIntError
	}

	data, err := dumpKey(args[2])
	if err != nil {
		return err
	}
	if data == nil {
		return ReplyNOKEY
	}

	t := time.Duration(timeout) * time.Millisecond
	r, err := redis.DialTimeout("tcp", string(args[0])+":"+string(args[1]), t, t, t)
	defer r.Close()
	if err != nil {
		return IOError{fmt.Errorf("error or timeout connecting to target instance")}
	}

	res, err := redis.String(r.Do("SELECT", args[3]))
	if _, ok := err.(redis.Error); ok {
		return fmt.Errorf("Target instance replied with error: %s", err)
	}
	if err != nil || res != "OK" {
		return IOError{fmt.Errorf("error or timeout performing SELECT of database %s on target instance", args[3])}
	}

	res, err = redis.String(r.Do("RESTORE", args[2], "0", data))
	if _, ok := err.(redis.Error); ok {
		return fmt.Errorf("Target instance replied with error: %s", err)
	}
	if err != nil || res != "OK" {
		return IOError{fmt.Errorf("error or timeout performing RESTORE of key on target instance")}
	}

	_, err = delKey(metaKey(args[2]), wb)
	if err != nil {
		return IOError{fmt.Errorf("error deleting key from local instance: %s", err)}
	}

	return ReplyOK
}
示例#5
0
文件: zset.go 项目: scozss/setdb
func zrangebyscore(args [][]byte, flag zrangeFlag, wb *levigo.WriteBatch) interface{} {
	// use a snapshot for this read so that the zcard is consistent
	snapshot := DB.NewSnapshot()
	opts := levigo.NewReadOptions()
	opts.SetSnapshot(snapshot)
	defer opts.Close()
	defer DB.ReleaseSnapshot(snapshot)

	mk := metaKey(args[0])
	card, err := zcard(mk, opts)
	if err != nil {
		return err
	}

	var minExclusive, maxExclusive bool
	if args[1][0] == '(' {
		minExclusive = true
		args[1] = args[1][1:]
	}
	if args[2][0] == '(' {
		maxExclusive = true
		args[2] = args[2][1:]
	}
	min, err := bconv.ParseFloat(args[1], 64)
	max, err2 := bconv.ParseFloat(args[2], 64)
	if err != nil || err2 != nil {
		return fmt.Errorf("min or max is not a float")
	}
	if flag == zrangeReverse {
		min, max = max, min
		minExclusive, maxExclusive = maxExclusive, minExclusive
	}

	if card == 0 || min > max {
		if flag <= zrangeReverse {
			return []interface{}{}
		} else {
			return 0
		}
	}

	// shortcut for zcount of -Inf to +Inf
	if flag == zrangeCount && math.IsInf(min, -1) && math.IsInf(max, 1) {
		return card
	}

	var withscores bool
	var offset, total int64 = 0, -1
	if flag <= zrangeReverse && len(args) > 3 {
		if len(args) == 4 || len(args) == 7 {
			if EqualIgnoreCase(args[3], []byte("withscores")) {
				withscores = true
			}
		} else if len(args) != 6 {
			return SyntaxError
		}
		if len(args) >= 6 {
			if EqualIgnoreCase(args[len(args)-3], []byte("limit")) {
				offset, err = bconv.ParseInt(args[len(args)-2], 10, 64)
				total, err2 = bconv.ParseInt(args[len(args)-1], 10, 64)
				if err != nil || err2 != nil {
					return InvalidIntError
				}
				if offset < 0 || total < 1 {
					return []interface{}{}
				}
			} else {
				return SyntaxError
			}
		}
	}

	it := DB.NewIterator(opts)
	defer it.Close()

	var deleted, count uint32
	var deleteKey *KeyBuffer
	if flag == zrangeDelete {
		deleteKey = NewKeyBuffer(ZSetKey, args[0], 0)
	}

	res := []interface{}{}
	iterKey := NewKeyBuffer(ZScoreKey, args[0], 8)
	if flag != zrangeReverse {
		setZScoreKeyScore(iterKey, min)
	} else {
		setZScoreKeyScore(iterKey, max)
		iterKey.ReverseIterKey()
	}
	it.Seek(iterKey.Key())
	for i := int64(0); it.Valid(); i++ {
		if flag == zrangeReverse {
			it.Prev()
		}
		if i >= offset {
			if total > -1 && i-offset >= total {
				break
			}
			k := it.Key()
			if !iterKey.IsPrefixOf(k) {
				break
			}
			score, member := parseZScoreKey(it.Key(), len(args[0]))
			if (!minExclusive && score < min) || (minExclusive && score <= min) {
				if flag != zrangeReverse {
					it.Next()
				}
				continue
			}
			if (!maxExclusive && score > max) || (maxExclusive && score >= max) {
				break
			}
			if flag <= zrangeReverse {
				res = append(res, member)
				if withscores {
					res = append(res, ftoa(score))
				}
			}
			if flag == zrangeDelete {
				deleteKey.SetSuffix(member)
				wb.Delete(k)
				wb.Delete(deleteKey.Key())
				deleted++
			}
			if flag == zrangeCount {
				count++
			}
		}
		if flag != zrangeReverse {
			it.Next()
		}
	}

	if flag == zrangeDelete && deleted == card {
		wb.Delete(mk)
	} else if deleted > 0 {
		setZcard(mk, card-deleted, wb)
	}
	if flag == zrangeDelete {
		return deleted
	}
	if flag == zrangeCount {
		return count
	}

	return res
}