experimental/blobs.go (123 lines of code) (raw):

package experimental import ( "fmt" "path/filepath" "strings" "sync" "github.com/Sirupsen/logrus" "github.com/dustin/go-humanize" ) type blobsData map[digest]*blobData var blobsLock sync.Mutex func (b blobsData) mark(digest digest) error { if *ignoreBlobs { return nil } blobsLock.Lock() defer blobsLock.Unlock() blob := b[digest] if blob == nil { return fmt.Errorf("blob not found: %v", digest) } blob.references++ return nil } func (b blobsData) etag(digest digest) string { blob := b[digest] if blob != nil { return blob.etag } return "" } func (b blobsData) size(digest digest) int64 { blob := b[digest] if blob != nil { return blob.size } return 0 } func (b blobsData) sweep() error { jg := jobsRunner.group() for _, blob_ := range b { blob := blob_ jg.dispatch(func() error { if blob.references > 0 { return nil } err := deleteFile(blob.path(), blob.size) if err != nil { return err } return nil }) } return jg.finish() } func (b blobsData) addBlob(segments []string, info fileInfo) error { if len(segments) != 4 { return fmt.Errorf("unparseable path: %v", segments) } if segments[3] != "data" { return fmt.Errorf("file needs to be data: %v", segments) } digest, err := newDigestFromScopedPath(segments[0:3]) if err != nil { return err } if segments[0] != "sha256" { return fmt.Errorf("path needs to start with sha256: %v", segments) } blobsLock.Lock() defer blobsLock.Unlock() blob := &blobData{ name: digest, size: info.size, etag: info.etag, } b[digest] = blob return nil } func (b blobsData) walkPath(walkPath string) error { logrus.Infoln("BLOBS DIR:", walkPath) return currentStorage.Walk(walkPath, "blobs", func(path string, info fileInfo, err error) error { err = b.addBlob(strings.Split(path, "/"), info) if err != nil { logrus.Errorln("BLOB:", path, ":", err) if *softErrors { return nil } } else { logrus.Infoln("BLOB:", path, ":", err) } return err }) } func (b blobsData) walk(parallel bool) error { logrus.Infoln("Walking BLOBS...") if parallel { listRootPath := filepath.Join("blobs", "sha256") return parallelWalk(listRootPath, b.walkPath) } else { return b.walkPath("blobs") } } func (b blobsData) info() { var blobsUsed, blobsUnused int var blobsUsedSize, blobsUnusedSize int64 if *ignoreBlobs { return } for _, blob := range b { if blob.references > 0 { blobsUsed++ blobsUsedSize += blob.size } else { blobsUnused++ blobsUnusedSize += blob.size } } logrus.Infoln("BLOBS INFO:", "Objects/Unused:", blobsUsed, "/", blobsUnused, "Data/Unused:", humanize.Bytes(uint64(blobsUsedSize)), "/", humanize.Bytes(uint64(blobsUnusedSize)), ) }