Esempio n. 1
0
        /// <summary>
        ///     Asynchronously obtains a grant of <paramref name="requestedBytes"/> for the requesting <paramref name="username"/>.
        /// </summary>
        /// <remarks>
        ///     This operation completes when any number of bytes can be granted. The amount returned may be smaller than the
        ///     requested amount.
        /// </remarks>
        /// <param name="username">The username of the requesting user.</param>
        /// <param name="requestedBytes">The number of requested bytes.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation.</param>
        /// <returns>The operation context, including the number of bytes granted.</returns>
        public Task <int> GetBytesAsync(string username, int requestedBytes, CancellationToken cancellationToken)
        {
            var group  = Users.GetGroup(username);
            var bucket = TokenBuckets.GetValueOrDefault(group ?? string.Empty, TokenBuckets[Application.DefaultGroup]);

            return(bucket.GetAsync(requestedBytes, cancellationToken));
        }
 public static async Task <ITokenBucket> GetTokenBucketAsync(CustomerThrottle customerThrottle)
 {
     return(await TokenBuckets.BucketWithFixedIntervalRefillStrategy(
                capacity : (long)customerThrottle.MaximumRequestsPerSecond,
                refillTokens : (long)customerThrottle.MaximumRequestsPerSecond,
                period : oneSecond).ConfigureAwait(false));
 }
        public void RateLimitTests()
        {
            const int totalConsumes = 500;
            const int refillRate    = 40;

            var tokenBucket = TokenBuckets.Construct()
                              .WithCapacity(refillRate)
                              .WithYieldingSleepStrategy()
                              .WithFixedIntervalRefillStrategy(1, TimeSpan.FromMilliseconds(1000d / refillRate))
                              .Build();

            var sw = new Stopwatch();

            sw.Start();
            for (var i = 0; i < totalConsumes; i++)
            {
                if (i % 3 == 0)
                {
                    Thread.Sleep(1000 / refillRate * 2);
                }
                tokenBucket.Consume();
            }

            sw.Stop();

            Assert.That(totalConsumes / (sw.Elapsed.TotalSeconds + 1), Is.EqualTo(refillRate).Within(0.1));
        }
Esempio n. 4
0
 public void SetUp()
 {
     _refillStrategy = new MockRefillStrategy();
     _sleepStrategy  = new Mock <ISleepStrategy>();
     _bucket         = TokenBuckets.Construct()
                       .WithCapacity(Capacity)
                       .WithRefillStrategy(_refillStrategy)
                       .WithSleepStrategy(_sleepStrategy.Object)
                       .Build();
 }
Esempio n. 5
0
        /// <summary>
        ///     Returns wasted bytes for redistribution.
        /// </summary>
        /// <param name="username">The username of the user that generated the waste.</param>
        /// <param name="attemptedBytes">The number of bytes that were attempted to be transferred.</param>
        /// <param name="grantedBytes">The number of bytes granted by all governors in the system.</param>
        /// <param name="actualBytes">The actual number of bytes transferred.</param>
        public void ReturnBytes(string username, int attemptedBytes, int grantedBytes, int actualBytes)
        {
            var waste = Math.Max(0, grantedBytes - actualBytes);

            if (waste == 0)
            {
                return;
            }

            var group  = Users.GetGroup(username);
            var bucket = TokenBuckets.GetValueOrDefault(group ?? string.Empty, TokenBuckets[Application.DefaultGroup]);

            // we don't have enough information to tell whether grantedBytes was reduced by the global limiter within
            // Soulseek.NET, so we just return the bytes that we know for sure that were wasted, which is grantedBytes - actualBytes.
            // example: we grant 1000 bytes. Soulseek.NET grants only 500. 250 bytes are written. ideally we would return 750
            // bytes, but instead we return 250. this discrepancy doesn't really matter because Soulseek.NET is the constraint in
            // this scenario and the additional tokens we would return would never be used.
            bucket.Return(waste);
        }
Esempio n. 6
0
        static void Main(string[] args)
        {
            // Create a token bucket with a capacity of 1 token that refills at a fixed interval of 1 token/sec.
            ITokenBucket bucket = TokenBuckets.Construct()
                                  .WithCapacity(100)
                                  .WithFixedIntervalRefillStrategy(100, TimeSpan.FromSeconds(1))
                                  .Build();

            // ...

            while (true)
            {
                // Consume a token from the token bucket.  If a token is not available this method will block until
                // the refill strategy adds one to the bucket.
                bucket.Consume(1);

                Poll();
            }
        }
        public void Add(Host host, LimitRule rule)
        {
            ITokenBucket ulBucket = null;
            ITokenBucket dlBucket = null;

            Remove(host);
            host.SetLimitRule(rule);

            if (rule.IsUploadLimited && !rule.IsUploadBlocked)
            {
                ulBucket = TokenBuckets.Construct()
                           .WithCapacity(rule.UploadRate.Value + (rule.UploadBurst ?? NetworkUtilities.GetDefaultBurst(rule.UploadRate.Value)))
                           .WithFixedIntervalRefillStrategy(rule.UploadRate.Value, TimeSpan.FromSeconds(1))
                           .Build();
            }

            if (rule.IsDownloadLimited && !rule.IsDownloadBlocked)
            {
                dlBucket = TokenBuckets.Construct()
                           .WithCapacity(rule.DownloadRate.Value + (rule.DownloadBurst ?? NetworkUtilities.GetDefaultBurst(rule.DownloadRate.Value)))
                           .WithFixedIntervalRefillStrategy(rule.DownloadRate.Value, TimeSpan.FromSeconds(1))
                           .Build();
            }

            if (ulBucket == null && dlBucket == null && !host.LimitRule.IsUploadBlocked && !host.LimitRule.IsDownloadBlocked)
            {
                return;
            }

            var buckets = new Tuple <ITokenBucket, ITokenBucket>(ulBucket, dlBucket);

            lock (_hostBucketDictLock) lock (_ipHostDict) lock (_bandwidthUploadDictLock) lock (_bandwidthDownloadDictLock)
                        {
                            _hostBucketDict.Add(host, buckets);
                            _ipHostDict.Add(IPAddress.Parse(host.IpAddress.ToString()), host);
                            _bandwidthUploadDict.Add(host, 0);
                            _bandwidthDownloadDict.Add(host, 0);
                        }
        }
        public async Task RateLimitTests()
        {
            const int totalConsumes = 500;
            const int refillRate    = 40;

            //initial capacity 40
            //add 1 token to the bucket ~ every 25ms
            var tokenBucket = await TokenBuckets.BucketWithFixedIntervalRefillStrategy(refillRate, 1, TimeSpan.FromMilliseconds(1000d / refillRate))
                              .ConfigureAwait(false);

            var sw = new Stopwatch();

            sw.Start();

            for (var i = 0; i < totalConsumes; i++)
            {
                await tokenBucket.WaitConsumeAsync().ConfigureAwait(false);
            }

            sw.Stop();

            // tokens consumed / time = refillRate
            Assert.That(totalConsumes / (sw.Elapsed.TotalSeconds + 1), Is.EqualTo(refillRate).Within(0.2));
        }
Esempio n. 9
0
 public async Task SetUp()
 {
     _refillStrategy = new MockRefillStrategy();
     _bucket         = await TokenBuckets.BucketWithRefillStrategy(Capacity, _refillStrategy).ConfigureAwait(false);
 }