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  }