o y`-=@sddlZddlZGdddeZGdddeZGdddeZGdd d eZGd d d eZGd d d eZ GdddeZ GdddeZ dS)NcseZdZfddZZS)RequestExceededExceptioncs,||_||_d||f}tt||dS)aError when requested amount exceeds what is allowed The request that raised this error should be retried after waiting the time specified by ``retry_time``. :type requested_amt: int :param requested_amt: The originally requested byte amount :type retry_time: float :param retry_time: The length in time to wait to retry for the requested amount zs zBandwidthLimitedStream.tellcCs"|jr |jr ||jdSr$)r(r*r2r&closerr r r r?s zBandwidthLimitedStream.closecCs|Sr$r rr r r __enter__sz BandwidthLimitedStream.__enter__cOs |dSr$)r?)rargskwargsr r r __exit__s zBandwidthLimitedStream.__exit__)Nr%)r)r rrrr/rr1r2r8r:r;r>r?r@rCr r r r rds   rc@sBeZdZ  dddZddZddZdd Zd d Zd d ZdS) LeakyBucketNcCs^t||_||_|durt|_t|_||_|dur t|_||_ |dur-t |_ dSdS)a9A leaky bucket abstraction to limit bandwidth consumption :type rate: int :type rate: The maximum rate to allow. This rate is in terms of bytes per second. :type time_utils: TimeUtils :param time_utils: The time utility to use for interacting with time :type rate_tracker: BandwidthRateTracker :param rate_tracker: Tracks bandwidth consumption :type consumption_scheduler: ConsumptionScheduler :param consumption_scheduler: Schedules consumption retries when necessary N) float _max_raterr threadingLock_lock _rate_trackerBandwidthRateTracker_consumption_schedulerConsumptionScheduler)rmax_rater rate_trackerconsumption_schedulerr r r rs   zLeakyBucket.__init__cCs|j=|j}|j|r||||WdS|||r+||||n |||WdSWddS1sCwYdS)acConsume an a requested amount :type amt: int :param amt: The amount of bytes to request to consume :type request_token: RequestToken :param request_token: The token associated to the consumption request that is used to identify the request. So if a RequestExceededException is raised the token should be used in subsequent retry consume() request. :raises RequestExceededException: If the consumption amount would exceed the maximum allocated bandwidth :rtype: int :returns: The amount consumed N) rIrrrL is_scheduled,_release_requested_amt_for_scheduled_request_projected_to_exceed_max_rate!_raise_request_exceeded_exception_release_requested_amtramt request_tokentime_nowr r r r5s    "zLeakyBucket.consumecCs|j||}||jkSr$)rJget_projected_raterF)rrWrYprojected_rater r r rS s z)LeakyBucket._projected_to_exceed_max_ratecCs|j||||Sr$)rLprocess_scheduled_consumptionrUrVr r r rRs z8LeakyBucket._release_requested_amt_for_scheduled_requestcCs*|t|j}|j|||}t||d)N)rr)rErFrLschedule_consumptionr)rrWrXrYallocated_timerr r r rTsz-LeakyBucket._raise_request_exceeded_exceptioncCs|j|||Sr$)rJrecord_consumption_rate)rrWrYr r r rUsz"LeakyBucket._release_requested_amt)NNN) r rrrr5rSrRrTrUr r r r rDs  rDc@s,eZdZddZddZddZddZd S) rMcCsi|_d|_dS)z*Schedules when to consume a desired amountrN) _tokens_to_scheduled_consumption _total_waitrr r r r!s zConsumptionScheduler.__init__cCs ||jvS)zIndicates if a consumption request has been scheduled :type token: RequestToken :param token: The token associated to the consumption request that is used to identify the request. )r`)rtokenr r r rQ&s z!ConsumptionScheduler.is_scheduledcCs&|j|7_|j|d|j|<|jS)aSchedules a wait time to be able to consume an amount :type amt: int :param amt: The amount of bytes scheduled to be consumed :type token: RequestToken :param token: The token associated to the consumption request that is used to identify the request. :type time_to_consume: float :param time_to_consume: The desired time it should take for that specific request amount to be consumed in regardless of previously scheduled consumption requests :rtype: float :returns: The amount of time to wait for the specific request before actually consuming the specified amount. ) wait_durationtime_to_consume)rar`)rrWrbrdr r r r]/s  z)ConsumptionScheduler.schedule_consumptioncCs&|j|}t|j|dd|_dS)zProcesses a scheduled consumption request that has completed :type token: RequestToken :param token: The token associated to the consumption request that is used to identify the request. rdrN)r`popmaxra)rrbscheduled_retryr r r r\Is  z2ConsumptionScheduler.process_scheduled_consumptionN)r rrrrQr]r\r r r r rM s  rMc@sBeZdZdddZeddZddZdd Zd d Zd d Z dS)rK皙?cCs||_d|_d|_dS)aTracks the rate of bandwidth consumption :type a: float :param a: The constant to use in calculating the exponentional moving average of the bandwidth rate. Specifically it is used in the following calculation: current_rate = alpha * new_rate + (1 - alpha) * current_rate This value of this constant should be between 0 and 1. N)_alpha _last_time _current_rate)ralphar r r rVs  zBandwidthRateTracker.__init__cCs|jdurdS|jS)zmThe current transfer rate :rtype: float :returns: The current tracked transfer rate N)rjrkrr r r current_ratefs z!BandwidthRateTracker.current_ratecCs|jdurdS|||S)aZGet the projected rate using a provided amount and time :type amt: int :param amt: The proposed amount to consume :type time_at_consumption: float :param time_at_consumption: The proposed time to consume at :rtype: float :returns: The consumption rate if that amt and time were consumed Nrm)rj*_calculate_exponential_moving_average_raterrWtime_at_consumptionr r r rZqs z'BandwidthRateTracker.get_projected_ratecCs2|jdur ||_d|_dS||||_||_dS)aRecord the consumption rate based off amount and time point :type amt: int :param amt: The amount that got consumed :type time_at_consumption: float :param time_at_consumption: The time at which the amount was consumed Nrm)rjrkrorpr r r r_s  z,BandwidthRateTracker.record_consumption_ratecCs"||j}|dkr tdS||S)Nrinf)rjrE)rrWrq time_deltar r r _calculate_rates z$BandwidthRateTracker._calculate_ratecCs&|||}|j|d|j|jS)N)rtrirk)rrWrqnew_rater r r ros z?BandwidthRateTracker._calculate_exponential_moving_average_rateN)rh) r rrrpropertyrnrZr_rtror r r r rKUs    rK) rrG ExceptionrobjectrrrrrDrMrKr r r r s %jR5