blobsum_service.go 2.6 KB

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