github.com/mgoltzsche/ctnr@v0.7.1-alpha/bundle/store/bundlestore.go (about) 1 package store 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "time" 8 9 "github.com/mgoltzsche/ctnr/bundle" 10 exterrors "github.com/mgoltzsche/ctnr/pkg/errors" 11 "github.com/mgoltzsche/ctnr/pkg/log" 12 "github.com/pkg/errors" 13 ) 14 15 var _ bundle.BundleStore = &BundleStore{} 16 17 type BundleStore struct { 18 dir string 19 debug log.FieldLogger 20 info log.FieldLogger 21 } 22 23 func NewBundleStore(dir string, info log.FieldLogger, debug log.FieldLogger) *BundleStore { 24 return &BundleStore{dir, debug, info} 25 } 26 27 func (s *BundleStore) Bundles() (l []bundle.Bundle, err error) { 28 fl, e := ioutil.ReadDir(s.dir) 29 l = make([]bundle.Bundle, 0, len(fl)) 30 if e != nil && !os.IsNotExist(e) { 31 return l, errors.Wrap(err, "bundles") 32 } 33 for _, f := range fl { 34 if f.IsDir() { 35 c, e := s.Bundle(f.Name()) 36 if e == nil { 37 l = append(l, c) 38 } else { 39 err = exterrors.Append(err, e) 40 } 41 } 42 } 43 return 44 } 45 46 func (s *BundleStore) Bundle(id string) (r bundle.Bundle, err error) { 47 return bundle.NewBundle(filepath.Join(s.dir, id)) 48 } 49 50 func (s *BundleStore) CreateBundle(id string, update bool) (b *bundle.LockedBundle, err error) { 51 dir := filepath.Join(s.dir, id) 52 if id == "" { 53 if err = os.MkdirAll(s.dir, 0750); err != nil { 54 return nil, errors.Wrap(err, "create bundle") 55 } 56 if dir, err = ioutil.TempDir(s.dir, ""); err != nil { 57 return nil, errors.Wrap(err, "create bundle") 58 } 59 update = true 60 } 61 return bundle.CreateLockedBundle(dir, update) 62 } 63 64 // Deletes all bundles that have not been used longer than the given TTL. 65 func (s *BundleStore) BundleGC(ttl time.Duration, containers bundle.ContainerStore) (r []bundle.Bundle, err error) { 66 s.debug.Printf("Running bundle GC with TTL of %s", ttl) 67 before := time.Now().Add(-ttl) 68 l, err := s.Bundles() 69 r = make([]bundle.Bundle, 0, len(l)) 70 for _, b := range l { 71 gcd, e := gc(b, before, containers) 72 if e != nil { 73 if gcd { 74 s.debug.WithField("id", b.ID()).Println("bundle gc:", e) 75 } 76 } else if gcd { 77 s.debug.WithField("id", b.ID()).Printf("bundle garbage collected") 78 r = append(r, b) 79 } 80 } 81 return 82 } 83 84 func gc(b bundle.Bundle, before time.Time, containers bundle.ContainerStore) (r bool, err error) { 85 defer exterrors.Wrapd(&err, "bundle gc check") 86 lastUsed, err := b.LastUsed() 87 if err != nil { 88 return false, err 89 } 90 if lastUsed.Before(before) { 91 // lock bundle 92 lb, err := bundle.OpenLockedBundle(b) 93 if err != nil { 94 return false, err 95 } 96 defer func() { 97 err = exterrors.Append(err, lb.Close()) 98 }() 99 100 // Check bundle usage time against expiry time 101 if lastUsed, err = b.LastUsed(); err != nil { 102 return true, err 103 } 104 if !lastUsed.Before(before) { 105 return false, nil 106 } 107 108 // Check if container is running 109 exists, err := containers.Exist(b.ID()) 110 if err != nil { 111 return true, err 112 } 113 if exists { 114 return false, nil 115 } 116 117 return true, lb.Delete() 118 } 119 return 120 }