github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/distribution/metadata/metadata.go (about) 1 package metadata // import "github.com/docker/docker/distribution/metadata" 2 3 import ( 4 "os" 5 "path/filepath" 6 "sync" 7 8 "github.com/docker/docker/pkg/ioutils" 9 ) 10 11 // Store implements a K/V store for mapping distribution-related IDs 12 // to on-disk layer IDs and image IDs. The namespace identifies the type of 13 // mapping (i.e. "v1ids" or "artifacts"). MetadataStore is goroutine-safe. 14 type Store interface { 15 // Get retrieves data by namespace and key. 16 Get(namespace string, key string) ([]byte, error) 17 // Set writes data indexed by namespace and key. 18 Set(namespace, key string, value []byte) error 19 // Delete removes data indexed by namespace and key. 20 Delete(namespace, key string) error 21 } 22 23 // FSMetadataStore uses the filesystem to associate metadata with layer and 24 // image IDs. 25 type FSMetadataStore struct { 26 sync.RWMutex 27 basePath string 28 } 29 30 // NewFSMetadataStore creates a new filesystem-based metadata store. 31 func NewFSMetadataStore(basePath string) (*FSMetadataStore, error) { 32 if err := os.MkdirAll(basePath, 0o700); err != nil { 33 return nil, err 34 } 35 return &FSMetadataStore{ 36 basePath: basePath, 37 }, nil 38 } 39 40 func (store *FSMetadataStore) path(namespace, key string) string { 41 return filepath.Join(store.basePath, namespace, key) 42 } 43 44 // Get retrieves data by namespace and key. The data is read from a file named 45 // after the key, stored in the namespace's directory. 46 func (store *FSMetadataStore) Get(namespace string, key string) ([]byte, error) { 47 store.RLock() 48 defer store.RUnlock() 49 50 return os.ReadFile(store.path(namespace, key)) 51 } 52 53 // Set writes data indexed by namespace and key. The data is written to a file 54 // named after the key, stored in the namespace's directory. 55 func (store *FSMetadataStore) Set(namespace, key string, value []byte) error { 56 store.Lock() 57 defer store.Unlock() 58 59 path := store.path(namespace, key) 60 if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { 61 return err 62 } 63 return ioutils.AtomicWriteFile(path, value, 0o644) 64 } 65 66 // Delete removes data indexed by namespace and key. The data file named after 67 // the key, stored in the namespace's directory is deleted. 68 func (store *FSMetadataStore) Delete(namespace, key string) error { 69 store.Lock() 70 defer store.Unlock() 71 72 path := store.path(namespace, key) 73 return os.Remove(path) 74 }