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 }