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.

129 lines
3.0 KiB

  1. package storage
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "sync"
  7. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  8. "github.com/chrislusf/seaweedfs/weed/util"
  9. )
  10. type NeedleMapType int
  11. const (
  12. NeedleMapInMemory NeedleMapType = iota
  13. NeedleMapLevelDb
  14. NeedleMapBoltDb
  15. NeedleMapBtree
  16. )
  17. const (
  18. NeedleIndexSize = 16
  19. )
  20. type NeedleMapper interface {
  21. Put(key uint64, offset uint32, size uint32) error
  22. Get(key uint64) (element *needle.NeedleValue, ok bool)
  23. Delete(key uint64, offset uint32) error
  24. Close()
  25. Destroy() error
  26. ContentSize() uint64
  27. DeletedSize() uint64
  28. FileCount() int
  29. DeletedCount() int
  30. MaxFileKey() uint64
  31. IndexFileSize() uint64
  32. IndexFileContent() ([]byte, error)
  33. IndexFileName() string
  34. }
  35. type baseNeedleMapper struct {
  36. indexFile *os.File
  37. indexFileAccessLock sync.Mutex
  38. mapMetric
  39. }
  40. func (nm *baseNeedleMapper) IndexFileSize() uint64 {
  41. stat, err := nm.indexFile.Stat()
  42. if err == nil {
  43. return uint64(stat.Size())
  44. }
  45. return 0
  46. }
  47. func (nm *baseNeedleMapper) IndexFileName() string {
  48. return nm.indexFile.Name()
  49. }
  50. func idxFileEntry(bytes []byte) (key uint64, offset uint32, size uint32) {
  51. key = util.BytesToUint64(bytes[:8])
  52. offset = util.BytesToUint32(bytes[8:12])
  53. size = util.BytesToUint32(bytes[12:16])
  54. return
  55. }
  56. func (nm *baseNeedleMapper) appendToIndexFile(key uint64, offset uint32, size uint32) error {
  57. bytes := make([]byte, 16)
  58. util.Uint64toBytes(bytes[0:8], key)
  59. util.Uint32toBytes(bytes[8:12], offset)
  60. util.Uint32toBytes(bytes[12:16], size)
  61. nm.indexFileAccessLock.Lock()
  62. defer nm.indexFileAccessLock.Unlock()
  63. if _, err := nm.indexFile.Seek(0, 2); err != nil {
  64. return fmt.Errorf("cannot seek end of indexfile %s: %v",
  65. nm.indexFile.Name(), err)
  66. }
  67. _, err := nm.indexFile.Write(bytes)
  68. return err
  69. }
  70. func (nm *baseNeedleMapper) IndexFileContent() ([]byte, error) {
  71. nm.indexFileAccessLock.Lock()
  72. defer nm.indexFileAccessLock.Unlock()
  73. return ioutil.ReadFile(nm.indexFile.Name())
  74. }
  75. type mapMetric struct {
  76. indexFile *os.File
  77. DeletionCounter int `json:"DeletionCounter"`
  78. FileCounter int `json:"FileCounter"`
  79. DeletionByteCounter uint64 `json:"DeletionByteCounter"`
  80. FileByteCounter uint64 `json:"FileByteCounter"`
  81. MaximumFileKey uint64 `json:"MaxFileKey"`
  82. }
  83. func (mm *mapMetric) logDelete(deletedByteCount uint32) {
  84. mm.DeletionByteCounter = mm.DeletionByteCounter + uint64(deletedByteCount)
  85. mm.DeletionCounter++
  86. }
  87. func (mm *mapMetric) logPut(key uint64, oldSize uint32, newSize uint32) {
  88. if key > mm.MaximumFileKey {
  89. mm.MaximumFileKey = key
  90. }
  91. mm.FileCounter++
  92. mm.FileByteCounter = mm.FileByteCounter + uint64(newSize)
  93. if oldSize > 0 {
  94. mm.DeletionCounter++
  95. mm.DeletionByteCounter = mm.DeletionByteCounter + uint64(oldSize)
  96. }
  97. }
  98. func (mm mapMetric) ContentSize() uint64 {
  99. return mm.FileByteCounter
  100. }
  101. func (mm mapMetric) DeletedSize() uint64 {
  102. return mm.DeletionByteCounter
  103. }
  104. func (mm mapMetric) FileCount() int {
  105. return mm.FileCounter
  106. }
  107. func (mm mapMetric) DeletedCount() int {
  108. return mm.DeletionCounter
  109. }
  110. func (mm mapMetric) MaxFileKey() uint64 {
  111. return mm.MaximumFileKey
  112. }