github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/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  		vols:  make(map[string]*volumeCounter),
    17  		locks: &locker.Locker{},
    18  	}
    19  }
    20  
    21  func (s *VolumeStore) get(name string) (*volumeCounter, bool) {
    22  	s.globalLock.Lock()
    23  	vc, exists := s.vols[name]
    24  	s.globalLock.Unlock()
    25  	return vc, exists
    26  }
    27  
    28  func (s *VolumeStore) set(name string, vc *volumeCounter) {
    29  	s.globalLock.Lock()
    30  	s.vols[name] = vc
    31  	s.globalLock.Unlock()
    32  }
    33  
    34  func (s *VolumeStore) remove(name string) {
    35  	s.globalLock.Lock()
    36  	delete(s.vols, name)
    37  	s.globalLock.Unlock()
    38  }
    39  
    40  // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts
    41  type VolumeStore struct {
    42  	vols       map[string]*volumeCounter
    43  	locks      *locker.Locker
    44  	globalLock sync.Mutex
    45  }
    46  
    47  // volumeCounter keeps track of references to a volume
    48  type volumeCounter struct {
    49  	volume.Volume
    50  	count uint
    51  }
    52  
    53  // AddAll adds a list of volumes to the store
    54  func (s *VolumeStore) AddAll(vols []volume.Volume) {
    55  	for _, v := range vols {
    56  		s.vols[normaliseVolumeName(v.Name())] = &volumeCounter{v, 0}
    57  	}
    58  }
    59  
    60  // Create tries to find an existing volume with the given name or create a new one from the passed in driver
    61  func (s *VolumeStore) Create(name, driverName string, opts map[string]string) (volume.Volume, error) {
    62  	name = normaliseVolumeName(name)
    63  	s.locks.Lock(name)
    64  	defer s.locks.Unlock(name)
    65  
    66  	if vc, exists := s.get(name); exists {
    67  		v := vc.Volume
    68  		return v, nil
    69  	}
    70  	logrus.Debugf("Registering new volume reference: driver %s, name %s", driverName, name)
    71  
    72  	vd, err := volumedrivers.GetDriver(driverName)
    73  	if err != nil {
    74  		return nil, &OpErr{Err: err, Name: driverName, Op: "create"}
    75  	}
    76  
    77  	// Validate the name in a platform-specific manner
    78  	valid, err := volume.IsVolumeNameValid(name)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	if !valid {
    83  		return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"}
    84  	}
    85  
    86  	v, err := vd.Create(name, opts)
    87  	if err != nil {
    88  		return nil, &OpErr{Op: "create", Name: name, Err: err}
    89  	}
    90  
    91  	s.set(name, &volumeCounter{v, 0})
    92  	return v, nil
    93  }
    94  
    95  // Get looks if a volume with the given name exists and returns it if so
    96  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
    97  	name = normaliseVolumeName(name)
    98  	s.locks.Lock(name)
    99  	defer s.locks.Unlock(name)
   100  
   101  	vc, exists := s.get(name)
   102  	if !exists {
   103  		return nil, &OpErr{Err: errNoSuchVolume, Name: name, Op: "get"}
   104  	}
   105  	return vc.Volume, nil
   106  }
   107  
   108  // Remove removes the requested volume. A volume is not removed if the usage count is > 0
   109  func (s *VolumeStore) Remove(v volume.Volume) error {
   110  	name := normaliseVolumeName(v.Name())
   111  	s.locks.Lock(name)
   112  	defer s.locks.Unlock(name)
   113  
   114  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   115  	vc, exists := s.get(name)
   116  	if !exists {
   117  		return &OpErr{Err: errNoSuchVolume, Name: name, Op: "remove"}
   118  	}
   119  
   120  	if vc.count > 0 {
   121  		return &OpErr{Err: errVolumeInUse, Name: name, Op: "remove"}
   122  	}
   123  
   124  	vd, err := volumedrivers.GetDriver(vc.DriverName())
   125  	if err != nil {
   126  		return &OpErr{Err: err, Name: vc.DriverName(), Op: "remove"}
   127  	}
   128  	if err := vd.Remove(vc.Volume); err != nil {
   129  		return &OpErr{Err: err, Name: name, Op: "remove"}
   130  	}
   131  
   132  	s.remove(name)
   133  	return nil
   134  }
   135  
   136  // Increment increments the usage count of the passed in volume by 1
   137  func (s *VolumeStore) Increment(v volume.Volume) {
   138  	name := normaliseVolumeName(v.Name())
   139  	s.locks.Lock(name)
   140  	defer s.locks.Unlock(name)
   141  
   142  	logrus.Debugf("Incrementing volume reference: driver %s, name %s", v.DriverName(), v.Name())
   143  	vc, exists := s.get(name)
   144  	if !exists {
   145  		s.set(name, &volumeCounter{v, 1})
   146  		return
   147  	}
   148  	vc.count++
   149  }
   150  
   151  // Decrement decrements the usage count of the passed in volume by 1
   152  func (s *VolumeStore) Decrement(v volume.Volume) {
   153  	name := normaliseVolumeName(v.Name())
   154  	s.locks.Lock(name)
   155  	defer s.locks.Unlock(name)
   156  	logrus.Debugf("Decrementing volume reference: driver %s, name %s", v.DriverName(), v.Name())
   157  
   158  	vc, exists := s.get(name)
   159  	if !exists {
   160  		return
   161  	}
   162  	if vc.count == 0 {
   163  		return
   164  	}
   165  	vc.count--
   166  }
   167  
   168  // Count returns the usage count of the passed in volume
   169  func (s *VolumeStore) Count(v volume.Volume) uint {
   170  	name := normaliseVolumeName(v.Name())
   171  	s.locks.Lock(name)
   172  	defer s.locks.Unlock(name)
   173  
   174  	vc, exists := s.get(name)
   175  	if !exists {
   176  		return 0
   177  	}
   178  	return vc.count
   179  }
   180  
   181  // List returns all the available volumes
   182  func (s *VolumeStore) List() []volume.Volume {
   183  	s.globalLock.Lock()
   184  	defer s.globalLock.Unlock()
   185  	var ls []volume.Volume
   186  	for _, vc := range s.vols {
   187  		ls = append(ls, vc.Volume)
   188  	}
   189  	return ls
   190  }
   191  
   192  // FilterByDriver returns the available volumes filtered by driver name
   193  func (s *VolumeStore) FilterByDriver(name string) []volume.Volume {
   194  	return s.filter(byDriver(name))
   195  }
   196  
   197  // filterFunc defines a function to allow filter volumes in the store
   198  type filterFunc func(vol volume.Volume) bool
   199  
   200  // byDriver generates a filterFunc to filter volumes by their driver name
   201  func byDriver(name string) filterFunc {
   202  	return func(vol volume.Volume) bool {
   203  		return vol.DriverName() == name
   204  	}
   205  }
   206  
   207  // filter returns the available volumes filtered by a filterFunc function
   208  func (s *VolumeStore) filter(f filterFunc) []volume.Volume {
   209  	s.globalLock.Lock()
   210  	defer s.globalLock.Unlock()
   211  	var ls []volume.Volume
   212  	for _, vc := range s.vols {
   213  		if f(vc.Volume) {
   214  			ls = append(ls, vc.Volume)
   215  		}
   216  	}
   217  	return ls
   218  }