예제 #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));
        }
예제 #2
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);
        }