Add implementation of the SETNX command

This is an optimized "SET if not exists" command,
which basically does an EXISTS call before the SET.
This commit is contained in:
Anders F Björklund 2023-02-19 13:23:40 +01:00
parent 9f71787fcd
commit 45df01b385
5 changed files with 72 additions and 0 deletions

View File

@ -34,6 +34,7 @@ Here's a full example of a Redis clone that accepts:
- SET key value - SET key value
- GET key - GET key
- SETNX key value
- DEL key - DEL key
- PING - PING
- QUIT - QUIT
@ -96,6 +97,22 @@ func main() {
} else { } else {
conn.WriteBulk(val) conn.WriteBulk(val)
} }
case "setnx":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.RLock()
_, ok := items[string(cmd.Args[1])]
mu.RUnlock()
if ok {
conn.WriteInt(0)
return
}
mu.Lock()
items[string(cmd.Args[1])] = cmd.Args[2]
mu.Unlock()
conn.WriteInt(1)
case "del": case "del":
if len(cmd.Args) != 2 { if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command") conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")

View File

@ -82,6 +82,22 @@ func main() {
} else { } else {
conn.WriteBulk(val) conn.WriteBulk(val)
} }
case "setnx":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.RLock()
_, ok := items[string(cmd.Args[1])]
mu.RUnlock()
if ok {
conn.WriteInt(0)
return
}
mu.Lock()
items[string(cmd.Args[1])] = cmd.Args[2]
mu.Unlock()
conn.WriteInt(1)
case "del": case "del":
if len(cmd.Args) != 2 { if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command") conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")

View File

@ -19,6 +19,7 @@ func main() {
mux.HandleFunc("quit", handler.quit) mux.HandleFunc("quit", handler.quit)
mux.HandleFunc("set", handler.set) mux.HandleFunc("set", handler.set)
mux.HandleFunc("get", handler.get) mux.HandleFunc("get", handler.get)
mux.HandleFunc("setnx", handler.setnx)
mux.HandleFunc("del", handler.delete) mux.HandleFunc("del", handler.delete)
err := redcon.ListenAndServe(addr, err := redcon.ListenAndServe(addr,

View File

@ -68,6 +68,28 @@ func (h *Handler) get(conn redcon.Conn, cmd redcon.Command) {
} }
} }
func (h *Handler) setnx(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
}
h.itemsMux.RLock()
_, ok := h.items[string(cmd.Args[1])]
h.itemsMux.RUnlock()
if ok {
conn.WriteInt(0)
return
}
h.itemsMux.Lock()
h.items[string(cmd.Args[1])] = cmd.Args[2]
h.itemsMux.Unlock()
conn.WriteInt(1)
}
func (h *Handler) delete(conn redcon.Conn, cmd redcon.Command) { func (h *Handler) delete(conn redcon.Conn, cmd redcon.Command) {
if len(cmd.Args) != 2 { if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command") conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")

View File

@ -88,6 +88,22 @@ func main() {
} else { } else {
conn.WriteBulk(val) conn.WriteBulk(val)
} }
case "setnx":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.RLock()
_, ok := items[string(cmd.Args[1])]
mu.RUnlock()
if ok {
conn.WriteInt(0)
return
}
mu.Lock()
items[string(cmd.Args[1])] = cmd.Args[2]
mu.Unlock()
conn.WriteInt(1)
case "del": case "del":
if len(cmd.Args) != 2 { if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command") conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")