mirror of
https://github.com/minio/minio.git
synced 2025-01-11 23:13:23 -05:00
Fetch fileinfo concurrently (#11700)
For non-erasure setups fetch up to 10 fileinfos concurrently. Fixes #11625
This commit is contained in:
parent
097e5eba9f
commit
3ff5f55dcb
@ -19,12 +19,12 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
humanize "github.com/dustin/go-humanize"
|
humanize "github.com/dustin/go-humanize"
|
||||||
"github.com/minio/minio/cmd/logger"
|
"github.com/minio/minio/cmd/logger"
|
||||||
|
"github.com/minio/minio/pkg/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -340,58 +340,83 @@ func listObjects(ctx context.Context, obj ObjectLayer, bucket, prefix, marker, d
|
|||||||
walkResultCh = startTreeWalk(ctx, bucket, prefix, marker, recursive, listDir, isLeaf, isLeafDir, endWalkCh)
|
walkResultCh = startTreeWalk(ctx, bucket, prefix, marker, recursive, listDir, isLeaf, isLeafDir, endWalkCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
var objInfos []ObjectInfo
|
|
||||||
var eof bool
|
var eof bool
|
||||||
var nextMarker string
|
var nextMarker string
|
||||||
|
|
||||||
// List until maxKeys requested.
|
// List until maxKeys requested.
|
||||||
for i := 0; i < maxKeys; {
|
g := errgroup.WithNErrs(maxKeys).WithConcurrency(10)
|
||||||
|
ctx, cancel := g.WithCancelOnError(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
objInfoFound := make([]*ObjectInfo, maxKeys)
|
||||||
|
var i int
|
||||||
|
for i = 0; i < maxKeys; i++ {
|
||||||
|
i := i
|
||||||
walkResult, ok := <-walkResultCh
|
walkResult, ok := <-walkResultCh
|
||||||
if !ok {
|
if !ok {
|
||||||
// Closed channel.
|
// Closed channel.
|
||||||
eof = true
|
eof = true
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var objInfo ObjectInfo
|
|
||||||
var err error
|
|
||||||
if HasSuffix(walkResult.entry, SlashSeparator) {
|
if HasSuffix(walkResult.entry, SlashSeparator) {
|
||||||
for _, getObjectInfoDir := range getObjectInfoDirs {
|
g.Go(func() error {
|
||||||
objInfo, err = getObjectInfoDir(ctx, bucket, walkResult.entry)
|
for _, getObjectInfoDir := range getObjectInfoDirs {
|
||||||
if err == nil {
|
objInfo, err := getObjectInfoDir(ctx, bucket, walkResult.entry)
|
||||||
break
|
if err == nil {
|
||||||
}
|
objInfoFound[i] = &objInfo
|
||||||
if err == errFileNotFound {
|
// Done...
|
||||||
err = nil
|
return nil
|
||||||
objInfo = ObjectInfo{
|
|
||||||
Bucket: bucket,
|
|
||||||
Name: walkResult.entry,
|
|
||||||
IsDir: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add temp, may be overridden,
|
||||||
|
if err == errFileNotFound {
|
||||||
|
objInfoFound[i] = &ObjectInfo{
|
||||||
|
Bucket: bucket,
|
||||||
|
Name: walkResult.entry,
|
||||||
|
IsDir: true,
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return toObjectErr(err, bucket, prefix)
|
||||||
}
|
}
|
||||||
}
|
return nil
|
||||||
|
}, i)
|
||||||
} else {
|
} else {
|
||||||
objInfo, err = getObjInfo(ctx, bucket, walkResult.entry)
|
g.Go(func() error {
|
||||||
|
objInfo, err := getObjInfo(ctx, bucket, walkResult.entry)
|
||||||
|
if err != nil {
|
||||||
|
// Ignore errFileNotFound as the object might have got
|
||||||
|
// deleted in the interim period of listing and getObjectInfo(),
|
||||||
|
// ignore quorum error as it might be an entry from an outdated disk.
|
||||||
|
if IsErrIgnored(err, []error{
|
||||||
|
errFileNotFound,
|
||||||
|
errErasureReadQuorum,
|
||||||
|
}...) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toObjectErr(err, bucket, prefix)
|
||||||
|
}
|
||||||
|
objInfoFound[i] = &objInfo
|
||||||
|
return nil
|
||||||
|
}, i)
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
// Ignore errFileNotFound as the object might have got
|
|
||||||
// deleted in the interim period of listing and getObjectInfo(),
|
|
||||||
// ignore quorum error as it might be an entry from an outdated disk.
|
|
||||||
if IsErrIgnored(err, []error{
|
|
||||||
errFileNotFound,
|
|
||||||
errErasureReadQuorum,
|
|
||||||
}...) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return loi, toObjectErr(err, bucket, prefix)
|
|
||||||
}
|
|
||||||
nextMarker = objInfo.Name
|
|
||||||
objInfos = append(objInfos, objInfo)
|
|
||||||
if walkResult.end {
|
if walkResult.end {
|
||||||
eof = true
|
eof = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
i++
|
}
|
||||||
|
if err := g.WaitErr(); err != nil {
|
||||||
|
return loi, err
|
||||||
|
}
|
||||||
|
// Copy found objects
|
||||||
|
objInfos := make([]ObjectInfo, 0, i+1)
|
||||||
|
for _, objInfo := range objInfoFound {
|
||||||
|
if objInfo == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
objInfos = append(objInfos, *objInfo)
|
||||||
|
nextMarker = objInfo.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save list routine for the next marker if we haven't reached EOF.
|
// Save list routine for the next marker if we haven't reached EOF.
|
||||||
|
Loading…
Reference in New Issue
Block a user