Canviant namespaces jerarquic
[makerl.git] / src / task.erl
blob0bc4bee0e2ebf82c468ebc03d88f3f789de6f904
1 %%%-------------------------------------------------------------------
2 %%% File : task.erl
3 %%% Author : <>
4 %%% Description :
5 %%%
6 %%% Created : 25 Mar 2011 by <>
7 %%%-------------------------------------------------------------------
8 -module(makerl.task).
9 -include("makerl.hrl").
11 -import(gen_server).
13 -behaviour(gen_server).
17 %% API
18 -export([new/1,
19 build_target/1]).
21 %% gen_server callbacks
22 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
23 terminate/2, code_change/3]).
25 -define(TIMEOUT, infinity).
27 %% Status: fulfilled,
29 % The status field could be calculated each time through Hook:build, but a
30 % poorly implemented hook could hang the system, so we considered a hook fulfilled
31 % if it has run once... and thus we need a field.
32 -record(state, { status :: status_type(),
33 target :: string(),
34 result :: build_result() }).
36 %%====================================================================
37 %% API
38 %%====================================================================
40 %% @doc Create a new task and register it.
41 -spec new(string()) -> {ok, pid()}.
42 new(Target) ->
43 gen_server:start_link(?MODULE, [Target], []).
45 build_target(Target) ->
46 {ok, Pid} = makerl.task_registry:find_pid_by_target(Target),
47 gen_server:call(Pid, build_target, ?TIMEOUT).
49 %%====================================================================
50 %% gen_server callbacks
51 %%====================================================================
53 %%--------------------------------------------------------------------
54 %% Function: init(Args) -> {ok, State} |
55 %% {ok, State, Timeout} |
56 %% ignore |
57 %% {stop, Reason}
58 %% Description: Initiates the server
59 %%--------------------------------------------------------------------
60 init([Target]) ->
61 {ok, Task} = makerl.task_registry:find_by_target(Target),
62 Hook = Task#task.module,
63 InitialStatus = Hook:get_status(Target,
64 Task#task.prerequisites,
65 Task#task.options),
66 makerl.task_registry:set_pid(Target, self()),
67 {ok, #state{status=InitialStatus,
68 target = Target,
69 result= makerl.dispatcher:unit() }}.
71 %%--------------------------------------------------------------------
72 %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
73 %% {reply, Reply, State, Timeout} |
74 %% {noreply, State} |
75 %% {noreply, State, Timeout} |
76 %% {stop, Reason, Reply, State} |
77 %% {stop, Reason, State}
78 %% Description: Handling call messages
79 %%--------------------------------------------------------------------
80 handle_call(build_target, _From, State) ->
81 case State#state.status of
82 fulfilled -> {reply, State#state.result, State};
83 %% Shouldn't we issue a warning and execute nevertheless?. This should't happen if
84 %% get_status worked properly *and* nothing strange happened...
85 unfulfilled ->
86 Task = get_task_from_state(State),
87 ?DEBUG("BUILDING: ~p~n", [Task]),
88 DepResultList = makerl.dispatcher:build_dependencies(Task#task.prerequisites),
89 AggregatedResult = makerl.dispatcher:aggregate_results(DepResultList),
90 Hook = Task#task.module,
91 Result = Hook:build(Task#task.target, Task#task.prerequisites, Task#task.options),
92 CombinedResult = makerl.dispatcher:combine_result(AggregatedResult, Result),
93 {reply, CombinedResult, State#state{ status = fulfilled, result = State#state.result } }
94 end.
96 handle_cast(_Msg, State) -> {noreply, State}.
97 handle_info(_Info, State) -> {noreply, State}.
98 terminate(_Reason, _State) -> ok.
99 code_change(_OldVsn, State, _Extra) -> {ok, State}.
101 %%--------------------------------------------------------------------
102 %% Internal functions
103 %%--------------------------------------------------------------------
104 get_task_from_state(State) ->
105 {ok, Task} = makerl.task_registry:find_by_target(State#state.target),
106 Task.