Skip to content

Commit e7bb29b

Browse files
authored
Merge pull request #1 from redis-go/list
List
2 parents 26aa282 + 928ef5c commit e7bb29b

35 files changed

+1336
-203
lines changed

Gopkg.lock

+11-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ go get -u github.com/redis-go/redis
3939
- [x] active key expirer
4040
- [ ] Implementing data structures
4141
- [x] String
42-
- [ ] List
42+
- [x] List
4343
- [ ] Set
4444
- [ ] Sorted Set
4545
- [ ] Hash

client.go

+9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ func (r *Redis) NewClient(conn redcon.Conn) *Client {
3434
return c
3535
}
3636

37+
// NextClientId atomically gets and increments a counter to return the next client id.
38+
func (r *Redis) NextClientId() ClientId {
39+
r.Mu().Lock()
40+
defer r.Mu().Unlock()
41+
id := r.nextClientId
42+
r.nextClientId++
43+
return id
44+
}
45+
3746
// Clients gets the current connected clients.
3847
func (r *Redis) Clients() Clients {
3948
r.Mu().RLock()

del.go renamed to cmd_del.go

File renamed without changes.

get.go renamed to cmd_get.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ func GetCommand(c *Client, cmd redcon.Command) {
1414
return
1515
}
1616

17-
if i.ValueType() != StringType {
18-
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.ValueTypeFancy(), StringTypeFancy))
17+
if i.Type() != StringType {
18+
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.TypeFancy(), StringTypeFancy))
1919
return
2020
}
2121

cmd_lpop.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package redis
2+
3+
import (
4+
"fmt"
5+
"github.com/redis-go/redcon"
6+
)
7+
8+
func LPopCommand(c *Client, cmd redcon.Command) {
9+
if len(cmd.Args) < 2 {
10+
c.Conn().WriteError(fmt.Sprintf(WrongNumOfArgsErr, "lpop"))
11+
return
12+
}
13+
key := string(cmd.Args[1])
14+
15+
db := c.Db()
16+
i := db.GetOrExpire(&key, true)
17+
if i == nil {
18+
c.Conn().WriteNull()
19+
return
20+
} else if i.Type() != ListType {
21+
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.TypeFancy(), ListTypeFancy))
22+
return
23+
}
24+
25+
l := i.(*List)
26+
c.Redis().Mu().Lock()
27+
v, b := l.LPop()
28+
if b {
29+
db.Delete(&key)
30+
}
31+
c.Redis().Mu().Unlock()
32+
33+
c.Conn().WriteBulkString(*v)
34+
}

cmd_lpush.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package redis
2+
3+
import (
4+
"fmt"
5+
"github.com/redis-go/redcon"
6+
"time"
7+
)
8+
9+
func LPushCommand(c *Client, cmd redcon.Command) {
10+
if len(cmd.Args) < 3 {
11+
c.Conn().WriteError(fmt.Sprintf(WrongNumOfArgsErr, "lpush"))
12+
return
13+
}
14+
key := string(cmd.Args[1])
15+
fmt.Println("KEY:", key)
16+
db := c.Db()
17+
i := db.GetOrExpire(&key, true)
18+
if i == nil {
19+
i = NewList()
20+
db.Set(&key, i, false, time.Time{})
21+
fmt.Println("CREATED NEW LIST")
22+
} else if i.Type() != ListType {
23+
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.TypeFancy(), ListTypeFancy))
24+
return
25+
}
26+
27+
l := i.(*List)
28+
var length int
29+
c.Redis().Mu().Lock()
30+
for j := 2; j < len(cmd.Args); j++ {
31+
v := string(cmd.Args[j])
32+
length = l.LPush(&v)
33+
}
34+
c.Redis().Mu().Unlock()
35+
36+
c.Conn().WriteInt(length)
37+
}

cmd_lrange.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package redis
2+
3+
import (
4+
"fmt"
5+
"github.com/redis-go/redcon"
6+
"strconv"
7+
)
8+
9+
func LRangeCommand(c *Client, cmd redcon.Command) {
10+
if len(cmd.Args) < 3 {
11+
c.Conn().WriteError(fmt.Sprintf(WrongNumOfArgsErr, "lrange"))
12+
return
13+
}
14+
key := string(cmd.Args[1])
15+
start, err := strconv.Atoi(string(cmd.Args[2]))
16+
if err != nil {
17+
c.Conn().WriteError(fmt.Sprintf("%s: %s", InvalidIntErr, err.Error()))
18+
return
19+
}
20+
end, err := strconv.Atoi(string(cmd.Args[3]))
21+
if err != nil {
22+
c.Conn().WriteError(fmt.Sprintf("%s: %s", InvalidIntErr, err.Error()))
23+
return
24+
}
25+
26+
db := c.Db()
27+
i := db.GetOrExpire(&key, true)
28+
if i == nil {
29+
c.Conn().WriteNull()
30+
return
31+
} else if i.Type() != ListType {
32+
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.TypeFancy(), ListTypeFancy))
33+
return
34+
}
35+
36+
l := i.(*List)
37+
c.Redis().Mu().RLock()
38+
values := l.LRange(start, end)
39+
c.Redis().Mu().RUnlock()
40+
41+
c.Conn().WriteArray(len(values))
42+
for _, v := range values {
43+
c.Conn().WriteBulkString(v)
44+
}
45+
}

ping.go renamed to cmd_ping.go

File renamed without changes.

cmd_rpop.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package redis
2+
3+
import (
4+
"fmt"
5+
"github.com/redis-go/redcon"
6+
)
7+
8+
func RPopCommand(c *Client, cmd redcon.Command) {
9+
if len(cmd.Args) < 2 {
10+
c.Conn().WriteError(fmt.Sprintf(WrongNumOfArgsErr, "rpop"))
11+
return
12+
}
13+
key := string(cmd.Args[1])
14+
15+
db := c.Db()
16+
i := db.GetOrExpire(&key, true)
17+
if i == nil {
18+
c.Conn().WriteNull()
19+
return
20+
} else if i.Type() != ListType {
21+
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.TypeFancy(), ListTypeFancy))
22+
return
23+
}
24+
25+
l := i.(*List)
26+
c.Redis().Mu().Lock()
27+
v, b := l.RPop()
28+
if b {
29+
db.Delete(&key)
30+
}
31+
c.Redis().Mu().Unlock()
32+
33+
c.Conn().WriteBulkString(*v)
34+
}

cmd_rpush.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package redis
2+
3+
import (
4+
"fmt"
5+
"github.com/redis-go/redcon"
6+
"time"
7+
)
8+
9+
func RPushCommand(c *Client, cmd redcon.Command) {
10+
if len(cmd.Args) < 3 {
11+
c.Conn().WriteError(fmt.Sprintf(WrongNumOfArgsErr, "rpush"))
12+
return
13+
}
14+
key := string(cmd.Args[1])
15+
16+
db := c.Db()
17+
i := db.GetOrExpire(&key, true)
18+
if i == nil {
19+
i := NewList()
20+
db.Set(&key, i, false, time.Time{})
21+
} else if i.Type() != ListType {
22+
c.Conn().WriteError(fmt.Sprintf("%s: key is a %s not a %s", WrongTypeErr, i.TypeFancy(), ListTypeFancy))
23+
return
24+
}
25+
26+
l := i.(*List)
27+
var length int
28+
c.Redis().Mu().Lock()
29+
for j := 2; j < len(cmd.Args); j++ {
30+
v := string(cmd.Args[j])
31+
length = l.RPush(&v)
32+
}
33+
c.Redis().Mu().Unlock()
34+
35+
c.Conn().WriteInt(length)
36+
}

set.go renamed to cmd_set.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99
)
1010

11+
// SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>]
1112
func SetCommand(c *Client, cmd redcon.Command) {
1213
if len(cmd.Args) == 1 { // nothing done
1314
c.Conn().WriteString("OK")
@@ -35,17 +36,17 @@ func SetCommand(c *Client, cmd redcon.Command) {
3536
arg := strings.ToLower(string(cmd.Args[i]))
3637
switch arg {
3738
default:
38-
c.Conn().WriteError(SyntaxERR)
39+
c.Conn().WriteError(SyntaxErr)
3940
return
4041
case "ex":
4142
if isPX { // is already px
42-
c.Conn().WriteError(SyntaxERR)
43+
c.Conn().WriteError(SyntaxErr)
4344
return
4445
}
4546

4647
// was last arg?
4748
if len(cmd.Args) == i {
48-
c.Conn().WriteError(SyntaxERR)
49+
c.Conn().WriteError(SyntaxErr)
4950
return
5051
}
5152

@@ -66,13 +67,13 @@ func SetCommand(c *Client, cmd redcon.Command) {
6667
continue
6768
case "px":
6869
if isEX { // is already ex
69-
c.Conn().WriteError(SyntaxERR)
70+
c.Conn().WriteError(SyntaxErr)
7071
return
7172
}
7273

7374
// was last arg?
7475
if len(cmd.Args) == i {
75-
c.Conn().WriteError(SyntaxERR)
76+
c.Conn().WriteError(SyntaxErr)
7677
return
7778
}
7879

@@ -93,15 +94,15 @@ func SetCommand(c *Client, cmd redcon.Command) {
9394
continue
9495
case "nx":
9596
if XX { // is already xx
96-
c.Conn().WriteError(SyntaxERR)
97+
c.Conn().WriteError(SyntaxErr)
9798
return
9899
}
99100
NX = true
100101
i++
101102
continue
102103
case "xx":
103104
if NX { // is already nx
104-
c.Conn().WriteError(SyntaxERR)
105+
c.Conn().WriteError(SyntaxErr)
105106
return
106107
}
107108
XX = true

ttl.go renamed to cmd_ttl.go

File renamed without changes.

command.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const (
2323
CMD_MODULE_NO_CLUSTER /* Deny on Redis Cluster. */
2424
)
2525

26-
// A registered.
26+
// A command can be registered.
2727
type Command struct {
2828
// The command name.
2929
name string
@@ -73,11 +73,24 @@ func (cmd *Command) Name() string {
7373
return cmd.name
7474
}
7575

76+
// RegisterCommands adds commands to the redis instance.
77+
// If a cmd already exists the handler is overridden.
78+
func (r *Redis) RegisterCommands(cmds []*Command) {
79+
r.Mu().Lock()
80+
defer r.Mu().Unlock()
81+
for _, cmd := range cmds {
82+
r.registerCommand(cmd)
83+
}
84+
}
85+
7686
// RegisterCommand adds a command to the redis instance.
77-
// If cmd exists already the handler is overridden.
87+
// If cmd already exists the handler is overridden.
7888
func (r *Redis) RegisterCommand(cmd *Command) {
7989
r.Mu().Lock()
8090
defer r.Mu().Unlock()
91+
r.registerCommand(cmd)
92+
}
93+
func (r *Redis) registerCommand(cmd *Command) {
8194
r.getCommands()[cmd.Name()] = cmd
8295
}
8396

0 commit comments

Comments
 (0)