github.com/uriddle/docker@v0.0.0-20210926094723-4072e6aeb013/distribution/metadata/v2_metadata_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 // V2MetadataService maps layer IDs to a set of known metadata for 11 // the layer. 12 type V2MetadataService struct { 13 store Store 14 } 15 16 // V2Metadata contains the digest and source repository information for a layer. 17 type V2Metadata struct { 18 Digest digest.Digest 19 SourceRepository string 20 } 21 22 // maxMetadata is the number of metadata entries to keep per layer DiffID. 23 const maxMetadata = 50 24 25 // NewV2MetadataService creates a new diff ID to v2 metadata mapping service. 26 func NewV2MetadataService(store Store) *V2MetadataService { 27 return &V2MetadataService{ 28 store: store, 29 } 30 } 31 32 func (serv *V2MetadataService) diffIDNamespace() string { 33 return "v2metadata-by-diffid" 34 } 35 36 func (serv *V2MetadataService) digestNamespace() string { 37 return "diffid-by-digest" 38 } 39 40 func (serv *V2MetadataService) diffIDKey(diffID layer.DiffID) string { 41 return string(digest.Digest(diffID).Algorithm()) + "/" + digest.Digest(diffID).Hex() 42 } 43 44 func (serv *V2MetadataService) digestKey(dgst digest.Digest) string { 45 return string(dgst.Algorithm()) + "/" + dgst.Hex() 46 } 47 48 // GetMetadata finds the metadata associated with a layer DiffID. 49 func (serv *V2MetadataService) GetMetadata(diffID layer.DiffID) ([]V2Metadata, error) { 50 jsonBytes, err := serv.store.Get(serv.diffIDNamespace(), serv.diffIDKey(diffID)) 51 if err != nil { 52 return nil, err 53 } 54 55 var metadata []V2Metadata 56 if err := json.Unmarshal(jsonBytes, &metadata); err != nil { 57 return nil, err 58 } 59 60 return metadata, nil 61 } 62 63 // GetDiffID finds a layer DiffID from a digest. 64 func (serv *V2MetadataService) GetDiffID(dgst digest.Digest) (layer.DiffID, error) { 65 diffIDBytes, err := serv.store.Get(serv.digestNamespace(), serv.digestKey(dgst)) 66 if err != nil { 67 return layer.DiffID(""), err 68 } 69 70 return layer.DiffID(diffIDBytes), nil 71 } 72 73 // Add associates metadata with a layer DiffID. If too many metadata entries are 74 // present, the oldest one is dropped. 75 func (serv *V2MetadataService) Add(diffID layer.DiffID, metadata V2Metadata) error { 76 oldMetadata, err := serv.GetMetadata(diffID) 77 if err != nil { 78 oldMetadata = nil 79 } 80 newMetadata := make([]V2Metadata, 0, len(oldMetadata)+1) 81 82 // Copy all other metadata to new slice 83 for _, oldMeta := range oldMetadata { 84 if oldMeta != metadata { 85 newMetadata = append(newMetadata, oldMeta) 86 } 87 } 88 89 newMetadata = append(newMetadata, metadata) 90 91 if len(newMetadata) > maxMetadata { 92 newMetadata = newMetadata[len(newMetadata)-maxMetadata:] 93 } 94 95 jsonBytes, err := json.Marshal(newMetadata) 96 if err != nil { 97 return err 98 } 99 100 err = serv.store.Set(serv.diffIDNamespace(), serv.diffIDKey(diffID), jsonBytes) 101 if err != nil { 102 return err 103 } 104 105 return serv.store.Set(serv.digestNamespace(), serv.digestKey(metadata.Digest), []byte(diffID)) 106 } 107 108 // Remove unassociates a metadata entry from a layer DiffID. 109 func (serv *V2MetadataService) Remove(metadata V2Metadata) error { 110 diffID, err := serv.GetDiffID(metadata.Digest) 111 if err != nil { 112 return err 113 } 114 oldMetadata, err := serv.GetMetadata(diffID) 115 if err != nil { 116 oldMetadata = nil 117 } 118 newMetadata := make([]V2Metadata, 0, len(oldMetadata)) 119 120 // Copy all other metadata to new slice 121 for _, oldMeta := range oldMetadata { 122 if oldMeta != metadata { 123 newMetadata = append(newMetadata, oldMeta) 124 } 125 } 126 127 if len(newMetadata) == 0 { 128 return serv.store.Delete(serv.diffIDNamespace(), serv.diffIDKey(diffID)) 129 } 130 131 jsonBytes, err := json.Marshal(newMetadata) 132 if err != nil { 133 return err 134 } 135 136 return serv.store.Set(serv.diffIDNamespace(), serv.diffIDKey(diffID), jsonBytes) 137 }