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.

106 lines
2.8 KiB

7 years ago
  1. package storage
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/glog"
  5. . "github.com/chrislusf/seaweedfs/weed/storage/types"
  6. "github.com/willf/bloom"
  7. "os"
  8. )
  9. type mapMetric struct {
  10. DeletionCounter int `json:"DeletionCounter"`
  11. FileCounter int `json:"FileCounter"`
  12. DeletionByteCounter uint64 `json:"DeletionByteCounter"`
  13. FileByteCounter uint64 `json:"FileByteCounter"`
  14. MaximumFileKey NeedleId `json:"MaxFileKey"`
  15. }
  16. func (mm *mapMetric) logDelete(deletedByteCount uint32) {
  17. mm.DeletionByteCounter = mm.DeletionByteCounter + uint64(deletedByteCount)
  18. mm.DeletionCounter++
  19. }
  20. func (mm *mapMetric) logPut(key NeedleId, oldSize uint32, newSize uint32) {
  21. if key > mm.MaximumFileKey {
  22. mm.MaximumFileKey = key
  23. }
  24. mm.FileCounter++
  25. mm.FileByteCounter = mm.FileByteCounter + uint64(newSize)
  26. if oldSize > 0 {
  27. mm.DeletionCounter++
  28. mm.DeletionByteCounter = mm.DeletionByteCounter + uint64(oldSize)
  29. }
  30. }
  31. func (mm mapMetric) ContentSize() uint64 {
  32. return mm.FileByteCounter
  33. }
  34. func (mm mapMetric) DeletedSize() uint64 {
  35. return mm.DeletionByteCounter
  36. }
  37. func (mm mapMetric) FileCount() int {
  38. return mm.FileCounter
  39. }
  40. func (mm mapMetric) DeletedCount() int {
  41. return mm.DeletionCounter
  42. }
  43. func (mm mapMetric) MaxFileKey() NeedleId {
  44. return mm.MaximumFileKey
  45. }
  46. func newNeedleMapMetricFromIndexFile(r *os.File) (mm *mapMetric, err error) {
  47. mm = &mapMetric{}
  48. var bf *bloom.BloomFilter
  49. buf := make([]byte, NeedleIdSize)
  50. err = reverseWalkIndexFile(r, func(entryCount int64) {
  51. bf = bloom.NewWithEstimates(uint(entryCount), 0.001)
  52. }, func(key NeedleId, offset Offset, size uint32) error {
  53. if key > mm.MaximumFileKey {
  54. mm.MaximumFileKey = key
  55. }
  56. NeedleIdToBytes(buf, key)
  57. if size != TombstoneFileSize {
  58. mm.FileByteCounter += uint64(size)
  59. }
  60. if !bf.Test(buf) {
  61. mm.FileCounter++
  62. bf.Add(buf)
  63. } else {
  64. // deleted file
  65. mm.DeletionCounter++
  66. if size != TombstoneFileSize {
  67. // previously already deleted file
  68. mm.DeletionByteCounter += uint64(size)
  69. }
  70. }
  71. return nil
  72. })
  73. return
  74. }
  75. func reverseWalkIndexFile(r *os.File, initFn func(entryCount int64), fn func(key NeedleId, offset Offset, size uint32) error) error {
  76. fi, err := r.Stat()
  77. if err != nil {
  78. return fmt.Errorf("file %s stat error: %v", r.Name(), err)
  79. }
  80. fileSize := fi.Size()
  81. if fileSize%NeedleEntrySize != 0 {
  82. return fmt.Errorf("unexpected file %s size: %d", r.Name(), fileSize)
  83. }
  84. initFn(fileSize / NeedleEntrySize)
  85. bytes := make([]byte, NeedleEntrySize)
  86. for readerOffset := fileSize - NeedleEntrySize; readerOffset >= 0; readerOffset -= NeedleEntrySize {
  87. count, e := r.ReadAt(bytes, readerOffset)
  88. glog.V(3).Infoln("file", r.Name(), "readerOffset", readerOffset, "count", count, "e", e)
  89. key, offset, size := IdxFileEntry(bytes)
  90. if e = fn(key, offset, size); e != nil {
  91. return e
  92. }
  93. }
  94. return nil
  95. }