1 %%%-------------------------------------------------------------------
2 %%% File : etorrent_rate.erl
3 %%% Author : Jesper Louis Andersen <>
4 %%% Description : Library of rate calculation code.
6 %%% Created : 10 Jul 2008 by Jesper Louis Andersen <>
7 %%%-------------------------------------------------------------------
8 -module(etorrent_rate
).
11 -export([init
/0, init
/1, update
/2, now_secs
/0, eta
/2]).
13 -include("etorrent_rate.hrl").
15 -define(MAX_RATE_PERIOD
, 20).
17 %%====================================================================
19 %%====================================================================
20 %%--------------------------------------------------------------------
22 %% Args: Fudge ::= integer() - The fudge skew to start out with
23 %% Description: Return an initialized rate tuple.
24 %%--------------------------------------------------------------------
25 init() -> init(?RATE_FUDGE
).
29 #peer_rate
{ next_expected
= T
+ Fudge
,
31 rate_since
= T
- Fudge
}.
33 %%--------------------------------------------------------------------
35 %% Args: Amount ::= integer() - Number of bytes that arrived
36 %% Rate ::= double() - Current rate
37 %% Total ::= integer() - Total amount of bytes downloaded
38 %% NextExpected ::= time() - When is the next update expected
39 %% Last ::= time() - When was the last update
40 %% RateSince ::= time() - Point in time where the rate has its
42 %% Description: Update the rate by Amount.
43 %%--------------------------------------------------------------------
44 update(#peer_rate
{rate
= Rate
,
46 next_expected
= NextExpected
,
48 rate_since
= RateSince
} = RT
, Amount
) when is_integer(Amount
) ->
50 case T
< NextExpected andalso Amount
=:= 0 of
52 %% We got 0 bytes, but we did not expect them yet, so just
53 %% return the current tuple (simplification candidate)
56 %% New rate: Timeslot between Last and RateSince contributes
57 %% with the old rate. Then we add the new Amount and calc.
58 %% the rate for the interval [T, RateSince].
59 R
= (Rate
* (Last
- RateSince
) + Amount
) / (T
- RateSince
),
60 #peer_rate
{ rate
= R
, %% New Rate
61 total
= Total
+ Amount
,
62 %% We expect the next data-block at the minimum of 5 secs or
63 %% when Amount bytes has been fetched at the current rate.
65 T
+ lists:min([5, Amount
/ lists:max([R
, 0.0001])]),
67 %% RateSince is manipulated so it does not go beyond
69 rate_since
= lists:max([RateSince
, T
- ?MAX_RATE_PERIOD
])}
73 %%--------------------------------------------------------------------
75 %% Args: Left ::= integer() - Number of bytes left to download
76 %% DownloadRate ::= double() - Download rate
77 %% Description: Calculate estimated time of arrival.
78 %% Returns: {Days, {Hours, Minutes, Seconds}}
79 %%--------------------------------------------------------------------
80 eta(Left
, DownloadRate
) ->
81 calendar:seconds_to_daystime(round(Left
/ DownloadRate
)).
83 %%====================================================================
85 %%====================================================================
87 calendar:datetime_to_gregorian_seconds(
88 calendar:local_time()).