Commits

wjzz committed adcea5b Draft

Downloads can now be stopped and resumed thanks to ets tables.

Comments (0)

Files changed (3)

Erlang/pieces.erl

 -record(state, {meta_data, 
                 file_name,
                 piece_dict=dict:new(),
-                finished=[]
+                finished
                }).
 
 -import(helpers, [div_ceil/2]).
 -export([
          start_link/1,
          downloaded_block/2,
+         completed_pieces/0,
          status_report/0,
          stop/0
          ]).
     gen_server:cast(?SERVER, {downloaded_block, PeerInfo, Block}).
 
 %%--------------------------------------------------------------------
+%% @doc Queries the pieces server for the numbers of downloaded pieces.
+%%
+%% @spec completed_pieces() -> [integer()]
+%% @end
+%%--------------------------------------------------------------------
+
+completed_pieces() ->
+    gen_server:call(?SERVER, completed_pieces).
+
+%%--------------------------------------------------------------------
 %% @doc Returns the list of downloaded pieces and blocks
 %%
 %% @spec status_report() -> ??? (TODO)
     FileName = filename:join(["download", "temp.dat"]),
     
     InitialFinished = try_read_backup(FileName),
+    InitLen = ets:info(InitialFinished, size),
     io:format("Backup read: already have ~p pieces.~n",
-              [length(InitialFinished)]),
+              [InitLen]),
 
     {ok, #state{meta_data = MetaData,
                 file_name = FileName,
     MetaData  = State#state.meta_data,
     PiecesNum = metadata:pieces_num(MetaData),
     
-    DoneNum = length(Finished),
+    %%DoneNum = length(Finished),
+    DoneNum = ets:info(Finished, size),
     Percentage = (100 * DoneNum) / PiecesNum,
     io:format("Finished ~p/~p pieces (~.2f%).~n",
               [DoneNum, 
         false -> ok;
         true -> 
             io:format("FINISHED!!!~n"),
+            FinishedPieces = ets:tab2list(Finished),
             create_downloaded_files("download", 
                                     metadata:file_infos(MetaData),
-                                    Finished)                                    
+                                    FinishedPieces)                                    
     end,
     {noreply, State};
 
 %% @end
 %%--------------------------------------------------------------------
  
+handle_call(completed_pieces, _From, State) ->
+    Finished = State#state.finished,
+    PiecesNos = [ Key || {Key, _} <- ets:tab2list(Finished) ],
+    {reply, PiecesNos, State};
+
 handle_call(status_report, _From, State) ->
     MetaData  = State#state.meta_data,
     PieceDict = State#state.piece_dict,
                     Finished = State#state.finished,
 
                     %% Do not store stuff we already have!
-                    NewFinished = 
-                        case lists:keyfind(PartNo,1,Finished) of
-                            false -> [{PartNo, PieceBinary} | Finished];
-                            {PartNo,_} -> Finished
-                        end,
-                    NewState = State#state{piece_dict = NewDict,
-                                           finished = NewFinished
+                    true = ets:insert(Finished, {PartNo, PieceBinary}),
+                    %% NewFinished = 
+                    %%     case lists:keyfind(PartNo,1,Finished) of
+                    %%         false -> [{PartNo, PieceBinary} | Finished];
+                    %%         {PartNo,_} -> Finished
+                    %%     end,
+                    NewState = State#state{piece_dict = NewDict
+                                           %% finished = NewFinished
                                           }, 
                     %% We use timeout, because we want to write
                     %% The new piece somewhere next.
 %%--------------------------------------------------------------------
                                                                   
 save_pieces_to_disk(FileName, Finished) ->
-    file:write_file(FileName,
-                    io_lib:format("~p~n.", [Finished])),
+    ets:tab2file(Finished, FileName),
+    %% file:write_file(FileName,
+    %%                 io_lib:format("~p~n.", [Finished])),
     io:format("Backup written to ~s~n", [FileName]),
     ok.    
 
 %%--------------------------------------------------------------------
 
 try_read_backup(FileName) ->
-    case file:consult(FileName) of
-        {ok, [Finished]} ->
-            Finished;
-        {error, _} ->
-            []
+    case ets:file2tab(FileName) of
+        {ok, Tab} -> Tab;
+        {error, _} -> ets:new(finished_ets, [])
     end.
+    %% case file:consult(FileName) of
+    %%     {ok, [Finished]} ->
+    %%         Finished;
+    %%     {error, _} ->
+    %%         []
+    %% end.
 
 %%%===================================================================
 %%% Tests

Erlang/scheduler.erl

 
 %% API
 -export([
-         start_link/1,
+         start_link/2,
          stop/0,
 
          piece_downloaded/2,
 %% @end
 %%--------------------------------------------------------------------
 
-start_link(MetaData) ->
-    gen_server:start_link({local, ?SERVER}, ?MODULE, [MetaData], []).
+start_link(MetaData, CompletedPieces) ->
+    gen_server:start_link({local, ?SERVER}, ?MODULE, 
+                          [MetaData, CompletedPieces], []).
 
 %%--------------------------------------------------------------------
 %% @doc Stops the scheduler.
 %%% gen_server callbacks
 %%%===================================================================
 
-init([MetaData]) ->
+init([MetaData, CompletedPieces]) ->
     PiecesNum     = metadata:pieces_num(MetaData),
-    MissingPieces = lists:seq(0,PiecesNum-1),
+    MissingPieces = lists:seq(0,PiecesNum-1) -- CompletedPieces,
     %% MissingPieces = lists:seq(PiecesNum-3,PiecesNum-1),
     %%MissingPieces = [PiecesNum-1],
 

Erlang/torrent.erl

     logging:start_event_logger(),
     start_worker(MetaInfo),
     peer_stats:start(MetaInfo),
+
     pieces:start_link(MetaInfo),
-    scheduler:start_link(MetaInfo),
+    CompletedPieces = pieces:completed_pieces(),
+    scheduler:start_link(MetaInfo, CompletedPieces),
 
     %% TO BE ENABLED LATER
     %%