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