fix.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package command
  2. import (
  3. "os"
  4. "path"
  5. "strconv"
  6. "github.com/chrislusf/seaweedfs/weed/glog"
  7. "github.com/chrislusf/seaweedfs/weed/storage"
  8. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  9. "github.com/chrislusf/seaweedfs/weed/storage/needle_map"
  10. "github.com/chrislusf/seaweedfs/weed/storage/super_block"
  11. "github.com/chrislusf/seaweedfs/weed/storage/types"
  12. )
  13. func init() {
  14. cmdFix.Run = runFix // break init cycle
  15. }
  16. var cmdFix = &Command{
  17. UsageLine: "fix -dir=/tmp -volumeId=234",
  18. Short: "run weed tool fix on index file if corrupted",
  19. Long: `Fix runs the SeaweedFS fix command to re-create the index .idx file.
  20. `,
  21. }
  22. var (
  23. fixVolumePath = cmdFix.Flag.String("dir", ".", "data directory to store files")
  24. fixVolumeCollection = cmdFix.Flag.String("collection", "", "the volume collection name")
  25. fixVolumeId = cmdFix.Flag.Int("volumeId", -1, "a volume id. The volume should already exist in the dir. The volume index file should not exist.")
  26. )
  27. type VolumeFileScanner4Fix struct {
  28. version needle.Version
  29. nm *needle_map.MemDb
  30. }
  31. func (scanner *VolumeFileScanner4Fix) VisitSuperBlock(superBlock super_block.SuperBlock) error {
  32. scanner.version = superBlock.Version
  33. return nil
  34. }
  35. func (scanner *VolumeFileScanner4Fix) ReadNeedleBody() bool {
  36. return false
  37. }
  38. func (scanner *VolumeFileScanner4Fix) VisitNeedle(n *needle.Needle, offset int64, needleHeader, needleBody []byte) error {
  39. glog.V(2).Infof("key %d offset %d size %d disk_size %d gzip %v", n.Id, offset, n.Size, n.DiskSize(scanner.version), n.IsGzipped())
  40. if n.Size > 0 && n.Size != types.TombstoneFileSize {
  41. pe := scanner.nm.Set(n.Id, types.ToOffset(offset), n.Size)
  42. glog.V(2).Infof("saved %d with error %v", n.Size, pe)
  43. } else {
  44. glog.V(2).Infof("skipping deleted file ...")
  45. return scanner.nm.Delete(n.Id)
  46. }
  47. return nil
  48. }
  49. func runFix(cmd *Command, args []string) bool {
  50. if *fixVolumeId == -1 {
  51. return false
  52. }
  53. baseFileName := strconv.Itoa(*fixVolumeId)
  54. if *fixVolumeCollection != "" {
  55. baseFileName = *fixVolumeCollection + "_" + baseFileName
  56. }
  57. indexFileName := path.Join(*fixVolumePath, baseFileName+".idx")
  58. nm := needle_map.NewMemDb()
  59. vid := needle.VolumeId(*fixVolumeId)
  60. scanner := &VolumeFileScanner4Fix{
  61. nm: nm,
  62. }
  63. if err := storage.ScanVolumeFile(*fixVolumePath, *fixVolumeCollection, vid, storage.NeedleMapInMemory, scanner); err != nil {
  64. glog.Fatalf("scan .dat File: %v", err)
  65. os.Remove(indexFileName)
  66. }
  67. if err := nm.SaveToIdx(indexFileName); err != nil {
  68. glog.Fatalf("save to .idx File: %v", err)
  69. os.Remove(indexFileName)
  70. }
  71. return true
  72. }