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
}).
23 -define(WATCH_WAIT_TIME
, timer:seconds(20)).
24 -define(SERVER
, ?MODULE
).
26 %%====================================================================
28 %%====================================================================
29 %%--------------------------------------------------------------------
30 %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
31 %% Description: Starts the server
32 %%--------------------------------------------------------------------
34 gen_server:start_link({local
, ?SERVER
}, ?MODULE
, [], []).
37 gen_server:call(dirwatcher
, dir_watched
).
39 %%====================================================================
40 %% gen_server callbacks
41 %%====================================================================
43 {ok
, Dir
} = application:get_env(etorrent
, dir
),
44 _Tid
= ets:new(etorrent_dirwatcher
, [named_table
, protected
]),
45 {ok
, #state
{dir
= Dir
}, 0}.
47 handle_call(dir_watched
, _Who
, S
) ->
48 {reply
, S#state
.dir
, S
, ?WATCH_WAIT_TIME
};
49 handle_call(_Request
, _From
, State
) ->
51 {reply
, Reply
, State
, ?WATCH_WAIT_TIME
}.
53 handle_cast(_Request
, S
) ->
54 {noreply
, S
, ?WATCH_WAIT_TIME
}.
56 handle_info(timeout
, S
) ->
58 {noreply
, S
, ?WATCH_WAIT_TIME
};
59 handle_info(_Info
, State
) ->
60 {noreply
, State
, ?WATCH_WAIT_TIME
}.
62 terminate(_Reason
, _State
) ->
65 code_change(_OldVsn
, State
, _Extra
) ->
68 %%--------------------------------------------------------------------
69 %%% Internal functions
70 %%--------------------------------------------------------------------
73 watch_directories(S
) ->
74 reset_marks(ets:first(etorrent_dirwatcher
)),
75 lists:foreach(fun process_file
/1,
76 filelib:wildcard("*.torrent", S#state
.dir
)),
78 ets:safe_fixtable(etorrent_dirwatcher
, true
),
79 start_stop(ets:first(etorrent_dirwatcher
)),
80 ets:safe_fixtable(etorrent_dirwatcher
, false
),
84 case ets:lookup(etorrent_dirwatcher
, F
) of
86 ets:insert(etorrent_dirwatcher
, {F
, new
});
88 ets:insert(etorrent_dirwatcher
, {F
, marked
})
91 reset_marks('$end_of_table') -> ok
;
93 ets:insert(etorrent_dirwatcher
, {Key
, unmarked
}),
94 reset_marks(ets:next(etorrent_dirwatcher
, Key
)).
96 start_stop('$end_of_table') -> ok
;
98 [{Key
, S
}] = ets:lookup(etorrent_dirwatcher
, Key
),
100 new
-> etorrent_mgr:start(Key
);
102 unmarked
-> etorrent_mgr:stop(Key
),
103 ets:delete(etorrent_dirwatcher
, Key
)
105 start_stop(ets:next(etorrent_dirwatcher
, Key
)).