Handle HAVE_ALL and HAVE_NONE. Cleanup the BITFIELD message.
[etorrent.git] / lib / etorrent-1.0 / src / etorrent_rate.erl
blob96dc31e38ed6cd5415bbe1f7c274996fd4b80952
1 %%%-------------------------------------------------------------------
2 %%% File : etorrent_rate.erl
3 %%% Author : Jesper Louis Andersen <>
4 %%% Description : Library of rate calculation code.
5 %%%
6 %%% Created : 10 Jul 2008 by Jesper Louis Andersen <>
7 %%%-------------------------------------------------------------------
8 -module(etorrent_rate).
10 %% API
11 -export([init/1, update/2, now_secs/0]).
13 -include("etorrent_rate.hrl").
15 -define(MAX_RATE_PERIOD, 20).
17 %%====================================================================
18 %% API
19 %%====================================================================
20 %%--------------------------------------------------------------------
21 %% Function: init/1
22 %% Args: Fudge ::= integer() - The fudge skew to start out with
23 %% Description: Return an initialized rate tuple.
24 %%--------------------------------------------------------------------
25 init(Fudge) ->
26 T = now_secs(),
27 #peer_rate { next_expected = T + Fudge,
28 last = T - Fudge,
29 rate_since = T - Fudge }.
31 %%--------------------------------------------------------------------
32 %% Function: update/2
33 %% Args: Amount ::= integer() - Number of bytes that arrived
34 %% Rate ::= double() - Current rate
35 %% Total ::= integer() - Total amount of bytes downloaded
36 %% NextExpected ::= time() - When is the next update expected
37 %% Last ::= time() - When was the last update
38 %% RateSince ::= time() - Point in time where the rate has its
39 %% basis
40 %% Description: Update the rate by Amount.
41 %%--------------------------------------------------------------------
42 update(#peer_rate {rate = Rate,
43 total = Total,
44 next_expected = NextExpected,
45 last = Last,
46 rate_since = RateSince} = RT, Amount) when is_integer(Amount) ->
47 T = now_secs(),
48 case T < NextExpected andalso Amount =:= 0 of
49 true ->
50 %% We got 0 bytes, but we did not expect them yet, so just
51 %% return the current tuple (simplification candidate)
52 RT;
53 false ->
54 %% New rate: Timeslot between Last and RateSince contributes
55 %% with the old rate. Then we add the new Amount and calc.
56 %% the rate for the interval [T, RateSince].
57 R = (Rate * (Last - RateSince) + Amount) / (T - RateSince),
58 #peer_rate { rate = R, %% New Rate
59 total = Total + Amount,
60 %% We expect the next data-block at the minimum of 5 secs or
61 %% when Amount bytes has been fetched at the current rate.
62 next_expected =
63 T + lists:min([5, Amount / lists:max([R, 0.0001])]),
64 last = T,
65 %% RateSince is manipulated so it does not go beyond
66 %% ?MAX_RATE_PERIOD
67 rate_since = lists:max([RateSince, T - ?MAX_RATE_PERIOD])}
68 end.
70 %%====================================================================
71 %% Internal functions
72 %%====================================================================
73 now_secs() ->
74 calendar:datetime_to_gregorian_seconds(
75 calendar:local_time()).