ledisdb/ledis/scan.go

137 lines
3.0 KiB
Go
Raw Normal View History

2014-08-14 11:24:41 +04:00
package ledis
import (
"errors"
2014-10-20 18:36:16 +04:00
"github.com/siddontang/ledisdb/store"
"regexp"
2014-08-14 11:24:41 +04:00
)
var errDataType = errors.New("error data type")
var errMetaKey = errors.New("error meta key")
func (db *DB) scan(dataType byte, key []byte, count int, inclusive bool, match string) ([][]byte, error) {
2014-10-20 18:36:16 +04:00
return db.scanGeneric(dataType, key, count, inclusive, match, false)
}
func (db *DB) revscan(dataType byte, key []byte, count int, inclusive bool, match string) ([][]byte, error) {
return db.scanGeneric(dataType, key, count, inclusive, match, true)
}
func (db *DB) scanGeneric(dataType byte, key []byte, count int,
inclusive bool, match string, reverse bool) ([][]byte, error) {
2014-08-14 11:24:41 +04:00
var minKey, maxKey []byte
var err error
var r *regexp.Regexp
if len(match) > 0 {
if r, err = regexp.Compile(match); err != nil {
return nil, err
}
}
2014-10-20 18:36:16 +04:00
tp := store.RangeOpen
if !reverse {
if minKey, err = db.encodeScanMinKey(dataType, key); err != nil {
2014-08-14 11:24:41 +04:00
return nil, err
}
2014-10-20 18:36:16 +04:00
if maxKey, err = db.encodeScanMaxKey(dataType, nil); err != nil {
2014-08-14 11:24:41 +04:00
return nil, err
}
2014-10-20 18:36:16 +04:00
if inclusive {
tp = store.RangeROpen
}
2014-08-14 11:24:41 +04:00
} else {
2014-10-20 18:36:16 +04:00
if minKey, err = db.encodeScanMinKey(dataType, nil); err != nil {
return nil, err
}
if maxKey, err = db.encodeScanMaxKey(dataType, key); err != nil {
2014-08-14 11:24:41 +04:00
return nil, err
}
2014-10-20 18:36:16 +04:00
if inclusive {
tp = store.RangeLOpen
}
2014-08-14 11:24:41 +04:00
}
if count <= 0 {
count = defaultScanCount
}
2014-10-20 18:36:16 +04:00
var it *store.RangeLimitIterator
if !reverse {
it = db.bucket.RangeIterator(minKey, maxKey, tp)
} else {
it = db.bucket.RevRangeIterator(minKey, maxKey, tp)
2014-08-14 11:24:41 +04:00
}
2014-10-20 18:36:16 +04:00
v := make([][]byte, 0, count)
for i := 0; it.Valid() && i < count; it.Next() {
2014-09-17 19:06:42 +04:00
if k, err := db.decodeScanKey(dataType, it.Key()); err != nil {
2014-08-14 11:24:41 +04:00
continue
} else if r != nil && !r.Match(k) {
continue
2014-08-14 11:24:41 +04:00
} else {
v = append(v, k)
i++
2014-08-14 11:24:41 +04:00
}
}
it.Close()
return v, nil
}
2014-10-20 18:36:16 +04:00
func (db *DB) encodeScanMinKey(dataType byte, key []byte) ([]byte, error) {
if len(key) == 0 {
return db.encodeScanKey(dataType, nil)
} else {
if err := checkKeySize(key); err != nil {
return nil, err
}
return db.encodeScanKey(dataType, key)
}
2014-08-14 11:24:41 +04:00
}
2014-10-20 18:36:16 +04:00
func (db *DB) encodeScanMaxKey(dataType byte, key []byte) ([]byte, error) {
if len(key) > 0 {
if err := checkKeySize(key); err != nil {
return nil, err
}
return db.encodeScanKey(dataType, key)
}
2014-09-17 19:06:42 +04:00
k, err := db.encodeScanKey(dataType, nil)
2014-08-14 15:05:17 +04:00
if err != nil {
return nil, err
}
2014-08-14 11:24:41 +04:00
k[len(k)-1] = dataType + 1
return k, nil
}
2014-09-17 19:06:42 +04:00
func (db *DB) encodeScanKey(dataType byte, key []byte) ([]byte, error) {
2014-08-14 11:24:41 +04:00
switch dataType {
case KVType:
return db.encodeKVKey(key), nil
case LMetaType:
return db.lEncodeMetaKey(key), nil
case HSizeType:
return db.hEncodeSizeKey(key), nil
case ZSizeType:
return db.zEncodeSizeKey(key), nil
case BitMetaType:
return db.bEncodeMetaKey(key), nil
2014-08-16 12:55:36 +04:00
case SSizeType:
return db.sEncodeSizeKey(key), nil
2014-08-14 11:24:41 +04:00
default:
2014-08-14 15:05:17 +04:00
return nil, errDataType
2014-08-14 11:24:41 +04:00
}
}
2014-09-17 19:06:42 +04:00
func (db *DB) decodeScanKey(dataType byte, ek []byte) ([]byte, error) {
2014-08-14 11:24:41 +04:00
if len(ek) < 2 || ek[0] != db.index || ek[1] != dataType {
return nil, errMetaKey
}
return ek[2:], nil
}