| package metadata // import "github.com/docker/docker/distribution/metadata" | |
| import ( | |
| "os" | |
| "path/filepath" | |
| "sync" | |
| "github.com/docker/docker/pkg/ioutils" | |
| ) | |
| // Store implements a K/V store for mapping distribution-related IDs | |
| // to on-disk layer IDs and image IDs. The namespace identifies the type of | |
| // mapping (i.e. "v1ids" or "artifacts"). MetadataStore is goroutine-safe. | |
| type Store interface { | |
| // Get retrieves data by namespace and key. | |
| Get(namespace string, key string) ([]byte, error) | |
| // Set writes data indexed by namespace and key. | |
| Set(namespace, key string, value []byte) error | |
| // Delete removes data indexed by namespace and key. | |
| Delete(namespace, key string) error | |
| } | |
| // FSMetadataStore uses the filesystem to associate metadata with layer and | |
| // image IDs. | |
| type FSMetadataStore struct { | |
| sync.RWMutex | |
| basePath string | |
| } | |
| // NewFSMetadataStore creates a new filesystem-based metadata store. | |
| func NewFSMetadataStore(basePath string) (*FSMetadataStore, error) { | |
| if err := os.MkdirAll(basePath, 0o700); err != nil { | |
| return nil, err | |
| } | |
| return &FSMetadataStore{ | |
| basePath: basePath, | |
| }, nil | |
| } | |
| func (store *FSMetadataStore) path(namespace, key string) string { | |
| return filepath.Join(store.basePath, namespace, key) | |
| } | |
| // Get retrieves data by namespace and key. The data is read from a file named | |
| // after the key, stored in the namespace's directory. | |
| func (store *FSMetadataStore) Get(namespace string, key string) ([]byte, error) { | |
| store.RLock() | |
| defer store.RUnlock() | |
| return os.ReadFile(store.path(namespace, key)) | |
| } | |
| // Set writes data indexed by namespace and key. The data is written to a file | |
| // named after the key, stored in the namespace's directory. | |
| func (store *FSMetadataStore) Set(namespace, key string, value []byte) error { | |
| store.Lock() | |
| defer store.Unlock() | |
| path := store.path(namespace, key) | |
| if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { | |
| return err | |
| } | |
| return ioutils.AtomicWriteFile(path, value, 0o644) | |
| } | |
| // Delete removes data indexed by namespace and key. The data file named after | |
| // the key, stored in the namespace's directory is deleted. | |
| func (store *FSMetadataStore) Delete(namespace, key string) error { | |
| store.Lock() | |
| defer store.Unlock() | |
| path := store.path(namespace, key) | |
| return os.Remove(path) | |
| } |