作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
// 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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}
作者:aegse
项目:rodi
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)
}