|
|
@ -20,12 +20,14 @@ import ( |
|
|
|
"context" |
|
|
|
"context" |
|
|
|
"encoding/json" |
|
|
|
"encoding/json" |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
|
|
|
|
"runtime" |
|
|
|
"strings" |
|
|
|
"strings" |
|
|
|
"sync" |
|
|
|
"sync" |
|
|
|
"time" |
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/minio/minio/cmd/logger" |
|
|
|
"github.com/minio/minio/cmd/logger" |
|
|
|
"github.com/minio/minio/pkg/madmin" |
|
|
|
"github.com/minio/minio/pkg/madmin" |
|
|
|
|
|
|
|
"github.com/minio/minio/pkg/sync/errgroup" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// healStatusSummary - overall short summary of a healing sequence
|
|
|
|
// healStatusSummary - overall short summary of a healing sequence
|
|
|
@ -622,17 +624,40 @@ func (h *healSequence) healBucket(bucket string) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
entries := runtime.NumCPU() * globalEndpoints.Nodes() |
|
|
|
|
|
|
|
|
|
|
|
marker := "" |
|
|
|
marker := "" |
|
|
|
isTruncated := true |
|
|
|
isTruncated := true |
|
|
|
for isTruncated { |
|
|
|
for isTruncated { |
|
|
|
|
|
|
|
if globalHTTPServer != nil { |
|
|
|
|
|
|
|
// Wait at max 1 minute for an inprogress request
|
|
|
|
|
|
|
|
// before proceeding to heal
|
|
|
|
|
|
|
|
waitCount := 60 |
|
|
|
|
|
|
|
// Any requests in progress, delay the heal.
|
|
|
|
|
|
|
|
for globalHTTPServer.GetRequestCount() > 0 && waitCount > 0 { |
|
|
|
|
|
|
|
waitCount-- |
|
|
|
|
|
|
|
time.Sleep(1 * time.Second) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Heal numCPU * nodes objects at a time.
|
|
|
|
objectInfos, err := objectAPI.ListObjectsHeal(h.ctx, bucket, |
|
|
|
objectInfos, err := objectAPI.ListObjectsHeal(h.ctx, bucket, |
|
|
|
h.objPrefix, marker, "", 1000) |
|
|
|
h.objPrefix, marker, "", entries) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return errFnHealFromAPIErr(err) |
|
|
|
return errFnHealFromAPIErr(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for _, o := range objectInfos.Objects { |
|
|
|
g := errgroup.WithNErrs(len(objectInfos.Objects)) |
|
|
|
if err := h.healObject(o.Bucket, o.Name); err != nil { |
|
|
|
for index := range objectInfos.Objects { |
|
|
|
|
|
|
|
index := index |
|
|
|
|
|
|
|
g.Go(func() error { |
|
|
|
|
|
|
|
o := objectInfos.Objects[index] |
|
|
|
|
|
|
|
return h.healObject(o.Bucket, o.Name) |
|
|
|
|
|
|
|
}, index) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, err := range g.Wait() { |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|