github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/distribution/metadata/blobsum_service.go (about)

     1  package metadata
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/docker/distribution/digest"
     7  	"github.com/docker/docker/layer"
     8  )
     9  
    10  // BlobSumService maps layer IDs to a set of known blobsums for
    11  // the layer.
    12  type BlobSumService struct {
    13  	store Store
    14  }
    15  
    16  // maxBlobSums is the number of blobsums to keep per layer DiffID.
    17  const maxBlobSums = 5
    18  
    19  // NewBlobSumService creates a new blobsum mapping service.
    20  func NewBlobSumService(store Store) *BlobSumService {
    21  	return &BlobSumService{
    22  		store: store,
    23  	}
    24  }
    25  
    26  func (blobserv *BlobSumService) diffIDNamespace() string {
    27  	return "blobsum-storage"
    28  }
    29  
    30  func (blobserv *BlobSumService) blobSumNamespace() string {
    31  	return "blobsum-lookup"
    32  }
    33  
    34  func (blobserv *BlobSumService) diffIDKey(diffID layer.DiffID) string {
    35  	return string(digest.Digest(diffID).Algorithm()) + "/" + digest.Digest(diffID).Hex()
    36  }
    37  
    38  func (blobserv *BlobSumService) blobSumKey(blobsum digest.Digest) string {
    39  	return string(blobsum.Algorithm()) + "/" + blobsum.Hex()
    40  }
    41  
    42  // GetBlobSums finds the blobsums associated with a layer DiffID.
    43  func (blobserv *BlobSumService) GetBlobSums(diffID layer.DiffID) ([]digest.Digest, error) {
    44  	jsonBytes, err := blobserv.store.Get(blobserv.diffIDNamespace(), blobserv.diffIDKey(diffID))
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	var blobsums []digest.Digest
    50  	if err := json.Unmarshal(jsonBytes, &blobsums); err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	return blobsums, nil
    55  }
    56  
    57  // GetDiffID finds a layer DiffID from a blobsum hash.
    58  func (blobserv *BlobSumService) GetDiffID(blobsum digest.Digest) (layer.DiffID, error) {
    59  	diffIDBytes, err := blobserv.store.Get(blobserv.blobSumNamespace(), blobserv.blobSumKey(blobsum))
    60  	if err != nil {
    61  		return layer.DiffID(""), err
    62  	}
    63  
    64  	return layer.DiffID(diffIDBytes), nil
    65  }
    66  
    67  // Add associates a blobsum with a layer DiffID. If too many blobsums are
    68  // present, the oldest one is dropped.
    69  func (blobserv *BlobSumService) Add(diffID layer.DiffID, blobsum digest.Digest) error {
    70  	oldBlobSums, err := blobserv.GetBlobSums(diffID)
    71  	if err != nil {
    72  		oldBlobSums = nil
    73  	}
    74  	newBlobSums := make([]digest.Digest, 0, len(oldBlobSums)+1)
    75  
    76  	// Copy all other blobsums to new slice
    77  	for _, oldSum := range oldBlobSums {
    78  		if oldSum != blobsum {
    79  			newBlobSums = append(newBlobSums, oldSum)
    80  		}
    81  	}
    82  
    83  	newBlobSums = append(newBlobSums, blobsum)
    84  
    85  	if len(newBlobSums) > maxBlobSums {
    86  		newBlobSums = newBlobSums[len(newBlobSums)-maxBlobSums:]
    87  	}
    88  
    89  	jsonBytes, err := json.Marshal(newBlobSums)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	err = blobserv.store.Set(blobserv.diffIDNamespace(), blobserv.diffIDKey(diffID), jsonBytes)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	return blobserv.store.Set(blobserv.blobSumNamespace(), blobserv.blobSumKey(blobsum), []byte(diffID))
   100  }