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.

82 lines
2.2 KiB

  1. package storage
  2. import (
  3. "code.google.com/p/weed-fs/go/glog"
  4. "fmt"
  5. "os"
  6. "time"
  7. )
  8. func (v *Volume) garbageLevel() float64 {
  9. return float64(v.nm.DeletedSize()) / float64(v.ContentSize())
  10. }
  11. func (v *Volume) Compact() error {
  12. glog.V(3).Infof("Compacting ...")
  13. v.accessLock.Lock()
  14. defer v.accessLock.Unlock()
  15. glog.V(3).Infof("Got Compaction lock...")
  16. filePath := v.FileName()
  17. glog.V(3).Infof("creating copies for volume %d ...", v.Id)
  18. return v.copyDataAndGenerateIndexFile(filePath+".cpd", filePath+".cpx")
  19. }
  20. func (v *Volume) commitCompact() error {
  21. glog.V(3).Infof("Committing vacuuming...")
  22. v.accessLock.Lock()
  23. defer v.accessLock.Unlock()
  24. glog.V(3).Infof("Got Committing lock...")
  25. _ = v.dataFile.Close()
  26. var e error
  27. if e = os.Rename(v.FileName()+".cpd", v.FileName()+".dat"); e != nil {
  28. return e
  29. }
  30. if e = os.Rename(v.FileName()+".cpx", v.FileName()+".idx"); e != nil {
  31. return e
  32. }
  33. //glog.V(3).Infof("Pretending to be vacuuming...")
  34. //time.Sleep(20 * time.Second)
  35. if e = v.load(true, false); e != nil {
  36. return e
  37. }
  38. return nil
  39. }
  40. func (v *Volume) copyDataAndGenerateIndexFile(dstName, idxName string) (err error) {
  41. var (
  42. dst, idx *os.File
  43. )
  44. if dst, err = os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
  45. return
  46. }
  47. defer dst.Close()
  48. if idx, err = os.OpenFile(idxName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
  49. return
  50. }
  51. defer idx.Close()
  52. nm := NewNeedleMap(idx)
  53. new_offset := int64(SuperBlockSize)
  54. err = ScanVolumeFile(v.dir, v.Collection, v.Id, func(superBlock SuperBlock) error {
  55. _, err = dst.Write(superBlock.Bytes())
  56. return err
  57. }, func(n *Needle, offset int64) error {
  58. nv, ok := v.nm.Get(n.Id)
  59. glog.V(4).Infoln("needle expected offset ", offset, "ok", ok, "nv", nv)
  60. if ok && int64(nv.Offset)*NeedlePaddingSize == offset && nv.Size > 0 {
  61. if _, err = nm.Put(n.Id, uint32(new_offset/NeedlePaddingSize), n.Size); err != nil {
  62. return fmt.Errorf("cannot put needle: %s", err)
  63. }
  64. if _, err = n.Append(dst, v.Version()); err != nil {
  65. return fmt.Errorf("cannot append needle: %s", err)
  66. }
  67. new_offset += n.DiskSize()
  68. glog.V(3).Infoln("saving key", n.Id, "volume offset", offset, "=>", new_offset, "data_size", n.Size)
  69. }
  70. return nil
  71. })
  72. return
  73. }