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.

126 lines
3.2 KiB

  1. package storage
  2. import (
  3. "io"
  4. "os"
  5. "github.com/chrislusf/weed-fs/go/glog"
  6. "github.com/chrislusf/weed-fs/go/util"
  7. )
  8. type NeedleMap struct {
  9. indexFile *os.File
  10. m CompactMap
  11. mapMetric
  12. }
  13. func NewNeedleMap(file *os.File) *NeedleMap {
  14. nm := &NeedleMap{
  15. m: NewCompactMap(),
  16. indexFile: file,
  17. }
  18. return nm
  19. }
  20. const (
  21. RowsToRead = 1024
  22. )
  23. func LoadNeedleMap(file *os.File) (*NeedleMap, error) {
  24. nm := NewNeedleMap(file)
  25. e := WalkIndexFile(file, func(key uint64, offset, size uint32) error {
  26. if key > nm.MaximumFileKey {
  27. nm.MaximumFileKey = key
  28. }
  29. nm.FileCounter++
  30. nm.FileByteCounter = nm.FileByteCounter + uint64(size)
  31. if offset > 0 {
  32. oldSize := nm.m.Set(Key(key), offset, size)
  33. glog.V(3).Infoln("reading key", key, "offset", offset*NeedlePaddingSize, "size", size, "oldSize", oldSize)
  34. if oldSize > 0 {
  35. nm.DeletionCounter++
  36. nm.DeletionByteCounter = nm.DeletionByteCounter + uint64(oldSize)
  37. }
  38. } else {
  39. oldSize := nm.m.Delete(Key(key))
  40. glog.V(3).Infoln("removing key", key, "offset", offset*NeedlePaddingSize, "size", size, "oldSize", oldSize)
  41. nm.DeletionCounter++
  42. nm.DeletionByteCounter = nm.DeletionByteCounter + uint64(oldSize)
  43. }
  44. return nil
  45. })
  46. glog.V(1).Infoln("max file key:", nm.MaximumFileKey)
  47. return nm, e
  48. }
  49. // walks through the index file, calls fn function with each key, offset, size
  50. // stops with the error returned by the fn function
  51. func WalkIndexFile(r *os.File, fn func(key uint64, offset, size uint32) error) error {
  52. var readerOffset int64
  53. bytes := make([]byte, 16*RowsToRead)
  54. count, e := r.ReadAt(bytes, readerOffset)
  55. glog.V(3).Infoln("file", r.Name(), "readerOffset", readerOffset, "count", count, "e", e)
  56. readerOffset += int64(count)
  57. var (
  58. key uint64
  59. offset, size uint32
  60. i int
  61. )
  62. for count > 0 && e == nil || e == io.EOF {
  63. for i = 0; i+16 <= count; i += 16 {
  64. key = util.BytesToUint64(bytes[i : i+8])
  65. offset = util.BytesToUint32(bytes[i+8 : i+12])
  66. size = util.BytesToUint32(bytes[i+12 : i+16])
  67. if e = fn(key, offset, size); e != nil {
  68. return e
  69. }
  70. }
  71. if e == io.EOF {
  72. return nil
  73. }
  74. count, e = r.ReadAt(bytes, readerOffset)
  75. glog.V(3).Infoln("file", r.Name(), "readerOffset", readerOffset, "count", count, "e", e)
  76. readerOffset += int64(count)
  77. }
  78. return e
  79. }
  80. func (nm *NeedleMap) Put(key uint64, offset uint32, size uint32) error {
  81. oldSize := nm.m.Set(Key(key), offset, size)
  82. nm.logPut(key, oldSize, size)
  83. return appendToIndexFile(nm.indexFile, key, offset, size)
  84. }
  85. func (nm *NeedleMap) Get(key uint64) (element *NeedleValue, ok bool) {
  86. element, ok = nm.m.Get(Key(key))
  87. return
  88. }
  89. func (nm *NeedleMap) Delete(key uint64) error {
  90. deletedBytes := nm.m.Delete(Key(key))
  91. nm.logDelete(deletedBytes)
  92. return appendToIndexFile(nm.indexFile, key, 0, 0)
  93. }
  94. func (nm *NeedleMap) Close() {
  95. _ = nm.indexFile.Close()
  96. }
  97. func (nm *NeedleMap) Destroy() error {
  98. nm.Close()
  99. return os.Remove(nm.indexFile.Name())
  100. }
  101. func (nm NeedleMap) ContentSize() uint64 {
  102. return nm.FileByteCounter
  103. }
  104. func (nm NeedleMap) DeletedSize() uint64 {
  105. return nm.DeletionByteCounter
  106. }
  107. func (nm NeedleMap) FileCount() int {
  108. return nm.FileCounter
  109. }
  110. func (nm NeedleMap) DeletedCount() int {
  111. return nm.DeletionCounter
  112. }
  113. func (nm NeedleMap) MaxFileKey() uint64 {
  114. return nm.MaximumFileKey
  115. }