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 }