<commit_before>%%%-------------------------------------------------------------------
%%% File    : torrent.erl
%%% Author  : <NAME> <<EMAIL>>
%%% License : See COPYING
%%% Description : Representation of a torrent for downloading
%%%
%%% Created :  9 Jul 2007 by <NAME>
%%%   <<EMAIL>>
%%%-------------------------------------------------------------------
-module(etorrent_t_control).

-behaviour(gen_fsm).

-include("etorrent_mnesia_table.hrl").

%% API
-export([start_link/3, token/1, start/1, stop/1, load_new_torrent/3,
	torrent_checked/2, tracker_error_report/2, seed/1,
	tracker_warning_report/2]).

%% gen_fsm callbacks
-export([init/1, handle_event/3, initializing/2, started/2,
	 stopped/2, handle_sync_event/4, handle_info/3, terminate/3,
	 code_change/4]).

-record(state, {id = none,

		path = none,
		torrent = none,
		peer_id = none,
		work_dir = none,

		parent_pid = none,
		tracker_pid = none,
		file_system_pid = none,
		peer_group_pid = none,

		disk_state = none,
		available_peers = []}).

-define(CHECK_WAIT_TIME, 3000).

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link() -> ok,Pid} | ignore | {error,Error}
%% Description:Creates a gen_fsm process which calls Module:init/1 to
%% initialize. To ensure a synchronized start-up procedure, this function
%% does not return until Module:init/1 has returned.
%%--------------------------------------------------------------------
start_link(Id, Path, PeerId) ->
    gen_fsm:start_link(?MODULE, [self(), Id, Path, PeerId], []).

token(Pid) ->
    gen_fsm:send_event(Pid, token).

stop(Pid) ->
    gen_fsm:send_event(Pid, stop).

start(Pid) ->
    gen_fsm:send_event(Pid, start).

load_new_torrent(Pid, File, PeerId) ->
    gen_fsm:send_event(Pid, {load_new_torrent, File, PeerId}).

torrent_checked(Pid, DiskState) ->
    gen_fsm:send_event(Pid, {torrent_checked, DiskState}).

tracker_error_report(Pid, Report) ->
    gen_fsm:send_event(Pid, {tracker_error_report, Report}).

tracker_warning_report(Pid, Report) ->
    gen_fsm:send_event(Pid, {tracker_warning_report, Report}).

seed(Pid) ->
    gen_fsm:send_event(Pid, seed).

%%====================================================================
%% gen_fsm callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, StateName, State} |
%%                         {ok, StateName, State, Timeout} |
%%                         ignore                              |
%%                         {stop, StopReason}
%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/3,4, this function is called by the new process to
%% initialize.
%%--------------------------------------------------------------------
init([Parent, Id, Path, PeerId]) ->
    {ok, WorkDir} = application:get_env(etorrent, dir),
    etorrent_tracking_map:new(Path, Parent, Id),
    {ok, initializing, #state{work_dir = WorkDir,
			      id = Id,
			      path = Path,
			      peer_id = PeerId,
			      parent_pid = Parent}, 0}. % Force timeout instantly.

%%--------------------------------------------------------------------
%% Function:
%% state_name(Event, State) -> {next_state, NextStateName, NextState}|
%%                             {next_state, NextStateName,
%%                                NextState, Timeout} |
%%                             {stop, Reason, NewState}
%% Description:There should be one instance of this function for each possible
%% state name. Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_event/2, the instance of this function with the same name as
%% the current state name StateName is called to handle the event. It is also
%% called if a timeout occurs.
%%--------------------------------------------------------------------
% Load a torrent at Path with Torrent
initializing(timeout, S) ->
    case etorrent_tracking_map:is_ready_for_checking(S#state.id) of
	false ->
	    {next_state, initializing, S, ?CHECK_WAIT_TIME};
	true ->
	    %% TODO: Try to coalesce some of these operations together.

	    %% Read the torrent, check its contents for what we are missing
	    {ok, Torrent, FSPid, InfoHash, NumberOfPieces} =
		etorrent_fs_checker:read_and_check_torrent(
		  S#state.id,
		  S#state.parent_pid,
		  S#state.work_dir,
		  S#state.path),
	    %% Update the tracking map. This torrent has been started.
	    etorrent_tracking_map:set_state(S#state.id, started),

	    %% Add a torrent entry for this torrent.
	    {atomic, _} =
		etorrent_torrent:new(
		  S#state.id,
		  {{uploaded, 0},
		   {downloaded, 0},
		   {left, calculate_amount_left(S#state.id)}},
		  NumberOfPieces),

	    %% Add a peer pool
	    %% TODO: We can pre-add this in the supervisor I think.
	    {ok, GroupPid} = etorrent_t_sup:add_peer_pool(S#state.parent_pid),

	    %% Are we leeching or seeding this torrent?
	    TorrentState = query_torrent_state(S#state.id),
	    {atomic, _} =
		etorrent_torrent:statechange(S#state.id, TorrentState),

	    %% And a process for controlling the peers for this torrent.
	    {ok, PeerGroupPid} =
		etorrent_t_sup:add_peer_group(
		  S#state.parent_pid,
		  GroupPid,
		  S#state.peer_id,
		  InfoHash,
		  FSPid,
		  TorrentState,
		  S#state.id),<commit_msg>etorrent_torrent:new returns the number of pieces. Fix a badmatch.<commit_after>%%%-------------------------------------------------------------------
%%% File    : torrent.erl
%%% Author  : <NAME> <<EMAIL>>
%%% License : See COPYING
%%% Description : Representation of a torrent for downloading
%%%
%%% Created :  9 Jul 2007 by <NAME>
%%%   <<EMAIL>>
%%%-------------------------------------------------------------------
-module(etorrent_t_control).

-behaviour(gen_fsm).

-include("etorrent_mnesia_table.hrl").

%% API
-export([start_link/3, token/1, start/1, stop/1, load_new_torrent/3,
	torrent_checked/2, tracker_error_report/2, seed/1,
	tracker_warning_report/2]).

%% gen_fsm callbacks
-export([init/1, handle_event/3, initializing/2, started/2,
	 stopped/2, handle_sync_event/4, handle_info/3, terminate/3,
	 code_change/4]).

-record(state, {id = none,

		path = none,
		torrent = none,
		peer_id = none,
		work_dir = none,

		parent_pid = none,
		tracker_pid = none,
		file_system_pid = none,
		peer_group_pid = none,

		disk_state = none,
		available_peers = []}).

-define(CHECK_WAIT_TIME, 3000).

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link() -> ok,Pid} | ignore | {error,Error}
%% Description:Creates a gen_fsm process which calls Module:init/1 to
%% initialize. To ensure a synchronized start-up procedure, this function
%% does not return until Module:init/1 has returned.
%%--------------------------------------------------------------------
start_link(Id, Path, PeerId) ->
    gen_fsm:start_link(?MODULE, [self(), Id, Path, PeerId], []).

token(Pid) ->
    gen_fsm:send_event(Pid, token).

stop(Pid) ->
    gen_fsm:send_event(Pid, stop).

start(Pid) ->
    gen_fsm:send_event(Pid, start).

load_new_torrent(Pid, File, PeerId) ->
    gen_fsm:send_event(Pid, {load_new_torrent, File, PeerId}).

torrent_checked(Pid, DiskState) ->
    gen_fsm:send_event(Pid, {torrent_checked, DiskState}).

tracker_error_report(Pid, Report) ->
    gen_fsm:send_event(Pid, {tracker_error_report, Report}).

tracker_warning_report(Pid, Report) ->
    gen_fsm:send_event(Pid, {tracker_warning_report, Report}).

seed(Pid) ->
    gen_fsm:send_event(Pid, seed).

%%====================================================================
%% gen_fsm callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, StateName, State} |
%%                         {ok, StateName, State, Timeout} |
%%                         ignore                              |
%%                         {stop, StopReason}
%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/3,4, this function is called by the new process to
%% initialize.
%%--------------------------------------------------------------------
init([Parent, Id, Path, PeerId]) ->
    {ok, WorkDir} = application:get_env(etorrent, dir),
    etorrent_tracking_map:new(Path, Parent, Id),
    {ok, initializing, #state{work_dir = WorkDir,
			      id = Id,
			      path = Path,
			      peer_id = PeerId,
			      parent_pid = Parent}, 0}. % Force timeout instantly.

%%--------------------------------------------------------------------
%% Function:
%% state_name(Event, State) -> {next_state, NextStateName, NextState}|
%%                             {next_state, NextStateName,
%%                                NextState, Timeout} |
%%                             {stop, Reason, NewState}
%% Description:There should be one instance of this function for each possible
%% state name. Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_event/2, the instance of this function with the same name as
%% the current state name StateName is called to handle the event. It is also
%% called if a timeout occurs.
%%--------------------------------------------------------------------
% Load a torrent at Path with Torrent
initializing(timeout, S) ->
    case etorrent_tracking_map:is_ready_for_checking(S#state.id) of
	false ->
	    {next_state, initializing, S, ?CHECK_WAIT_TIME};
	true ->
	    %% TODO: Try to coalesce some of these operations together.

	    %% Read the torrent, check its contents for what we are missing
	    {ok, Torrent, FSPid, InfoHash, NumberOfPieces} =
		etorrent_fs_checker:read_and_check_torrent(
		  S#state.id,
		  S#state.parent_pid,
		  S#state.work_dir,
		  S#state.path),
	    %% Update the tracking map. This torrent has been started.
	    etorrent_tracking_map:set_state(S#state.id, started),

	    %% Add a torrent entry for this torrent.
	    etorrent_torrent:new(
	      S#state.id,
	      {{uploaded, 0},
	       {downloaded, 0},
	       {left, calculate_amount_left(S#state.id)}},
	      NumberOfPieces),

	    %% Add a peer pool
	    %% TODO: We can pre-add this in the supervisor I think.
	    {ok, GroupPid} = etorrent_t_sup:add_peer_pool(S#state.parent_pid),

	    %% Are we leeching or seeding this torrent?
	    TorrentState = query_torrent_state(S#state.id),
	    {atomic, _} =
		etorrent_torrent:statechange(S#state.id, TorrentState),

	    %% And a process for controlling the peers for this torrent.
	    {ok, PeerGroupPid} =
		etorrent_t_sup:add_peer_group(
		  S#state.parent_pid,
		  GroupPid,
		  S#state.peer_id,
		  InfoHash,
		  FSPid,
		  TorrentState,
		  S#state.id),
{'fraction_non_alphanumeric': 0.257026291931097, 'fraction_numerical': 0.006708975521305531, 'mean_word_length': 2.3744264301009483, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3095952', 'n_tokens_mistral': 3568, 'n_tokens_neox': 3265, 'n_words': 790}