func getrange(v resp.CommandArgs, ex *CommandExtras) error { start, err := strconv.Atoi(string(v[1])) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } end, err := strconv.Atoi(string(v[2])) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } ex.DB.RLock() defer ex.DB.RUnlock() exists, tipe, _ := ex.DB.Has(v[0]) if !exists { return resp.EmptyBulkString.WriteTo(ex.Buffer) } if tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := ex.DB.GetString(v[0]) start, end = calcRange(start, end, len(val)) if end <= start { return resp.EmptyBulkString.WriteTo(ex.Buffer) } return resp.BulkString(val[start:end]).WriteTo(ex.Buffer) }
func getbit(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() exists, tipe, _ := ex.DB.Has(v[0]) if !exists { return resp.ZeroInteger.WriteTo(ex.Buffer) } if tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := ex.DB.GetString(v[0]) offset, err := strconv.Atoi(string(v[1])) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } if offset >= 8*len(val) { return resp.ZeroInteger.WriteTo(ex.Buffer) } byten := offset / 8 pos := offset % 8 k := val[byten] >> uint32(7-pos) & 0x01 return resp.Integer(k).WriteTo(ex.Buffer) }
func setrange(v resp.CommandArgs, ex *CommandExtras) error { i64, err := strconv.ParseInt(string(v[1]), 10, 32) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } offset := int(i64) if offset < 0 { return resp.NewError(ErrOffsetOutRange).WriteTo(ex.Buffer) } if offset+len(v[2]) > 536870912 { // 512M is the limit length return resp.NewError(ErrStringExccedLimit).WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() exists, tipe, expireAt := ex.DB.Has(v[0]) if exists && tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := []byte("") if exists { val = ex.DB.GetString(v[0]) } if len(val) < offset+len(v[2]) { val = append(val, make([]byte, len(v[2])+offset-len(val))...) } copy(val[offset:], v[2]) ex.DB.PutString(v[0], val, expireAt) return resp.Integer(len(val)).WriteTo(ex.Buffer) }
func hmget(v resp.CommandArgs, ex *CommandExtras) error { if len(v) < 2 { return resp.NewError(ErrFmtWrongNumberArgument, "hmget").WriteTo(ex.Buffer) } ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } fields := v[1:].ToBytes() hash := ex.DB.GetHashFields(v[0], fields) arr := resp.Array{} var keys []string for k := range hash { keys = append(keys, k) } sort.Strings(keys) for _, field := range keys { value := hash[field] arr = append(arr, resp.BulkString(value)) } return arr.WriteTo(ex.Buffer) }
func hincrbyfloat(v resp.CommandArgs, ex *CommandExtras) error { by, err := strconv.ParseFloat(v[2].String(), 64) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() keyExists, tipe, expireAt := ex.DB.Has(v[0]) if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } hash := ex.DB.GetHashFields(v[0], [][]byte{v[1]}) newVal := 0.0 if hash[string(v[1])] == nil { newVal += by } else { f, err := strconv.ParseFloat(string(hash[string(v[1])]), 64) if err != nil { return resp.NewError(ErrNotValidFloat).WriteTo(ex.Buffer) } newVal = f + by } hash[string(v[1])] = []byte(strconv.FormatFloat(newVal, 'f', -1, 64)) ex.DB.PutHash(v[0], hash, expireAt) return resp.BulkString(hash[string(v[1])]).WriteTo(ex.Buffer) }
func hdel(v resp.CommandArgs, ex *CommandExtras) error { if len(v) < 2 { return resp.NewError(ErrFmtWrongNumberArgument, "hdel").WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if !keyExists { return resp.ZeroInteger.WriteTo(ex.Buffer) } if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } fields := [][]byte{} for _, field := range v[1:] { fields = append(fields, []byte(field)) } hash := ex.DB.GetHashFields(v[0], fields) count := 0 for _, value := range hash { if value != nil { count++ } } ex.DB.DeleteHashFields(v[0], fields) return resp.Integer(count).WriteTo(ex.Buffer) }
func incrbyfloat(v resp.CommandArgs, ex *CommandExtras) error { by, err := strconv.ParseFloat(v[1].String(), 64) if err != nil { return resp.NewError(ErrNotValidFloat).WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() exists, tipe, expireAt := ex.DB.Has(v[0]) if exists && tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } newVal := 0.0 if !exists { newVal += by } else { val := ex.DB.GetString(v[0]) f, err := strconv.ParseFloat(string(val), 64) if err != nil { return resp.NewError(ErrNotValidFloat).WriteTo(ex.Buffer) } newVal = f + by } s := []byte(strconv.FormatFloat(newVal, 'f', -1, 64)) ex.DB.PutString(v[0], s, expireAt) return resp.BulkString(s).WriteTo(ex.Buffer) }
func auth(v resp.CommandArgs, ex *CommandExtras) error { if ex.Password == "" { return resp.NewError(ErrNoNeedPassword).WriteTo(ex.Buffer) } if v[0].String() != ex.Password { ex.IsConnAuthed = false return resp.NewError(ErrWrongPassword).WriteTo(ex.Buffer) } ex.IsConnAuthed = true return resp.OkSimpleString.WriteTo(ex.Buffer) }
func selectDB(v resp.CommandArgs, ex *CommandExtras) error { s := v[0].String() index, err := strconv.Atoi(s) if err != nil { return resp.NewError(ErrSelectInvalidIndex).WriteTo(ex.Buffer) } if index < 0 || index > 15 { return resp.NewError(ErrSelectInvalidIndex).WriteTo(ex.Buffer) } ex.DB = storage.SelectStorage(index) return resp.OkSimpleString.WriteTo(ex.Buffer) }
func bitcount(v resp.CommandArgs, ex *CommandExtras) error { if len(v) == 0 { return resp.NewError(ErrFmtWrongNumberArgument, "bitcount").WriteTo(ex.Buffer) } ex.DB.RLock() defer ex.DB.RUnlock() exists, tipe, _ := ex.DB.Has(v[0]) if !exists { return resp.ZeroInteger.WriteTo(ex.Buffer) } if tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } if len(v) != 1 && len(v) != 3 { return resp.NewError(ErrFmtSyntax).WriteTo(ex.Buffer) } val := ex.DB.GetString(v[0]) start := 0 end := len(val) var err error if len(v) == 3 { start, err = strconv.Atoi(string(v[1])) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } end, err = strconv.Atoi(string(v[2])) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } start, end = calcRange(start, end, len(val)) } if end <= start { return resp.ZeroInteger.WriteTo(ex.Buffer) } sum := 0 for _, b := range val[start:end] { sum += countSetBits[b] } return resp.Integer(sum).WriteTo(ex.Buffer) }
func setbit(v resp.CommandArgs, ex *CommandExtras) error { i64, err := strconv.ParseInt(string(v[1]), 10, 32) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } offset := uint32(i64) pos := offset % 8 byten := offset / 8 if int(byten)+1 > STRLIMIT { return resp.NewError(ErrStringExccedLimit).WriteTo(ex.Buffer) } bit, err := strconv.Atoi(string(v[2])) if err != nil || bit != 0 && bit != 1 { return resp.NewError(ErrBitValueInvalid).WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() exists, tipe, expireAt := ex.DB.Has(v[0]) if exists && tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := []byte("") if exists { val = ex.DB.GetString(v[0]) } if uint32(len(val)) < byten+1 { val = append(val, make([]byte, int(byten)+1-len(val))...) } k := val[byten] >> uint32(7-pos) & 0x01 switch bit { case 0: clear := byte(^(0x01 << (7 - pos))) val[byten] = val[byten] & clear case 1: set := byte(0x01 << (7 - pos)) val[byten] = val[byten] | set } ex.DB.PutString(v[0], val, expireAt) return resp.Integer(k).WriteTo(ex.Buffer) }
func hgetall(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if !keyExists { return resp.EmptyArray.WriteTo(ex.Buffer) } if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } hash := ex.DB.GetHash(v[0]) arr := resp.Array{} var keys []string for k := range hash { keys = append(keys, k) } sort.Strings(keys) for _, field := range keys { value := hash[field] arr = append(arr, resp.BulkString([]byte(field)), resp.BulkString(value)) } return arr.WriteTo(ex.Buffer) }
func incrby(v resp.CommandArgs, ex *CommandExtras) error { by, err := strconv.ParseInt(v[1].String(), 10, 64) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } return incrdecrHelper(v, ex, by) }
func del(v resp.CommandArgs, ex *CommandExtras) error { if len(v) == 0 { return resp.NewError(ErrFmtWrongNumberArgument, "del").WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() count := 0 for _, key := range v { exists, tipe, _ := ex.DB.Has(key) if !exists { continue } switch tipe { case storage.String: ex.DB.DeleteString(key) case storage.Hash: ex.DB.DeleteHash(key) } count++ } return resp.Integer(count).WriteTo(ex.Buffer) }
func hmset(v resp.CommandArgs, ex *CommandExtras) error { if len(v) <= 1 || len(v)%2 != 1 { return resp.NewError(ErrFmtWrongNumberArgument, "hmset").WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() keyExists, tipe, expireAt := ex.DB.Has(v[0]) if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } hash := make(map[string][]byte) for i := 1; i < len(v); { hash[string(v[i])] = v[i+1] i += 2 } ex.DB.PutHash(v[0], hash, expireAt) return resp.OkSimpleString.WriteTo(ex.Buffer) }
// use appendx for append command, because append is a key word of golang func appendx(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.Lock() defer ex.DB.Unlock() exists, tipe, expireAt := ex.DB.Has(v[0]) if exists && tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := []byte("") if exists { val = ex.DB.GetString(v[0]) } if len(val)+len(v[1]) > STRLIMIT { return resp.NewError(ErrStringExccedLimit).WriteTo(ex.Buffer) } val = append(val, v[1]...) ex.DB.PutString(v[0], val, expireAt) return resp.Integer(len(val)).WriteTo(ex.Buffer) }
func get(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() exists, tipe, _ := ex.DB.Has(v[0]) if !exists { return resp.NilBulkString.WriteTo(ex.Buffer) } if tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := ex.DB.GetString(v[0]) return resp.BulkString(val).WriteTo(ex.Buffer) }
func mset(v resp.CommandArgs, ex *CommandExtras) error { if len(v) == 0 || len(v)%2 != 0 { return resp.NewError(ErrFmtWrongNumberArgument, "mset").WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() for i := 0; i < len(v); { ex.DB.PutString(v[i], v[i+1], nil) i += 2 } return resp.OkSimpleString.WriteTo(ex.Buffer) }
func incrdecrHelper(v resp.CommandArgs, ex *CommandExtras, by int64) error { ex.DB.Lock() defer ex.DB.Unlock() exists, tipe, expireAt := ex.DB.Has(v[0]) if exists && tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } newVal := int64(0) if !exists { newVal += by } else { val := ex.DB.GetString(v[0]) i, err := strconv.ParseInt(string(val), 10, 64) if err != nil { return resp.NewError(ErrNotValidInt).WriteTo(ex.Buffer) } newVal = i + by } ex.DB.PutString(v[0], []byte(strconv.FormatInt(newVal, 10)), expireAt) return resp.Integer(newVal).WriteTo(ex.Buffer) }
func hlen(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if !keyExists { return resp.ZeroInteger.WriteTo(ex.Buffer) } if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } fields := ex.DB.GetHashFieldNames(v[0]) return resp.Integer(len(fields)).WriteTo(ex.Buffer) }
func getset(v resp.CommandArgs, ex *CommandExtras) error { if len(v[1]) > STRLIMIT { return resp.NewError(ErrStringExccedLimit).WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() exists, tipe, expireAt := ex.DB.Has(v[0]) if exists && tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } var oldValue []byte if exists { oldValue = ex.DB.GetString(v[0]) } ex.DB.PutString(v[0], v[1], expireAt) if !exists { return resp.NilBulkString.WriteTo(ex.Buffer) } return resp.BulkString(oldValue).WriteTo(ex.Buffer) }
func strlen(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() exists, tipe, _ := ex.DB.Has(v[0]) if !exists { return resp.ZeroInteger.WriteTo(ex.Buffer) } if tipe != storage.String { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } val := ex.DB.GetString(v[0]) return resp.Integer(len(val)).WriteTo(ex.Buffer) }
func hexists(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } hash := ex.DB.GetHashFields(v[0], [][]byte{v[1]}) if hash[string(v[1])] == nil { return resp.ZeroInteger.WriteTo(ex.Buffer) } return resp.OneInteger.WriteTo(ex.Buffer) }
func hget(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if !keyExists { return resp.NilBulkString.WriteTo(ex.Buffer) } if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } hash := ex.DB.GetHashFields(v[0], [][]byte{v[1]}) return resp.BulkString(hash[string(v[1])]).WriteTo(ex.Buffer) }
func exists(v resp.CommandArgs, ex *CommandExtras) error { if len(v) == 0 { return resp.NewError(ErrFmtWrongNumberArgument, "exists").WriteTo(ex.Buffer) } ex.DB.RLock() defer ex.DB.RUnlock() count := 0 for _, key := range v { exists, _, _ := ex.DB.Has(key) if !exists { continue } count++ } return resp.Integer(count).WriteTo(ex.Buffer) }
func hkeys(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if !keyExists { return resp.EmptyArray.WriteTo(ex.Buffer) } if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } fields := ex.DB.GetHashFieldNames(v[0]) arr := resp.Array{} for _, field := range fields { arr = append(arr, resp.BulkString(field)) } return arr.WriteTo(ex.Buffer) }
func hvals(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.RLock() defer ex.DB.RUnlock() keyExists, tipe, _ := ex.DB.Has(v[0]) if !keyExists { return resp.EmptyArray.WriteTo(ex.Buffer) } if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } hash := ex.DB.GetHash(v[0]) arr := resp.Array{} for _, value := range hash { arr = append(arr, resp.BulkString([]byte(value))) } return arr.WriteTo(ex.Buffer) }
func mget(v resp.CommandArgs, ex *CommandExtras) error { if len(v) < 1 { return resp.NewError(ErrFmtWrongNumberArgument, "mget").WriteTo(ex.Buffer) } ex.DB.RLock() defer ex.DB.RUnlock() arr := make(resp.Array, len(v)) for i, g := range v { exists, tipe, _ := ex.DB.Has(g) if !exists || tipe != storage.String { arr[i] = resp.NilBulkString } else { val := ex.DB.GetString(g) arr[i] = resp.BulkString(val) } } return arr.WriteTo(ex.Buffer) }
func hsetnx(v resp.CommandArgs, ex *CommandExtras) error { ex.DB.Lock() defer ex.DB.Unlock() keyExists, tipe, expireAt := ex.DB.Has(v[0]) if keyExists && tipe != storage.Hash { return resp.NewError(ErrWrongType).WriteTo(ex.Buffer) } fieldExists := false hash := ex.DB.GetHashFields(v[0], [][]byte{v[1]}) if hash[string(v[1])] != nil { fieldExists = true } if !fieldExists { hash[string(v[1])] = v[2] ex.DB.PutHash(v[0], hash, expireAt) return resp.OneInteger.WriteTo(ex.Buffer) } return resp.ZeroInteger.WriteTo(ex.Buffer) }
func msetnx(v resp.CommandArgs, ex *CommandExtras) error { if len(v) == 0 || len(v)%2 != 0 { return resp.NewError(ErrFmtWrongNumberArgument, "msetnx").WriteTo(ex.Buffer) } ex.DB.Lock() defer ex.DB.Unlock() for i := 0; i < len(v); { exists, _, _ := ex.DB.Has(v[i]) if exists { return resp.ZeroInteger.WriteTo(ex.Buffer) // If any key exists, return 0 } i += 2 } for i := 0; i < len(v); { // every key does not exist, put all into level db. ex.DB.PutString(v[i], v[i+1], nil) i += 2 } return resp.OneInteger.WriteTo(ex.Buffer) }