github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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 } 19 20 // FSMetadataStore uses the filesystem to associate metadata with layer and 21 // image IDs. 22 type FSMetadataStore struct { 23 sync.RWMutex 24 basePath string 25 } 26 27 // NewFSMetadataStore creates a new filesystem-based metadata store. 28 func NewFSMetadataStore(basePath string) (*FSMetadataStore, error) { 29 if err := os.MkdirAll(basePath, 0700); err != nil { 30 return nil, err 31 } 32 return &FSMetadataStore{ 33 basePath: basePath, 34 }, nil 35 } 36 37 func (store *FSMetadataStore) path(namespace, key string) string { 38 return filepath.Join(store.basePath, namespace, key) 39 } 40 41 // Get retrieves data by namespace and key. The data is read from a file named 42 // after the key, stored in the namespace's directory. 43 func (store *FSMetadataStore) Get(namespace string, key string) ([]byte, error) { 44 store.RLock() 45 defer store.RUnlock() 46 47 return ioutil.ReadFile(store.path(namespace, key)) 48 } 49 50 // Set writes data indexed by namespace and key. The data is written to a file 51 // named after the key, stored in the namespace's directory. 52 func (store *FSMetadataStore) Set(namespace, key string, value []byte) error { 53 store.Lock() 54 defer store.Unlock() 55 56 path := store.path(namespace, key) 57 tempFilePath := path + ".tmp" 58 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { 59 return err 60 } 61 if err := ioutil.WriteFile(tempFilePath, value, 0644); err != nil { 62 return err 63 } 64 return os.Rename(tempFilePath, path) 65 }