dotcloud/docker

View on GitHub
volume/service/db.go

Summary

Maintainability
A
0 mins
Test Coverage
package service // import "github.com/docker/docker/volume/service"

import (
    "context"
    "encoding/json"

    "github.com/containerd/log"
    "github.com/docker/docker/errdefs"
    "github.com/pkg/errors"
    bolt "go.etcd.io/bbolt"
)

var volumeBucketName = []byte("volumes")

type volumeMetadata struct {
    Name    string
    Driver  string
    Labels  map[string]string
    Options map[string]string
}

func (s *VolumeStore) setMeta(name string, meta volumeMetadata) error {
    return s.db.Update(func(tx *bolt.Tx) error {
        return setMeta(tx, name, meta)
    })
}

func setMeta(tx *bolt.Tx, name string, meta volumeMetadata) error {
    metaJSON, err := json.Marshal(meta)
    if err != nil {
        return err
    }
    b, err := tx.CreateBucketIfNotExists(volumeBucketName)
    if err != nil {
        return errors.Wrap(err, "error creating volume bucket")
    }
    return errors.Wrap(b.Put([]byte(name), metaJSON), "error setting volume metadata")
}

func (s *VolumeStore) getMeta(name string) (volumeMetadata, error) {
    var meta volumeMetadata
    err := s.db.View(func(tx *bolt.Tx) error {
        return getMeta(tx, name, &meta)
    })
    return meta, err
}

func getMeta(tx *bolt.Tx, name string, meta *volumeMetadata) error {
    b := tx.Bucket(volumeBucketName)
    if b == nil {
        return errdefs.NotFound(errors.New("volume bucket does not exist"))
    }
    val := b.Get([]byte(name))
    if len(val) == 0 {
        return nil
    }
    if err := json.Unmarshal(val, meta); err != nil {
        return errors.Wrap(err, "error unmarshaling volume metadata")
    }
    return nil
}

func (s *VolumeStore) removeMeta(name string) error {
    return s.db.Update(func(tx *bolt.Tx) error {
        return removeMeta(tx, name)
    })
}

func removeMeta(tx *bolt.Tx, name string) error {
    b := tx.Bucket(volumeBucketName)
    return errors.Wrap(b.Delete([]byte(name)), "error removing volume metadata")
}

// listMeta is used during restore to get the list of volume metadata
// from the on-disk database.
// Any errors that occur are only logged.
func listMeta(tx *bolt.Tx) []volumeMetadata {
    var ls []volumeMetadata
    b := tx.Bucket(volumeBucketName)
    b.ForEach(func(k, v []byte) error {
        if len(v) == 0 {
            // don't try to unmarshal an empty value
            return nil
        }

        var m volumeMetadata
        if err := json.Unmarshal(v, &m); err != nil {
            // Just log the error
            log.G(context.TODO()).Errorf("Error while reading volume metadata for volume %q: %v", string(k), err)
            return nil
        }
        ls = append(ls, m)
        return nil
    })
    return ls
}