From 91817d0d1abe8062cef34a519ddcc555b32cf9e0 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 29 Jun 2020 17:07:23 -0700 Subject: [PATCH] fix: implement generic Walk for gateway (#9938) Walk() functionality was missing on gateway implementations leading to missing functionality for the browser UI such as remove multiple objects, download as zip file etc. This PR brings a generic implementation across all gateway's, it is not required to repeat the same code in all gateway's --- cmd/gateway-main.go | 51 ++++++++++++++++++++++++++++++++++++++ cmd/gateway-unsupported.go | 16 ------------ 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index fe778f6c6..e0a3f6091 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -45,6 +45,57 @@ var ( } ) +// GatewayLocker implements custom NewNSLock implementation +type GatewayLocker struct { + ObjectLayer + nsMutex *nsLockMap +} + +// NewNSLock - implements gateway level locker +func (l *GatewayLocker) NewNSLock(ctx context.Context, bucket string, objects ...string) RWLocker { + return l.nsMutex.NewNSLock(ctx, nil, bucket, objects...) +} + +// Walk - implements common gateway level Walker, to walk on all objects recursively at a prefix +func (l *GatewayLocker) Walk(ctx context.Context, bucket, prefix string, results chan<- ObjectInfo) error { + walk := func(ctx context.Context, bucket, prefix string, results chan<- ObjectInfo) error { + var marker string + for { + // set maxKeys to '0' to list maximum possible objects in single call. + loi, err := l.ObjectLayer.ListObjects(ctx, bucket, prefix, marker, "", 0) + if err != nil { + return err + } + marker = loi.NextMarker + for _, obj := range loi.Objects { + select { + case results <- obj: + case <-ctx.Done(): + return nil + } + } + if !loi.IsTruncated { + break + } + } + return nil + } + + if err := l.ObjectLayer.Walk(ctx, bucket, prefix, results); err != nil { + if _, ok := err.(NotImplemented); ok { + return walk(ctx, bucket, prefix, results) + } + return err + } + + return nil +} + +// NewGatewayLayerWithLocker - initialize gateway with locker. +func NewGatewayLayerWithLocker(gwLayer ObjectLayer) ObjectLayer { + return &GatewayLocker{ObjectLayer: gwLayer, nsMutex: newNSLock(false)} +} + // RegisterGatewayCommand registers a new command for gateway. func RegisterGatewayCommand(cmd cli.Command) error { cmd.Flags = append(append(cmd.Flags, ServerFlags...), GlobalFlags...) diff --git a/cmd/gateway-unsupported.go b/cmd/gateway-unsupported.go index 9823fec26..462304f22 100644 --- a/cmd/gateway-unsupported.go +++ b/cmd/gateway-unsupported.go @@ -31,22 +31,6 @@ import ( "github.com/minio/minio/pkg/madmin" ) -// GatewayLocker implements custom NeNSLock implementation -type GatewayLocker struct { - ObjectLayer - nsMutex *nsLockMap -} - -// NewNSLock - implements gateway level locker -func (l *GatewayLocker) NewNSLock(ctx context.Context, bucket string, objects ...string) RWLocker { - return l.nsMutex.NewNSLock(ctx, nil, bucket, objects...) -} - -// NewGatewayLayerWithLocker - initialize gateway with locker. -func NewGatewayLayerWithLocker(gwLayer ObjectLayer) ObjectLayer { - return &GatewayLocker{ObjectLayer: gwLayer, nsMutex: newNSLock(false)} -} - // GatewayUnsupported list of unsupported call stubs for gateway. type GatewayUnsupported struct{}