Skip to content

Commit

Permalink
Merge pull request redis#470 from go-redis/fix/remove-scanner
Browse files Browse the repository at this point in the history
Remove Scanner in favor of ScanCmd.
  • Loading branch information
vmihailenco authored Jan 3, 2017
2 parents 67acf6e + 10c56ce commit b9cc17b
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 58 deletions.
15 changes: 12 additions & 3 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -683,12 +683,14 @@ type ScanCmd struct {

page []string
cursor uint64

process func(cmd Cmder) error
}

func NewScanCmd(args ...interface{}) *ScanCmd {
cmd := newBaseCmd(args)
func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
return &ScanCmd{
baseCmd: cmd,
baseCmd: newBaseCmd(args),
process: process,
}
}

Expand All @@ -709,6 +711,13 @@ func (cmd *ScanCmd) readReply(cn *pool.Conn) error {
return cmd.err
}

// Iterator creates a new ScanIterator.
func (cmd *ScanCmd) Iterator() *ScanIterator {
return &ScanIterator{
cmd: cmd,
}
}

//------------------------------------------------------------------------------

type ClusterNode struct {
Expand Down
44 changes: 16 additions & 28 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ type Cmdable interface {
SortInterfaces(key string, sort Sort) *SliceCmd
TTL(key string) *DurationCmd
Type(key string) *StatusCmd
Scan(cursor uint64, match string, count int64) Scanner
SScan(key string, cursor uint64, match string, count int64) Scanner
HScan(key string, cursor uint64, match string, count int64) Scanner
ZScan(key string, cursor uint64, match string, count int64) Scanner
Scan(cursor uint64, match string, count int64) *ScanCmd
SScan(key string, cursor uint64, match string, count int64) *ScanCmd
HScan(key string, cursor uint64, match string, count int64) *ScanCmd
ZScan(key string, cursor uint64, match string, count int64) *ScanCmd
Append(key, value string) *IntCmd
BitCount(key string, bitCount *BitCount) *IntCmd
BitOpAnd(destKey string, keys ...string) *IntCmd
Expand Down Expand Up @@ -515,68 +515,56 @@ func (c *cmdable) Type(key string) *StatusCmd {
return cmd
}

func (c *cmdable) Scan(cursor uint64, match string, count int64) Scanner {
func (c *cmdable) Scan(cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"scan", cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(args...)
cmd := NewScanCmd(c.process, args...)
c.process(cmd)
return Scanner{
client: c,
ScanCmd: cmd,
}
return cmd
}

func (c *cmdable) SScan(key string, cursor uint64, match string, count int64) Scanner {
func (c *cmdable) SScan(key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"sscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(args...)
cmd := NewScanCmd(c.process, args...)
c.process(cmd)
return Scanner{
client: c,
ScanCmd: cmd,
}
return cmd
}

func (c *cmdable) HScan(key string, cursor uint64, match string, count int64) Scanner {
func (c *cmdable) HScan(key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"hscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(args...)
cmd := NewScanCmd(c.process, args...)
c.process(cmd)
return Scanner{
client: c,
ScanCmd: cmd,
}
return cmd
}

func (c *cmdable) ZScan(key string, cursor uint64, match string, count int64) Scanner {
func (c *cmdable) ZScan(key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"zscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(args...)
cmd := NewScanCmd(c.process, args...)
c.process(cmd)
return Scanner{
client: c,
ScanCmd: cmd,
}
return cmd
}

//------------------------------------------------------------------------------
Expand Down
43 changes: 16 additions & 27 deletions iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,18 @@ package redis

import "sync"

type Scanner struct {
client *cmdable
*ScanCmd
}

// Iterator creates a new ScanIterator.
func (s Scanner) Iterator() *ScanIterator {
return &ScanIterator{
Scanner: s,
}
}

// ScanIterator is used to incrementally iterate over a collection of elements.
// It's safe for concurrent use by multiple goroutines.
type ScanIterator struct {
mu sync.Mutex // protects Scanner and pos
Scanner
mu sync.Mutex // protects Scanner and pos
cmd *ScanCmd
pos int
}

// Err returns the last iterator error, if any.
func (it *ScanIterator) Err() error {
it.mu.Lock()
err := it.ScanCmd.Err()
err := it.cmd.Err()
it.mu.Unlock()
return err
}
Expand All @@ -36,37 +24,38 @@ func (it *ScanIterator) Next() bool {
defer it.mu.Unlock()

// Instantly return on errors.
if it.ScanCmd.Err() != nil {
if it.cmd.Err() != nil {
return false
}

// Advance cursor, check if we are still within range.
if it.pos < len(it.ScanCmd.page) {
if it.pos < len(it.cmd.page) {
it.pos++
return true
}

for {
// Return if there is no more data to fetch.
if it.ScanCmd.cursor == 0 {
if it.cmd.cursor == 0 {
return false
}

// Fetch next page.
if it.ScanCmd._args[0] == "scan" {
it.ScanCmd._args[1] = it.ScanCmd.cursor
if it.cmd._args[0] == "scan" {
it.cmd._args[1] = it.cmd.cursor
} else {
it.ScanCmd._args[2] = it.ScanCmd.cursor
it.cmd._args[2] = it.cmd.cursor
}
it.client.process(it.ScanCmd)
if it.ScanCmd.Err() != nil {

err := it.cmd.process(it.cmd)
if err != nil {
return false
}

it.pos = 1

// Redis can occasionally return empty page
if len(it.ScanCmd.page) > 0 {
// Redis can occasionally return empty page.
if len(it.cmd.page) > 0 {
return true
}
}
Expand All @@ -76,8 +65,8 @@ func (it *ScanIterator) Next() bool {
func (it *ScanIterator) Val() string {
var v string
it.mu.Lock()
if it.ScanCmd.Err() == nil && it.pos > 0 && it.pos <= len(it.ScanCmd.page) {
v = it.ScanCmd.page[it.pos-1]
if it.cmd.Err() == nil && it.pos > 0 && it.pos <= len(it.cmd.page) {
v = it.cmd.page[it.pos-1]
}
it.mu.Unlock()
return v
Expand Down

0 comments on commit b9cc17b

Please sign in to comment.