github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/volume/store/store.go (about)

     1  package store
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/Sirupsen/logrus"
     7  	"github.com/docker/docker/pkg/locker"
     8  	"github.com/docker/docker/volume"
     9  	"github.com/docker/docker/volume/drivers"
    10  )
    11  
    12  // New initializes a VolumeStore to keep
    13  // reference counting of volumes in the system.
    14  func New() *VolumeStore {
    15  	return &VolumeStore{
    16  		locks: &locker.Locker{},
    17  		names: make(map[string]volume.Volume),
    18  		refs:  make(map[string][]string),
    19  	}
    20  }
    21  
    22  func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) {
    23  	s.globalLock.Lock()
    24  	v, exists := s.names[name]
    25  	s.globalLock.Unlock()
    26  	return v, exists
    27  }
    28  
    29  func (s *VolumeStore) setNamed(v volume.Volume, ref string) {
    30  	s.globalLock.Lock()
    31  	s.names[v.Name()] = v
    32  	if len(ref) > 0 {
    33  		s.refs[v.Name()] = append(s.refs[v.Name()], ref)
    34  	}
    35  	s.globalLock.Unlock()
    36  }
    37  
    38  func (s *VolumeStore) purge(name string) {
    39  	s.globalLock.Lock()
    40  	delete(s.names, name)
    41  	delete(s.refs, name)
    42  	s.globalLock.Unlock()
    43  }
    44  
    45  // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts
    46  type VolumeStore struct {
    47  	locks      *locker.Locker
    48  	globalLock sync.Mutex
    49  	// names stores the volume name -> driver name relationship.
    50  	// This is used for making lookups faster so we don't have to probe all drivers
    51  	names map[string]volume.Volume
    52  	// refs stores the volume name and the list of things referencing it
    53  	refs map[string][]string
    54  }
    55  
    56  // List proxies to all registered volume drivers to get the full list of volumes
    57  // If a driver returns a volume that has name which conflicts with another volume from a different driver,
    58  // the first volume is chosen and the conflicting volume is dropped.
    59  func (s *VolumeStore) List() ([]volume.Volume, []string, error) {
    60  	vols, warnings, err := s.list()
    61  	if err != nil {
    62  		return nil, nil, &OpErr{Err: err, Op: "list"}
    63  	}
    64  	var out []volume.Volume
    65  
    66  	for _, v := range vols {
    67  		name := normaliseVolumeName(v.Name())
    68  
    69  		s.locks.Lock(name)
    70  		storedV, exists := s.getNamed(name)
    71  		if !exists {
    72  			s.setNamed(v, "")
    73  		}
    74  		if exists && storedV.DriverName() != v.DriverName() {
    75  			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName())
    76  			s.locks.Unlock(v.Name())
    77  			continue
    78  		}
    79  
    80  		out = append(out, v)
    81  		s.locks.Unlock(v.Name())
    82  	}
    83  	return out, warnings, nil
    84  }
    85  
    86  // list goes through each volume driver and asks for its list of volumes.
    87  func (s *VolumeStore) list() ([]volume.Volume, []string, error) {
    88  	drivers, err := volumedrivers.GetAllDrivers()
    89  	if err != nil {
    90  		return nil, nil, err
    91  	}
    92  	var (
    93  		ls       []volume.Volume
    94  		warnings []string
    95  	)
    96  
    97  	type vols struct {
    98  		vols       []volume.Volume
    99  		err        error
   100  		driverName string
   101  	}
   102  	chVols := make(chan vols, len(drivers))
   103  
   104  	for _, vd := range drivers {
   105  		go func(d volume.Driver) {
   106  			vs, err := d.List()
   107  			if err != nil {
   108  				chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
   109  				return
   110  			}
   111  			chVols <- vols{vols: vs}
   112  		}(vd)
   113  	}
   114  
   115  	badDrivers := make(map[string]struct{})
   116  	for i := 0; i < len(drivers); i++ {
   117  		vs := <-chVols
   118  
   119  		if vs.err != nil {
   120  			warnings = append(warnings, vs.err.Error())
   121  			badDrivers[vs.driverName] = struct{}{}
   122  			logrus.Warn(vs.err)
   123  		}
   124  		ls = append(ls, vs.vols...)
   125  	}
   126  
   127  	if len(badDrivers) > 0 {
   128  		for _, v := range s.names {
   129  			if _, exists := badDrivers[v.DriverName()]; exists {
   130  				ls = append(ls, v)
   131  			}
   132  		}
   133  	}
   134  	return ls, warnings, nil
   135  }
   136  
   137  // CreateWithRef creates a volume with the given name and driver and stores the ref
   138  // This is just like Create() except we store the reference while holding the lock.
   139  // This ensures there's no race between creating a volume and then storing a reference.
   140  func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts map[string]string) (volume.Volume, error) {
   141  	name = normaliseVolumeName(name)
   142  	s.locks.Lock(name)
   143  	defer s.locks.Unlock(name)
   144  
   145  	v, err := s.create(name, driverName, opts)
   146  	if err != nil {
   147  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   148  	}
   149  
   150  	s.setNamed(v, ref)
   151  	return v, nil
   152  }
   153  
   154  // Create creates a volume with the given name and driver.
   155  func (s *VolumeStore) Create(name, driverName string, opts map[string]string) (volume.Volume, error) {
   156  	name = normaliseVolumeName(name)
   157  	s.locks.Lock(name)
   158  	defer s.locks.Unlock(name)
   159  
   160  	v, err := s.create(name, driverName, opts)
   161  	if err != nil {
   162  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   163  	}
   164  	s.setNamed(v, "")
   165  	return v, nil
   166  }
   167  
   168  // create asks the given driver to create a volume with the name/opts.
   169  // If a volume with the name is already known, it will ask the stored driver for the volume.
   170  // If the passed in driver name does not match the driver name which is stored for the given volume name, an error is returned.
   171  // It is expected that callers of this function hold any necessary locks.
   172  func (s *VolumeStore) create(name, driverName string, opts map[string]string) (volume.Volume, error) {
   173  	// Validate the name in a platform-specific manner
   174  	valid, err := volume.IsVolumeNameValid(name)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  	if !valid {
   179  		return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"}
   180  	}
   181  
   182  	if v, exists := s.getNamed(name); exists {
   183  		if v.DriverName() != driverName && driverName != "" && driverName != volume.DefaultDriverName {
   184  			return nil, errNameConflict
   185  		}
   186  		return v, nil
   187  	}
   188  
   189  	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
   190  	if driverName == "" {
   191  		v, _ := s.getVolume(name)
   192  		if v != nil {
   193  			return v, nil
   194  		}
   195  	}
   196  
   197  	vd, err := volumedrivers.GetDriver(driverName)
   198  
   199  	if err != nil {
   200  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   201  	}
   202  
   203  	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
   204  
   205  	if v, _ := vd.Get(name); v != nil {
   206  		return v, nil
   207  	}
   208  	return vd.Create(name, opts)
   209  }
   210  
   211  // GetWithRef gets a volume with the given name from the passed in driver and stores the ref
   212  // This is just like Get(), but we store the reference while holding the lock.
   213  // This makes sure there are no races between checking for the existence of a volume and adding a reference for it
   214  func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) {
   215  	name = normaliseVolumeName(name)
   216  	s.locks.Lock(name)
   217  	defer s.locks.Unlock(name)
   218  
   219  	vd, err := volumedrivers.GetDriver(driverName)
   220  	if err != nil {
   221  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   222  	}
   223  
   224  	v, err := vd.Get(name)
   225  	if err != nil {
   226  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   227  	}
   228  
   229  	s.setNamed(v, ref)
   230  	return v, nil
   231  }
   232  
   233  // Get looks if a volume with the given name exists and returns it if so
   234  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
   235  	name = normaliseVolumeName(name)
   236  	s.locks.Lock(name)
   237  	defer s.locks.Unlock(name)
   238  
   239  	v, err := s.getVolume(name)
   240  	if err != nil {
   241  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   242  	}
   243  	s.setNamed(v, "")
   244  	return v, nil
   245  }
   246  
   247  // getVolume requests the volume, if the driver info is stored it just accesses that driver,
   248  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   249  // it is expected that callers of this function hold any necessary locks
   250  func (s *VolumeStore) getVolume(name string) (volume.Volume, error) {
   251  	logrus.Debugf("Getting volume reference for name: %s", name)
   252  	if v, exists := s.names[name]; exists {
   253  		vd, err := volumedrivers.GetDriver(v.DriverName())
   254  		if err != nil {
   255  			return nil, err
   256  		}
   257  		return vd.Get(name)
   258  	}
   259  
   260  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   261  	drivers, err := volumedrivers.GetAllDrivers()
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  
   266  	for _, d := range drivers {
   267  		v, err := d.Get(name)
   268  		if err != nil {
   269  			continue
   270  		}
   271  		return v, nil
   272  	}
   273  	return nil, errNoSuchVolume
   274  }
   275  
   276  // Remove removes the requested volume. A volume is not removed if it has any refs
   277  func (s *VolumeStore) Remove(v volume.Volume) error {
   278  	name := normaliseVolumeName(v.Name())
   279  	s.locks.Lock(name)
   280  	defer s.locks.Unlock(name)
   281  
   282  	if refs, exists := s.refs[name]; exists && len(refs) > 0 {
   283  		return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: refs}
   284  	}
   285  
   286  	vd, err := volumedrivers.GetDriver(v.DriverName())
   287  	if err != nil {
   288  		return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
   289  	}
   290  
   291  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   292  	if err := vd.Remove(v); err != nil {
   293  		return &OpErr{Err: err, Name: name, Op: "remove"}
   294  	}
   295  
   296  	s.purge(name)
   297  	return nil
   298  }
   299  
   300  // Dereference removes the specified reference to the volume
   301  func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
   302  	s.locks.Lock(v.Name())
   303  	defer s.locks.Unlock(v.Name())
   304  
   305  	s.globalLock.Lock()
   306  	defer s.globalLock.Unlock()
   307  	var refs []string
   308  
   309  	for _, r := range s.refs[v.Name()] {
   310  		if r != ref {
   311  			refs = append(refs, r)
   312  		}
   313  	}
   314  	s.refs[v.Name()] = refs
   315  }
   316  
   317  // Refs gets the current list of refs for the given volume
   318  func (s *VolumeStore) Refs(v volume.Volume) []string {
   319  	s.locks.Lock(v.Name())
   320  	defer s.locks.Unlock(v.Name())
   321  
   322  	s.globalLock.Lock()
   323  	defer s.globalLock.Unlock()
   324  	refs, exists := s.refs[v.Name()]
   325  	if !exists {
   326  		return nil
   327  	}
   328  
   329  	refsOut := make([]string, len(refs))
   330  	copy(refsOut, refs)
   331  	return refsOut
   332  }
   333  
   334  // FilterByDriver returns the available volumes filtered by driver name
   335  func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
   336  	vd, err := volumedrivers.GetDriver(name)
   337  	if err != nil {
   338  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   339  	}
   340  	ls, err := vd.List()
   341  	if err != nil {
   342  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   343  	}
   344  	return ls, nil
   345  }
   346  
   347  // FilterByUsed returns the available volumes filtered by if they are in use or not.
   348  // `used=true` returns only volumes that are being used, while `used=false` returns
   349  // only volumes that are not being used.
   350  func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume {
   351  	return s.filter(vols, func(v volume.Volume) bool {
   352  		s.locks.Lock(v.Name())
   353  		l := len(s.refs[v.Name()])
   354  		s.locks.Unlock(v.Name())
   355  		if (used && l > 0) || (!used && l == 0) {
   356  			return true
   357  		}
   358  		return false
   359  	})
   360  }
   361  
   362  // filterFunc defines a function to allow filter volumes in the store
   363  type filterFunc func(vol volume.Volume) bool
   364  
   365  // filter returns the available volumes filtered by a filterFunc function
   366  func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume {
   367  	var ls []volume.Volume
   368  	for _, v := range vols {
   369  		if f(v) {
   370  			ls = append(ls, v)
   371  		}
   372  	}
   373  	return ls
   374  }