github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/builder/builder-next/adapters/snapshot/leasemanager.go (about) 1 package snapshot 2 3 import ( 4 "context" 5 "sync" 6 7 "github.com/containerd/containerd/leases" 8 "github.com/containerd/log" 9 bolt "go.etcd.io/bbolt" 10 ) 11 12 type sLM struct { 13 manager leases.Manager 14 s *snapshotter 15 16 mu sync.Mutex 17 byLease map[string]map[string]struct{} 18 bySnapshot map[string]map[string]struct{} 19 } 20 21 func newLeaseManager(s *snapshotter, lm leases.Manager) *sLM { 22 return &sLM{ 23 s: s, 24 manager: lm, 25 26 byLease: map[string]map[string]struct{}{}, 27 bySnapshot: map[string]map[string]struct{}{}, 28 } 29 } 30 31 func (l *sLM) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, error) { 32 return l.manager.Create(ctx, opts...) 33 } 34 35 func (l *sLM) Delete(ctx context.Context, lease leases.Lease, opts ...leases.DeleteOpt) error { 36 if err := l.manager.Delete(ctx, lease, opts...); err != nil { 37 return err 38 } 39 l.mu.Lock() 40 if snaps, ok := l.byLease[lease.ID]; ok { 41 for sID := range snaps { 42 l.delRef(lease.ID, sID) 43 } 44 } 45 l.mu.Unlock() 46 return nil 47 } 48 49 func (l *sLM) List(ctx context.Context, filters ...string) ([]leases.Lease, error) { 50 return l.manager.List(ctx, filters...) 51 } 52 53 func (l *sLM) AddResource(ctx context.Context, lease leases.Lease, resource leases.Resource) error { 54 if err := l.manager.AddResource(ctx, lease, resource); err != nil { 55 return err 56 } 57 if resource.Type == "snapshots/default" { 58 l.mu.Lock() 59 l.addRef(lease.ID, resource.ID) 60 l.mu.Unlock() 61 } 62 return nil 63 } 64 65 func (l *sLM) DeleteResource(ctx context.Context, lease leases.Lease, resource leases.Resource) error { 66 if err := l.manager.DeleteResource(ctx, lease, resource); err != nil { 67 return err 68 } 69 if resource.Type == "snapshots/default" { 70 l.mu.Lock() 71 l.delRef(lease.ID, resource.ID) 72 l.mu.Unlock() 73 } 74 return nil 75 } 76 77 func (l *sLM) ListResources(ctx context.Context, lease leases.Lease) ([]leases.Resource, error) { 78 return l.manager.ListResources(ctx, lease) 79 } 80 81 func (l *sLM) addRef(lID, sID string) { 82 load := false 83 snapshots, ok := l.byLease[lID] 84 if !ok { 85 snapshots = map[string]struct{}{} 86 l.byLease[lID] = snapshots 87 } 88 if _, ok := snapshots[sID]; !ok { 89 snapshots[sID] = struct{}{} 90 } 91 leases, ok := l.bySnapshot[sID] 92 if !ok { 93 leases = map[string]struct{}{} 94 l.byLease[sID] = leases 95 load = true 96 } 97 if _, ok := leases[lID]; !ok { 98 leases[lID] = struct{}{} 99 } 100 101 if load { 102 l.s.getLayer(sID, true) 103 if _, ok := l.s.chainID(sID); ok { 104 l.s.db.Update(func(tx *bolt.Tx) error { 105 b, err := tx.CreateBucketIfNotExists([]byte(lID)) 106 if err != nil { 107 return err 108 } 109 return b.Put(keyChainID, []byte(sID)) 110 }) 111 } 112 } 113 } 114 115 func (l *sLM) delRef(lID, sID string) { 116 snapshots, ok := l.byLease[lID] 117 if !ok { 118 delete(snapshots, sID) 119 if len(snapshots) == 0 { 120 delete(l.byLease, lID) 121 } 122 } 123 leases, ok := l.bySnapshot[sID] 124 if !ok { 125 delete(leases, lID) 126 if len(leases) == 0 { 127 delete(l.bySnapshot, sID) 128 if err := l.s.remove(context.TODO(), sID); err != nil { 129 log.G(context.TODO()).Warnf("failed to remove snapshot %v", sID) 130 } 131 } 132 } 133 }