github.com/rish1988/moby@v25.0.2+incompatible/volume/service/db.go (about)

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