Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/set #45

Closed
wants to merge 82 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
6bc2c7a
code set v1
gengxinMT Jan 16, 2019
3c4e813
code set v1
gengxinMT Jan 18, 2019
d7f931b
fix
YIDWang Jan 21, 2019
5ac42cd
finish getbit
YIDWang Jan 21, 2019
bb23375
Looking for bug
gengxinMT Jan 21, 2019
cec53b9
code set
gengxinMT Jan 21, 2019
83e5b4d
code set
gengxinMT Jan 22, 2019
46a979c
add smove
gengxinMT Jan 22, 2019
c5654cb
add SMove
gengxinMT Jan 22, 2019
49e8934
add smove
gengxinMT Jan 22, 2019
c98c48d
modify fmt
YIDWang Jan 23, 2019
e3a406c
Merge branch 'master' into feature/getbit
YIDWang Jan 23, 2019
623fed7
Merge remote-tracking branch 'github/master' into feature/getbit
YIDWang Jan 23, 2019
88d39b3
add design
gengxinMT Jan 23, 2019
94048b7
modify spop
gengxinMT Jan 23, 2019
6d33809
delete design.md
gengxinMT Jan 23, 2019
1f32dd2
modify golint
gengxinMT Jan 23, 2019
fcdf874
modify test
gengxinMT Jan 23, 2019
9ecafda
modify review
gengxinMT Jan 28, 2019
176eebe
modify review
gengxinMT Jan 28, 2019
4e1b941
Merge pull request #40 from meitu/feature/getbit
shafreeck Feb 1, 2019
62d23d8
move interval to config file from gc/expire work
Jan 31, 2019
540faee
add config comment
Feb 1, 2019
888f535
fix config comment
Feb 11, 2019
d6e1c56
modify review
gengxinMT Feb 11, 2019
da197ec
modify review
gengxinMT Feb 11, 2019
d552cd5
modify review
gengxinMT Feb 11, 2019
40bca27
Merge pull request #50 from meitu/feature/gc-interval-conf
YIDWang Feb 12, 2019
9e33957
modify review
gengxinMT Feb 12, 2019
6b25de3
modify review
gengxinMT Feb 12, 2019
b9083a4
Add codelingo.yaml file at project root.
CodeLingoBot Feb 13, 2019
a845d90
Add .codelingoignore file at project root.
CodeLingoBot Feb 13, 2019
4c9df84
Merge pull request #54 from CodeLingoBot/init_codelingo
shafreeck Feb 13, 2019
593a5b0
modify review
gengxinMT Feb 13, 2019
cc4c2b8
modify review
gengxinMT Feb 13, 2019
6463cd6
modify review
gengxinMT Feb 13, 2019
05bd491
modify review
gengxinMT Feb 14, 2019
b944052
modify review
gengxinMT Feb 15, 2019
2dbecba
fix get hash check expired failed
Feb 20, 2019
2f349fe
fix hash unit test
Feb 20, 2019
9f542de
Merge pull request #56 from meitu/bugfix/hash-check-expire
YIDWang Feb 20, 2019
a5917d9
modify set
gengxinMT Feb 21, 2019
0764e0b
modify set
gengxinMT Feb 21, 2019
156fef0
modify set err
gengxinMT Feb 21, 2019
14102c4
modify set iter
gengxinMT Feb 22, 2019
01b1265
modify set union for
gengxinMT Feb 25, 2019
5246b6a
code set v1
gengxinMT Jan 16, 2019
9f2fc54
code set v1
gengxinMT Jan 18, 2019
e63f500
Looking for bug
gengxinMT Jan 21, 2019
2c8cd9c
code set
gengxinMT Jan 21, 2019
ee98ac8
code set
gengxinMT Jan 22, 2019
e5c7e5c
add smove
gengxinMT Jan 22, 2019
0c22475
add SMove
gengxinMT Jan 22, 2019
fd62a57
add smove
gengxinMT Jan 22, 2019
7e55d52
add design
gengxinMT Jan 23, 2019
a1056cd
modify spop
gengxinMT Jan 23, 2019
db3b51b
delete design.md
gengxinMT Jan 23, 2019
8cf5b32
modify golint
gengxinMT Jan 23, 2019
d2ff5a8
modify test
gengxinMT Jan 23, 2019
03a6ece
modify review
gengxinMT Jan 28, 2019
53cb295
modify review
gengxinMT Jan 28, 2019
5813c3e
modify review
gengxinMT Feb 11, 2019
09c23f0
modify review
gengxinMT Feb 11, 2019
cdc9707
modify review
gengxinMT Feb 11, 2019
8abd22d
modify review
gengxinMT Feb 12, 2019
a24a6b8
modify review
gengxinMT Feb 12, 2019
97e6035
modify review
gengxinMT Feb 13, 2019
32bfced
modify review
gengxinMT Feb 13, 2019
16eb071
modify review
gengxinMT Feb 13, 2019
613a599
modify review
gengxinMT Feb 14, 2019
fb74d59
modify review
gengxinMT Feb 15, 2019
dd41746
modify set
gengxinMT Feb 21, 2019
1c4ac89
modify set
gengxinMT Feb 21, 2019
47720d8
modify set err
gengxinMT Feb 21, 2019
319f4ae
modify set iter
gengxinMT Feb 22, 2019
f7d01dd
modify set union for
gengxinMT Feb 25, 2019
c734423
modify set for
gengxinMT Feb 25, 2019
2a23bf6
rebase master
gengxinMT Feb 25, 2019
bd8c58d
modify set nilline
gengxinMT Feb 26, 2019
463dcad
modify set spop
gengxinMT Feb 26, 2019
394e324
modify min and max
gengxinMT Mar 4, 2019
6cc0a9e
modify Sdiff for
gengxinMT Mar 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -175,7 +183,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 {
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
return nil, errors.New("ERR " + err.Error())
}
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
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())
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
}
}
set, err = txn.Set(key)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
members, err = set.SPop(int64(count))
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
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:] {
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
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
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
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
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
}

// 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
YIDWang marked this conversation as resolved.
Show resolved Hide resolved
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)
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
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)

}
gengxinMT marked this conversation as resolved.
Show resolved Hide resolved
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
YIDWang marked this conversation as resolved.
Show resolved Hide resolved

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
}