seaweedfs/weed/util/skiplist/name_batch.go

103 lines
2.0 KiB
Go
Raw Normal View History

2021-10-04 08:54:25 +08:00
package skiplist
import (
"github.com/seaweedfs/seaweedfs/weed/glog"
"golang.org/x/exp/slices"
2022-08-18 03:05:07 +08:00
"google.golang.org/protobuf/proto"
2021-10-04 08:54:25 +08:00
"strings"
)
type NameBatch struct {
key string
names map[string]struct{}
}
func (nb *NameBatch) ContainsName(name string) (found bool) {
_, found = nb.names[name]
return
}
func (nb *NameBatch) WriteName(name string) {
if nb.key == "" || strings.Compare(nb.key, name) > 0 {
nb.key = name
}
nb.names[name] = struct{}{}
}
func (nb *NameBatch) DeleteName(name string) {
delete(nb.names, name)
if nb.key == name {
nb.key = ""
for n := range nb.names {
if nb.key == "" || strings.Compare(nb.key, n) > 0 {
nb.key = n
}
}
}
}
func (nb *NameBatch) ListNames(startFrom string, visitNamesFn func(name string) bool) bool {
var names []string
2021-10-04 16:01:31 +08:00
needFilter := startFrom != ""
2021-10-04 08:54:25 +08:00
for n := range nb.names {
if !needFilter || strings.Compare(n, startFrom) >= 0 {
names = append(names, n)
}
}
slices.SortFunc(names, func(a, b string) int {
return strings.Compare(a, b)
2021-10-04 08:54:25 +08:00
})
for _, n := range names {
if !visitNamesFn(n) {
return false
}
}
return true
}
func NewNameBatch() *NameBatch {
return &NameBatch{
names: make(map[string]struct{}),
}
}
func LoadNameBatch(data []byte) *NameBatch {
t := &NameBatchData{}
if len(data) > 0 {
err := proto.Unmarshal(data, t)
if err != nil {
glog.Errorf("unmarshal into NameBatchData{} : %v", err)
return nil
}
}
nb := NewNameBatch()
for _, n := range t.Names {
name := string(n)
if nb.key == "" || strings.Compare(nb.key, name) > 0 {
nb.key = name
}
nb.names[name] = struct{}{}
}
return nb
}
func (nb *NameBatch) ToBytes() []byte {
t := &NameBatchData{}
for n := range nb.names {
t.Names = append(t.Names, []byte(n))
}
data, _ := proto.Marshal(t)
return data
}
func (nb *NameBatch) SplitBy(name string) (x, y *NameBatch) {
x, y = NewNameBatch(), NewNameBatch()
for n := range nb.names {
// there should be no equal case though
if strings.Compare(n, name) <= 0 {
x.WriteName(n)
} else {
y.WriteName(n)
}
}
return
}