mirror of
https://github.com/minio/minio.git
synced 2025-04-19 02:05:24 -04:00
Avoid showing buckets without quorum in each pool (#18125)
This commit is contained in:
parent
e101eeeda9
commit
aec023f537
@ -23,6 +23,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
xhttp "github.com/minio/minio/internal/http"
|
xhttp "github.com/minio/minio/internal/http"
|
||||||
@ -123,8 +124,10 @@ func NewS3PeerSys(endpoints EndpointServerPools) *S3PeerSys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListBuckets lists buckets across all servers and returns a possible consistent view
|
// ListBuckets lists buckets across all nodes and returns a consistent view:
|
||||||
func (sys *S3PeerSys) ListBuckets(ctx context.Context, opts BucketOptions) (result []BucketInfo, err error) {
|
// - Return an error when a pool cannot return N/2+1 valid bucket information
|
||||||
|
// - For each pool, check if the bucket exists in N/2+1 nodes before including it in the final result
|
||||||
|
func (sys *S3PeerSys) ListBuckets(ctx context.Context, opts BucketOptions) ([]BucketInfo, error) {
|
||||||
g := errgroup.WithNErrs(len(sys.peerClients))
|
g := errgroup.WithNErrs(len(sys.peerClients))
|
||||||
|
|
||||||
nodeBuckets := make([][]BucketInfo, len(sys.peerClients))
|
nodeBuckets := make([][]BucketInfo, len(sys.peerClients))
|
||||||
@ -148,24 +151,51 @@ func (sys *S3PeerSys) ListBuckets(ctx context.Context, opts BucketOptions) (resu
|
|||||||
|
|
||||||
errs = append(errs, g.Wait()...)
|
errs = append(errs, g.Wait()...)
|
||||||
|
|
||||||
quorum := len(sys.peerClients)/2 + 1
|
// The list of buckets in a map to avoid duplication
|
||||||
if err = reduceReadQuorumErrs(ctx, errs, bucketOpIgnoredErrs, quorum); err != nil {
|
resultMap := make(map[string]BucketInfo)
|
||||||
return nil, err
|
|
||||||
|
for poolIdx := 0; poolIdx < sys.poolsCount; poolIdx++ {
|
||||||
|
perPoolErrs := make([]error, 0, len(sys.peerClients))
|
||||||
|
for i, client := range sys.peerClients {
|
||||||
|
if slices.Contains(client.GetPools(), poolIdx) {
|
||||||
|
perPoolErrs = append(perPoolErrs, errs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quorum := len(perPoolErrs)/2 + 1
|
||||||
|
if poolErr := reduceWriteQuorumErrs(ctx, perPoolErrs, bucketOpIgnoredErrs, quorum); poolErr != nil {
|
||||||
|
return nil, poolErr
|
||||||
}
|
}
|
||||||
|
|
||||||
bucketsMap := make(map[string]struct{})
|
bucketsMap := make(map[string]int)
|
||||||
for idx, buckets := range nodeBuckets {
|
for idx, buckets := range nodeBuckets {
|
||||||
if errs[idx] != nil {
|
if buckets == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !slices.Contains(sys.peerClients[idx].GetPools(), poolIdx) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, bi := range buckets {
|
for _, bi := range buckets {
|
||||||
_, ok := bucketsMap[bi.Name]
|
_, ok := resultMap[bi.Name]
|
||||||
if !ok {
|
if ok {
|
||||||
bucketsMap[bi.Name] = struct{}{}
|
// Skip it, this bucket is found in another pool
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bucketsMap[bi.Name]++
|
||||||
|
if bucketsMap[bi.Name] == quorum {
|
||||||
|
resultMap[bi.Name] = bi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]BucketInfo, 0, len(resultMap))
|
||||||
|
for _, bi := range resultMap {
|
||||||
result = append(result, bi)
|
result = append(result, bi)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Name < result[j].Name
|
||||||
|
})
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/minio/minio/internal/logger"
|
"github.com/minio/minio/internal/logger"
|
||||||
"github.com/minio/mux"
|
"github.com/minio/mux"
|
||||||
@ -124,10 +123,6 @@ func listBucketsLocal(ctx context.Context, opts BucketOptions) (buckets []Bucket
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(buckets, func(i, j int) bool {
|
|
||||||
return buckets[i].Name < buckets[j].Name
|
|
||||||
})
|
|
||||||
|
|
||||||
return buckets, nil
|
return buckets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user