leasemanager.go 2.9 KB

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