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.

107 lines
2.8 KiB

  1. package storage
  2. import (
  3. "code.google.com/p/weed-fs/go/util"
  4. "fmt"
  5. "os"
  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, error) {
  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, e
  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) error {
  75. nm.deletionByteCounter = nm.deletionByteCounter + uint64(nm.m.Delete(Key(key)))
  76. offset, err := nm.indexFile.Seek(0, 1)
  77. if err != nil {
  78. return fmt.Errorf("cannot get position of indexfile: %s", err)
  79. }
  80. util.Uint64toBytes(nm.bytes[0:8], key)
  81. util.Uint32toBytes(nm.bytes[8:12], 0)
  82. util.Uint32toBytes(nm.bytes[12:16], 0)
  83. if _, err = nm.indexFile.Write(nm.bytes); err != nil {
  84. nm.indexFile.Truncate(offset)
  85. return fmt.Errorf("error writing to indexfile %s: %s", nm.indexFile, err)
  86. }
  87. nm.deletionCounter++
  88. return nil
  89. }
  90. func (nm *NeedleMap) Close() {
  91. nm.indexFile.Close()
  92. }
  93. func (nm *NeedleMap) ContentSize() uint64 {
  94. return nm.fileByteCounter
  95. }
  96. func (nm *NeedleMap) Visit(visit func(NeedleValue) error) (err error) {
  97. return nm.m.Visit(visit)
  98. }