github.com/a4a881d4/docker@v1.9.0-rc2/volume/store/store.go (about) 1 package store 2 3 import ( 4 "errors" 5 "sync" 6 7 "github.com/Sirupsen/logrus" 8 "github.com/docker/docker/volume" 9 "github.com/docker/docker/volume/drivers" 10 ) 11 12 var ( 13 // ErrVolumeInUse is a typed error returned when trying to remove a volume that is currently in use by a container 14 ErrVolumeInUse = errors.New("volume is in use") 15 // ErrNoSuchVolume is a typed error returned if the requested volume doesn't exist in the volume store 16 ErrNoSuchVolume = errors.New("no such volume") 17 ) 18 19 // New initializes a VolumeStore to keep 20 // reference counting of volumes in the system. 21 func New() *VolumeStore { 22 return &VolumeStore{ 23 vols: make(map[string]*volumeCounter), 24 } 25 } 26 27 // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts 28 type VolumeStore struct { 29 vols map[string]*volumeCounter 30 mu sync.Mutex 31 } 32 33 // volumeCounter keeps track of references to a volume 34 type volumeCounter struct { 35 volume.Volume 36 count uint 37 } 38 39 // AddAll adds a list of volumes to the store 40 func (s *VolumeStore) AddAll(vols []volume.Volume) { 41 for _, v := range vols { 42 s.vols[v.Name()] = &volumeCounter{v, 0} 43 } 44 } 45 46 // Create tries to find an existing volume with the given name or create a new one from the passed in driver 47 func (s *VolumeStore) Create(name, driverName string, opts map[string]string) (volume.Volume, error) { 48 s.mu.Lock() 49 if vc, exists := s.vols[name]; exists { 50 v := vc.Volume 51 s.mu.Unlock() 52 return v, nil 53 } 54 s.mu.Unlock() 55 logrus.Debugf("Registering new volume reference: driver %s, name %s", driverName, name) 56 57 vd, err := volumedrivers.GetDriver(driverName) 58 if err != nil { 59 return nil, err 60 } 61 62 v, err := vd.Create(name, opts) 63 if err != nil { 64 return nil, err 65 } 66 67 s.mu.Lock() 68 s.vols[v.Name()] = &volumeCounter{v, 0} 69 s.mu.Unlock() 70 71 return v, nil 72 } 73 74 // Get looks if a volume with the given name exists and returns it if so 75 func (s *VolumeStore) Get(name string) (volume.Volume, error) { 76 s.mu.Lock() 77 defer s.mu.Unlock() 78 vc, exists := s.vols[name] 79 if !exists { 80 return nil, ErrNoSuchVolume 81 } 82 return vc.Volume, nil 83 } 84 85 // Remove removes the requested volume. A volume is not removed if the usage count is > 0 86 func (s *VolumeStore) Remove(v volume.Volume) error { 87 s.mu.Lock() 88 defer s.mu.Unlock() 89 name := v.Name() 90 logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name) 91 vc, exists := s.vols[name] 92 if !exists { 93 return ErrNoSuchVolume 94 } 95 96 if vc.count > 0 { 97 return ErrVolumeInUse 98 } 99 100 vd, err := volumedrivers.GetDriver(vc.DriverName()) 101 if err != nil { 102 return err 103 } 104 if err := vd.Remove(vc.Volume); err != nil { 105 return err 106 } 107 delete(s.vols, name) 108 return nil 109 } 110 111 // Increment increments the usage count of the passed in volume by 1 112 func (s *VolumeStore) Increment(v volume.Volume) { 113 s.mu.Lock() 114 defer s.mu.Unlock() 115 logrus.Debugf("Incrementing volume reference: driver %s, name %s", v.DriverName(), v.Name()) 116 117 vc, exists := s.vols[v.Name()] 118 if !exists { 119 s.vols[v.Name()] = &volumeCounter{v, 1} 120 return 121 } 122 vc.count++ 123 } 124 125 // Decrement decrements the usage count of the passed in volume by 1 126 func (s *VolumeStore) Decrement(v volume.Volume) { 127 s.mu.Lock() 128 defer s.mu.Unlock() 129 logrus.Debugf("Decrementing volume reference: driver %s, name %s", v.DriverName(), v.Name()) 130 131 vc, exists := s.vols[v.Name()] 132 if !exists { 133 return 134 } 135 if vc.count == 0 { 136 return 137 } 138 vc.count-- 139 } 140 141 // Count returns the usage count of the passed in volume 142 func (s *VolumeStore) Count(v volume.Volume) uint { 143 s.mu.Lock() 144 defer s.mu.Unlock() 145 vc, exists := s.vols[v.Name()] 146 if !exists { 147 return 0 148 } 149 return vc.count 150 } 151 152 // List returns all the available volumes 153 func (s *VolumeStore) List() []volume.Volume { 154 s.mu.Lock() 155 defer s.mu.Unlock() 156 var ls []volume.Volume 157 for _, vc := range s.vols { 158 ls = append(ls, vc.Volume) 159 } 160 return ls 161 } 162 163 // FilterByDriver returns the available volumes filtered by driver name 164 func (s *VolumeStore) FilterByDriver(name string) []volume.Volume { 165 return s.filter(byDriver(name)) 166 } 167 168 // filterFunc defines a function to allow filter volumes in the store 169 type filterFunc func(vol volume.Volume) bool 170 171 // byDriver generates a filterFunc to filter volumes by their driver name 172 func byDriver(name string) filterFunc { 173 return func(vol volume.Volume) bool { 174 return vol.DriverName() == name 175 } 176 } 177 178 // filter returns the available volumes filtered by a filterFunc function 179 func (s *VolumeStore) filter(f filterFunc) []volume.Volume { 180 s.mu.Lock() 181 defer s.mu.Unlock() 182 var ls []volume.Volume 183 for _, vc := range s.vols { 184 if f(vc.Volume) { 185 ls = append(ls, vc.Volume) 186 } 187 } 188 return ls 189 }