mirror of
https://github.com/kopia/kopia.git
synced 2026-01-20 12:27:53 -05:00
Remove unused-parameter exclusion for `ctx` in revive linter. --------- Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com> Co-authored-by: Matthieu MOREL <matthieu.morel35@gmail.com>
155 lines
4.5 KiB
Go
155 lines
4.5 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"path/filepath"
|
|
"sync/atomic"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/kopia/kopia/fs"
|
|
"github.com/kopia/kopia/fs/localfs"
|
|
"github.com/kopia/kopia/internal/ospath"
|
|
"github.com/kopia/kopia/internal/serverapi"
|
|
"github.com/kopia/kopia/internal/uitask"
|
|
"github.com/kopia/kopia/internal/units"
|
|
"github.com/kopia/kopia/snapshot"
|
|
"github.com/kopia/kopia/snapshot/policy"
|
|
"github.com/kopia/kopia/snapshot/upload"
|
|
)
|
|
|
|
type estimateTaskProgress struct {
|
|
ctrl uitask.Controller
|
|
}
|
|
|
|
func (p estimateTaskProgress) Processing(_ context.Context, dirname string) {
|
|
p.ctrl.ReportProgressInfo(dirname)
|
|
}
|
|
|
|
func (p estimateTaskProgress) Error(ctx context.Context, dirname string, err error, isIgnored bool) {
|
|
if isIgnored {
|
|
log(ctx).Errorf("ignored error in %v: %v", dirname, err)
|
|
} else {
|
|
log(ctx).Errorf("error in %v: %v", dirname, err)
|
|
}
|
|
}
|
|
|
|
func (p estimateTaskProgress) Stats(ctx context.Context, st *snapshot.Stats, included, excluded upload.SampleBuckets, excludedDirs []string, final bool) {
|
|
_ = excludedDirs
|
|
_ = final
|
|
|
|
p.ctrl.ReportCounters(map[string]uitask.CounterValue{
|
|
"Bytes": uitask.BytesCounter(atomic.LoadInt64(&st.TotalFileSize)),
|
|
"Excluded Bytes": uitask.BytesCounter(atomic.LoadInt64(&st.ExcludedTotalFileSize)),
|
|
"Files": uitask.SimpleCounter(int64(atomic.LoadInt32(&st.TotalFileCount))),
|
|
"Directories": uitask.SimpleCounter(int64(atomic.LoadInt32(&st.TotalDirectoryCount))),
|
|
"Excluded Files": uitask.SimpleCounter(int64(atomic.LoadInt32(&st.ExcludedFileCount))),
|
|
"Excluded Directories": uitask.SimpleCounter(int64(atomic.LoadInt32(&st.ExcludedDirCount))),
|
|
"Errors": uitask.ErrorCounter(int64(atomic.LoadInt32(&st.ErrorCount))),
|
|
"Ignored Errors": uitask.ErrorCounter(int64(atomic.LoadInt32(&st.IgnoredErrorCount))),
|
|
})
|
|
|
|
if final {
|
|
logBucketSamples(ctx, included, "Included", false)
|
|
logBucketSamples(ctx, excluded, "Excluded", true)
|
|
}
|
|
}
|
|
|
|
func logBucketSamples(ctx context.Context, buckets upload.SampleBuckets, prefix string, showExamples bool) {
|
|
hasAny := false
|
|
|
|
for i, bucket := range buckets {
|
|
if bucket.Count == 0 {
|
|
continue
|
|
}
|
|
|
|
var sizeRange string
|
|
|
|
if i == 0 {
|
|
sizeRange = fmt.Sprintf("< %-6v",
|
|
units.BytesString(bucket.MinSize))
|
|
} else {
|
|
sizeRange = fmt.Sprintf("%-6v...%6v",
|
|
units.BytesString(bucket.MinSize),
|
|
units.BytesString(buckets[i-1].MinSize))
|
|
}
|
|
|
|
log(ctx).Infof("%v files %v: %7v files, total size %v\n",
|
|
prefix,
|
|
sizeRange,
|
|
bucket.Count, units.BytesString(bucket.TotalSize))
|
|
|
|
hasAny = true
|
|
|
|
if showExamples && len(bucket.Examples) > 0 {
|
|
log(ctx).Info("Examples:")
|
|
|
|
for _, sample := range bucket.Examples {
|
|
log(ctx).Infof(" - %v\n", sample)
|
|
}
|
|
}
|
|
}
|
|
|
|
if !hasAny {
|
|
log(ctx).Infof("%v files: None", prefix)
|
|
}
|
|
}
|
|
|
|
var _ upload.EstimateProgress = estimateTaskProgress{}
|
|
|
|
func handleEstimate(ctx context.Context, rc requestContext) (interface{}, *apiError) {
|
|
var req serverapi.EstimateRequest
|
|
|
|
if err := json.Unmarshal(rc.body, &req); err != nil {
|
|
return nil, requestError(serverapi.ErrorMalformedRequest, "malformed request body")
|
|
}
|
|
|
|
resolvedRoot := filepath.Clean(ospath.ResolveUserFriendlyPath(req.Root, true))
|
|
|
|
e, err := localfs.NewEntry(resolvedRoot)
|
|
if err != nil {
|
|
return nil, internalServerError(errors.Wrap(err, "can't get local fs entry"))
|
|
}
|
|
|
|
dir, ok := e.(fs.Directory)
|
|
if !ok {
|
|
return nil, internalServerError(errors.Wrap(err, "estimation is only supported on directories"))
|
|
}
|
|
|
|
taskIDChan := make(chan string)
|
|
|
|
policyTree, err := policy.TreeForSourceWithOverride(ctx, rc.rep, snapshot.SourceInfo{
|
|
Host: rc.rep.ClientOptions().Hostname,
|
|
UserName: rc.rep.ClientOptions().Username,
|
|
Path: resolvedRoot,
|
|
}, req.PolicyOverride)
|
|
if err != nil {
|
|
return nil, internalServerError(errors.Wrap(err, "unable to get policy tree"))
|
|
}
|
|
|
|
// launch a goroutine that will continue the estimate and can be observed in the Tasks UI.
|
|
|
|
//nolint:errcheck
|
|
go rc.srv.taskManager().Run(ctx, "Estimate", resolvedRoot, func(ctx context.Context, ctrl uitask.Controller) error {
|
|
taskIDChan <- ctrl.CurrentTaskID()
|
|
|
|
estimatectx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
|
|
ctrl.OnCancel(cancel)
|
|
|
|
return upload.Estimate(estimatectx, dir, policyTree, estimateTaskProgress{ctrl}, req.MaxExamplesPerBucket)
|
|
})
|
|
|
|
taskID := <-taskIDChan
|
|
|
|
task, ok := rc.srv.taskManager().GetTask(taskID)
|
|
if !ok {
|
|
return nil, internalServerError(errors.New("task not found"))
|
|
}
|
|
|
|
return task, nil
|
|
}
|