Skip to content

Commit

Permalink
Sets structure modified & redis protocol fix
Browse files Browse the repository at this point in the history
  • Loading branch information
diiyw committed Apr 20, 2024
1 parent 248e0e0 commit 9579252
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 79 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,16 @@ Windows 11: 12C/32G
goos: windows
goarch: amd64
pkg: github.com/diiyw/nodis/bench
BenchmarkSet-12 1499077 760.3 ns/op 591 B/op 8 allocs/op
BenchmarkGet-12 8211410 130.9 ns/op 55 B/op 1 allocs/op
BenchmarkLPush-12 1000000 1355 ns/op 663 B/op 10 allocs/op
BenchmarkLPop-12 25775683 46.52 ns/op 49 B/op 1 allocs/op
BenchmarkSAdd-12 1270429 857.2 ns/op 711 B/op 11 allocs/op
BenchmarkSMembers-12 9298605 128.3 ns/op 56 B/op 2 allocs/op
BenchmarkZAdd-12 1358121 946.8 ns/op 598 B/op 11 allocs/op
BenchmarkZRank-12 8748981 137.4 ns/op 55 B/op 1 allocs/op
BenchmarkHSet-12 1295605 861.9 ns/op 791 B/op 12 allocs/op
BenchmarkHGet-12 7266126 144.3 ns/op 55 B/op 1 allocs/op
BenchmarkSet-12 1469863 715.9 ns/op 543 B/op 7 allocs/op
BenchmarkGet-12 12480278 96.47 ns/op 7 B/op 0 allocs/op
BenchmarkLPush-12 1484466 786.2 ns/op 615 B/op 9 allocs/op
BenchmarkLPop-12 77275986 15.10 ns/op 0 B/op 0 allocs/op
BenchmarkSAdd-12 1542252 831.9 ns/op 663 B/op 10 allocs/op
BenchmarkSMembers-12 12739020 95.18 ns/op 8 B/op 1 allocs/op
BenchmarkZAdd-12 1000000 1177 ns/op 550 B/op 10 allocs/op
BenchmarkZRank-12 11430135 104.1 ns/op 7 B/op 0 allocs/op
BenchmarkHSet-12 1341817 863.5 ns/op 743 B/op 11 allocs/op
BenchmarkHGet-12 9801158 105.9 ns/op 7 B/op 0 allocs/op
```
Linux VM: 2C/8GB
```bash
Expand Down
25 changes: 13 additions & 12 deletions ds/set/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

type Set struct {
data btree.Set[string]
data btree.Map[string, struct{}]
}

// NewSet creates a new set
Expand All @@ -23,7 +23,7 @@ func (s *Set) SAdd(member ...string) int64 {

func (s *Set) sAdd(member ...string) int64 {
for _, m := range member {
s.data.Insert(m)
s.data.Set(m, struct{}{})
}
return int64(len(member))
}
Expand All @@ -36,10 +36,10 @@ func (s *Set) SCard() int64 {
// SDiff gets the difference between sets.
func (s *Set) SDiff(sets ...*Set) []string {
diff := make([]string, 0, 32)
s.data.Scan(func(member string) bool {
s.data.Scan(func(member string, _ struct{}) bool {
found := false
for _, set := range sets {
found = set.data.Contains(member)
_, found = set.data.Get(member)
if found {
break
}
Expand All @@ -63,10 +63,10 @@ func (s *Set) SDiffStore(destination *Set, sets ...*Set) {
// SInter gets the intersection between sets.
func (s *Set) SInter(sets ...*Set) []string {
inter := make([]string, 0, 32)
s.data.Scan(func(member string) bool {
s.data.Scan(func(member string, _ struct{}) bool {
found := true
for _, set := range sets {
found = set.data.Contains(member)
_, found = set.data.Get(member)
if !found {
break
}
Expand Down Expand Up @@ -94,7 +94,8 @@ func (s *Set) SMembers() []string {

// SIsMember checks if a member is in the set.
func (s *Set) SIsMember(member string) bool {
return s.data.Contains(member)
_, ok := s.data.Get(member)
return ok
}

// SRem removes a member from the set.
Expand All @@ -116,7 +117,7 @@ func (s *Set) SPop(count int64) []string {
count = int64(s.data.Len())
}
members := make([]string, 0, count)
s.data.Scan(func(member string) bool {
s.data.Scan(func(member string, _ struct{}) bool {
if count > 0 {
s.data.Delete(member)
members = append(members, member)
Expand All @@ -131,8 +132,8 @@ func (s *Set) SPop(count int64) []string {
func (s *Set) SUnion(sets ...*Set) []string {
union := s.data.Keys()
for _, set := range sets {
set.data.Scan(func(member string) bool {
if !s.data.Contains(member) {
set.data.Scan(func(member string, _ struct{}) bool {
if _, ok := s.data.Get(member); !ok {
union = append(union, member)
}
return true
Expand All @@ -155,7 +156,7 @@ func (s *Set) SScan(cursor int64, match string, count int64) (int64, []string) {
if cursor >= int64(s.data.Len()) {
return 0, nil
}
s.data.Scan(func(member string) bool {
s.data.Scan(func(member string, _ struct{}) bool {
if count > 0 && int64(len(keys)) >= count {
return false
}
Expand All @@ -180,6 +181,6 @@ func (s *Set) GetValue() []string {
// SetValue the bytes to string
func (s *Set) SetValue(members []string) {
for _, member := range members {
s.data.Insert(member)
s.data.Set(member, struct{}{})
}
}
34 changes: 13 additions & 21 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func init() {
redisCommands.Set("CONFIG", config)
redisCommands.Set("PING", ping)
redisCommands.Set("QUIT", quit)
redisCommands.Set("FLUSHDB", flushdb)
redisCommands.Set("FLUSHDB", flushDB)
redisCommands.Set("INFO", info)
redisCommands.Set("DEL", del)
redisCommands.Set("EXISTS", exists)
Expand Down Expand Up @@ -106,45 +106,37 @@ func client(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {

func config(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {
if len(args) == 0 {
return redis.ErrorValue("CONFIG subcommand must be provided")
return redis.ErrorValue("CONFIG GET requires at least one argument")
}
switch strings.ToUpper(args[0].Bulk) {
case "GET":
if len(args) == 1 {
return redis.ErrorValue("CONFIG GET requires at least one argument")
}
if args[1].Bulk == "databases" {
if cmd.Options["GET"] {
if args[0].Bulk == "databases" {
return redis.ArrayValue(redis.StringValue("databases"), redis.IntegerValue(0))
}
return redis.BulkValue("CONFIG GET")
case "SET":
if len(args) == 1 {
return redis.ErrorValue("CONFIG SET requires at least one argument")
}
return redis.BulkValue("CONFIG SET")
default:
return redis.ErrorValue("CONFIG subcommand must be provided")
}
if cmd.Options["SET"] {

}
return redis.NullValue()
}

func info(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {
memStats := runtime.MemStats{}
runtime.ReadMemStats(&memStats)
usedMemory := strconv.FormatUint(memStats.Sys, 10)
usedMemory := strconv.FormatUint(memStats.HeapInuse+memStats.StackInuse, 10)
pid := strconv.Itoa(os.Getpid())
return redis.BulkValue(`# Server
redis_version:6.0.0
nodis_version:1.3.0
os:` + runtime.GOOS + `
process_id:` + pid + `
# Memory
used_memory:` + usedMemory)
used_memory:` + usedMemory + `
`)
}

func flushdb(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {
func flushDB(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {
n.Clear()
return redis.StringValue("OK")

}

func quit(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {
Expand All @@ -153,7 +145,7 @@ func quit(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {

func ping(n *Nodis, cmd redis.Value, args []redis.Value) redis.Value {
if len(args) == 0 {
return redis.StringValue("PONG")
return redis.BulkValue("PONG")
}
return redis.BulkValue(args[0].Bulk)
}
Expand Down
71 changes: 36 additions & 35 deletions redis/resp.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import (
)

const (
STRING = '+'
ERROR = '-'
INTEGER = ':'
BULK = '$'
ARRAY = '*'
MAP = '%'
DOUBLE = ','
StringType = '+'
ErrType = '-'
IntegerType = ':'
BulkType = '$'
ArrayType = '*'
MapType = '%'
DoubleType = ','
NullType = '_'
)

var (
Expand All @@ -42,7 +43,7 @@ var (
)

type Value struct {
typ string
typ uint8
Str string
Integer int64
Bulk string
Expand All @@ -54,35 +55,35 @@ type Value struct {
}

func StringValue(v string) Value {
return Value{typ: "string", Str: v}
return Value{typ: StringType, Str: v}
}

func ErrorValue(v string) Value {
return Value{typ: "error", Str: v}
return Value{typ: ErrType, Str: v}
}

func BulkValue(v string) Value {
return Value{typ: "bulk", Bulk: v}
return Value{typ: BulkType, Bulk: v}
}

func IntegerValue(v int64) Value {
return Value{typ: "integer", Integer: v}
return Value{typ: IntegerType, Integer: v}
}

func DoubleValue(v float64) Value {
return Value{typ: "double", Double: v}
return Value{typ: DoubleType, Double: v}
}

func ArrayValue(v ...Value) Value {
return Value{typ: "array", Array: v}
return Value{typ: ArrayType, Array: v}
}

func MapValue(v map[string]Value) Value {
return Value{typ: "map", Map: v}
return Value{typ: MapType, Map: v}
}

func NullValue() Value {
return Value{typ: "null"}
return Value{typ: NullType}
}

type Resp struct {
Expand Down Expand Up @@ -128,9 +129,9 @@ func (r *Resp) Read() (Value, error) {
}

switch _type {
case ARRAY:
case ArrayType:
return r.readArray()
case BULK:
case BulkType:
return r.readBulk()
default:
log.Printf("Unknown type: %v \n", string(_type))
Expand All @@ -143,7 +144,7 @@ func (r *Resp) readArray() (Value, error) {
Options: make(map[string]bool),
Args: make(map[string]Value),
}
v.typ = "array"
v.typ = ArrayType

// read length of array
l, _, err := r.readInteger()
Expand Down Expand Up @@ -185,7 +186,7 @@ func (r *Resp) readArray() (Value, error) {
func (r *Resp) readBulk() (Value, error) {
v := Value{}

v.typ = "bulk"
v.typ = BulkType

l, _, err := r.readInteger()
if err != nil {
Expand All @@ -207,21 +208,21 @@ func (r *Resp) readBulk() (Value, error) {
// Marshal Value to bytes
func (v Value) Marshal() []byte {
switch v.typ {
case "array":
case ArrayType:
return v.marshalArray()
case "bulk":
case BulkType:
return v.marshalBulk()
case "string":
case StringType:
return v.marshalString()
case "null":
case NullType:
return v.marshallNull()
case "error":
case ErrType:
return v.marshallError()
case "integer":
case IntegerType:
return v.marshallInteger()
case "map":
case MapType:
return v.marshallMap()
case "double":
case DoubleType:
return v.marshallDouble()
default:
return []byte{}
Expand All @@ -230,7 +231,7 @@ func (v Value) Marshal() []byte {

func (v Value) marshalString() []byte {
var bytes []byte
bytes = append(bytes, STRING)
bytes = append(bytes, StringType)
bytes = append(bytes, v.Str...)
bytes = append(bytes, '\r', '\n')

Expand All @@ -239,7 +240,7 @@ func (v Value) marshalString() []byte {

func (v Value) marshalBulk() []byte {
var bytes []byte
bytes = append(bytes, BULK)
bytes = append(bytes, BulkType)
bytes = append(bytes, strconv.Itoa(len(v.Bulk))...)
bytes = append(bytes, '\r', '\n')
bytes = append(bytes, v.Bulk...)
Expand All @@ -251,7 +252,7 @@ func (v Value) marshalBulk() []byte {
func (v Value) marshalArray() []byte {
l := len(v.Array)
var bytes []byte
bytes = append(bytes, ARRAY)
bytes = append(bytes, ArrayType)
bytes = append(bytes, strconv.Itoa(l)...)
bytes = append(bytes, '\r', '\n')

Expand All @@ -264,7 +265,7 @@ func (v Value) marshalArray() []byte {

func (v Value) marshallError() []byte {
var bytes []byte
bytes = append(bytes, ERROR)
bytes = append(bytes, ErrType)
bytes = append(bytes, v.Str...)
bytes = append(bytes, '\r', '\n')

Expand All @@ -277,23 +278,23 @@ func (v Value) marshallNull() []byte {

func (v Value) marshallInteger() []byte {
var bytes []byte
bytes = append(bytes, INTEGER)
bytes = append(bytes, IntegerType)
bytes = append(bytes, strconv.FormatInt(v.Integer, 10)...)
bytes = append(bytes, '\r', '\n')
return bytes
}

func (v Value) marshallDouble() []byte {
var bytes []byte
bytes = append(bytes, DOUBLE)
bytes = append(bytes, DoubleType)
bytes = append(bytes, strconv.FormatFloat(v.Double, 'f', -1, 64)...)
bytes = append(bytes, '\r', '\n')
return bytes
}

func (v Value) marshallMap() []byte {
var bytes []byte
bytes = append(bytes, MAP)
bytes = append(bytes, MapType)
bytes = append(bytes, strconv.Itoa(len(v.Map))...)
bytes = append(bytes, '\r', '\n')
for k, v := range v.Map {
Expand Down
2 changes: 1 addition & 1 deletion redis/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func handleConn(conn net.Conn, handler func(cmd Value, args []Value) Value) {
return
}

if value.typ != "array" {
if value.typ != ArrayType {
log.Println("Invalid request, expected array")
continue
}
Expand Down

0 comments on commit 9579252

Please sign in to comment.