You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.2 KiB
111 lines
2.2 KiB
3 years ago
|
package remote
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
iteratorOnce = 300
|
||
|
)
|
||
|
|
||
|
type RemoteIterator struct {
|
||
|
db *RemoteDatabase
|
||
|
lock sync.Mutex
|
||
|
|
||
|
limit []byte
|
||
|
start []byte
|
||
|
|
||
|
err error
|
||
|
end bool
|
||
|
pos int
|
||
|
|
||
|
keys, values [][]byte
|
||
|
currentKey, currentValue []byte
|
||
|
}
|
||
|
|
||
|
func newRemoteIterator(db *RemoteDatabase, start, limit []byte) *RemoteIterator {
|
||
|
return &RemoteIterator{
|
||
|
db: db,
|
||
|
start: start,
|
||
|
limit: limit,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Next moves the iterator to the next key/value pair. It returns whether the
|
||
|
// iterator is exhausted.
|
||
|
func (i *RemoteIterator) Next() bool {
|
||
|
if i.end {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if i.keys == nil {
|
||
|
if next := i.scanNext(); !next {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i.currentKey = i.keys[i.pos]
|
||
|
i.currentValue = i.values[i.pos]
|
||
|
i.pos++
|
||
|
|
||
|
if i.pos >= len(i.keys) {
|
||
|
i.scanNext()
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// scanNext real scan from tikv, and cache it
|
||
|
func (i *RemoteIterator) scanNext() bool {
|
||
|
keys, values, err := i.db.client.Scan(context.Background(), i.start, i.limit, iteratorOnce)
|
||
|
if err != nil {
|
||
|
i.err = err
|
||
|
i.end = true
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if len(keys) == 0 {
|
||
|
i.end = true
|
||
|
return false
|
||
|
} else {
|
||
|
i.start = append(keys[len(keys)-1], 0)
|
||
|
}
|
||
|
|
||
|
i.pos = 0
|
||
|
i.keys = keys
|
||
|
i.values = values
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// Error returns any accumulated error. Exhausting all the key/value pairs
|
||
|
// is not considered to be an error.
|
||
|
func (i *RemoteIterator) Error() error {
|
||
|
return i.err
|
||
|
}
|
||
|
|
||
|
// Key returns the key of the current key/value pair, or nil if done. The caller
|
||
|
// should not modify the contents of the returned slice, and its contents may
|
||
|
// change on the next call to Next.
|
||
|
func (i *RemoteIterator) Key() []byte {
|
||
|
return i.currentKey
|
||
|
}
|
||
|
|
||
|
// Value returns the value of the current key/value pair, or nil if done. The
|
||
|
// caller should not modify the contents of the returned slice, and its contents
|
||
|
// may change on the next call to Next.
|
||
|
func (i *RemoteIterator) Value() []byte {
|
||
|
return i.currentValue
|
||
|
}
|
||
|
|
||
|
// Release releases associated resources. Release should always succeed and can
|
||
|
// be called multiple times without causing error.
|
||
|
func (i *RemoteIterator) Release() {
|
||
|
i.db = nil
|
||
|
i.end = true
|
||
|
i.keys = nil
|
||
|
i.values = nil
|
||
|
i.currentKey = nil
|
||
|
i.currentValue = nil
|
||
|
}
|