mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix N+1 calling Path()
on volume ls
Implements a `CachedPath` function on the volume plugin adapter that we call from the volume list function instead of `Path. If a driver does not implement `CachedPath` it will just call `Path`. Also makes sure we store the path on Mount and remove the path on Unmount. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
f3dcc1c462
commit
9e6b1852a7
6 changed files with 48 additions and 11 deletions
|
@ -183,5 +183,7 @@ func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[str
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
|
daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
|
||||||
return volumeToAPIType(v), nil
|
apiV := volumeToAPIType(v)
|
||||||
|
apiV.Mountpoint = v.Path()
|
||||||
|
return apiV, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,9 @@ func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return volumeToAPIType(v), nil
|
apiV := volumeToAPIType(v)
|
||||||
|
apiV.Mountpoint = v.Path()
|
||||||
|
return apiV, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings {
|
func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings {
|
||||||
|
|
|
@ -491,7 +491,15 @@ func (daemon *Daemon) Volumes(filter string) ([]*types.Volume, []string, error)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
for _, v := range filterVolumes {
|
for _, v := range filterVolumes {
|
||||||
volumesOut = append(volumesOut, volumeToAPIType(v))
|
apiV := volumeToAPIType(v)
|
||||||
|
if vv, ok := v.(interface {
|
||||||
|
CachedPath() string
|
||||||
|
}); ok {
|
||||||
|
apiV.Mountpoint = vv.CachedPath()
|
||||||
|
} else {
|
||||||
|
apiV.Mountpoint = v.Path()
|
||||||
|
}
|
||||||
|
volumesOut = append(volumesOut, apiV)
|
||||||
}
|
}
|
||||||
return volumesOut, warnings, nil
|
return volumesOut, warnings, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,8 @@ type mounts []container.Mount
|
||||||
// volumeToAPIType converts a volume.Volume to the type used by the remote API
|
// volumeToAPIType converts a volume.Volume to the type used by the remote API
|
||||||
func volumeToAPIType(v volume.Volume) *types.Volume {
|
func volumeToAPIType(v volume.Volume) *types.Volume {
|
||||||
tv := &types.Volume{
|
tv := &types.Volume{
|
||||||
Name: v.Name(),
|
Name: v.Name(),
|
||||||
Driver: v.DriverName(),
|
Driver: v.DriverName(),
|
||||||
Mountpoint: v.Path(),
|
|
||||||
}
|
}
|
||||||
if v, ok := v.(interface {
|
if v, ok := v.(interface {
|
||||||
Labels() map[string]string
|
Labels() map[string]string
|
||||||
|
|
|
@ -441,3 +441,22 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverGetEmptyResponse(c *
|
||||||
c.Assert(err, checker.NotNil, check.Commentf(out))
|
c.Assert(err, checker.NotNil, check.Commentf(out))
|
||||||
c.Assert(out, checker.Contains, "No such volume")
|
c.Assert(out, checker.Contains, "No such volume")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure only cached paths are used in volume list to prevent N+1 calls to `VolumeDriver.Path`
|
||||||
|
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverPathCalls(c *check.C) {
|
||||||
|
c.Assert(s.d.Start(), checker.IsNil)
|
||||||
|
c.Assert(s.ec.paths, checker.Equals, 0)
|
||||||
|
|
||||||
|
out, err := s.d.Cmd("volume", "create", "--name=test", "--driver=test-external-volume-driver")
|
||||||
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||||
|
c.Assert(s.ec.paths, checker.Equals, 1)
|
||||||
|
|
||||||
|
out, err = s.d.Cmd("volume", "ls")
|
||||||
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||||
|
c.Assert(s.ec.paths, checker.Equals, 1)
|
||||||
|
|
||||||
|
out, err = s.d.Cmd("volume", "inspect", "--format='{{.Mountpoint}}'", "test")
|
||||||
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||||
|
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
||||||
|
c.Assert(s.ec.paths, checker.Equals, 1)
|
||||||
|
}
|
||||||
|
|
|
@ -88,11 +88,14 @@ func (a *volumeAdapter) DriverName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *volumeAdapter) Path() string {
|
func (a *volumeAdapter) Path() string {
|
||||||
if len(a.eMount) > 0 {
|
if len(a.eMount) == 0 {
|
||||||
return a.eMount
|
a.eMount, _ = a.proxy.Path(a.name)
|
||||||
}
|
}
|
||||||
m, _ := a.proxy.Path(a.name)
|
return a.eMount
|
||||||
return m
|
}
|
||||||
|
|
||||||
|
func (a *volumeAdapter) CachedPath() string {
|
||||||
|
return a.eMount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *volumeAdapter) Mount() (string, error) {
|
func (a *volumeAdapter) Mount() (string, error) {
|
||||||
|
@ -102,5 +105,9 @@ func (a *volumeAdapter) Mount() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *volumeAdapter) Unmount() error {
|
func (a *volumeAdapter) Unmount() error {
|
||||||
return a.proxy.Unmount(a.name)
|
err := a.proxy.Unmount(a.name)
|
||||||
|
if err == nil {
|
||||||
|
a.eMount = ""
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue