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.

102 lines
2.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package skiplist
  2. import (
  3. "github.com/golang/protobuf/proto"
  4. "github.com/seaweedfs/seaweedfs/weed/glog"
  5. "golang.org/x/exp/slices"
  6. "strings"
  7. )
  8. type NameBatch struct {
  9. key string
  10. names map[string]struct{}
  11. }
  12. func (nb *NameBatch) ContainsName(name string) (found bool) {
  13. _, found = nb.names[name]
  14. return
  15. }
  16. func (nb *NameBatch) WriteName(name string) {
  17. if nb.key == "" || strings.Compare(nb.key, name) > 0 {
  18. nb.key = name
  19. }
  20. nb.names[name] = struct{}{}
  21. }
  22. func (nb *NameBatch) DeleteName(name string) {
  23. delete(nb.names, name)
  24. if nb.key == name {
  25. nb.key = ""
  26. for n := range nb.names {
  27. if nb.key == "" || strings.Compare(nb.key, n) > 0 {
  28. nb.key = n
  29. }
  30. }
  31. }
  32. }
  33. func (nb *NameBatch) ListNames(startFrom string, visitNamesFn func(name string) bool) bool {
  34. var names []string
  35. needFilter := startFrom != ""
  36. for n := range nb.names {
  37. if !needFilter || strings.Compare(n, startFrom) >= 0 {
  38. names = append(names, n)
  39. }
  40. }
  41. slices.SortFunc(names, func(a, b string) bool {
  42. return strings.Compare(a, b) < 0
  43. })
  44. for _, n := range names {
  45. if !visitNamesFn(n) {
  46. return false
  47. }
  48. }
  49. return true
  50. }
  51. func NewNameBatch() *NameBatch {
  52. return &NameBatch{
  53. names: make(map[string]struct{}),
  54. }
  55. }
  56. func LoadNameBatch(data []byte) *NameBatch {
  57. t := &NameBatchData{}
  58. if len(data) > 0 {
  59. err := proto.Unmarshal(data, t)
  60. if err != nil {
  61. glog.Errorf("unmarshal into NameBatchData{} : %v", err)
  62. return nil
  63. }
  64. }
  65. nb := NewNameBatch()
  66. for _, n := range t.Names {
  67. name := string(n)
  68. if nb.key == "" || strings.Compare(nb.key, name) > 0 {
  69. nb.key = name
  70. }
  71. nb.names[name] = struct{}{}
  72. }
  73. return nb
  74. }
  75. func (nb *NameBatch) ToBytes() []byte {
  76. t := &NameBatchData{}
  77. for n := range nb.names {
  78. t.Names = append(t.Names, []byte(n))
  79. }
  80. data, _ := proto.Marshal(t)
  81. return data
  82. }
  83. func (nb *NameBatch) SplitBy(name string) (x, y *NameBatch) {
  84. x, y = NewNameBatch(), NewNameBatch()
  85. for n := range nb.names {
  86. // there should be no equal case though
  87. if strings.Compare(n, name) <= 0 {
  88. x.WriteName(n)
  89. } else {
  90. y.WriteName(n)
  91. }
  92. }
  93. return
  94. }