func lrangeCommand(c *client) error { args := c.args if len(args) != 3 { return ErrCmdParams } var start int64 var stop int64 var err error start, err = ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } stop, err = ledis.StrInt64(args[2], nil) if err != nil { return ErrValue } if v, err := c.db.LRange(args[0], int32(start), int32(stop)); err != nil { return err } else { c.resp.writeSliceArray(v) } return nil }
func zaddCommand(c *client) error { args := c.args if len(args) < 3 { return ErrCmdParams } key := args[0] if len(args[1:])&1 != 0 { return ErrCmdParams } args = args[1:] params := make([]ledis.ScorePair, len(args)>>1) for i := 0; i < len(params); i++ { score, err := ledis.StrInt64(args[2*i], nil) if err != nil { return ErrValue } params[i].Score = score params[i].Member = args[2*i+1] } n, err := c.db.ZAdd(key, params...) if err == nil { c.resp.writeInteger(n) } return err }
func lindexCommand(c *client) error { args := c.args if len(args) != 2 { return ErrCmdParams } index, err := ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } if v, err := c.db.LIndex(args[0], int32(index)); err != nil { return err } else { c.resp.writeBulk(v) } return nil }
func lexpireAtCommand(c *client) error { args := c.args if len(args) != 2 { return ErrCmdParams } when, err := ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } if v, err := c.db.LExpireAt(args[0], when); err != nil { return err } else { c.resp.writeInteger(v) } return nil }
func sexpireCommand(c *client) error { args := c.args if len(args) != 2 { return ErrCmdParams } duration, err := ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } if v, err := c.db.SExpire(args[0], duration); err != nil { return err } else { c.resp.writeInteger(v) } return nil }
func hincrbyCommand(c *client) error { args := c.args if len(args) != 3 { return ErrCmdParams } delta, err := ledis.StrInt64(args[2], nil) if err != nil { return ErrValue } var n int64 if n, err = c.db.HIncrBy(args[0], args[1], delta); err != nil { return err } else { c.resp.writeInteger(n) } return nil }
func setexCommand(c *client) error { args := c.args if len(args) != 3 { return ErrCmdParams } sec, err := ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } if err := c.db.SetEX(args[0], sec, args[2]); err != nil { return err } else { c.resp.writeStatus(OK) } return nil }
func decrbyCommand(c *client) error { args := c.args if len(args) != 2 { return ErrCmdParams } delta, err := ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } if n, err := c.db.DecrBy(c.args[0], delta); err != nil { return err } else { c.resp.writeInteger(n) } return nil }
// unlike redis, restore will try to delete old key first func restoreCommand(c *client) error { args := c.args if len(args) != 3 { return ErrCmdParams } key := args[0] ttl, err := ledis.StrInt64(args[1], nil) if err != nil { return err } data := args[2] if err = c.db.Restore(key, ttl, data); err != nil { return err } else { c.resp.writeStatus(OK) } return nil }
func zincrbyCommand(c *client) error { args := c.args if len(args) != 3 { return ErrCmdParams } key := args[0] delta, err := ledis.StrInt64(args[1], nil) if err != nil { return ErrValue } v, err := c.db.ZIncrBy(key, delta, args[2]) if err == nil { c.resp.writeBulk(num.FormatInt64ToSlice(v)) } return err }
// maybe only used in xcodis for redis data port func xrestoreCommand(c *client) error { args := c.args if len(args) != 4 { return ErrCmdParams } // tp := strings.ToUpper(string(args[2])) key := args[1] ttl, err := ledis.StrInt64(args[2], nil) if err != nil { return err } data := args[3] if err = c.db.Restore(key, ttl, data); err != nil { return err } else { c.resp.writeStatus(OK) } return nil }
//XMIGRATE host port type key destination-db timeout //will block any other write operations //maybe only for xcodis func xmigrateCommand(c *client) error { args := c.args if len(args) != 6 { return ErrCmdParams } addr := fmt.Sprintf("%s:%s", string(args[0]), string(args[1])) if addr == c.app.cfg.Addr { //same server, can not migrate return fmt.Errorf("migrate in same server is not allowed") } tp := strings.ToUpper(string(args[2])) key := args[3] db, err := parseMigrateDB(c, args[4]) if err != nil { return err } timeout, err := ledis.StrInt64(args[5], nil) if err != nil { return err } else if timeout < 0 { return fmt.Errorf("invalid timeout %d", timeout) } conn, err := getMigrateDBConn(c, addr, db) if err != nil { return err } defer conn.Close() // if key is in migrating, we will wait 500ms and retry again for i := 0; i < 10; i++ { if tp == "ALL" { // if tp is ALL, we will migrate the key in all types // this feature is useful for xcodis RESTORE or other commands that we don't know the data type exactly err = migrateAllTypeKeys(c, conn, key, timeout) } else { err = migrateKey(c, conn, tp, key, timeout) } if err != errKeyInMigrating { break } else { log.Infof("%s key %s is in migrating, wait 500ms and retry", tp, key) time.Sleep(500 * time.Millisecond) } } if err != nil { if err == errNoKey { c.resp.writeStatus(NOKEY) return nil } else { return err } } c.resp.writeStatus(OK) return nil }
//XMIGRATEDB host port tp count db timeout //select count tp type keys and migrate //will block any other write operations //maybe only for xcodis func xmigratedbCommand(c *client) error { args := c.args if len(args) != 6 { return ErrCmdParams } addr := fmt.Sprintf("%s:%s", string(args[0]), string(args[1])) if addr == c.app.cfg.Addr { //same server, can not migrate return fmt.Errorf("migrate in same server is not allowed") } tp := strings.ToUpper(string(args[2])) count, err := ledis.StrInt64(args[3], nil) if err != nil { return err } else if count <= 0 { count = 10 } db, err := parseMigrateDB(c, args[4]) if err != nil { return err } timeout, err := ledis.StrInt64(args[5], nil) if err != nil { return err } else if timeout < 0 { return fmt.Errorf("invalid timeout %d", timeout) } keys, err := xscan(c.db, tp, int(count)) if err != nil { return err } else if len(keys) == 0 { c.resp.writeInteger(0) return nil } conn, err := getMigrateDBConn(c, addr, db) if err != nil { return err } defer conn.Close() migrateNum := int64(0) for _, key := range keys { err = migrateKey(c, conn, tp, key, timeout) if err != nil { if err == errNoKey || err == errKeyInMigrating { continue } else { return err } } migrateNum++ } c.resp.writeInteger(migrateNum) return nil }
func zparseZsetoptStore(args [][]byte) (destKey []byte, srcKeys [][]byte, weights []int64, aggregate byte, err error) { destKey = args[0] nKeys, err := strconv.Atoi(hack.String(args[1])) if err != nil { err = ErrValue return } args = args[2:] if len(args) < nKeys { err = ErrSyntax return } srcKeys = args[:nKeys] args = args[nKeys:] var weightsFlag = false var aggregateFlag = false for len(args) > 0 { if strings.ToLower(hack.String(args[0])) == "weights" { if weightsFlag { err = ErrSyntax return } args = args[1:] if len(args) < nKeys { err = ErrSyntax return } weights = make([]int64, nKeys) for i, arg := range args[:nKeys] { if weights[i], err = ledis.StrInt64(arg, nil); err != nil { err = ErrValue return } } args = args[nKeys:] weightsFlag = true } else if strings.ToLower(hack.String(args[0])) == "aggregate" { if aggregateFlag { err = ErrSyntax return } if len(args) < 2 { err = ErrSyntax return } if strings.ToLower(hack.String(args[1])) == "sum" { aggregate = ledis.AggregateSum } else if strings.ToLower(hack.String(args[1])) == "min" { aggregate = ledis.AggregateMin } else if strings.ToLower(hack.String(args[1])) == "max" { aggregate = ledis.AggregateMax } else { err = ErrSyntax return } args = args[2:] aggregateFlag = true } else { err = ErrSyntax return } } if !aggregateFlag { aggregate = ledis.AggregateSum } return }
func zparseScoreRange(minBuf []byte, maxBuf []byte) (min int64, max int64, err error) { if strings.ToLower(hack.String(minBuf)) == "-inf" { min = math.MinInt64 } else { if len(minBuf) == 0 { err = ErrCmdParams return } var lopen bool = false if minBuf[0] == '(' { lopen = true minBuf = minBuf[1:] } min, err = ledis.StrInt64(minBuf, nil) if err != nil { err = ErrValue return } if min <= ledis.MinScore || min >= ledis.MaxScore { err = errScoreOverflow return } if lopen { min++ } } if strings.ToLower(hack.String(maxBuf)) == "+inf" { max = math.MaxInt64 } else { var ropen = false if len(maxBuf) == 0 { err = ErrCmdParams return } if maxBuf[0] == '(' { ropen = true maxBuf = maxBuf[1:] } if maxBuf[0] == '(' { ropen = true maxBuf = maxBuf[1:] } max, err = ledis.StrInt64(maxBuf, nil) if err != nil { err = ErrValue return } if max <= ledis.MinScore || max >= ledis.MaxScore { err = errScoreOverflow return } if ropen { max-- } } return }