diff --git a/fs/accounting/token_bucket.go b/fs/accounting/token_bucket.go index a59268a31..bb017a25f 100644 --- a/fs/accounting/token_bucket.go +++ b/fs/accounting/token_bucket.go @@ -133,25 +133,31 @@ func init() { rc.Add(rc.Call{ Path: "core/bwlimit", Fn: func(ctx context.Context, in rc.Params) (out rc.Params, err error) { - ibwlimit, ok := in["rate"] - if !ok { - return out, errors.Errorf("parameter rate not found") + if in["rate"] != nil { + bwlimit, err := in.GetString("rate") + if err != nil { + return out, err + } + var bws fs.BwTimetable + err = bws.Set(bwlimit) + if err != nil { + return out, errors.Wrap(err, "bad bwlimit") + } + if len(bws) != 1 { + return out, errors.New("need exactly 1 bandwidth setting") + } + bw := bws[0] + SetBwLimit(bw.Bandwidth) } - bwlimit, ok := ibwlimit.(string) - if !ok { - return out, errors.Errorf("value must be string rate=%v", ibwlimit) + bytesPerSecond := int64(-1) + if tokenBucket != nil { + bytesPerSecond = int64(tokenBucket.Limit()) } - var bws fs.BwTimetable - err = bws.Set(bwlimit) - if err != nil { - return out, errors.Wrap(err, "bad bwlimit") + out = rc.Params{ + "rate": fs.SizeSuffix(bytesPerSecond).String(), + "bytesPerSecond": bytesPerSecond, } - if len(bws) != 1 { - return out, errors.New("need exactly 1 bandwidth setting") - } - bw := bws[0] - SetBwLimit(bw.Bandwidth) - return rc.Params{"rate": bw.Bandwidth.String()}, nil + return out, nil }, Title: "Set the bandwidth limit.", Help: ` @@ -159,11 +165,31 @@ This sets the bandwidth limit to that passed in. Eg - rclone rc core/bwlimit rate=1M rclone rc core/bwlimit rate=off + { + "bytesPerSecond": -1, + "rate": "off" + } + rclone rc core/bwlimit rate=1M + { + "bytesPerSecond": 1048576, + "rate": "1M" + } + + +If the rate parameter is not suppied then the bandwidth is queried + + rclone rc core/bwlimit + { + "bytesPerSecond": 1048576, + "rate": "1M" + } The format of the parameter is exactly the same as passed to --bwlimit except only one bandwidth may be specified. + +In either case "rate" is returned as a human readable string, and +"bytesPerSecond" is returned as a number. `, }) } diff --git a/fs/accounting/token_bucket_test.go b/fs/accounting/token_bucket_test.go new file mode 100644 index 000000000..d9980fdde --- /dev/null +++ b/fs/accounting/token_bucket_test.go @@ -0,0 +1,59 @@ +package accounting + +import ( + "context" + "testing" + + "github.com/ncw/rclone/fs/rc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/time/rate" +) + +func TestRcBwLimit(t *testing.T) { + call := rc.Calls.Get("core/bwlimit") + assert.NotNil(t, call) + + // Set + in := rc.Params{ + "rate": "1M", + } + out, err := call.Fn(context.Background(), in) + require.NoError(t, err) + assert.Equal(t, rc.Params{ + "bytesPerSecond": int64(1048576), + "rate": "1M", + }, out) + assert.Equal(t, rate.Limit(1048576), tokenBucket.Limit()) + + // Query + in = rc.Params{} + out, err = call.Fn(context.Background(), in) + require.NoError(t, err) + assert.Equal(t, rc.Params{ + "bytesPerSecond": int64(1048576), + "rate": "1M", + }, out) + + // Reset + in = rc.Params{ + "rate": "off", + } + out, err = call.Fn(context.Background(), in) + require.NoError(t, err) + assert.Equal(t, rc.Params{ + "bytesPerSecond": int64(-1), + "rate": "off", + }, out) + assert.Nil(t, tokenBucket) + + // Query + in = rc.Params{} + out, err = call.Fn(context.Background(), in) + require.NoError(t, err) + assert.Equal(t, rc.Params{ + "bytesPerSecond": int64(-1), + "rate": "off", + }, out) + +}