Skip to content

Commit

Permalink
Merge 176eebe into 9f6c3f1
Browse files Browse the repository at this point in the history
  • Loading branch information
gengxinMT committed Jan 28, 2019
2 parents 9f6c3f1 + 176eebe commit 5080391
Show file tree
Hide file tree
Showing 7 changed files with 1,451 additions and 150 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,19 +174,19 @@ redis-cli -p 7369

### Sets

- [ ] sadd
- [ ] scard
- [ ] sdiff
- [x] sadd
- [x] scard
- [x] sdiff
- [ ] sdiffstore
- [ ] sinter
- [x] sinter
- [ ] sinterstore
- [ ] sismember
- [ ] smembers
- [ ] smove
- [ ] spop
- [x] sismember
- [x] smembers
- [x] smove
- [x] spop
- [ ] srandmember
- [ ] srem
- [ ] sunion
- [x] srem
- [x] sunion
- [ ] sunionstore
- [ ] sscan

Expand Down
24 changes: 20 additions & 4 deletions command/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,16 @@ func init() {
"hscan": HScan,

// sets
"sadd": SAdd,
"smembers": SMembers,
"sadd": SAdd,
"smembers": SMembers,
"scard": SCard,
"sismember": SIsmember,
"spop": SPop,
"srem": SRem,
"suion": SUion,
"sinter": SInter,
"sdiff": SDiff,
"smove": SMove,
}

// commands contains all commands that open to clients
Expand Down Expand Up @@ -176,7 +184,15 @@ func init() {
"hscan": Desc{Proc: AutoCommit(HScan), Cons: Constraint{-3, flags("rR"), 0, 0, 0}},

// sets
"sadd": Desc{Proc: AutoCommit(SAdd), Cons: Constraint{-3, flags("wmF"), 1, 1, 1}},
"smembers": Desc{Proc: AutoCommit(SMembers), Cons: Constraint{2, flags("rS"), 1, 1, 1}},
"sadd": Desc{Proc: AutoCommit(SAdd), Cons: Constraint{-3, flags("wmF"), 1, 1, 1}},
"smembers": Desc{Proc: AutoCommit(SMembers), Cons: Constraint{2, flags("rS"), 1, 1, 1}},
"scard": Desc{Proc: AutoCommit(SCard), Cons: Constraint{2, flags("rF"), 1, 1, 1}},
"sismember": Desc{Proc: AutoCommit(SIsmember), Cons: Constraint{3, flags("rF"), 1, 1, 1}},
"spop": Desc{Proc: AutoCommit(SPop), Cons: Constraint{-2, flags("wRF"), 1, 1, 1}},
"srem": Desc{Proc: AutoCommit(SRem), Cons: Constraint{-3, flags("wF"), 1, 1, 1}},
"suion": Desc{Proc: AutoCommit(SUion), Cons: Constraint{-2, flags("rS"), 1, -1, 1}},
"sinter": Desc{Proc: AutoCommit(SInter), Cons: Constraint{-2, flags("rS"), 1, -1, 1}},
"sdiff": Desc{Proc: AutoCommit(SDiff), Cons: Constraint{-2, flags("rS"), 1, -1, 1}},
"smove": Desc{Proc: AutoCommit(SMove), Cons: Constraint{4, flags("wF"), 1, 2, 1}},
}
}
275 changes: 266 additions & 9 deletions command/sets.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,299 @@
package command

import (
"bytes"
"errors"
"strconv"

"github.com/meitu/titan/db"
)

// SAdd adds the specified members to the set stored at key
func SAdd(ctx *Context, txn *db.Transaction) (OnCommit, error) {
key := []byte(ctx.Args[0])

members := make([][]byte, len(ctx.Args[1:]))
for i, member := range ctx.Args[1:] {
members[i] = []byte(member)
}
set, err := txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
added, err := set.SAdd(members)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, added), nil
}

// SMembers returns all the members of the set value stored at key
func SMembers(ctx *Context, txn *db.Transaction) (OnCommit, error) {
key := []byte(ctx.Args[0])

set, err := txn.Set(key)
if err != nil {
return nil, err
return nil, errors.New("ERR " + err.Error())
}

members, err := set.SMembers()
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return BytesArray(ctx.Out, members), nil
}

// SCard returns the set cardinality (number of elements) of the set stored at key
func SCard(ctx *Context, txn *db.Transaction) (OnCommit, error) {
key := []byte(ctx.Args[0])

set, err := txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
count, err := set.SCard()
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, int64(count)), nil
}

// SIsmember returns if member is a member of the set stored at key
func SIsmember(ctx *Context, txn *db.Transaction) (OnCommit, error) {
key := []byte(ctx.Args[0])
member := []byte(ctx.Args[1])
set, err := txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
count, err := set.SIsmember(member)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, int64(count)), nil

}

// SPop removes and returns one or more random elements from the set value store at key
func SPop(ctx *Context, txn *db.Transaction) (OnCommit, error) {
var count int
var err error
var members [][]byte
var set *db.Set
key := []byte(ctx.Args[0])

if len(ctx.Args) == 2 {
count, err = strconv.Atoi(ctx.Args[1])
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
}
set, err = txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
members, err = set.SPop(int64(count))
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return BytesArray(ctx.Out, members), nil
}

// SRem removes the specified members from the set stored at key
func SRem(ctx *Context, txn *db.Transaction) (OnCommit, error) {
var members [][]byte
key := []byte(ctx.Args[0])
for _, member := range ctx.Args[1:] {
members = append(members, []byte(member))
}
set, err := txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
count, err := set.SRem(members)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, int64(count)), nil
}

added, err := set.SAdd(members)
// SMove movies member from the set at source to the set at destination
func SMove(ctx *Context, txn *db.Transaction) (OnCommit, error) {
member := make([]byte, 0, len(ctx.Args[2]))
key := []byte(ctx.Args[0])
destkey := []byte(ctx.Args[1])
member = []byte(ctx.Args[2])

set, err := txn.Set(key)
if err != nil {
return nil, err
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, added), nil
count, err := set.SMove(destkey, member)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, int64(count)), nil
}

// SMembers returns all the members of the set value stored at key
func SMembers(ctx *Context, txn *db.Transaction) (OnCommit, error) {
// SUion returns the members of the set resulting from the union of all the given sets.
func SUion(ctx *Context, txn *db.Transaction) (OnCommit, error) {
var members [][]byte
keys := make([][]byte, len(ctx.Args))
for i, key := range ctx.Args {
keys[i] = []byte(key)
}

for i := range keys {
set, err := txn.Set(keys[i])
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
if !set.Exists() {
continue
}
if n, _ := set.SCard(); n == 0 {
continue
}
ms, err := set.SMembers()
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
for i := range ms {
members = append(members, ms[i])
}
}
return BytesArray(ctx.Out, db.RemoveRepByMap(members)), nil
}

// SInter returns the members of the set resulting from the intersection of all the given sets.
func SInter(ctx *Context, txn *db.Transaction) (OnCommit, error) {
var members [][]byte
keys := make([][]byte, len(ctx.Args[1:]))
key := []byte(ctx.Args[0])

for i, key := range ctx.Args[1:] {
keys[i] = []byte(key)
}
set, err := txn.Set(key)
if err != nil {
return nil, err
return nil, errors.New("ERR " + err.Error())
}

members, err := set.SMembers()
if !set.Exists() {
return nil, nil
}
if n, _ := set.SCard(); n == 0 {
return nil, nil
}
members, err = set.SMembers()
if err != nil {
return nil, err
return nil, errors.New("ERR " + err.Error())
}

for i := range keys {
set, err := txn.Set(keys[i])
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
if !set.Exists() {
return nil, nil
}
if n, _ := set.SCard(); n == 0 {
return nil, nil
}
ms, err := set.SMembers()
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
members = sliceInter(members, ms)

}
return BytesArray(ctx.Out, members), nil
}

// SDiff returns the members of the set resulting from the difference between the first set and all the successive sets.
func SDiff(ctx *Context, txn *db.Transaction) (OnCommit, error) {
var keys [][]byte
var members [][]byte

key := []byte(ctx.Args[0])
set, err := txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
if !set.Exists() {
return nil, nil
}
if n, _ := set.SCard(); n == 0 {
return nil, nil
}

members, err = set.SMembers()
if err != nil {
return nil, errors.New("ERR " + err.Error())
}

for _, key := range ctx.Args[1:] {
keys = append(keys, []byte(key))
}

for i := range keys {
set, err := txn.Set(keys[i])
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
if !set.Exists() {
continue
}
if n, _ := set.SCard(); n == 0 {
continue
}
ms, err := set.SMembers()
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
members = sliceDiff(members, ms)
}
return BytesArray(ctx.Out, members), nil
}

// InSliceInter checks given interface in interface slice.
func inSliceInter(v []byte, sl [][]byte) bool {
for _, vv := range sl {
if bytes.Equal(vv, v) {
return true
}
}
return false
}

// SliceIntersect returns slice that are present in all the slice1 and slice2.
func sliceInter(slice1, slice2 [][]byte) (interslice [][]byte) {
for _, v := range slice1 {
if inSliceInter(v, slice2) {
interslice = append(interslice, v)
}
}
return
}

// InSliceDiff checks given interface in interface slice.
func inSliceDiff(v []byte, sl [][]byte) bool {
for _, vv := range sl {
if bytes.Equal(vv, v) {
return false
}
}
return true
}

// SliceIntersect returns all slices in slice1 that are not present in slice2.
func sliceDiff(slice1, slice2 [][]byte) [][]byte {
var diffslice [][]byte
for _, v := range slice1 {
if inSliceDiff(v, slice2) {
diffslice = append(diffslice, v)
}
}
return diffslice
}

0 comments on commit 5080391

Please sign in to comment.