1 %%%-------------------------------------------------------------------
2 %%% File : dirwatcher.erl
3 %%% Author : Jesper Louis Andersen <jlouis@succubus>
4 %%% License : See COPYING
5 %%% Description : Watch a directory for the presence of torrent files.
6 %%% Send commands when files are added and removed.
8 %%% Created : 24 Jan 2007 by Jesper Louis Andersen <jlouis@succubus>
9 %%%-------------------------------------------------------------------
10 -module(etorrent_dirwatcher
).
11 -author("Jesper Louis Andersen <jesper.louis.andersen@gmail.com>").
12 -behaviour(gen_server
).
16 -export([start_link
/0, dir_watched
/0]).
18 %% gen_server callbacks
19 -export([init
/1, handle_call
/3, handle_cast
/2, handle_info
/2,
20 terminate
/2, code_change
/3]).
22 -record(state
, {dir
= none
,
24 -define(WATCH_WAIT_TIME
, 5000).
25 -define(SERVER
, ?MODULE
).
27 %%====================================================================
29 %%====================================================================
30 %%--------------------------------------------------------------------
31 %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
32 %% Description: Starts the server
33 %%--------------------------------------------------------------------
35 gen_server:start_link({local
, ?SERVER
}, ?MODULE
, [], []).
38 gen_server:call(dirwatcher
, dir_watched
).
40 %%====================================================================
41 %% gen_server callbacks
42 %%====================================================================
44 {ok
, Dir
} = application:get_env(etorrent
, dir
),
45 % Provide a timeout in 100 ms to get up fast
46 {ok
, #state
{dir
= Dir
, fileset
= sets:new()}, 100}.
48 handle_call(report_on_files
, _Who
, S
) ->
49 {reply
, sets:to_list(S#state
.fileset
), S
, ?WATCH_WAIT_TIME
};
50 handle_call(dir_watched
, _Who
, S
) ->
51 {reply
, S#state
.dir
, S
, ?WATCH_WAIT_TIME
};
52 handle_call(_Request
, _From
, State
) ->
54 {reply
, Reply
, State
, ?WATCH_WAIT_TIME
}.
56 handle_cast(_Request
, S
) ->
57 {noreply
, S
, ?WATCH_WAIT_TIME
}.
59 handle_info(timeout
, S
) ->
60 N
= watch_directories(S
),
61 {noreply
, N
, ?WATCH_WAIT_TIME
};
62 handle_info(_Info
, State
) ->
63 {noreply
, State
, ?WATCH_WAIT_TIME
}.
65 terminate(_Reason
, _State
) ->
68 code_change(_OldVsn
, State
, _Extra
) ->
71 %%--------------------------------------------------------------------
72 %%% Internal functions
73 %%--------------------------------------------------------------------
76 watch_directories(S
) ->
77 {ok
, A
, R
, N
} = scan_files_in_dir(S
),
78 lists:foreach(fun(F
) ->
79 etorrent_mgr:start_torrent(F
)
82 lists:foreach(fun(F
) ->
83 etorrent_mgr:stop_torrent(F
) end,
87 scan_files_in_dir(S
) ->
88 Files
= filelib:fold_files(S#state
.dir
, ".*\.torrent", false
,
89 fun(F
, Accum
) -> [F
| Accum
] end, []),
90 FilesSet
= sets:from_list(Files
),
91 Added
= sets:subtract(FilesSet
, S#state
.fileset
),
92 Removed
= sets:subtract(S#state
.fileset
, FilesSet
),
93 NewState
= S#state
{fileset
= FilesSet
},
94 {ok
, Added
, Removed
, NewState
}.