github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/volume/store/restore.go (about) 1 package store 2 3 import ( 4 "sync" 5 6 "github.com/boltdb/bolt" 7 "github.com/docker/docker/volume" 8 "github.com/docker/docker/volume/drivers" 9 "github.com/sirupsen/logrus" 10 ) 11 12 // restore is called when a new volume store is created. 13 // It's primary purpose is to ensure that all drivers' refcounts are set based 14 // on known volumes after a restart. 15 // This only attempts to track volumes that are actually stored in the on-disk db. 16 // It does not probe the available drivers to find anything that may have been added 17 // out of band. 18 func (s *VolumeStore) restore() { 19 var ls []volumeMetadata 20 s.db.View(func(tx *bolt.Tx) error { 21 ls = listMeta(tx) 22 return nil 23 }) 24 25 chRemove := make(chan *volumeMetadata, len(ls)) 26 var wg sync.WaitGroup 27 for _, meta := range ls { 28 wg.Add(1) 29 // this is potentially a very slow operation, so do it in a goroutine 30 go func(meta volumeMetadata) { 31 defer wg.Done() 32 33 var v volume.Volume 34 var err error 35 if meta.Driver != "" { 36 v, err = lookupVolume(meta.Driver, meta.Name) 37 if err != nil && err != errNoSuchVolume { 38 logrus.WithError(err).WithField("driver", meta.Driver).WithField("volume", meta.Name).Warn("Error restoring volume") 39 return 40 } 41 if v == nil { 42 // doesn't exist in the driver, remove it from the db 43 chRemove <- &meta 44 return 45 } 46 } else { 47 v, err = s.getVolume(meta.Name) 48 if err != nil { 49 if err == errNoSuchVolume { 50 chRemove <- &meta 51 } 52 return 53 } 54 55 meta.Driver = v.DriverName() 56 if err := s.setMeta(v.Name(), meta); err != nil { 57 logrus.WithError(err).WithField("driver", meta.Driver).WithField("volume", v.Name()).Warn("Error updating volume metadata on restore") 58 } 59 } 60 61 // increment driver refcount 62 volumedrivers.CreateDriver(meta.Driver) 63 64 // cache the volume 65 s.globalLock.Lock() 66 s.options[v.Name()] = meta.Options 67 s.labels[v.Name()] = meta.Labels 68 s.names[v.Name()] = v 69 s.globalLock.Unlock() 70 }(meta) 71 } 72 73 wg.Wait() 74 close(chRemove) 75 s.db.Update(func(tx *bolt.Tx) error { 76 for meta := range chRemove { 77 if err := removeMeta(tx, meta.Name); err != nil { 78 logrus.WithField("volume", meta.Name).Warnf("Error removing stale entry from volume db: %v", err) 79 } 80 } 81 return nil 82 }) 83 }