o ãÄd=ã@s†ddlZddlZGdd„deƒZGdd„dƒZGdd„dƒZGdd „d ƒZGd d „d ƒZGd d „d ƒZGdd„dƒZ Gdd„dƒZ dS)éNcseZdZ‡fdd„Z‡ZS)ÚRequestExceededExceptioncs(||_||_d ||¡}tƒ |¡dS)a Error 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 zÂs zBandwidthLimitedStream.tellcCs"|jr |jr | ¡|j ¡dSr%)r)r+r2r'Úcloserr r r r?Ås zBandwidthLimitedStream.closecCs|Sr%r rr r r Ú __enter__Ïsz BandwidthLimitedStream.__enter__cOs | ¡dSr%)r?)rÚargsÚkwargsr r r Ú__exit__Òs zBandwidthLimitedStream.__exit__)Nr&)r)rrrrr/rr1r2r8r:r;r>r?r@rCr r r r res ú#  rc@sDeZdZ   ddd„Zdd„Zdd„Zdd „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Ú threadingÚLockÚ_lockÚ _rate_trackerÚBandwidthRateTrackerÚ_consumption_schedulerÚConsumptionScheduler)rZmax_raterZ rate_trackerZconsumption_schedulerr r r r×s   ÿzLeakyBucket.__init__cCs”|j�=|j ¡}|j |¡r| |||¡WdƒS| ||¡r+| |||¡n | ||¡WdƒSWdƒdS1sCwYdS)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_amt©rÚamtÚ request_tokenÚtime_nowr r r r5ús  ÿý ÿ õ"ùzLeakyBucket.consumecCs|j ||¡}||jkSr%)rJÚget_projected_raterF)rrTrVZprojected_rater r r rPs z)LeakyBucket._projected_to_exceed_max_ratecCs|j |¡| ||¡Sr%)rLÚprocess_scheduled_consumptionrRrSr r r rOsÿ z8LeakyBucket._release_requested_amt_for_scheduled_requestcCs*|t|jƒ}|j |||¡}t||d�‚)N)rr)rErFrLÚschedule_consumptionr)rrTrUrVZallocated_timerr r r rQ%sÿÿz-LeakyBucket._raise_request_exceeded_exceptioncCs|j ||¡|Sr%)rJÚrecord_consumption_rate)rrTrVr r r rR.sz"LeakyBucket._release_requested_amt)NNN) rrrrr5rPrOrQrRr r r r rDÖs û# rDc@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) rMcCsi|_d|_dS)z*Schedules when to consume a desired amountrN)Ú _tokens_to_scheduled_consumptionÚ _total_waitrr r r r4s zConsumptionScheduler.__init__cCs ||jvS)zÙIndicates 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[)rÚtokenr r r rN9s z!ConsumptionScheduler.is_scheduledcCs&|j|7_|j|dœ|j|<|jS)a´Schedules 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. )Z wait_durationÚtime_to_consume)r\r[)rrTr]r^r r r rYBs  þz)ConsumptionScheduler.schedule_consumptioncCs&|j |¡}t|j|ddƒ|_dS)zàProcesses 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. r^rN)r[ÚpopÚmaxr\)rr]Zscheduled_retryr r r rX\s  ÿz2ConsumptionScheduler.process_scheduled_consumptionN)rrrrrNrYrXr r r r rM3s  rMc@sBeZdZddd„Zedd„ƒZdd„Zdd „Zd d „Zd d „Z dS)rKçš™™™™™é?cCs||_d|_d|_dS)a’Tracks 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)rÚalphar r r rjs  zBandwidthRateTracker.__init__cCs|jdurdS|jS)zmThe current transfer rate :rtype: float :returns: The current tracked transfer rate Nç)rcrdrr r r Ú current_ratezs 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 Nrf)rcÚ*_calculate_exponential_moving_average_rate©rrTÚtime_at_consumptionr r r rW…s ÿ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 Nrf)rcrdrhrir r r rZ—s ÿ z,BandwidthRateTracker.record_consumption_ratecCs"||j}|dkr tdƒS||S)NrÚinf)rcrE)rrTrjZ time_deltar r r Ú_calculate_rate©s z$BandwidthRateTracker._calculate_ratecCs&| ||¡}|j|d|j|jS)Né)rlrbrd)rrTrjZnew_rater r r rh³s z?BandwidthRateTracker._calculate_exponential_moving_average_rateN)ra) rrrrÚpropertyrgrWrZrlrhr r r r rKis    rK) rGrÚ ExceptionrrrrrrDrMrKr r r r Ús &q]6