github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/volume/store/store.go (about)

     1  package store // import "github.com/docker/docker/volume/store"
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	"github.com/boltdb/bolt"
    14  	"github.com/docker/docker/pkg/locker"
    15  	"github.com/docker/docker/volume"
    16  	"github.com/docker/docker/volume/drivers"
    17  	"github.com/sirupsen/logrus"
    18  )
    19  
    20  const (
    21  	volumeDataDir = "volumes"
    22  )
    23  
    24  type volumeWrapper struct {
    25  	volume.Volume
    26  	labels  map[string]string
    27  	scope   string
    28  	options map[string]string
    29  }
    30  
    31  func (v volumeWrapper) Options() map[string]string {
    32  	if v.options == nil {
    33  		return nil
    34  	}
    35  	options := make(map[string]string, len(v.options))
    36  	for key, value := range v.options {
    37  		options[key] = value
    38  	}
    39  	return options
    40  }
    41  
    42  func (v volumeWrapper) Labels() map[string]string {
    43  	if v.labels == nil {
    44  		return nil
    45  	}
    46  
    47  	labels := make(map[string]string, len(v.labels))
    48  	for key, value := range v.labels {
    49  		labels[key] = value
    50  	}
    51  	return labels
    52  }
    53  
    54  func (v volumeWrapper) Scope() string {
    55  	return v.scope
    56  }
    57  
    58  func (v volumeWrapper) CachedPath() string {
    59  	if vv, ok := v.Volume.(interface {
    60  		CachedPath() string
    61  	}); ok {
    62  		return vv.CachedPath()
    63  	}
    64  	return v.Volume.Path()
    65  }
    66  
    67  // New initializes a VolumeStore to keep
    68  // reference counting of volumes in the system.
    69  func New(rootPath string) (*VolumeStore, error) {
    70  	vs := &VolumeStore{
    71  		locks:   &locker.Locker{},
    72  		names:   make(map[string]volume.Volume),
    73  		refs:    make(map[string]map[string]struct{}),
    74  		labels:  make(map[string]map[string]string),
    75  		options: make(map[string]map[string]string),
    76  	}
    77  
    78  	if rootPath != "" {
    79  		// initialize metadata store
    80  		volPath := filepath.Join(rootPath, volumeDataDir)
    81  		if err := os.MkdirAll(volPath, 750); err != nil {
    82  			return nil, err
    83  		}
    84  
    85  		dbPath := filepath.Join(volPath, "metadata.db")
    86  
    87  		var err error
    88  		vs.db, err = bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
    89  		if err != nil {
    90  			return nil, errors.Wrap(err, "error while opening volume store metadata database")
    91  		}
    92  
    93  		// initialize volumes bucket
    94  		if err := vs.db.Update(func(tx *bolt.Tx) error {
    95  			if _, err := tx.CreateBucketIfNotExists(volumeBucketName); err != nil {
    96  				return errors.Wrap(err, "error while setting up volume store metadata database")
    97  			}
    98  			return nil
    99  		}); err != nil {
   100  			return nil, err
   101  		}
   102  	}
   103  
   104  	vs.restore()
   105  
   106  	return vs, nil
   107  }
   108  
   109  func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) {
   110  	s.globalLock.RLock()
   111  	v, exists := s.names[name]
   112  	s.globalLock.RUnlock()
   113  	return v, exists
   114  }
   115  
   116  func (s *VolumeStore) setNamed(v volume.Volume, ref string) {
   117  	name := v.Name()
   118  
   119  	s.globalLock.Lock()
   120  	s.names[name] = v
   121  	if len(ref) > 0 {
   122  		if s.refs[name] == nil {
   123  			s.refs[name] = make(map[string]struct{})
   124  		}
   125  		s.refs[name][ref] = struct{}{}
   126  	}
   127  	s.globalLock.Unlock()
   128  }
   129  
   130  // hasRef returns true if the given name has at least one ref.
   131  // Callers of this function are expected to hold the name lock.
   132  func (s *VolumeStore) hasRef(name string) bool {
   133  	s.globalLock.RLock()
   134  	l := len(s.refs[name])
   135  	s.globalLock.RUnlock()
   136  	return l > 0
   137  }
   138  
   139  // getRefs gets the list of refs for a given name
   140  // Callers of this function are expected to hold the name lock.
   141  func (s *VolumeStore) getRefs(name string) []string {
   142  	s.globalLock.RLock()
   143  	defer s.globalLock.RUnlock()
   144  
   145  	refs := make([]string, 0, len(s.refs[name]))
   146  	for r := range s.refs[name] {
   147  		refs = append(refs, r)
   148  	}
   149  
   150  	return refs
   151  }
   152  
   153  // Purge allows the cleanup of internal data on docker in case
   154  // the internal data is out of sync with volumes driver plugins.
   155  func (s *VolumeStore) Purge(name string) {
   156  	s.globalLock.Lock()
   157  	v, exists := s.names[name]
   158  	if exists {
   159  		driverName := v.DriverName()
   160  		if _, err := volumedrivers.ReleaseDriver(driverName); err != nil {
   161  			logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
   162  		}
   163  	}
   164  	if err := s.removeMeta(name); err != nil {
   165  		logrus.Errorf("Error removing volume metadata for volume %q: %v", name, err)
   166  	}
   167  	delete(s.names, name)
   168  	delete(s.refs, name)
   169  	delete(s.labels, name)
   170  	delete(s.options, name)
   171  	s.globalLock.Unlock()
   172  }
   173  
   174  // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts
   175  type VolumeStore struct {
   176  	// locks ensures that only one action is being performed on a particular volume at a time without locking the entire store
   177  	// since actions on volumes can be quite slow, this ensures the store is free to handle requests for other volumes.
   178  	locks *locker.Locker
   179  	// globalLock is used to protect access to mutable structures used by the store object
   180  	globalLock sync.RWMutex
   181  	// names stores the volume name -> volume relationship.
   182  	// This is used for making lookups faster so we don't have to probe all drivers
   183  	names map[string]volume.Volume
   184  	// refs stores the volume name and the list of things referencing it
   185  	refs map[string]map[string]struct{}
   186  	// labels stores volume labels for each volume
   187  	labels map[string]map[string]string
   188  	// options stores volume options for each volume
   189  	options map[string]map[string]string
   190  	db      *bolt.DB
   191  }
   192  
   193  // List proxies to all registered volume drivers to get the full list of volumes
   194  // If a driver returns a volume that has name which conflicts with another volume from a different driver,
   195  // the first volume is chosen and the conflicting volume is dropped.
   196  func (s *VolumeStore) List() ([]volume.Volume, []string, error) {
   197  	vols, warnings, err := s.list()
   198  	if err != nil {
   199  		return nil, nil, &OpErr{Err: err, Op: "list"}
   200  	}
   201  	var out []volume.Volume
   202  
   203  	for _, v := range vols {
   204  		name := normalizeVolumeName(v.Name())
   205  
   206  		s.locks.Lock(name)
   207  		storedV, exists := s.getNamed(name)
   208  		// Note: it's not safe to populate the cache here because the volume may have been
   209  		// deleted before we acquire a lock on its name
   210  		if exists && storedV.DriverName() != v.DriverName() {
   211  			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName())
   212  			s.locks.Unlock(v.Name())
   213  			continue
   214  		}
   215  
   216  		out = append(out, v)
   217  		s.locks.Unlock(v.Name())
   218  	}
   219  	return out, warnings, nil
   220  }
   221  
   222  // list goes through each volume driver and asks for its list of volumes.
   223  func (s *VolumeStore) list() ([]volume.Volume, []string, error) {
   224  	var (
   225  		ls       []volume.Volume
   226  		warnings []string
   227  	)
   228  
   229  	drivers, err := volumedrivers.GetAllDrivers()
   230  	if err != nil {
   231  		return nil, nil, err
   232  	}
   233  
   234  	type vols struct {
   235  		vols       []volume.Volume
   236  		err        error
   237  		driverName string
   238  	}
   239  	chVols := make(chan vols, len(drivers))
   240  
   241  	for _, vd := range drivers {
   242  		go func(d volume.Driver) {
   243  			vs, err := d.List()
   244  			if err != nil {
   245  				chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
   246  				return
   247  			}
   248  			for i, v := range vs {
   249  				s.globalLock.RLock()
   250  				vs[i] = volumeWrapper{v, s.labels[v.Name()], d.Scope(), s.options[v.Name()]}
   251  				s.globalLock.RUnlock()
   252  			}
   253  
   254  			chVols <- vols{vols: vs}
   255  		}(vd)
   256  	}
   257  
   258  	badDrivers := make(map[string]struct{})
   259  	for i := 0; i < len(drivers); i++ {
   260  		vs := <-chVols
   261  
   262  		if vs.err != nil {
   263  			warnings = append(warnings, vs.err.Error())
   264  			badDrivers[vs.driverName] = struct{}{}
   265  			logrus.Warn(vs.err)
   266  		}
   267  		ls = append(ls, vs.vols...)
   268  	}
   269  
   270  	if len(badDrivers) > 0 {
   271  		s.globalLock.RLock()
   272  		for _, v := range s.names {
   273  			if _, exists := badDrivers[v.DriverName()]; exists {
   274  				ls = append(ls, v)
   275  			}
   276  		}
   277  		s.globalLock.RUnlock()
   278  	}
   279  	return ls, warnings, nil
   280  }
   281  
   282  // CreateWithRef creates a volume with the given name and driver and stores the ref
   283  // This ensures there's no race between creating a volume and then storing a reference.
   284  func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) {
   285  	name = normalizeVolumeName(name)
   286  	s.locks.Lock(name)
   287  	defer s.locks.Unlock(name)
   288  
   289  	v, err := s.create(name, driverName, opts, labels)
   290  	if err != nil {
   291  		if _, ok := err.(*OpErr); ok {
   292  			return nil, err
   293  		}
   294  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   295  	}
   296  
   297  	s.setNamed(v, ref)
   298  	return v, nil
   299  }
   300  
   301  // Create creates a volume with the given name and driver.
   302  // This is just like CreateWithRef() except we don't store a reference while holding the lock.
   303  func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   304  	return s.CreateWithRef(name, driverName, "", opts, labels)
   305  }
   306  
   307  // checkConflict checks the local cache for name collisions with the passed in name,
   308  // for existing volumes with the same name but in a different driver.
   309  // This is used by `Create` as a best effort to prevent name collisions for volumes.
   310  // If a matching volume is found that is not a conflict that is returned so the caller
   311  // does not need to perform an additional lookup.
   312  // When no matching volume is found, both returns will be nil
   313  //
   314  // Note: This does not probe all the drivers for name collisions because v1 plugins
   315  // are very slow, particularly if the plugin is down, and cause other issues,
   316  // particularly around locking the store.
   317  // TODO(cpuguy83): With v2 plugins this shouldn't be a problem. Could also potentially
   318  // use a connect timeout for this kind of check to ensure we aren't blocking for a
   319  // long time.
   320  func (s *VolumeStore) checkConflict(name, driverName string) (volume.Volume, error) {
   321  	// check the local cache
   322  	v, _ := s.getNamed(name)
   323  	if v == nil {
   324  		return nil, nil
   325  	}
   326  
   327  	vDriverName := v.DriverName()
   328  	var conflict bool
   329  	if driverName != "" {
   330  		// Retrieve canonical driver name to avoid inconsistencies (for example
   331  		// "plugin" vs. "plugin:latest")
   332  		vd, err := volumedrivers.GetDriver(driverName)
   333  		if err != nil {
   334  			return nil, err
   335  		}
   336  
   337  		if vDriverName != vd.Name() {
   338  			conflict = true
   339  		}
   340  	}
   341  
   342  	// let's check if the found volume ref
   343  	// is stale by checking with the driver if it still exists
   344  	exists, err := volumeExists(v)
   345  	if err != nil {
   346  		return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err)
   347  	}
   348  
   349  	if exists {
   350  		if conflict {
   351  			return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name)
   352  		}
   353  		return v, nil
   354  	}
   355  
   356  	if s.hasRef(v.Name()) {
   357  		// Containers are referencing this volume but it doesn't seem to exist anywhere.
   358  		// Return a conflict error here, the user can fix this with `docker volume rm -f`
   359  		return nil, errors.Wrapf(errNameConflict, "found references to volume '%s' in driver '%s' but the volume was not found in the driver -- you may need to remove containers referencing this volume or force remove the volume to re-create it", name, vDriverName)
   360  	}
   361  
   362  	// doesn't exist, so purge it from the cache
   363  	s.Purge(name)
   364  	return nil, nil
   365  }
   366  
   367  // volumeExists returns if the volume is still present in the driver.
   368  // An error is returned if there was an issue communicating with the driver.
   369  func volumeExists(v volume.Volume) (bool, error) {
   370  	exists, err := lookupVolume(v.DriverName(), v.Name())
   371  	if err != nil {
   372  		return false, err
   373  	}
   374  	return exists != nil, nil
   375  }
   376  
   377  // create asks the given driver to create a volume with the name/opts.
   378  // If a volume with the name is already known, it will ask the stored driver for the volume.
   379  // If the passed in driver name does not match the driver name which is stored
   380  //  for the given volume name, an error is returned after checking if the reference is stale.
   381  // If the reference is stale, it will be purged and this create can continue.
   382  // It is expected that callers of this function hold any necessary locks.
   383  func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   384  	// Validate the name in a platform-specific manner
   385  
   386  	// volume name validation is specific to the host os and not on container image
   387  	// windows/lcow should have an equivalent volumename validation logic so we create a parser for current host OS
   388  	parser := volume.NewParser(runtime.GOOS)
   389  	err := parser.ValidateVolumeName(name)
   390  	if err != nil {
   391  		return nil, err
   392  	}
   393  
   394  	v, err := s.checkConflict(name, driverName)
   395  	if err != nil {
   396  		return nil, err
   397  	}
   398  
   399  	if v != nil {
   400  		// there is an existing volume, if we already have this stored locally, return it.
   401  		// TODO: there could be some inconsistent details such as labels here
   402  		if vv, _ := s.getNamed(v.Name()); vv != nil {
   403  			return vv, nil
   404  		}
   405  	}
   406  
   407  	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
   408  	if driverName == "" {
   409  		v, _ = s.getVolume(name)
   410  		if v != nil {
   411  			return v, nil
   412  		}
   413  	}
   414  
   415  	vd, err := volumedrivers.CreateDriver(driverName)
   416  	if err != nil {
   417  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   418  	}
   419  
   420  	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
   421  	if v, _ = vd.Get(name); v == nil {
   422  		v, err = vd.Create(name, opts)
   423  		if err != nil {
   424  			if _, err := volumedrivers.ReleaseDriver(driverName); err != nil {
   425  				logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
   426  			}
   427  			return nil, err
   428  		}
   429  	}
   430  
   431  	s.globalLock.Lock()
   432  	s.labels[name] = labels
   433  	s.options[name] = opts
   434  	s.refs[name] = make(map[string]struct{})
   435  	s.globalLock.Unlock()
   436  
   437  	metadata := volumeMetadata{
   438  		Name:    name,
   439  		Driver:  vd.Name(),
   440  		Labels:  labels,
   441  		Options: opts,
   442  	}
   443  
   444  	if err := s.setMeta(name, metadata); err != nil {
   445  		return nil, err
   446  	}
   447  	return volumeWrapper{v, labels, vd.Scope(), opts}, nil
   448  }
   449  
   450  // GetWithRef gets a volume with the given name from the passed in driver and stores the ref
   451  // This is just like Get(), but we store the reference while holding the lock.
   452  // This makes sure there are no races between checking for the existence of a volume and adding a reference for it
   453  func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) {
   454  	name = normalizeVolumeName(name)
   455  	s.locks.Lock(name)
   456  	defer s.locks.Unlock(name)
   457  
   458  	vd, err := volumedrivers.GetDriver(driverName)
   459  	if err != nil {
   460  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   461  	}
   462  
   463  	v, err := vd.Get(name)
   464  	if err != nil {
   465  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   466  	}
   467  
   468  	s.setNamed(v, ref)
   469  
   470  	s.globalLock.RLock()
   471  	defer s.globalLock.RUnlock()
   472  	return volumeWrapper{v, s.labels[name], vd.Scope(), s.options[name]}, nil
   473  }
   474  
   475  // Get looks if a volume with the given name exists and returns it if so
   476  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
   477  	name = normalizeVolumeName(name)
   478  	s.locks.Lock(name)
   479  	defer s.locks.Unlock(name)
   480  
   481  	v, err := s.getVolume(name)
   482  	if err != nil {
   483  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   484  	}
   485  	s.setNamed(v, "")
   486  	return v, nil
   487  }
   488  
   489  // getVolume requests the volume, if the driver info is stored it just accesses that driver,
   490  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   491  // it is expected that callers of this function hold any necessary locks
   492  func (s *VolumeStore) getVolume(name string) (volume.Volume, error) {
   493  	var meta volumeMetadata
   494  	meta, err := s.getMeta(name)
   495  	if err != nil {
   496  		return nil, err
   497  	}
   498  
   499  	driverName := meta.Driver
   500  	if driverName == "" {
   501  		s.globalLock.RLock()
   502  		v, exists := s.names[name]
   503  		s.globalLock.RUnlock()
   504  		if exists {
   505  			meta.Driver = v.DriverName()
   506  			if err := s.setMeta(name, meta); err != nil {
   507  				return nil, err
   508  			}
   509  		}
   510  	}
   511  
   512  	if meta.Driver != "" {
   513  		vol, err := lookupVolume(meta.Driver, name)
   514  		if err != nil {
   515  			return nil, err
   516  		}
   517  		if vol == nil {
   518  			s.Purge(name)
   519  			return nil, errNoSuchVolume
   520  		}
   521  
   522  		var scope string
   523  		vd, err := volumedrivers.GetDriver(meta.Driver)
   524  		if err == nil {
   525  			scope = vd.Scope()
   526  		}
   527  		return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil
   528  	}
   529  
   530  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   531  	drivers, err := volumedrivers.GetAllDrivers()
   532  	if err != nil {
   533  		return nil, err
   534  	}
   535  
   536  	for _, d := range drivers {
   537  		v, err := d.Get(name)
   538  		if err != nil || v == nil {
   539  			continue
   540  		}
   541  		meta.Driver = v.DriverName()
   542  		if err := s.setMeta(name, meta); err != nil {
   543  			return nil, err
   544  		}
   545  		return volumeWrapper{v, meta.Labels, d.Scope(), meta.Options}, nil
   546  	}
   547  	return nil, errNoSuchVolume
   548  }
   549  
   550  // lookupVolume gets the specified volume from the specified driver.
   551  // This will only return errors related to communications with the driver.
   552  // If the driver returns an error that is not communication related the
   553  //   error is logged but not returned.
   554  // If the volume is not found it will return `nil, nil``
   555  func lookupVolume(driverName, volumeName string) (volume.Volume, error) {
   556  	vd, err := volumedrivers.GetDriver(driverName)
   557  	if err != nil {
   558  		return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   559  	}
   560  	v, err := vd.Get(volumeName)
   561  	if err != nil {
   562  		err = errors.Cause(err)
   563  		if _, ok := err.(net.Error); ok {
   564  			if v != nil {
   565  				volumeName = v.Name()
   566  				driverName = v.DriverName()
   567  			}
   568  			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   569  		}
   570  
   571  		// At this point, the error could be anything from the driver, such as "no such volume"
   572  		// Let's not check an error here, and instead check if the driver returned a volume
   573  		logrus.WithError(err).WithField("driver", driverName).WithField("volume", volumeName).Warnf("Error while looking up volume")
   574  	}
   575  	return v, nil
   576  }
   577  
   578  // Remove removes the requested volume. A volume is not removed if it has any refs
   579  func (s *VolumeStore) Remove(v volume.Volume) error {
   580  	name := normalizeVolumeName(v.Name())
   581  	s.locks.Lock(name)
   582  	defer s.locks.Unlock(name)
   583  
   584  	if s.hasRef(name) {
   585  		return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: s.getRefs(name)}
   586  	}
   587  
   588  	vd, err := volumedrivers.GetDriver(v.DriverName())
   589  	if err != nil {
   590  		return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
   591  	}
   592  
   593  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   594  	vol := unwrapVolume(v)
   595  	if err := vd.Remove(vol); err != nil {
   596  		return &OpErr{Err: err, Name: name, Op: "remove"}
   597  	}
   598  
   599  	s.Purge(name)
   600  	return nil
   601  }
   602  
   603  // Dereference removes the specified reference to the volume
   604  func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
   605  	name := v.Name()
   606  
   607  	s.locks.Lock(name)
   608  	defer s.locks.Unlock(name)
   609  
   610  	s.globalLock.Lock()
   611  	defer s.globalLock.Unlock()
   612  
   613  	if s.refs[name] != nil {
   614  		delete(s.refs[name], ref)
   615  	}
   616  }
   617  
   618  // Refs gets the current list of refs for the given volume
   619  func (s *VolumeStore) Refs(v volume.Volume) []string {
   620  	name := v.Name()
   621  
   622  	s.locks.Lock(name)
   623  	defer s.locks.Unlock(name)
   624  
   625  	return s.getRefs(name)
   626  }
   627  
   628  // FilterByDriver returns the available volumes filtered by driver name
   629  func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
   630  	vd, err := volumedrivers.GetDriver(name)
   631  	if err != nil {
   632  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   633  	}
   634  	ls, err := vd.List()
   635  	if err != nil {
   636  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   637  	}
   638  	for i, v := range ls {
   639  		options := map[string]string{}
   640  		s.globalLock.RLock()
   641  		for key, value := range s.options[v.Name()] {
   642  			options[key] = value
   643  		}
   644  		ls[i] = volumeWrapper{v, s.labels[v.Name()], vd.Scope(), options}
   645  		s.globalLock.RUnlock()
   646  	}
   647  	return ls, nil
   648  }
   649  
   650  // FilterByUsed returns the available volumes filtered by if they are in use or not.
   651  // `used=true` returns only volumes that are being used, while `used=false` returns
   652  // only volumes that are not being used.
   653  func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume {
   654  	return s.filter(vols, func(v volume.Volume) bool {
   655  		s.locks.Lock(v.Name())
   656  		hasRef := s.hasRef(v.Name())
   657  		s.locks.Unlock(v.Name())
   658  		return used == hasRef
   659  	})
   660  }
   661  
   662  // filterFunc defines a function to allow filter volumes in the store
   663  type filterFunc func(vol volume.Volume) bool
   664  
   665  // filter returns the available volumes filtered by a filterFunc function
   666  func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume {
   667  	var ls []volume.Volume
   668  	for _, v := range vols {
   669  		if f(v) {
   670  			ls = append(ls, v)
   671  		}
   672  	}
   673  	return ls
   674  }
   675  
   676  func unwrapVolume(v volume.Volume) volume.Volume {
   677  	if vol, ok := v.(volumeWrapper); ok {
   678  		return vol.Volume
   679  	}
   680  
   681  	return v
   682  }
   683  
   684  // Shutdown releases all resources used by the volume store
   685  // It does not make any changes to volumes, drivers, etc.
   686  func (s *VolumeStore) Shutdown() error {
   687  	return s.db.Close()
   688  }