github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/signaturestore.go (about)

     1  package storage
     2  
     3  import (
     4  	"path"
     5  	"sync"
     6  
     7  	"github.com/docker/distribution"
     8  	"github.com/docker/distribution/context"
     9  	"github.com/docker/distribution/digest"
    10  )
    11  
    12  type signatureStore struct {
    13  	*repository
    14  }
    15  
    16  var _ distribution.SignatureService = &signatureStore{}
    17  
    18  func (s *signatureStore) Get(dgst digest.Digest) ([][]byte, error) {
    19  	signaturesPath, err := s.pm.path(manifestSignaturesPathSpec{
    20  		name:     s.Name(),
    21  		revision: dgst,
    22  	})
    23  
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  
    28  	// Need to append signature digest algorithm to path to get all items.
    29  	// Perhaps, this should be in the pathMapper but it feels awkward. This
    30  	// can be eliminated by implementing listAll on drivers.
    31  	signaturesPath = path.Join(signaturesPath, "sha256")
    32  
    33  	signaturePaths, err := s.driver.List(signaturesPath)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	var wg sync.WaitGroup
    39  	type result struct {
    40  		index     int
    41  		signature []byte
    42  		err       error
    43  	}
    44  	ch := make(chan result)
    45  
    46  	for i, sigPath := range signaturePaths {
    47  		// Append the link portion
    48  		sigPath = path.Join(sigPath, "link")
    49  
    50  		wg.Add(1)
    51  		go func(idx int, sigPath string) {
    52  			defer wg.Done()
    53  			context.GetLogger(s.ctx).
    54  				Debugf("fetching signature from %q", sigPath)
    55  
    56  			r := result{index: idx}
    57  			if p, err := s.blobStore.linked(sigPath); err != nil {
    58  				context.GetLogger(s.ctx).
    59  					Errorf("error fetching signature from %q: %v", sigPath, err)
    60  				r.err = err
    61  			} else {
    62  				r.signature = p
    63  			}
    64  
    65  			ch <- r
    66  		}(i, sigPath)
    67  	}
    68  	done := make(chan struct{})
    69  	go func() {
    70  		wg.Wait()
    71  		close(done)
    72  	}()
    73  
    74  	// aggregrate the results
    75  	signatures := make([][]byte, len(signaturePaths))
    76  loop:
    77  	for {
    78  		select {
    79  		case result := <-ch:
    80  			signatures[result.index] = result.signature
    81  			if result.err != nil && err == nil {
    82  				// only set the first one.
    83  				err = result.err
    84  			}
    85  		case <-done:
    86  			break loop
    87  		}
    88  	}
    89  
    90  	return signatures, err
    91  }
    92  
    93  func (s *signatureStore) Put(dgst digest.Digest, signatures ...[]byte) error {
    94  	for _, signature := range signatures {
    95  		signatureDigest, err := s.blobStore.put(signature)
    96  		if err != nil {
    97  			return err
    98  		}
    99  
   100  		signaturePath, err := s.pm.path(manifestSignatureLinkPathSpec{
   101  			name:      s.Name(),
   102  			revision:  dgst,
   103  			signature: signatureDigest,
   104  		})
   105  
   106  		if err != nil {
   107  			return err
   108  		}
   109  
   110  		if err := s.blobStore.link(signaturePath, signatureDigest); err != nil {
   111  			return err
   112  		}
   113  	}
   114  	return nil
   115  }