github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/volume/service/db.go (about)

     1  package service // import "github.com/docker/docker/volume/service"
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/docker/docker/errdefs"
     7  	"github.com/pkg/errors"
     8  	"github.com/sirupsen/logrus"
     9  	bolt "go.etcd.io/bbolt"
    10  )
    11  
    12  var volumeBucketName = []byte("volumes")
    13  
    14  type volumeMetadata struct {
    15  	Name    string
    16  	Driver  string
    17  	Labels  map[string]string
    18  	Options map[string]string
    19  }
    20  
    21  func (s *VolumeStore) setMeta(name string, meta volumeMetadata) error {
    22  	return s.db.Update(func(tx *bolt.Tx) error {
    23  		return setMeta(tx, name, meta)
    24  	})
    25  }
    26  
    27  func setMeta(tx *bolt.Tx, name string, meta volumeMetadata) error {
    28  	metaJSON, err := json.Marshal(meta)
    29  	if err != nil {
    30  		return err
    31  	}
    32  	b, err := tx.CreateBucketIfNotExists(volumeBucketName)
    33  	if err != nil {
    34  		return errors.Wrap(err, "error creating volume bucket")
    35  	}
    36  	return errors.Wrap(b.Put([]byte(name), metaJSON), "error setting volume metadata")
    37  }
    38  
    39  func (s *VolumeStore) getMeta(name string) (volumeMetadata, error) {
    40  	var meta volumeMetadata
    41  	err := s.db.View(func(tx *bolt.Tx) error {
    42  		return getMeta(tx, name, &meta)
    43  	})
    44  	return meta, err
    45  }
    46  
    47  func getMeta(tx *bolt.Tx, name string, meta *volumeMetadata) error {
    48  	b := tx.Bucket(volumeBucketName)
    49  	if b == nil {
    50  		return errdefs.NotFound(errors.New("volume bucket does not exist"))
    51  	}
    52  	val := b.Get([]byte(name))
    53  	if len(val) == 0 {
    54  		return nil
    55  	}
    56  	if err := json.Unmarshal(val, meta); err != nil {
    57  		return errors.Wrap(err, "error unmarshaling volume metadata")
    58  	}
    59  	return nil
    60  }
    61  
    62  func (s *VolumeStore) removeMeta(name string) error {
    63  	return s.db.Update(func(tx *bolt.Tx) error {
    64  		return removeMeta(tx, name)
    65  	})
    66  }
    67  
    68  func removeMeta(tx *bolt.Tx, name string) error {
    69  	b := tx.Bucket(volumeBucketName)
    70  	return errors.Wrap(b.Delete([]byte(name)), "error removing volume metadata")
    71  }
    72  
    73  // listMeta is used during restore to get the list of volume metadata
    74  // from the on-disk database.
    75  // Any errors that occur are only logged.
    76  func listMeta(tx *bolt.Tx) []volumeMetadata {
    77  	var ls []volumeMetadata
    78  	b := tx.Bucket(volumeBucketName)
    79  	b.ForEach(func(k, v []byte) error {
    80  		if len(v) == 0 {
    81  			// don't try to unmarshal an empty value
    82  			return nil
    83  		}
    84  
    85  		var m volumeMetadata
    86  		if err := json.Unmarshal(v, &m); err != nil {
    87  			// Just log the error
    88  			logrus.Errorf("Error while reading volume metadata for volume %q: %v", string(k), err)
    89  			return nil
    90  		}
    91  		ls = append(ls, m)
    92  		return nil
    93  	})
    94  	return ls
    95  }