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  }