github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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]string),
    18  		refs:  make(map[string][]string),
    19  	}
    20  }
    21  
    22  func (s *VolumeStore) getNamed(name string) (string, bool) {
    23  	s.globalLock.Lock()
    24  	driverName, exists := s.names[name]
    25  	s.globalLock.Unlock()
    26  	return driverName, exists
    27  }
    28  
    29  func (s *VolumeStore) setNamed(name, driver, ref string) {
    30  	s.globalLock.Lock()
    31  	s.names[name] = driver
    32  	if len(ref) > 0 {
    33  		s.refs[name] = append(s.refs[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]string
    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 a 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  		driverName, exists := s.getNamed(name)
    71  		if !exists {
    72  			s.setNamed(name, v.DriverName(), "")
    73  		}
    74  		if exists && driverName != v.DriverName() {
    75  			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), 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  	}
   101  	chVols := make(chan vols, len(drivers))
   102  
   103  	for _, vd := range drivers {
   104  		go func(d volume.Driver) {
   105  			vs, err := d.List()
   106  			if err != nil {
   107  				chVols <- vols{err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
   108  				return
   109  			}
   110  			chVols <- vols{vols: vs}
   111  		}(vd)
   112  	}
   113  
   114  	for i := 0; i < len(drivers); i++ {
   115  		vs := <-chVols
   116  
   117  		if vs.err != nil {
   118  			warnings = append(warnings, vs.err.Error())
   119  			logrus.Warn(vs.err)
   120  			continue
   121  		}
   122  		ls = append(ls, vs.vols...)
   123  	}
   124  	return ls, warnings, nil
   125  }
   126  
   127  // CreateWithRef creates a volume with the given name and driver and stores the ref
   128  // This is just like Create() except we store the reference while holding the lock.
   129  // This ensures there's no race between creating a volume and then storing a reference.
   130  func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts map[string]string) (volume.Volume, error) {
   131  	name = normaliseVolumeName(name)
   132  	s.locks.Lock(name)
   133  	defer s.locks.Unlock(name)
   134  
   135  	v, err := s.create(name, driverName, opts)
   136  	if err != nil {
   137  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   138  	}
   139  
   140  	s.setNamed(name, v.DriverName(), ref)
   141  	return v, nil
   142  }
   143  
   144  // Create creates a volume with the given name and driver.
   145  func (s *VolumeStore) Create(name, driverName string, opts map[string]string) (volume.Volume, error) {
   146  	name = normaliseVolumeName(name)
   147  	s.locks.Lock(name)
   148  	defer s.locks.Unlock(name)
   149  
   150  	v, err := s.create(name, driverName, opts)
   151  	if err != nil {
   152  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   153  	}
   154  	s.setNamed(name, v.DriverName(), "")
   155  	return v, nil
   156  }
   157  
   158  // create asks the given driver to create a volume with the name/opts.
   159  // If a volume with the name is already known, it will ask the stored driver for the volume.
   160  // If the passed in driver name does not match the driver name which is stored for the given volume name, an error is returned.
   161  // It is expected that callers of this function hold any neccessary locks.
   162  func (s *VolumeStore) create(name, driverName string, opts map[string]string) (volume.Volume, error) {
   163  	// Validate the name in a platform-specific manner
   164  	valid, err := volume.IsVolumeNameValid(name)
   165  	if err != nil {
   166  		return nil, err
   167  	}
   168  	if !valid {
   169  		return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"}
   170  	}
   171  
   172  	vdName, exists := s.getNamed(name)
   173  	if exists {
   174  		if vdName != driverName && driverName != "" && driverName != volume.DefaultDriverName {
   175  			return nil, errNameConflict
   176  		}
   177  		driverName = vdName
   178  	}
   179  
   180  	logrus.Debugf("Registering new volume reference: driver %s, name %s", driverName, name)
   181  	vd, err := volumedrivers.GetDriver(driverName)
   182  	if err != nil {
   183  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   184  	}
   185  
   186  	if v, err := vd.Get(name); err == nil {
   187  		return v, nil
   188  	}
   189  	return vd.Create(name, opts)
   190  }
   191  
   192  // GetWithRef gets a volume with the given name from the passed in driver and stores the ref
   193  // This is just like Get(), but we store the reference while holding the lock.
   194  // This makes sure there are no races between checking for the existance of a volume and adding a reference for it
   195  func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) {
   196  	name = normaliseVolumeName(name)
   197  	s.locks.Lock(name)
   198  	defer s.locks.Unlock(name)
   199  
   200  	vd, err := volumedrivers.GetDriver(driverName)
   201  	if err != nil {
   202  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   203  	}
   204  
   205  	v, err := vd.Get(name)
   206  	if err != nil {
   207  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   208  	}
   209  
   210  	s.setNamed(name, v.DriverName(), ref)
   211  	return v, nil
   212  }
   213  
   214  // Get looks if a volume with the given name exists and returns it if so
   215  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
   216  	name = normaliseVolumeName(name)
   217  	s.locks.Lock(name)
   218  	defer s.locks.Unlock(name)
   219  
   220  	v, err := s.getVolume(name)
   221  	if err != nil {
   222  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   223  	}
   224  	return v, nil
   225  }
   226  
   227  // get requests the volume, if the driver info is stored it just access that driver,
   228  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   229  // it is expected that callers of this function hold any neccessary locks
   230  func (s *VolumeStore) getVolume(name string) (volume.Volume, error) {
   231  	logrus.Debugf("Getting volume reference for name: %s", name)
   232  	if vdName, exists := s.names[name]; exists {
   233  		vd, err := volumedrivers.GetDriver(vdName)
   234  		if err != nil {
   235  			return nil, err
   236  		}
   237  		return vd.Get(name)
   238  	}
   239  
   240  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   241  	drivers, err := volumedrivers.GetAllDrivers()
   242  	if err != nil {
   243  		return nil, err
   244  	}
   245  
   246  	for _, d := range drivers {
   247  		v, err := d.Get(name)
   248  		if err != nil {
   249  			continue
   250  		}
   251  		return v, nil
   252  	}
   253  	return nil, errNoSuchVolume
   254  }
   255  
   256  // Remove removes the requested volume. A volume is not removed if it has any refs
   257  func (s *VolumeStore) Remove(v volume.Volume) error {
   258  	name := normaliseVolumeName(v.Name())
   259  	s.locks.Lock(name)
   260  	defer s.locks.Unlock(name)
   261  
   262  	if refs, exists := s.refs[name]; exists && len(refs) > 0 {
   263  		return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: refs}
   264  	}
   265  
   266  	vd, err := volumedrivers.GetDriver(v.DriverName())
   267  	if err != nil {
   268  		return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
   269  	}
   270  
   271  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   272  	if err := vd.Remove(v); err != nil {
   273  		return &OpErr{Err: err, Name: name, Op: "remove"}
   274  	}
   275  
   276  	s.purge(name)
   277  	return nil
   278  }
   279  
   280  // Dereference removes the specified reference to the volume
   281  func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
   282  	s.locks.Lock(v.Name())
   283  	defer s.locks.Unlock(v.Name())
   284  
   285  	s.globalLock.Lock()
   286  	refs, exists := s.refs[v.Name()]
   287  	if !exists {
   288  		return
   289  	}
   290  
   291  	for i, r := range refs {
   292  		if r == ref {
   293  			s.refs[v.Name()] = append(s.refs[v.Name()][:i], s.refs[v.Name()][i+1:]...)
   294  		}
   295  	}
   296  	s.globalLock.Unlock()
   297  }
   298  
   299  // Refs gets the current list of refs for the given volume
   300  func (s *VolumeStore) Refs(v volume.Volume) []string {
   301  	s.locks.Lock(v.Name())
   302  	defer s.locks.Unlock(v.Name())
   303  
   304  	s.globalLock.Lock()
   305  	defer s.globalLock.Unlock()
   306  	refs, exists := s.refs[v.Name()]
   307  	if !exists {
   308  		return nil
   309  	}
   310  
   311  	refsOut := make([]string, len(refs))
   312  	copy(refsOut, refs)
   313  	return refsOut
   314  }
   315  
   316  // FilterByDriver returns the available volumes filtered by driver name
   317  func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
   318  	vd, err := volumedrivers.GetDriver(name)
   319  	if err != nil {
   320  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   321  	}
   322  	ls, err := vd.List()
   323  	if err != nil {
   324  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   325  	}
   326  	return ls, nil
   327  }
   328  
   329  // FilterByUsed returns the available volumes filtered by if they are not in use
   330  func (s *VolumeStore) FilterByUsed(vols []volume.Volume) []volume.Volume {
   331  	return s.filter(vols, func(v volume.Volume) bool {
   332  		s.locks.Lock(v.Name())
   333  		defer s.locks.Unlock(v.Name())
   334  		return len(s.refs[v.Name()]) == 0
   335  	})
   336  }
   337  
   338  // filterFunc defines a function to allow filter volumes in the store
   339  type filterFunc func(vol volume.Volume) bool
   340  
   341  // filter returns the available volumes filtered by a filterFunc function
   342  func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume {
   343  	var ls []volume.Volume
   344  	for _, v := range vols {
   345  		if f(v) {
   346  			ls = append(ls, v)
   347  		}
   348  	}
   349  	return ls
   350  }