github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/volume/service/restore.go (about) 1 package service // import "github.com/demonoid81/moby/volume/service" 2 3 import ( 4 "context" 5 "sync" 6 7 "github.com/demonoid81/moby/volume" 8 "github.com/sirupsen/logrus" 9 bolt "go.etcd.io/bbolt" 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 ctx := context.Background() 25 26 chRemove := make(chan *volumeMetadata, len(ls)) 27 var wg sync.WaitGroup 28 for _, meta := range ls { 29 wg.Add(1) 30 // this is potentially a very slow operation, so do it in a goroutine 31 go func(meta volumeMetadata) { 32 defer wg.Done() 33 34 var v volume.Volume 35 var err error 36 if meta.Driver != "" { 37 v, err = lookupVolume(ctx, s.drivers, meta.Driver, meta.Name) 38 if err != nil && err != errNoSuchVolume { 39 logrus.WithError(err).WithField("driver", meta.Driver).WithField("volume", meta.Name).Warn("Error restoring volume") 40 return 41 } 42 if v == nil { 43 // doesn't exist in the driver, remove it from the db 44 chRemove <- &meta 45 return 46 } 47 } else { 48 v, err = s.getVolume(ctx, meta.Name, meta.Driver) 49 if err != nil { 50 if err == errNoSuchVolume { 51 chRemove <- &meta 52 } 53 return 54 } 55 56 meta.Driver = v.DriverName() 57 if err := s.setMeta(v.Name(), meta); err != nil { 58 logrus.WithError(err).WithField("driver", meta.Driver).WithField("volume", v.Name()).Warn("Error updating volume metadata on restore") 59 } 60 } 61 62 // increment driver refcount 63 s.drivers.CreateDriver(meta.Driver) 64 65 // cache the volume 66 s.globalLock.Lock() 67 s.options[v.Name()] = meta.Options 68 s.labels[v.Name()] = meta.Labels 69 s.names[v.Name()] = v 70 s.refs[v.Name()] = make(map[string]struct{}) 71 s.globalLock.Unlock() 72 }(meta) 73 } 74 75 wg.Wait() 76 close(chRemove) 77 s.db.Update(func(tx *bolt.Tx) error { 78 for meta := range chRemove { 79 if err := removeMeta(tx, meta.Name); err != nil { 80 logrus.WithField("volume", meta.Name).Warnf("Error removing stale entry from volume db: %v", err) 81 } 82 } 83 return nil 84 }) 85 }