mirror of
https://github.com/minio/minio.git
synced 2026-02-10 21:00:16 -05:00
fix: Allow Walk to honor load balanced drives (#10610)
This commit is contained in:
@@ -1750,17 +1750,17 @@ func (z *erasureZones) Walk(ctx context.Context, bucket, prefix string, results
|
||||
return err
|
||||
}
|
||||
|
||||
var zoneDrivesPerSet []int
|
||||
for _, zone := range z.zones {
|
||||
zoneDrivesPerSet = append(zoneDrivesPerSet, zone.listTolerancePerSet-2)
|
||||
}
|
||||
|
||||
if opts.WalkVersions {
|
||||
var zonesEntryChs [][]FileInfoVersionsCh
|
||||
for _, zone := range z.zones {
|
||||
zonesEntryChs = append(zonesEntryChs, zone.startMergeWalksVersions(ctx, bucket, prefix, "", true, ctx.Done()))
|
||||
}
|
||||
|
||||
var zoneDrivesPerSet []int
|
||||
for _, zone := range z.zones {
|
||||
zoneDrivesPerSet = append(zoneDrivesPerSet, zone.setDriveCount)
|
||||
}
|
||||
|
||||
var zonesEntriesInfos [][]FileInfoVersions
|
||||
var zonesEntriesValid [][]bool
|
||||
for _, entryChs := range zonesEntryChs {
|
||||
@@ -1772,20 +1772,17 @@ func (z *erasureZones) Walk(ctx context.Context, bucket, prefix string, results
|
||||
defer close(results)
|
||||
|
||||
for {
|
||||
entry, quorumCount, zoneIndex, ok := lexicallySortedEntryZoneVersions(zonesEntryChs, zonesEntriesInfos, zonesEntriesValid)
|
||||
entry, quorumCount, _, ok := lexicallySortedEntryZoneVersions(zonesEntryChs, zonesEntriesInfos, zonesEntriesValid)
|
||||
if !ok {
|
||||
// We have reached EOF across all entryChs, break the loop.
|
||||
return
|
||||
}
|
||||
|
||||
if quorumCount >= zoneDrivesPerSet[zoneIndex]/2 {
|
||||
// Read quorum exists proceed
|
||||
if quorumCount > 0 {
|
||||
for _, version := range entry.Versions {
|
||||
results <- version.ToObjectInfo(bucket, version.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// skip entries which do not have quorum
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -1793,10 +1790,8 @@ func (z *erasureZones) Walk(ctx context.Context, bucket, prefix string, results
|
||||
}
|
||||
|
||||
zonesEntryChs := make([][]FileInfoCh, 0, len(z.zones))
|
||||
zoneDrivesPerSet := make([]int, 0, len(z.zones))
|
||||
for _, zone := range z.zones {
|
||||
zonesEntryChs = append(zonesEntryChs, zone.startMergeWalks(ctx, bucket, prefix, "", true, ctx.Done()))
|
||||
zoneDrivesPerSet = append(zoneDrivesPerSet, zone.setDriveCount)
|
||||
}
|
||||
|
||||
zonesEntriesInfos := make([][]FileInfo, 0, len(zonesEntryChs))
|
||||
@@ -1810,17 +1805,15 @@ func (z *erasureZones) Walk(ctx context.Context, bucket, prefix string, results
|
||||
defer close(results)
|
||||
|
||||
for {
|
||||
entry, quorumCount, zoneIndex, ok := lexicallySortedEntryZone(zonesEntryChs, zonesEntriesInfos, zonesEntriesValid)
|
||||
entry, quorumCount, _, ok := lexicallySortedEntryZone(zonesEntryChs, zonesEntriesInfos, zonesEntriesValid)
|
||||
if !ok {
|
||||
// We have reached EOF across all entryChs, break the loop.
|
||||
return
|
||||
}
|
||||
|
||||
if quorumCount >= zoneDrivesPerSet[zoneIndex]/2 {
|
||||
// Read quorum exists proceed
|
||||
if quorumCount > 0 {
|
||||
results <- entry.ToObjectInfo(bucket, entry.Name)
|
||||
}
|
||||
// skip entries which do not have quorum
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -1859,6 +1852,7 @@ func (z *erasureZones) HealObjects(ctx context.Context, bucket, prefix string, o
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
// Indicate that first attempt was a success and subsequent loop
|
||||
// knows that its not our first attempt at 'prefix'
|
||||
err = nil
|
||||
@@ -1866,6 +1860,7 @@ func (z *erasureZones) HealObjects(ctx context.Context, bucket, prefix string, o
|
||||
if zoneIndex >= len(zoneDrivesPerSet) || zoneIndex < 0 {
|
||||
return fmt.Errorf("invalid zone index returned: %d", zoneIndex)
|
||||
}
|
||||
|
||||
if quorumCount == zoneDrivesPerSet[zoneIndex] && opts.ScanMode == madmin.HealNormalScan {
|
||||
// Skip good entries.
|
||||
continue
|
||||
|
||||
20
cmd/net.go
20
cmd/net.go
@@ -189,21 +189,13 @@ func isHostIP(ipAddress string) bool {
|
||||
// Note: The check method tries to listen on given port and closes it.
|
||||
// It is possible to have a disconnected client in this tiny window of time.
|
||||
func checkPortAvailability(host, port string) (err error) {
|
||||
network := []string{"tcp", "tcp4", "tcp6"}
|
||||
for _, n := range network {
|
||||
l, err := net.Listen(n, net.JoinHostPort(host, port))
|
||||
if err == nil {
|
||||
// As we are able to listen on this network, the port is not in use.
|
||||
// Close the listener and continue check other networks.
|
||||
if err = l.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
l, err := net.Listen("tcp", net.JoinHostPort(host, port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
// As we are able to listen on this network, the port is not in use.
|
||||
// Close the listener and continue check other networks.
|
||||
return l.Close()
|
||||
}
|
||||
|
||||
// extractHostPort - extracts host/port from many address formats
|
||||
|
||||
@@ -2788,7 +2788,8 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
||||
if rec.Code == http.StatusOK {
|
||||
// Verify whether the bucket obtained object is same as the one created.
|
||||
if !bytes.Equal(testCase.expectedContent, actualContent) {
|
||||
t.Errorf("Test %d : MinIO %s: Object content differs from expected value.", i+1, instanceType)
|
||||
t.Errorf("Test %d : MinIO %s: CompleteMultipart response content differs from expected value. got %s, expecte %s", i+1, instanceType,
|
||||
string(actualContent), string(testCase.expectedContent))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -935,9 +935,16 @@ func testWebHandlerDownloadZip(obj ObjectLayer, instanceType string, t TestErrHa
|
||||
t.Fatalf("%s : %s", instanceType, err)
|
||||
}
|
||||
|
||||
obj.PutObject(context.Background(), bucket, "a/one", mustGetPutObjReader(t, strings.NewReader(fileOne), int64(len(fileOne)), "", ""), opts)
|
||||
obj.PutObject(context.Background(), bucket, "a/b/two", mustGetPutObjReader(t, strings.NewReader(fileTwo), int64(len(fileTwo)), "", ""), opts)
|
||||
obj.PutObject(context.Background(), bucket, "a/c/three", mustGetPutObjReader(t, strings.NewReader(fileThree), int64(len(fileThree)), "", ""), opts)
|
||||
for objName, value := range map[string]string{
|
||||
"a/one": fileOne,
|
||||
"a/b/two": fileTwo,
|
||||
"a/c/three": fileThree,
|
||||
} {
|
||||
_, err = obj.PutObject(context.Background(), bucket, objName, mustGetPutObjReader(t, strings.NewReader(value), int64(len(value)), "", ""), opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
test := func(token string) (int, []byte) {
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
Reference in New Issue
Block a user