diff options
Diffstat (limited to 'handlers.go')
| -rw-r--r-- | handlers.go | 672 |
1 files changed, 0 insertions, 672 deletions
diff --git a/handlers.go b/handlers.go deleted file mode 100644 index 1569771..0000000 --- a/handlers.go +++ /dev/null @@ -1,672 +0,0 @@ -package main - -import ( - "errors" - "net" - "path/filepath" - "redisClone/pkg/core" - "sort" - "strconv" - "time" -) - -func handleGet(args []string)interface{} { - if len(args) != 2 { - err := errors.New("wrong number of arguments for 'GET'") - return err - } - - key := args[1] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{}{ - item, exists := s.Data[key] - if !exists { - return nil - } - - if item.ExpiresAt != nil && time.Now().After(*item.ExpiresAt) { - delete(s.Data, key) - return nil - } - - strValue, ok := item.Value.(string) - if !ok { - err := errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - return err - } - return strValue - }) - - return result -} - -func handleExists(args []string)interface{} { - if len(args) != 2 { - err := errors.New("wrong number of arguments for 'EXISTS'") - return err - } - - key := args[1] - result := db.ExecuteRead(key, func(s *core.Shard) interface{}{ - _, exists := s.Data[key] - if exists { - return 1 - } else { - return 0 - } - }) - - return result -} - -func handleSet(args []string)interface{} { - if len(args) != 3 { - err := errors.New("wrong number of arguments for 'SET'") - return err - } - - key := args[1] - result := db.Execute(key, func(s *core.Shard) interface{}{ - item := core.Item{Value: args[2]} - s.Data[key] = item - return core.SimpleString("OK") - }) - - return result -} - -func handleDel(args []string)interface{} { - - if len(args) < 2 { - err := errors.New("wrong number of arguments for 'DEL'") - return err - } - keys := args[1:] - deletedKeys := db.ExecuteMulti(keys, func(shards []*core.Shard) interface{}{ - count := 0 - for _, key := range keys{ - shard := db.GetShard(key) - _, exists := shard.Data[key] - if exists { - delete(shard.Data, key) - count += 1 - } - } - return count - }) - - return deletedKeys -} - - -func handleIncr(args []string)interface{} { - - if len(args) != 2 { - err := errors.New("wrong number of arguments for 'INCR'") - return err - } - - key := args[1] - result := db.Execute(key, func(s *core.Shard)interface{}{ - item, exists := s.Data[key] - if exists { - strValue, ok := item.Value.(string) - if !ok { - err := errors.New("value is not an integer or out of range") - return err - } - - currentInt, err := strconv.Atoi(strValue) - if err != nil { - err := errors.New("value is not an integer or out of range") - return err - } - - newValueStr := strconv.Itoa(currentInt + 1) - s.Data[key] = core.Item{Value: newValueStr} - return currentInt + 1 - } else { - s.Data[key] = core.Item{Value: "1"} - return 1 - } - - }) - - return result -} - -func handleDecr(args []string)interface{} { - - if len(args) != 2 { - err := errors.New("wrong number of arguments for 'DECR'") - return err - } - - key := args[1] - result := db.Execute(key, func(s *core.Shard)interface{}{ - item, exists := s.Data[key] - if exists { - strValue, ok := item.Value.(string) - if !ok { - err := errors.New("value is not an integer or out of range") - return err - } - - currentInt, err := strconv.Atoi(strValue) - if err != nil { - err := errors.New("value is not an integer or out of range") - return err - } - - newValueStr := strconv.Itoa(currentInt + 1) - s.Data[key] = core.Item{Value: newValueStr} - return currentInt - 1 - } else { - s.Data[key] = core.Item{Value: "1"} - return -1 - } - - }) - return result -} - -func handlePing(conn net.Conn, args []string) { - conn.Write(core.SerializeRESP(core.SimpleString("OK"))) -} - -func handleFlushall(args []string)interface{} { - if len(args) != 1 { - err := errors.New("wrong number of arguments for 'FLUSHALL'") - return err - } - result := db.ExecuteAll(func(shards []*core.Shard)interface{}{ - for _, shard := range shards{ - shard.Data = make(map[string]core.Item) - } - return core.SimpleString("OK") - }) - return result -} - -func handleRename(args []string)interface{}{ - if len(args) != 3 { - err := errors.New("wrong number of arguments for 'RENAME'") - return err - } - keys := args[1:] - - result := db.ExecuteMulti(keys,func(shards []*core.Shard)interface{}{ - item, exists := db.GetShard(keys[0]).Data[keys[0]] - if !exists { - - return errors.New("no such key") - } - - db.GetShard(keys[1]).Data[keys[1]] = item - delete(db.GetShard(keys[0]).Data, keys[0]) - - return core.SimpleString("OK") - }) - return result -} - -func handleRpush(args []string)interface{} { - if len(args) < 3 { - err := errors.New("wrong number of arguments for 'RPUSH'") - return err - } - key := args[1] - newItems := args[2:] - - result := db.Execute(key, func(s *core.Shard) interface{} { - var list []string - existingItem, exists := s.Data[key] - if exists { - var ok bool - list, ok = existingItem.Value.([]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - } else { - list = []string{} - } - list = append(list, newItems...) - s.Data[key] = core.Item{Value: list} - return len(list) - }) - return result -} - -func handleLpush(args []string)interface{} { - if len(args) < 3 { - err := errors.New("wrong number of arguments for 'LPUSH'") - return err - } - key := args[1] - newItems := args[2:] - - result := db.Execute(key, func(s *core.Shard) interface{} { - var list []string - existingItem, exists := s.Data[key] - if exists { - var ok bool - list, ok = existingItem.Value.([]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - } else { - list = []string{} - } - list = append(newItems, list...) - s.Data[key] = core.Item{Value: list} - return len(list) - }) - - return result -} - -func handleLrange(args []string)interface{} { - if len(args) != 4 { - err := errors.New("wrong number of arguments for 'LRANGE'") - return err - } - start, err1 := strconv.Atoi(args[2]) - stop, err2 := strconv.Atoi(args[3]) - if err1 != nil || err2 != nil { - err := errors.New("value is not an integer or out of range") - return err - } - key := args[1] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return []string{} - } - if item.ExpiresAt != nil && time.Now().After(*item.ExpiresAt) { - delete(s.Data, key) - return nil - } - typedList, ok := item.Value.([]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - size := len(typedList) - if start < 0 { - start += size - if start < 0 { - start = 0 - } - } - if stop < 0 { - stop += size - if stop < 0 { - stop = 0 - } - } - if stop >= size { - stop = size - 1 - } - if start > stop || start >= size { - return []string{} - } - return typedList[start : stop+1] - }) - return result -} - -func handleLpop(args []string)interface{} { - if len(args) != 2 { - err := errors.New("wrong number of arguments for 'LPOP'") - return err - } - key := args[1] - - result := db.Execute(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return nil - } - typedList, ok := item.Value.([]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - if len(typedList) == 0 { - return nil - } - newItem := typedList[0] - newList := typedList[1:] - if len(newList) <= 0 { - delete(s.Data, key) - } else { - s.Data[key] = core.Item{Value: newList} - } - return newItem - }) - return result -} - -func handleRpop(args []string)interface{} { - if len(args) != 2 { - err := errors.New("wrong number of arguments for 'RPOP'") - return err - } - key := args[1] - - result := db.Execute(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return nil - } - typedList, ok := item.Value.([]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - if len(typedList) == 0 { - return nil - } - newItem := typedList[len(typedList)-1] - newList := typedList[:len(typedList)-1] - if len(newList) <= 0 { - delete(s.Data, key) - } else { - s.Data[key] = core.Item{Value: newList} - } - return newItem - }) - return result -} - -func handleExpire(args []string)interface{} { - if len(args) != 3 { - return errors.New("wrong number of arguments for 'EXPIRE'") - } - key := args[1] - seconds, err := strconv.Atoi(args[2]) - if err != nil { - return errors.New("value is not an integer") - } - - result := db.Execute(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return 0 - } - expiry := time.Now().Add(time.Duration(seconds) * time.Second) - item.ExpiresAt = &expiry - s.Data[key] = item - return 1 - }) - return result -} - -func handleHset(args []string)interface{}{ - if len(args) < 4 || (len(args)-2)%2 != 0 { - err := errors.New("wrong number of arguments for 'HSET'") - return err - } - key := args[1] - - result := db.Execute(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - var hash map[string]string - if exists { - var ok bool - hash, ok = item.Value.(map[string]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - } else { - hash = make(map[string]string) - } - count := 0 - for i := 2; i < len(args); i += 2 { - hash[args[i]] = args[i+1] - count++ - } - s.Data[key] = core.Item{Value: hash} - return count - }) - return result -} - -func handleHget(args []string)interface{} { - if len(args) != 3 { - return errors.New("wrong number of arguments for 'HGET'") - } - key := args[1] - field := args[2] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return nil - } - hash, ok := item.Value.(map[string]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - val, found := hash[field] - if !found { - return nil - } - return val - }) - return result -} - -func handleHgetall(args []string)interface{} { - if len(args) != 2 { - return errors.New("wrong number of arguments for 'HGETALL'") - } - key := args[1] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return nil - } - hash, ok := item.Value.(map[string]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - return hash - }) - return result -} - -func handleHkeys(args []string)interface{} { - if len(args) != 2 { - return errors.New("wrong number of arguments for 'HKEYS'") - } - key := args[1] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return nil - } - hash, ok := item.Value.(map[string]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - keys := make([]string, 0, len(hash)) - for k := range hash { - keys = append(keys, k) - } - return keys - }) - return result -} - -func handleHvalues(args []string)interface{} { - if len(args) != 2 { - return errors.New("wrong number of arguments for 'HVALUES'") - } - key := args[1] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return nil - } - hash, ok := item.Value.(map[string]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - values := make([]string, 0, len(hash)) - for _, v := range hash { - values = append(values, v) - } - return values - }) - return result -} - -func handleType(args []string)interface{} { - if len(args) != 2 { - return errors.New("wrong number of arguments for 'TYPE'") - } - key := args[1] - - result := db.ExecuteRead(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return core.SimpleString("none") - } - switch item.Value.(type) { - case string: - return core.SimpleString("string") - case []string: - return core.SimpleString("list") - case map[string]string: - return core.SimpleString("hash") - default: - return core.SimpleString("unknown") - } - }) - return result -} - -func handleDbsize(args []string)interface{} { - if len(args) != 1 { - return errors.New("wrong number of arguments for 'DBSIZE'") - } - result := db.ExecuteReadAll(func(shards []*core.Shard) interface{} { - count := 0 - for _, shard := range shards { - count += len(shard.Data) - } - return count - }) - return result -} - -func handleKeys(args []string)interface{} { - if len(args) < 2 || len(args) > 3 { - return errors.New("wrong number of arguments for 'KEYS'") - } - pattern := args[1] - limit := -1 - if len(args) == 3 { - val, err := strconv.Atoi(args[2]) - if err != nil { - return errors.New("value is not an integer") - } - limit = val - } - - result := db.ExecuteReadAll(func(shards []*core.Shard) interface{} { - var matches []string - for _, shard := range shards { - for key := range shard.Data { - matched, err := filepath.Match(pattern, key) - if err != nil { - return errors.New("illegal glob pattern") - } - if matched { - matches = append(matches, key) - } - } - } - sort.Strings(matches) - if limit != -1 && len(matches) > limit { - matches = matches[:limit] - } - return matches - }) - return result -} - -func handleLrem(args []string)interface{} { - if len(args) != 4 { - return errors.New("wrong number of arguments for 'LREM'") - } - key := args[1] - count, err := strconv.Atoi(args[2]) - toBeRemoved := args[3] - if err != nil { - return errors.New("value is not an integer") - } - - result := db.Execute(key, func(s *core.Shard) interface{} { - item, exists := s.Data[key] - if !exists { - return 0 - } - list, ok := item.Value.([]string) - if !ok { - return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - } - - counter := 0 - absCount := count - if count < 0 { - absCount = -count - } - - var newList []string - if count == 0 { - newList = []string{} - for _, value := range list { - if value == toBeRemoved { - counter++ - } else { - newList = append(newList, value) - } - } - } else if count > 0 { - newList = []string{} - for _, value := range list { - if value == toBeRemoved && counter < absCount { - counter++ - } else { - newList = append(newList, value) - } - } - } else { // count < 0 - reversedNewList := []string{} - for i := len(list) - 1; i >= 0; i-- { - value := list[i] - if value == toBeRemoved && counter < absCount { - counter++ - } else { - reversedNewList = append(reversedNewList, value) - } - } - newList = make([]string, len(reversedNewList)) - for i, v := range reversedNewList { - newList[len(reversedNewList)-1-i] = v - } - } - - if len(newList) == 0 { - delete(s.Data, key) - } else { - item.Value = newList - s.Data[key] = item - } - return counter - }) - return result -}
\ No newline at end of file |
