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.

99 lines
2.6 KiB

  1. package storage
  2. import (
  3. //"log"
  4. "os"
  5. "code.google.com/p/weed-fs/weed/util"
  6. )
  7. type NeedleMap struct {
  8. indexFile *os.File
  9. m CompactMap
  10. //transient
  11. bytes []byte
  12. deletionCounter int
  13. fileCounter int
  14. deletionByteCounter uint64
  15. fileByteCounter uint64
  16. }
  17. func NewNeedleMap(file *os.File) *NeedleMap {
  18. nm := &NeedleMap{
  19. m: NewCompactMap(),
  20. bytes: make([]byte, 16),
  21. indexFile: file,
  22. }
  23. return nm
  24. }
  25. const (
  26. RowsToRead = 1024
  27. )
  28. func LoadNeedleMap(file *os.File) *NeedleMap {
  29. nm := NewNeedleMap(file)
  30. bytes := make([]byte, 16*RowsToRead)
  31. count, e := nm.indexFile.Read(bytes)
  32. for count > 0 && e == nil {
  33. for i := 0; i < count; i += 16 {
  34. key := util.BytesToUint64(bytes[i : i+8])
  35. offset := util.BytesToUint32(bytes[i+8 : i+12])
  36. size := util.BytesToUint32(bytes[i+12 : i+16])
  37. nm.fileCounter++
  38. nm.fileByteCounter = nm.fileByteCounter + uint64(size)
  39. if offset > 0 {
  40. oldSize := nm.m.Set(Key(key), offset, size)
  41. //log.Println("reading key", key, "offset", offset, "size", size, "oldSize", oldSize)
  42. if oldSize > 0 {
  43. nm.deletionCounter++
  44. nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize)
  45. }
  46. } else {
  47. oldSize := nm.m.Delete(Key(key))
  48. //log.Println("removing key", key, "offset", offset, "size", size, "oldSize", oldSize)
  49. nm.deletionCounter++
  50. nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize)
  51. }
  52. }
  53. count, e = nm.indexFile.Read(bytes)
  54. }
  55. return nm
  56. }
  57. func (nm *NeedleMap) Put(key uint64, offset uint32, size uint32) (int, error) {
  58. oldSize := nm.m.Set(Key(key), offset, size)
  59. util.Uint64toBytes(nm.bytes[0:8], key)
  60. util.Uint32toBytes(nm.bytes[8:12], offset)
  61. util.Uint32toBytes(nm.bytes[12:16], size)
  62. nm.fileCounter++
  63. nm.fileByteCounter = nm.fileByteCounter + uint64(size)
  64. if oldSize > 0 {
  65. nm.deletionCounter++
  66. nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize)
  67. }
  68. return nm.indexFile.Write(nm.bytes)
  69. }
  70. func (nm *NeedleMap) Get(key uint64) (element *NeedleValue, ok bool) {
  71. element, ok = nm.m.Get(Key(key))
  72. return
  73. }
  74. func (nm *NeedleMap) Delete(key uint64) {
  75. nm.deletionByteCounter = nm.deletionByteCounter + uint64(nm.m.Delete(Key(key)))
  76. util.Uint64toBytes(nm.bytes[0:8], key)
  77. util.Uint32toBytes(nm.bytes[8:12], 0)
  78. util.Uint32toBytes(nm.bytes[12:16], 0)
  79. nm.indexFile.Write(nm.bytes)
  80. nm.deletionCounter++
  81. }
  82. func (nm *NeedleMap) Close() {
  83. nm.indexFile.Close()
  84. }
  85. func (nm *NeedleMap) ContentSize() uint64 {
  86. return nm.fileByteCounter
  87. }
  88. func (nm *NeedleMap) Visit(visit func(NeedleValue) error) (err error) {
  89. return nm.m.Visit(visit)
  90. }