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 }
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 }
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 }
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 }
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 }