func runFix(cmd *Command, args []string) bool { if *fixVolumeId == -1 { return false } fileName := strconv.Itoa(*fixVolumeId) if *fixVolumeCollection != "" { fileName = *fixVolumeCollection + "_" + fileName } indexFile, err := os.OpenFile(path.Join(*fixVolumePath, fileName+".idx"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { glog.Fatalf("Create Volume Index [ERROR] %s\n", err) } defer indexFile.Close() nm := storage.NewNeedleMap(indexFile) defer nm.Close() vid := storage.VolumeId(*fixVolumeId) err = storage.ScanVolumeFile(*fixVolumePath, *fixVolumeCollection, vid, func(superBlock storage.SuperBlock) error { return nil }, false, func(n *storage.Needle, offset int64) error { debug("key", n.Id, "offset", offset, "size", n.Size, "disk_size", n.DiskSize(), "gzip", n.IsGzipped()) if n.Size > 0 { count, pe := nm.Put(n.Id, uint32(offset/storage.NeedlePaddingSize), n.Size) debug("saved", count, "with error", pe) } else { debug("skipping deleted file ...") return nm.Delete(n.Id) } return nil }) if err != nil { glog.Fatalf("Export Volume File [ERROR] %s\n", err) } return true }
//如果 dest == - 则表示标准输出 func runExport(cmd *Command, args []string) bool { if *exportVolumeId == -1 { return false } var err error if *dest != "" { if *dest != "-" && !strings.HasSuffix(*dest, ".tar") { fmt.Println("the output file", *dest, "should be '-' or end with .tar") return false } if fnTmpl, err = template.New("name").Parse(*format); err != nil { fmt.Println("cannot parse format " + *format + ": " + err.Error()) return false } var fh *os.File if *dest == "-" { //标准输出 fh = os.Stdout } else { if fh, err = os.Create(*dest); err != nil { glog.Fatalf("cannot open output tar %s: %s", *dest, err) } } defer fh.Close() tarFh = tar.NewWriter(fh) defer tarFh.Close() t := time.Now() tarHeader = tar.Header{Mode: 0644, ModTime: t, Uid: os.Getuid(), Gid: os.Getgid(), Typeflag: tar.TypeReg, AccessTime: t, ChangeTime: t} } fileName := strconv.Itoa(*exportVolumeId) if *exportCollection != "" { fileName = *exportCollection + "_" + fileName } vid := storage.VolumeId(*exportVolumeId) indexFile, err := os.OpenFile(path.Join(*exportVolumePath, fileName+".idx"), os.O_RDONLY, 0644) if err != nil { glog.Fatalf("Create Volume Index [ERROR] %s\n", err) } defer indexFile.Close() //从index文件中加载整个volume的needle信息 nm, err := storage.LoadNeedleMap(indexFile) if err != nil { glog.Fatalf("cannot load needle map from %s: %s", indexFile.Name(), err) } var version storage.Version err = storage.ScanVolumeFile(*exportVolumePath, *exportCollection, vid, func(superBlock storage.SuperBlock) error { version = superBlock.Version() return nil }, true, func(n *storage.Needle, offset int64) error { nv, ok := nm.Get(n.Id) glog.V(3).Infoln("key", n.Id, "offset", offset, "size", n.Size, "disk_size", n.DiskSize(), "gzip", n.IsGzipped(), "ok", ok, "nv", nv) if ok && nv.Size > 0 { return walker(vid, n, version) } else { if !ok { debug("This seems deleted", n.Id, "size", n.Size) } else { debug("Id", n.Id, "size", n.Size) } } return nil }) if err != nil { glog.Fatalf("Export Volume File [ERROR] %s\n", err) } return true }