Skip to content
This repository
Browse code

add tracking of active transfers to web interface, with stats

  • Loading branch information...
commit 2ce2f04e3c24339350ac0b3497390d69cde2ccb1 1 parent 24e28f3
Richard Jones authored January 08, 2010
32  playdar_modules/playdar-tcp/src/playdartcp_router.erl
@@ -7,13 +7,13 @@
7 7
 		 connect/2, connect/3, peers/0, bytes/0, broadcast/1, broadcast/2, broadcast/3,
8 8
          seen_qid/1, disconnect/1, sanitize_msg/1, 
9 9
          register_transfer/2, consume_transfer/1,
10  
-         stream_started/2, stream_ended/1, streams/0
  10
+         stream_started/3, stream_ended/1, streams/0
11 11
         ]).
12 12
 
13 13
 %% gen_server callbacks
14 14
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
15 15
 
16  
--record(state, {listener, conns, seenqids, piddb, namedb}).
  16
+-record(state, {listener, conns, seenqids, piddb, namedb, streamsdb}).
17 17
 
18 18
 start_link(Port) -> gen_server:start({local, ?MODULE}, ?MODULE, [Port], []).
19 19
 
@@ -39,9 +39,12 @@ seen_qid(Qid) -> gen_server:cast(?MODULE, {seen_qid, Qid}).
39 39
 register_transfer(Key, Pid) -> gen_server:cast(?MODULE, {register_transfer, Key, Pid}).
40 40
 consume_transfer(Key) -> gen_server:call(?MODULE, {consume_transfer, Key}).
41 41
 
42  
-stream_started(Pid, Sid) -> gen_server:cast(?MODULE, {stream_started, Pid, Sid}).
43  
-stream_ended(Pid) -> gen_server:cast(?MODULE, {stream_ended, Pid}).
44  
-streams() -> gen_server:call(?MODULE, {streams}).
  42
+stream_started(Pid, Sid, Props) -> 
  43
+    gen_server:cast(?MODULE, {stream_started, Pid, Sid, Props}).
  44
+stream_ended(Pid) -> 
  45
+    gen_server:cast(?MODULE, {stream_ended, Pid}).
  46
+streams() -> 
  47
+    gen_server:call(?MODULE, {streams}).
45 48
 
46 49
 %% ====================================================================
47 50
 %% Server functions
@@ -61,7 +64,8 @@ init([Port]) ->
61 64
 					seenqids=ets:new(seenqids,[]), 
62 65
 					conns=[],
63 66
                     piddb=ets:new(piddb,[]),
64  
-                    namedb=ets:new(namedb,[])
  67
+                    namedb=ets:new(namedb,[]),
  68
+                    streamsdb=ets:new(streamsdb,[])
65 69
                }}.
66 70
 
67 71
 handle_call({disconnect, Name}, _From, State) ->
@@ -96,9 +100,9 @@ handle_call(bytes, _From, State) ->
96 100
 handle_call({consume_transfer, Key}, _From, State) -> {reply, erlang:erase({transfer, Key}), State};    
97 101
     
98 102
 handle_call({streams}, _From, State) ->
99  
-    Streams = [ {Pid, Sid, Localtime, Nowtime} 
100  
-                || {{stream, Pid}, {Sid, Localtime, Nowtime}} <- erlang:get() ],
101  
-    {reply, Streams, State};
  103
+    R = [ {Pid, Sid, Props} || 
  104
+          {Pid, {Sid, Props}} <- ets:tab2list(State#state.streamsdb) ],
  105
+    {reply, R, State};
102 106
     
103 107
 handle_call({register_connection, Pid, Name, Sharing = {WeShare, TheyShare}}, _From, State) ->
104 108
     % TODO we should probably kick the old conn with this name
@@ -120,13 +124,13 @@ handle_call({register_connection, Pid, Name, Sharing = {WeShare, TheyShare}}, _F
120 124
 
121 125
 %%
122 126
 
123  
-handle_cast({stream_started, Pid, Sid}, State) ->
  127
+handle_cast({stream_started, Pid, Sid, Props}, State) ->
124 128
     link(Pid),
125  
-    erlang:put({stream, Pid}, {Sid, erlang:localtime(), erlang:now()}),
  129
+    ets:insert(State#state.streamsdb, {Pid, {Sid, Props}}), 
126 130
     {noreply, State};
127 131
 
128  
-handle_cast({stream_ended, Pid}, State) -> 
129  
-    erlang:erase({stream, Pid}),
  132
+handle_cast({stream_ended, Pid}, State) ->
  133
+    ets:delete(State#state.streamsdb, Pid),
130 134
     {noreply, State};
131 135
 
132 136
 handle_cast({register_transfer, Key, Pid}, State) -> 
@@ -201,7 +205,7 @@ handle_info(calculate_bandwidth_secs, State) ->
201 205
 
202 206
 handle_info({'EXIT', Pid, Reason}, State) ->
203 207
     ?LOG(info, "Caught exit of ~p because ~p", [Pid, Reason]),
204  
-    _Streamrm = erlang:erase({stream, Pid}),
  208
+    ets:delete(State#state.streamsdb, Pid), % might be a stream process
205 209
     case ets:lookup(State#state.piddb, Pid) of
206 210
         [{_, Name, _Bw, _Sharing}] ->
207 211
             ?LOG(info, "Removing user from registered cons: ~p", [Name]),
15  playdar_modules/playdar-tcp/src/playdartcp_stream.erl
... ...
@@ -1,4 +1,6 @@
1 1
 % manages tcp connection used for transfering files
  2
+% TODO push all state into the registry held by the router, inc the Sock
  3
+% so stats can be extracted outside this process (it's spammed by data)
2 4
 -module(playdartcp_stream).
3 5
 -behaviour(gen_server).
4 6
 -include("playdar.hrl").
@@ -170,8 +172,13 @@ handle_packet({sending, Ref, Sid}, State = #state{current=setup, mode=Mode, sock
170 172
                 _ -> nothing
171 173
             end,
172 174
             ?LOG(info, "current -> receive_stream", []),
173  
-            playdartcp_router:stream_started(Pid, Sid),
174 175
             State1 = lookup_track(Sid, State),
  176
+            playdartcp_router:stream_started(self(), Sid, 
  177
+                                             [{now, State#state.start_now},
  178
+                                              {localtime, State#state.start_localtime},
  179
+                                              {track, State1#state.track},
  180
+                                              {mode, receive_stream},
  181
+                                              {sock, Sock}]),
175 182
             {noreply, State1#state{current=receive_stream,ref=Ref, sid=Sid, pid=Pid}};
176 183
                     
177 184
         unknown ->
@@ -200,6 +207,12 @@ handle_packet({requesting, Ref, Sid}, State = #state{current=setup, mode=Mode, s
200 207
                 Sfun ->         
201 208
                     Sfun(),
202 209
                     State1 = lookup_track(Sid, State),
  210
+                    playdartcp_router:stream_started(self(), Sid, 
  211
+                                             [{now, State#state.start_now},
  212
+                                              {localtime, State#state.start_localtime},
  213
+                                              {track, State1#state.track},
  214
+                                              {mode, send_stream},
  215
+                                              {sock, Sock}]),
203 216
                     {noreply, State1#state{current=send_stream, ref=Ref, sid=Sid}}                    
204 217
             end;
205 218
 
49  playdar_modules/playdar-tcp/src/playdartcp_web.erl
@@ -23,7 +23,10 @@ http_req(Req, DocRoot) ->
23 23
 index(Path, Req, DocRoot) ->
24 24
     case Path of
25 25
         "" ->
  26
+            Streams = get_streams(),
  27
+            ?LOG(info, "~p", [Streams]),
26 28
             Vars = [{ftok, playdar_auth:gen_formtoken()},
  29
+                    {streams, Streams},
27 30
                     {peers,
28 31
                      [ begin
29 32
                            ShareWe   = case WeShare of true -> "yes"; _ -> "no" end,
@@ -44,4 +47,48 @@ index(Path, Req, DocRoot) ->
44 47
         
45 48
         _ ->
46 49
             Req:not_found()
47  
-    end.
  50
+    end.
  51
+
  52
+get_streams() ->
  53
+    S  = playdartcp_router:streams(),
  54
+%    ?LOG(info, "Streams: ~p", [S]),
  55
+    S2 = [ begin
  56
+              Sock = proplists:get_value(sock, L),
  57
+              Current =  proplists:get_value(mode, L), 
  58
+              case inet:getstat(Sock) of
  59
+                   {ok,BW} when is_list(BW) ->
  60
+                       % elapsed transfer time in secs:
  61
+                       Tdiff = timer:now_diff(erlang:now(),  proplists:get_value(now, L))/1000000,
  62
+
  63
+                       case Current of
  64
+                           receive_stream ->
  65
+                               B = proplists:get_value(recv_oct, BW),
  66
+                               A = ((B*8)/Tdiff)/1024, % kbps
  67
+                               [{transferred, B},
  68
+                                {kbps, erlang:round(A)}];
  69
+                           send_stream ->
  70
+                               B = proplists:get_value(send_oct, BW),
  71
+                               A = ((B*8)/Tdiff)/1024, % kbps
  72
+                               [{transferred, B},
  73
+                                {kbps, erlang:round(A)}]
  74
+                       end;
  75
+                {error,_} ->
  76
+                    [{transferred, -1},{kbps,-1}]
  77
+              end
  78
+              ++
  79
+              [ {mode, atom_to_list(Current)},
  80
+                {sid, Sid} ] 
  81
+              ++
  82
+              case proplists:get_value(track, L) of
  83
+                  undefined -> [{artist,""},{album,""},{track,""}];
  84
+                  {struct, Trk} -> 
  85
+                         [ {artist,proplists:get_value(<<"artist">>,Trk,"")},
  86
+                           {track, proplists:get_value(<<"track">>,Trk,"")},
  87
+                           {album, proplists:get_value(<<"album">>,Trk,"")}
  88
+                         ]
  89
+              end                      
  90
+           end  
  91
+           || {_Pid, Sid, L} <- S ],
  92
+    S2.
  93
+    
  94
+    
30  priv/www/playdartcp/index.html
... ...
@@ -1,6 +1,9 @@
1 1
 {% extends "../base.tpl" %}
2 2
 {% block content %}
3  
-<h3>Peers</h3>
  3
+<h3>Peers ({{peers|length}})</h3>
  4
+{% if not peers %}
  5
+You can connect to peers using: <pre>playdarctl connect &lt;host&gt; &lt;port&gt; &lt;true|false&gt;</pre>
  6
+{% else %}
4 7
 <table style="width:100%">
5 8
 <tr style="font-weight:bold">
6 9
 <td>Name</td>
@@ -24,4 +27,29 @@
24 27
 </tr>
25 28
 {% endfor %}
26 29
 </table>
  30
+{% endif %}
  31
+
  32
+<h3>Streams ({{streams|length}})</h3>
  33
+{% if not streams %}
  34
+<i>No active p2p transfers</i>
  35
+{% else %}
  36
+<table style="width:100%">
  37
+<tr style="font-weight:bold">
  38
+<td>Track</td>
  39
+<td>Mode</td>
  40
+<td>Bytes Transferred</td>
  41
+<td>Avg Speed (Kbps)</td>
  42
+</tr>
  43
+{% for s in streams %}
  44
+<tr style="background-color: {% cycle white,lightyellow %}">
  45
+<td>{{s.artist|force_escape}} - {{s.track|force_escape}} &nbsp; <i>{{s.album|force_escape}}</i></td>
  46
+<td>{{s.mode}}</td>
  47
+<td>{{s.transferred}}</td>
  48
+<td>{{s.kbps}}</td>
  49
+</tr>
  50
+{% endfor %}
  51
+</table>
  52
+{% endif %}
  53
+
  54
+
27 55
 {% endblock %}

0 notes on commit 2ce2f04

Please sign in to comment.
Something went wrong with that request. Please try again.