diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/cmd/server/config.toml b/cmd/server/config.toml new file mode 100644 index 0000000..76efb65 --- /dev/null +++ b/cmd/server/config.toml @@ -0,0 +1,2 @@ +[server] +address = ":6379" diff --git a/cmd/server/handlers.go b/cmd/server/handlers.go new file mode 100644 index 0000000..1b7ea42 --- /dev/null +++ b/cmd/server/handlers.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + + "github.com/tidwall/redcon" +) + +func (app *App) ping(conn redcon.Conn, cmd redcon.Command) { + conn.WriteString("PONG") +} + +func (app *App) quit(conn redcon.Conn, cmd redcon.Command) { + conn.WriteString("OK") + conn.Close() +} + +func (app *App) set(conn redcon.Conn, cmd redcon.Command) { + if len(cmd.Args) != 3 { + conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command") + return + } + var ( + key = string(cmd.Args[1]) + val = cmd.Args[2] + ) + if err := app.barrel.Put(key, val); err != nil { + conn.WriteString(fmt.Sprintf("ERR: %s", err)) + return + } + + conn.WriteString("OK") +} + +func (app *App) get(conn redcon.Conn, cmd redcon.Command) { + if len(cmd.Args) != 2 { + conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command") + return + } + var ( + key = string(cmd.Args[1]) + ) + val, err := app.barrel.Get(key) + if err != nil { + conn.WriteString(fmt.Sprintf("ERR: %s", err)) + return + } + + conn.WriteBulk(val) +} diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..ae022bf --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "log" + "os" + + "github.com/mr-karan/barreldb/pkg/barrel" + "github.com/tidwall/redcon" +) + +var ( + // Version of the build. This is injected at build-time. + buildString = "unknown" + lo = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile) + addr = ":6380" +) + +type App struct { + barrel *barrel.Barrel +} + +func main() { + barrel, err := barrel.Init(barrel.Opts{ + Dir: ".", + ReadOnly: false, + EnableFSync: true, + MaxFileSize: 1 << 4, + }) + if err != nil { + lo.Fatal("error opening barrel db: %w", err) + } + + app := &App{ + barrel: barrel, + } + + mux := redcon.NewServeMux() + mux.HandleFunc("ping", app.ping) + mux.HandleFunc("quit", app.quit) + mux.HandleFunc("set", app.set) + mux.HandleFunc("get", app.get) + // mux.HandleFunc("del", app.delete) + + err = redcon.ListenAndServe(addr, + mux.ServeRESP, + func(conn redcon.Conn) bool { + // use this function to accept or deny the connection. + return true + }, + func(conn redcon.Conn, err error) { + // this is called when the connection has been closed + }, + ) + if err != nil { + lo.Fatal("error starting server: %w", err) + } + +} diff --git a/go.mod b/go.mod index 0e6fe51..caa4938 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,12 @@ module github.com/mr-karan/barreldb go 1.19 -require golang.org/x/sys v0.2.0 +require ( + github.com/tidwall/redcon v1.6.0 + golang.org/x/sys v0.2.0 +) + +require ( + github.com/tidwall/btree v1.1.0 // indirect + github.com/tidwall/match v1.1.1 // indirect +) diff --git a/go.sum b/go.sum index beac707..38b54e6 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,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.0 h1:ekkYf2xwk1+VmyTVrefZElJC71EK/1JOLwlGSllmPIk= +github.com/tidwall/redcon v1.6.0/go.mod h1:p5Wbsgeyi2VSTBWOcA5vRXrOb9arFTcU2+ZzFjqV75Y= golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/barrel/barrel.go b/pkg/barrel/barrel.go index b1fc42d..7d2c528 100644 --- a/pkg/barrel/barrel.go +++ b/pkg/barrel/barrel.go @@ -38,7 +38,6 @@ type Opts struct { // Init initialises a datastore for storing data. func Init(opts Opts) (*Barrel, error) { - // Initialise logger. // TODO: Check for stale files and create an index automatically. var ( @@ -81,9 +80,9 @@ func Init(opts Opts) (*Barrel, error) { // TODO: Add a sane default later. opts.MergeInterval = time.Second * 5 } - go barrel.MergeFiles(opts.MergeInterval) - // Spawn a goroutine which checks for the file size of the active file at periodic interval. - go barrel.ExamineFileSize(time.Minute * 1) + // go barrel.MergeFiles(opts.MergeInterval) + // // Spawn a goroutine which checks for the file size of the active file at periodic interval. + // go barrel.ExamineFileSize(time.Minute * 1) return barrel, nil }