package cli import ( "context" "strconv" "github.com/alecthomas/kingpin/v2" "github.com/pkg/errors" "github.com/kopia/kopia/internal/units" "github.com/kopia/kopia/repo/blob/throttling" ) type commonThrottleSet struct { setDownloadBytesPerSecond string setUploadBytesPerSecond string setReadsPerSecond string setWritesPerSecond string setListsPerSecond string setConcurrentReads string setConcurrentWrites string } func (c *commonThrottleSet) setup(cmd *kingpin.CmdClause) { cmd.Flag("download-bytes-per-second", "Set the download bytes per second").StringVar(&c.setDownloadBytesPerSecond) cmd.Flag("upload-bytes-per-second", "Set the upload bytes per second").StringVar(&c.setUploadBytesPerSecond) cmd.Flag("read-requests-per-second", "Set max reads per second").StringVar(&c.setReadsPerSecond) cmd.Flag("write-requests-per-second", "Set max writes per second").StringVar(&c.setWritesPerSecond) cmd.Flag("list-requests-per-second", "Set max lists per second").StringVar(&c.setListsPerSecond) cmd.Flag("concurrent-reads", "Set max concurrent reads").StringVar(&c.setConcurrentReads) cmd.Flag("concurrent-writes", "Set max concurrent writes").StringVar(&c.setConcurrentWrites) } func (c *commonThrottleSet) apply(ctx context.Context, limits *throttling.Limits, changeCount *int) error { if err := c.setThrottleFloat64(ctx, "max download speed", true, &limits.DownloadBytesPerSecond, c.setDownloadBytesPerSecond, changeCount); err != nil { return err } if err := c.setThrottleFloat64(ctx, "max upload speed", true, &limits.UploadBytesPerSecond, c.setUploadBytesPerSecond, changeCount); err != nil { return err } if err := c.setThrottleFloat64(ctx, "reads per second", false, &limits.ReadsPerSecond, c.setReadsPerSecond, changeCount); err != nil { return err } if err := c.setThrottleFloat64(ctx, "writes per second", false, &limits.WritesPerSecond, c.setWritesPerSecond, changeCount); err != nil { return err } if err := c.setThrottleFloat64(ctx, "lists per second", false, &limits.ListsPerSecond, c.setListsPerSecond, changeCount); err != nil { return err } if err := c.setThrottleInt(ctx, "concurrent reads", &limits.ConcurrentReads, c.setConcurrentReads, changeCount); err != nil { return err } return c.setThrottleInt(ctx, "concurrent writes", &limits.ConcurrentWrites, c.setConcurrentWrites, changeCount) } func (c *commonThrottleSet) setThrottleFloat64(ctx context.Context, desc string, bps bool, val *float64, str string, changeCount *int) error { if str == "" { // not changed return nil } if str == "unlimited" || str == "-" { *changeCount++ log(ctx).Infof("Setting %v to a unlimited.", desc) *val = 0 return nil } v, err := strconv.ParseFloat(str, 64) if err != nil { return errors.Wrapf(err, "can't parse the %v %q", desc, str) } *changeCount++ if bps { log(ctx).Infof("Setting %v to %v.", desc, units.BytesPerSecondsString(v)) } else { log(ctx).Infof("Setting %v to %v.", desc, v) } *val = v return nil } func (c *commonThrottleSet) setThrottleInt(ctx context.Context, desc string, val *int, str string, changeCount *int) error { if str == "" { // not changed return nil } if str == "unlimited" || str == "-" { *changeCount++ log(ctx).Infof("Setting %v to a unlimited.", desc) *val = 0 return nil } v, err := strconv.Atoi(str) if err != nil { return errors.Wrapf(err, "can't parse the %v %q", desc, str) } *changeCount++ log(ctx).Infof("Setting %v to %v.", desc, v) *val = v return nil }