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.

112 lines
2.7 KiB

  1. package needle_map
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/syndtr/goleveldb/leveldb"
  6. "github.com/syndtr/goleveldb/leveldb/opt"
  7. "github.com/syndtr/goleveldb/leveldb/storage"
  8. "github.com/chrislusf/seaweedfs/weed/glog"
  9. "github.com/chrislusf/seaweedfs/weed/storage/idx"
  10. . "github.com/chrislusf/seaweedfs/weed/storage/types"
  11. "github.com/chrislusf/seaweedfs/weed/util"
  12. )
  13. //This map uses in memory level db
  14. type MemDb struct {
  15. db *leveldb.DB
  16. }
  17. func NewMemDb() *MemDb {
  18. opts := &opt.Options{}
  19. var err error
  20. t := &MemDb{}
  21. if t.db, err = leveldb.Open(storage.NewMemStorage(), opts); err != nil {
  22. glog.V(0).Infof("MemDb fails to open: %v", err)
  23. return nil
  24. }
  25. return t
  26. }
  27. func (cm *MemDb) Set(key NeedleId, offset Offset, size uint32) error {
  28. bytes := ToBytes(key, offset, size)
  29. if err := cm.db.Put(bytes[0:NeedleIdSize], bytes[NeedleIdSize:NeedleIdSize+OffsetSize+SizeSize], nil); err != nil {
  30. return fmt.Errorf("failed to write temp leveldb: %v", err)
  31. }
  32. return nil
  33. }
  34. func (cm *MemDb) Delete(key NeedleId) error {
  35. bytes := make([]byte, NeedleIdSize)
  36. NeedleIdToBytes(bytes, key)
  37. return cm.db.Delete(bytes, nil)
  38. }
  39. func (cm *MemDb) Get(key NeedleId) (*NeedleValue, bool) {
  40. bytes := make([]byte, NeedleIdSize)
  41. NeedleIdToBytes(bytes[0:NeedleIdSize], key)
  42. data, err := cm.db.Get(bytes, nil)
  43. if err != nil || len(data) != OffsetSize+SizeSize {
  44. return nil, false
  45. }
  46. offset := BytesToOffset(data[0:OffsetSize])
  47. size := util.BytesToUint32(data[OffsetSize : OffsetSize+SizeSize])
  48. return &NeedleValue{Key: key, Offset: offset, Size: size}, true
  49. }
  50. // Visit visits all entries or stop if any error when visiting
  51. func (cm *MemDb) AscendingVisit(visit func(NeedleValue) error) (ret error) {
  52. iter := cm.db.NewIterator(nil, nil)
  53. for iter.Next() {
  54. key := BytesToNeedleId(iter.Key())
  55. data := iter.Value()
  56. offset := BytesToOffset(data[0:OffsetSize])
  57. size := util.BytesToUint32(data[OffsetSize : OffsetSize+SizeSize])
  58. needle := NeedleValue{Key: key, Offset: offset, Size: size}
  59. ret = visit(needle)
  60. if ret != nil {
  61. return
  62. }
  63. }
  64. iter.Release()
  65. ret = iter.Error()
  66. return
  67. }
  68. func (cm *MemDb) SaveToIdx(idxName string) (ret error) {
  69. idxFile, err := os.OpenFile(idxName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
  70. if err != nil {
  71. return
  72. }
  73. defer idxFile.Close()
  74. return cm.AscendingVisit(func(value NeedleValue) error {
  75. _, err := idxFile.Write(value.ToBytes())
  76. return err
  77. })
  78. }
  79. func (cm *MemDb) LoadFromIdx(idxName string) (ret error) {
  80. idxFile, err := os.OpenFile(idxName, os.O_RDONLY, 0644)
  81. if err != nil {
  82. return
  83. }
  84. defer idxFile.Close()
  85. return idx.WalkIndexFile(idxFile, func(key NeedleId, offset Offset, size uint32) error {
  86. if offset.IsZero() || size == TombstoneFileSize {
  87. return nil
  88. }
  89. return cm.Set(key, offset, size)
  90. })
  91. }