diff --git a/src/cmd/linuxkit/cache/cacheindex.go b/src/cmd/linuxkit/cache/cacheindex.go index ecf3b5197..31bd6328b 100644 --- a/src/cmd/linuxkit/cache/cacheindex.go +++ b/src/cmd/linuxkit/cache/cacheindex.go @@ -6,13 +6,19 @@ package cache import ( "errors" "fmt" + "path/filepath" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/match" + "github.com/linuxkit/linuxkit/src/cmd/linuxkit/util" imagespec "github.com/opencontainers/image-spec/specs-go/v1" log "github.com/sirupsen/logrus" ) +const ( + indexFile = "index.json" +) + // DescriptorWrite writes a descriptor to the cache index; it validates that it has a name // and replaces any existing one func (p *Provider) DescriptorWrite(image string, desc v1.Descriptor) error { @@ -25,6 +31,17 @@ func (p *Provider) DescriptorWrite(image string, desc v1.Descriptor) error { desc.Annotations[imagespec.AnnotationRefName] = image log.Debugf("writing descriptor for image %s", image) + // get our lock + lock, err := util.Lock(filepath.Join(p.dir, indexFile)) + if err != nil { + return fmt.Errorf("unable to lock cache index for writing descriptor for %s: %v", image, err) + } + defer func() { + if err := lock.Unlock(); err != nil { + log.Errorf("unable to close lock for cache index after writing descriptor for %s: %v", image, err) + } + }() + // do we update an existing one? Or create a new one? if err := p.cache.RemoveDescriptors(match.Name(image)); err != nil { return fmt.Errorf("unable to remove old descriptors for %s: %v", image, err) @@ -40,6 +57,15 @@ func (p *Provider) DescriptorWrite(image string, desc v1.Descriptor) error { // RemoveDescriptors removes all descriptors that match the provided matcher. // It does so in a parallel-access-safe way func (p *Provider) RemoveDescriptors(matcher match.Matcher) error { - // will be replaced with locking + // get our lock + lock, err := util.Lock(filepath.Join(p.dir, indexFile)) + if err != nil { + return fmt.Errorf("unable to lock cache index for removing descriptor for %v: %v", matcher, err) + } + defer func() { + if err := lock.Unlock(); err != nil { + log.Errorf("unable to close lock for cache index after writing descriptor for %v: %v", matcher, err) + } + }() return p.cache.RemoveDescriptors(matcher) } diff --git a/src/cmd/linuxkit/cache/open.go b/src/cmd/linuxkit/cache/open.go index d4b307589..d0d20c5fd 100644 --- a/src/cmd/linuxkit/cache/open.go +++ b/src/cmd/linuxkit/cache/open.go @@ -2,9 +2,12 @@ package cache import ( "fmt" + "path/filepath" "github.com/google/go-containerregistry/pkg/v1/empty" "github.com/google/go-containerregistry/pkg/v1/layout" + "github.com/linuxkit/linuxkit/src/cmd/linuxkit/util" + log "github.com/sirupsen/logrus" ) // Get get or initialize the cache @@ -12,6 +15,15 @@ func Get(cache string) (layout.Path, error) { // initialize the cache path if needed p, err := layout.FromPath(cache) if err != nil { + lock, err := util.Lock(filepath.Join(cache, indexFile)) + if err != nil { + return "", fmt.Errorf("unable to lock cache index for writing descriptor for new cache: %v", err) + } + defer func() { + if err := lock.Unlock(); err != nil { + log.Errorf("unable to close lock for cache index after writing descriptor for new cache: %v", err) + } + }() p, err = layout.Write(cache, empty.Index) if err != nil { return p, fmt.Errorf("could not initialize cache at path %s: %v", cache, err) diff --git a/src/cmd/linuxkit/cache/provider.go b/src/cmd/linuxkit/cache/provider.go index 1f1ee0765..ec2a12f6d 100644 --- a/src/cmd/linuxkit/cache/provider.go +++ b/src/cmd/linuxkit/cache/provider.go @@ -10,6 +10,7 @@ import ( type Provider struct { cache layout.Path store content.Store + dir string } // NewProvider create a new CacheProvider based in the provided directory @@ -22,5 +23,5 @@ func NewProvider(dir string) (*Provider, error) { if err != nil { return nil, err } - return &Provider{p, store}, nil + return &Provider{p, store, dir}, nil }