Skip to content

Commit

Permalink
Compatible with redis protocol(RESP)
Browse files Browse the repository at this point in the history
  • Loading branch information
qishenonly committed Jan 24, 2024
1 parent 4a36750 commit e2250d7
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 5 deletions.
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ require (
github.com/spaolacci/murmur3 v1.1.0
github.com/stretchr/testify v1.8.2
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c
github.com/tidwall/redcon v1.6.2
go.etcd.io/bbolt v1.3.7
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/net v0.8.0
golang.org/x/sys v0.6.0
google.golang.org/grpc v1.55.0
google.golang.org/protobuf v1.31.0
)
Expand All @@ -47,13 +50,12 @@ require (
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/panjf2000/ants v1.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/tidwall/btree v1.1.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/panjf2000/ants v1.3.0 h1:8pQ+8leaLc9lys2viEEr8md0U4RN6uOSUCE9bOYjQ9M=
github.com/panjf2000/ants v1.3.0/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down Expand Up @@ -190,6 +188,12 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM=
github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/redcon v1.6.2 h1:5qfvrrybgtO85jnhSravmkZyC0D+7WstbfCs3MmPhow=
github.com/tidwall/redcon v1.6.2/go.mod h1:p5Wbsgeyi2VSTBWOcA5vRXrOb9arFTcU2+ZzFjqV75Y=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
Expand Down
60 changes: 60 additions & 0 deletions lib/redis/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package redis

import (
"fmt"
_const "github.com/ByteStorage/FlyDB/lib/const"
"strings"

"github.com/tidwall/redcon"
)

type FlyDBClient struct {
DB map[int]interface{}
Server *FlyDBServer
}

func NewWrongNumberOfArgsError(cmd string) error {
return fmt.Errorf("ERR wrong number of arguments for '%s' command", cmd)
}

type CmdHandler func(cli *FlyDBClient, args [][]byte) (interface{}, error)

var FlyDBSupportCommands = map[string]CmdHandler{
// string
"use-string": UseString,
"set": Set,
"get": Get,

// hash
"use-hash": UseHash,
"hset": HSet,
"hget": HGet,
}

func ClientCommands(conn redcon.Conn, cmd redcon.Command) {
command := strings.ToLower(string(cmd.Args[0]))
cmdFunc, ok := FlyDBSupportCommands[command]
if !ok {
conn.WriteError("Err unsupported command: '" + command + "'")
return
}

cli, _ := conn.Context().(*FlyDBClient)
switch command {
case "ping":
conn.WriteString("PONG")
case "quit":
_ = conn.Close()
default:
res, err := cmdFunc(cli, cmd.Args[1:])
if err != nil {
if err == _const.ErrKeyNotFound {
conn.WriteNull()
} else {
conn.WriteError(err.Error())
}
return
}
conn.WriteAny(res)
}
}
32 changes: 32 additions & 0 deletions lib/redis/cmd/flydb_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"github.com/ByteStorage/FlyDB/config"
"github.com/ByteStorage/FlyDB/lib/redis"
flydb_stru "github.com/ByteStorage/FlyDB/structure"
"github.com/tidwall/redcon"
)

func main() {
// 打开 Redis 数据结构服务
stringStructure, err := flydb_stru.NewStringStructure(config.DefaultOptions)
if err != nil {
panic(err)
}
hashStructure, err := flydb_stru.NewHashStructure(config.DefaultOptions)
if err != nil {
panic(err)
}

// 初始化 FlyDBServer
flydbServer := &redis.FlyDBServer{
Dbs: make(map[int]interface{}),
}
flydbServer.Dbs[0] = stringStructure
flydbServer.Dbs[1] = hashStructure

// 初始化一个 Redis 服务端
flydbServer.Server = redcon.NewServer(config.DefaultAddr,
redis.ClientCommands, flydbServer.Accept, nil)
flydbServer.Listen()
}
44 changes: 44 additions & 0 deletions lib/redis/hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package redis

import (
"github.com/ByteStorage/FlyDB/structure"
"github.com/tidwall/redcon"
)

func HSet(cli *FlyDBClient, args [][]byte) (interface{}, error) {
if len(args) != 3 {
return nil, NewWrongNumberOfArgsError("hset")
}

var ok = 0
key, field, value := args[0], args[1], args[2]
res, err := cli.DB[1].(*structure.HashStructure).HSet(string(key), field, value)
if err != nil {
return nil, err
}
if res {
ok = 1
}
return redcon.SimpleInt(ok), nil
}

func HGet(cli *FlyDBClient, args [][]byte) (interface{}, error) {
if len(args) != 2 {
return nil, NewWrongNumberOfArgsError("hget")
}

value, err := cli.DB[1].(*structure.HashStructure).HGet(string(args[0]), args[1])
if err != nil {
return nil, err
}
return value, nil
}

func UseHash(cli *FlyDBClient, args [][]byte) (interface{}, error) {
if len(args) != 0 {
return nil, NewWrongNumberOfArgsError("use-hash")
}

cli.DB[0].(*structure.StringStructure).Close()
return redcon.SimpleString("OK"), nil
}
40 changes: 40 additions & 0 deletions lib/redis/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package redis

import (
"github.com/ByteStorage/FlyDB/structure"
"log"
"sync"

"github.com/tidwall/redcon"
)

type FlyDBServer struct {
Dbs map[int]interface{}
Server *redcon.Server
lock sync.RWMutex
}

func (svr *FlyDBServer) Listen() {
log.Println("FlyDB-Redis Server running, ready to accept connections...")
_ = svr.Server.ListenAndServe()
}

func (svr *FlyDBServer) Accept(conn redcon.Conn) bool {
svr.lock.Lock()
defer svr.lock.Unlock()

cli := new(FlyDBClient)
cli.Server = svr
cli.DB = svr.Dbs
conn.SetContext(cli)
return true
}

func (svr *FlyDBServer) Close() error {
if db, ok := svr.Dbs[0].(*structure.StringStructure); ok {
db.Clean()
} else if dbh, ok := svr.Dbs[1].(*structure.HashStructure); ok {
dbh.Clean()
}
return svr.Server.Close()
}
40 changes: 40 additions & 0 deletions lib/redis/string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package redis

import (
"github.com/ByteStorage/FlyDB/structure"
"github.com/tidwall/redcon"
)

func Set(cli *FlyDBClient, args [][]byte) (interface{}, error) {
if len(args) != 2 {
return nil, NewWrongNumberOfArgsError("set")
}

key, value := args[0], args[1]
if err := cli.DB[0].(*structure.StringStructure).Set(string(key), string(value), 0); err != nil {
return nil, err
}
return redcon.SimpleString("OK"), nil
}

func Get(cli *FlyDBClient, args [][]byte) (interface{}, error) {
if len(args) != 1 {
return nil, NewWrongNumberOfArgsError("get")
}

value, err := cli.DB[0].(*structure.StringStructure).Get(string(args[0]))
if err != nil {
return nil, err
}
return value, nil
}

func UseString(cli *FlyDBClient, args [][]byte) (interface{}, error) {
if len(args) != 0 {
return nil, NewWrongNumberOfArgsError("use-string")
}

cli.DB[1].(*structure.HashStructure).Stop()

Check failure on line 37 in lib/redis/string.go

View workflow job for this annotation

GitHub Actions / build (1.18)

Error return value of `(*github.com/ByteStorage/FlyDB/structure.HashStructure).Stop` is not checked (errcheck)

Check failure on line 37 in lib/redis/string.go

View workflow job for this annotation

GitHub Actions / build (1.18)

Error return value of `(*github.com/ByteStorage/FlyDB/structure.HashStructure).Stop` is not checked (errcheck)

return redcon.SimpleString("OK"), nil
}
4 changes: 4 additions & 0 deletions structure/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,3 +627,7 @@ func (s *StringStructure) Stop() error {
func (s *StringStructure) Clean() {
s.db.Clean()
}

func (s *StringStructure) Close() {
s.db.Close()
}

0 comments on commit e2250d7

Please sign in to comment.