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.

163 lines
3.7 KiB

2 years ago
  1. package needle_map
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "github.com/syndtr/goleveldb/leveldb"
  7. "github.com/syndtr/goleveldb/leveldb/iterator"
  8. "github.com/syndtr/goleveldb/leveldb/opt"
  9. "github.com/syndtr/goleveldb/leveldb/storage"
  10. "github.com/seaweedfs/seaweedfs/weed/glog"
  11. "github.com/seaweedfs/seaweedfs/weed/storage/idx"
  12. . "github.com/seaweedfs/seaweedfs/weed/storage/types"
  13. )
  14. // This map uses in memory level db
  15. type MemDb struct {
  16. db *leveldb.DB
  17. }
  18. func NewMemDb() *MemDb {
  19. opts := &opt.Options{}
  20. var err error
  21. t := &MemDb{}
  22. if t.db, err = leveldb.Open(storage.NewMemStorage(), opts); err != nil {
  23. glog.V(0).Infof("MemDb fails to open: %v", err)
  24. return nil
  25. }
  26. return t
  27. }
  28. func (cm *MemDb) Set(key NeedleId, offset Offset, size Size) error {
  29. bytes := ToBytes(key, offset, size)
  30. if err := cm.db.Put(bytes[0:NeedleIdSize], bytes[NeedleIdSize:NeedleIdSize+OffsetSize+SizeSize], nil); err != nil {
  31. return fmt.Errorf("failed to write temp leveldb: %v", err)
  32. }
  33. return nil
  34. }
  35. func (cm *MemDb) Delete(key NeedleId) error {
  36. bytes := make([]byte, NeedleIdSize)
  37. NeedleIdToBytes(bytes, key)
  38. return cm.db.Delete(bytes, nil)
  39. }
  40. func (cm *MemDb) Get(key NeedleId) (*NeedleValue, bool) {
  41. bytes := make([]byte, NeedleIdSize)
  42. NeedleIdToBytes(bytes[0:NeedleIdSize], key)
  43. data, err := cm.db.Get(bytes, nil)
  44. if err != nil || len(data) != OffsetSize+SizeSize {
  45. return nil, false
  46. }
  47. offset := BytesToOffset(data[0:OffsetSize])
  48. size := BytesToSize(data[OffsetSize : OffsetSize+SizeSize])
  49. return &NeedleValue{Key: key, Offset: offset, Size: size}, true
  50. }
  51. // Visit visits all entries or stop if any error when visiting
  52. func doVisit(iter iterator.Iterator, visit func(NeedleValue) error) (ret error) {
  53. key := BytesToNeedleId(iter.Key())
  54. data := iter.Value()
  55. offset := BytesToOffset(data[0:OffsetSize])
  56. size := BytesToSize(data[OffsetSize : OffsetSize+SizeSize])
  57. needle := NeedleValue{Key: key, Offset: offset, Size: size}
  58. ret = visit(needle)
  59. if ret != nil {
  60. return
  61. }
  62. return nil
  63. }
  64. func (cm *MemDb) AscendingVisit(visit func(NeedleValue) error) (ret error) {
  65. iter := cm.db.NewIterator(nil, nil)
  66. if iter.First() {
  67. if ret = doVisit(iter, visit); ret != nil {
  68. return
  69. }
  70. }
  71. for iter.Next() {
  72. if ret = doVisit(iter, visit); ret != nil {
  73. return
  74. }
  75. }
  76. iter.Release()
  77. ret = iter.Error()
  78. return
  79. }
  80. func (cm *MemDb) DescendingVisit(visit func(NeedleValue) error) (ret error) {
  81. iter := cm.db.NewIterator(nil, nil)
  82. if iter.Last() {
  83. if ret = doVisit(iter, visit); ret != nil {
  84. return
  85. }
  86. }
  87. for iter.Prev() {
  88. if ret = doVisit(iter, visit); ret != nil {
  89. return
  90. }
  91. }
  92. iter.Release()
  93. ret = iter.Error()
  94. return
  95. }
  96. func (cm *MemDb) SaveToIdx(idxName string) (ret error) {
  97. idxFile, err := os.OpenFile(idxName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
  98. if err != nil {
  99. return
  100. }
  101. defer func() {
  102. idxFile.Sync()
  103. idxFile.Close()
  104. }()
  105. return cm.AscendingVisit(func(value NeedleValue) error {
  106. if value.Offset.IsZero() || value.Size.IsDeleted() {
  107. return nil
  108. }
  109. _, err := idxFile.Write(value.ToBytes())
  110. return err
  111. })
  112. }
  113. func (cm *MemDb) LoadFromIdx(idxName string) (ret error) {
  114. idxFile, err := os.OpenFile(idxName, os.O_RDONLY, 0644)
  115. if err != nil {
  116. return
  117. }
  118. defer idxFile.Close()
  119. return cm.LoadFromReaderAt(idxFile)
  120. }
  121. func (cm *MemDb) LoadFromReaderAt(readerAt io.ReaderAt) (ret error) {
  122. return cm.LoadFilterFromReaderAt(readerAt, true, true)
  123. }
  124. func (cm *MemDb) LoadFilterFromReaderAt(readerAt io.ReaderAt, isFilterOffsetZero bool, isFilterDeleted bool) (ret error) {
  125. return idx.WalkIndexFile(readerAt, 0, func(key NeedleId, offset Offset, size Size) error {
  126. if (isFilterOffsetZero && offset.IsZero()) || (isFilterDeleted && size.IsDeleted()) {
  127. return cm.Delete(key)
  128. }
  129. return cm.Set(key, offset, size)
  130. })
  131. }
  132. func (cm *MemDb) Close() {
  133. cm.db.Close()
  134. }