From 2cb8c634d79c329445c9f49f32f4eab5a8c7ad00 Mon Sep 17 00:00:00 2001 From: wangduan <276361270@qq.com> Date: Wed, 2 Sep 2015 23:09:08 +0800 Subject: [PATCH 1/3] supurrt otp 18 --- src/resource_discovery.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resource_discovery.erl b/src/resource_discovery.erl index bb1c6ea..ccb874e 100644 --- a/src/resource_discovery.erl +++ b/src/resource_discovery.erl @@ -88,7 +88,7 @@ start() -> start(_Type, _StartArgs) -> % Create the storage for the local parameters; i.e. LocalTypes % and TargetTypes. - random:seed(now()), + random:seed(erlang:timestamp()), rd_store:new(), rd_sup:start_link(). From 72b13659ae469a8313c090d9905aa5c30092a109 Mon Sep 17 00:00:00 2001 From: wangrui <276361270@qq.com> Date: Tue, 8 Sep 2015 10:59:18 +0800 Subject: [PATCH 2/3] format format --- rebar.config | 2 +- src/rd_core.erl | 280 ++++++++++++++--------------- src/rd_heartbeat.erl | 34 ++-- src/rd_store.erl | 228 +++++++++++------------ src/rd_sup.erl | 50 +++--- src/rd_util.erl | 105 ++++++----- src/resource_discovery.app.src | 64 +++---- src/resource_discovery.erl | 290 +++++++++++++++--------------- src/sys.config | 14 +- test/rd_store_tests.erl | 116 ++++++------ test/resource_discovery_tests.erl | 281 +++++++++++++++-------------- 11 files changed, 731 insertions(+), 733 deletions(-) diff --git a/rebar.config b/rebar.config index 5c2d31c..f5494c8 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ -{lib_dirs,["deps"]}. +{lib_dirs, ["deps"]}. {src_dirs, ["src", "test"]}. {excl_archive_filters, [".*"]}. {cover_enabled, true}. diff --git a/src/rd_core.erl b/src/rd_core.erl index b8ea3f8..881e92d 100644 --- a/src/rd_core.erl +++ b/src/rd_core.erl @@ -11,48 +11,48 @@ %% API -export([ - start_link/0, - sync_resources/2, - trade_resources/0, - filter_resource_tuples_by_types/2, - make_callbacks/1 - ]). + start_link/0, + sync_resources/2, + trade_resources/0, + filter_resource_tuples_by_types/2, + make_callbacks/1 +]). % Fetch -export([ - round_robin_get/1, - all_of_type_get/1, - get_resource_types/0, - get_num_resource_types/0, - get_num_resource/1, - get_local_resource_tuples/0, - get_target_resource_types/0, - get_deleted_resource_tuples/0 - ]). + round_robin_get/1, + all_of_type_get/1, + get_resource_types/0, + get_num_resource_types/0, + get_num_resource/1, + get_local_resource_tuples/0, + get_target_resource_types/0, + get_deleted_resource_tuples/0 +]). % Store -export([ - store_local_resource_tuples/1, - store_callback_modules/1, - store_target_resource_types/1, - store_resource_tuples/1 - ]). + store_local_resource_tuples/1, + store_callback_modules/1, + store_target_resource_types/1, + store_resource_tuples/1 +]). % Delete -export([ - delete_local_resource_tuple/1, - delete_target_resource_type/1, - delete_callback_module/1, - delete_resource_tuple/1 - ]). + delete_local_resource_tuple/1, + delete_target_resource_type/1, + delete_callback_module/1, + delete_resource_tuple/1 +]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + terminate/2, code_change/3]). -include("../include/resource_discovery.hrl"). --define(SERVER, ?MODULE). +-define(SERVER, ?MODULE). -record(state, {}). @@ -68,7 +68,7 @@ %% @end %%-------------------------------------------------------------------- start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %%-------------------------------------------------------------------- %% @doc call each subscribed callback function for each new @@ -77,13 +77,13 @@ start_link() -> %%-------------------------------------------------------------------- -spec make_callbacks([resource_tuple()]) -> ok. make_callbacks(NewResources) -> - lists:foreach( - fun(Module) -> - lists:foreach(fun(Resource) -> - spawn(fun() -> Module:resource_up(Resource) end) end, - NewResources) - end, - rd_store:get_callback_modules()). + lists:foreach( + fun(Module) -> + lists:foreach(fun(Resource) -> + spawn(fun() -> Module:resource_up(Resource) end) end, + NewResources) + end, + rd_store:get_callback_modules()). %%-------------------------------------------------------------------- %% @doc return a list of resources that have a resource_type() found in the target @@ -92,14 +92,14 @@ make_callbacks(NewResources) -> %%-------------------------------------------------------------------- -spec filter_resource_tuples_by_types([resource_type()], [resource_tuple()]) -> [resource_tuple()]. filter_resource_tuples_by_types(TargetTypes, Resources) -> - Fun = - fun({Type, _Instance} = Resource, Acc) -> - case lists:member(Type, TargetTypes) of - true -> [Resource|Acc]; - false -> Acc - end - end, - lists:foldl(Fun, [], Resources). + Fun = + fun({Type, _Instance} = Resource, Acc) -> + case lists:member(Type, TargetTypes) of + true -> [Resource | Acc]; + false -> Acc + end + end, + lists:foldl(Fun, [], Resources). %%----------------------------------------------------------------------- @@ -107,8 +107,8 @@ filter_resource_tuples_by_types(TargetTypes, Resources) -> %% @end %%----------------------------------------------------------------------- -spec store_callback_modules([atom()]) -> no_return(). -store_callback_modules([H|_] = Modules) when is_atom(H) -> - gen_server:call(?SERVER, {store_callback_modules, Modules}). +store_callback_modules([H | _] = Modules) when is_atom(H) -> + gen_server:call(?SERVER, {store_callback_modules, Modules}). %%----------------------------------------------------------------------- %% @doc Store the target types for the local system. Store an "I Want" @@ -116,21 +116,21 @@ store_callback_modules([H|_] = Modules) when is_atom(H) -> %% @end %%----------------------------------------------------------------------- -spec store_target_resource_types([atom()]) -> no_return(). -store_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> - gen_server:call(?SERVER, {store_target_resource_types, TargetTypes}). +store_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> + gen_server:call(?SERVER, {store_target_resource_types, TargetTypes}). %%----------------------------------------------------------------------- %% @doc Store the "I haves" or local_resources for resource discovery. %% @end %%----------------------------------------------------------------------- -spec store_local_resource_tuples([resource_tuple()]) -> ok. -store_local_resource_tuples([{_,_}|_] = LocalResourceTuples) -> - gen_server:call(?SERVER, {store_local_resource_tuples, LocalResourceTuples}). +store_local_resource_tuples([{_, _} | _] = LocalResourceTuples) -> + gen_server:call(?SERVER, {store_local_resource_tuples, LocalResourceTuples}). -spec store_resource_tuples([resource_tuple()]) -> ok. store_resource_tuples(Resource) -> - gen_server:call(?SERVER, {store_resource_tuples, Resource}). + gen_server:call(?SERVER, {store_resource_tuples, Resource}). %%----------------------------------------------------------------------- %% @doc Remove a callback module. @@ -138,7 +138,7 @@ store_resource_tuples(Resource) -> %%----------------------------------------------------------------------- -spec delete_callback_module(atom()) -> true. delete_callback_module(CallBackModule) -> - gen_server:call(?SERVER, {delete_callback_module, CallBackModule}). + gen_server:call(?SERVER, {delete_callback_module, CallBackModule}). %%----------------------------------------------------------------------- %% @doc Remove a target type. @@ -146,7 +146,7 @@ delete_callback_module(CallBackModule) -> %%----------------------------------------------------------------------- -spec delete_target_resource_type(atom()) -> true. delete_target_resource_type(TargetType) -> - gen_server:call(?SERVER, {delete_target_resource_type, TargetType}). + gen_server:call(?SERVER, {delete_target_resource_type, TargetType}). %%----------------------------------------------------------------------- %% @doc Remove a local resource. @@ -154,15 +154,15 @@ delete_target_resource_type(TargetType) -> %%----------------------------------------------------------------------- -spec delete_local_resource_tuple(resource_tuple()) -> ok | {error, local_resource_not_found, resource_tuple()}. delete_local_resource_tuple(LocalResourceTuple) -> - gen_server:call(?SERVER, {delete_local_resource_tuple, LocalResourceTuple}). + gen_server:call(?SERVER, {delete_local_resource_tuple, LocalResourceTuple}). %%----------------------------------------------------------------------- %% @doc Remove a resource. %% @end %%----------------------------------------------------------------------- -spec delete_resource_tuple(resource_tuple()) -> ok. -delete_resource_tuple({_,_} = ResourceTuple) -> - gen_server:call(?SERVER, {delete_resource_tuple, ResourceTuple}). +delete_resource_tuple({_, _} = ResourceTuple) -> + gen_server:call(?SERVER, {delete_resource_tuple, ResourceTuple}). %%-------------------------------------------------------------------- %% @doc inform an rd_core server of local resources and target types. @@ -172,7 +172,7 @@ delete_resource_tuple({_,_} = ResourceTuple) -> %%-------------------------------------------------------------------- -spec trade_resources() -> ok. trade_resources() -> - gen_server:cast(?SERVER, trade_resources). + gen_server:cast(?SERVER, trade_resources). %%----------------------------------------------------------------------- %% @doc @@ -181,8 +181,8 @@ trade_resources() -> %%----------------------------------------------------------------------- -spec round_robin_get(resource_type()) -> {ok, resource()} | {error, not_found}. round_robin_get(Type) -> - gen_server:call(?SERVER, {round_robin_get, Type}). - + gen_server:call(?SERVER, {round_robin_get, Type}). + %%-------------------------------------------------------------------- %% @doc %% Gets all cached resources of a given type @@ -190,7 +190,7 @@ round_robin_get(Type) -> %%-------------------------------------------------------------------- -spec all_of_type_get(resource_type()) -> [resource()]. all_of_type_get(Type) -> - gen_server:call(?SERVER, {all_of_type_get, Type}). + gen_server:call(?SERVER, {all_of_type_get, Type}). %%----------------------------------------------------------------------- %% @doc Gets resource of a particular type outputs and places it in last position. @@ -198,11 +198,11 @@ all_of_type_get(Type) -> %%----------------------------------------------------------------------- %%-spec sync_resources(node(), {LocalResourceTuples, TargetTypes, DeletedTuples}) -> ok. sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}) -> - error_logger:info_msg("synch resources for node: ~p", [Node]), - {ok, FilteredRemotes} = gen_server:call({?SERVER, Node}, {sync_resources, {LocalResourceTuples, TargetTypes, DeletedTuples}}), - rd_store:store_resource_tuples(FilteredRemotes), - make_callbacks(FilteredRemotes), - ok. + error_logger:info_msg("synch resources for node: ~p", [Node]), + {ok, FilteredRemotes} = gen_server:call({?SERVER, Node}, {sync_resources, {LocalResourceTuples, TargetTypes, DeletedTuples}}), + rd_store:store_resource_tuples(FilteredRemotes), + make_callbacks(FilteredRemotes), + ok. %%-------------------------------------------------------------------- %% @doc @@ -211,7 +211,7 @@ sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}) -> %%-------------------------------------------------------------------- -spec get_resource_types() -> [resource_type()]. get_resource_types() -> - gen_server:call(?SERVER, get_resource_types). + gen_server:call(?SERVER, get_resource_types). %%------------------------------------------------------------------------------ %% @doc Gets the number of resource types locally cached. @@ -219,7 +219,7 @@ get_resource_types() -> %%------------------------------------------------------------------------------ -spec get_num_resource_types() -> integer(). get_num_resource_types() -> - gen_server:call(?SERVER, get_num_resource_types). + gen_server:call(?SERVER, get_num_resource_types). %%-------------------------------------------------------------------- %% @doc @@ -228,15 +228,15 @@ get_num_resource_types() -> %%-------------------------------------------------------------------- -spec get_num_resource(resource_type()) -> integer(). get_num_resource(Type) -> - gen_server:call(?SERVER, {get_num_resource, Type}). + gen_server:call(?SERVER, {get_num_resource, Type}). -spec get_local_resource_tuples() -> [resource_tuple()]. get_local_resource_tuples() -> - gen_server:call(?SERVER, get_local_resource_tuples). + gen_server:call(?SERVER, get_local_resource_tuples). -spec get_target_resource_types() -> [atom()]. get_target_resource_types() -> - gen_server:call(?SERVER, get_target_resource_types). + gen_server:call(?SERVER, get_target_resource_types). %%-------------------------------------------------------------------- %% @doc @@ -245,7 +245,7 @@ get_target_resource_types() -> %%-------------------------------------------------------------------- -spec get_deleted_resource_tuples() -> [resource_tuple()]. get_deleted_resource_tuples() -> - gen_server:call(?SERVER, get_deleted_resource_tuples). + gen_server:call(?SERVER, get_deleted_resource_tuples). %%%=================================================================== @@ -253,101 +253,101 @@ get_deleted_resource_tuples() -> %%%=================================================================== init([]) -> - {ok, #state{}}. + {ok, #state{}}. handle_call({sync_resources, {Remotes, RemoteTargetTypes, RemoteDeletedTuples}}, _From, State) -> - error_logger:info_msg("sync_resources, got remotes: ~p deleted: ~p", [Remotes, RemoteDeletedTuples]), - LocalResourceTuples = rd_store:get_local_resource_tuples(), - TargetTypes = rd_store:get_target_resource_types(), - FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), - FilteredLocals = filter_resource_tuples_by_types(RemoteTargetTypes, LocalResourceTuples), - error_logger:info_msg("sync_resources, storing filted remotes: ~p", [FilteredRemotes]), - rd_store:store_resource_tuples(FilteredRemotes), - [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], - make_callbacks(FilteredRemotes), - {reply, {ok, FilteredLocals}, State}; + error_logger:info_msg("sync_resources, got remotes: ~p deleted: ~p", [Remotes, RemoteDeletedTuples]), + LocalResourceTuples = rd_store:get_local_resource_tuples(), + TargetTypes = rd_store:get_target_resource_types(), + FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), + FilteredLocals = filter_resource_tuples_by_types(RemoteTargetTypes, LocalResourceTuples), + error_logger:info_msg("sync_resources, storing filted remotes: ~p", [FilteredRemotes]), + rd_store:store_resource_tuples(FilteredRemotes), + [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], + make_callbacks(FilteredRemotes), + {reply, {ok, FilteredLocals}, State}; handle_call({round_robin_get, Type}, _From, State) -> - Reply = rd_store:round_robin_get(Type), - {reply, Reply, State}; + Reply = rd_store:round_robin_get(Type), + {reply, Reply, State}; handle_call({all_of_type_get, Type}, _From, State) -> - Reply = rd_store:get_resources(Type), - {reply, Reply, State}; + Reply = rd_store:get_resources(Type), + {reply, Reply, State}; handle_call({store_callback_modules, Modules}, _From, State) -> - rd_store:store_callback_modules(Modules), - {reply, ok, State}; + rd_store:store_callback_modules(Modules), + {reply, ok, State}; handle_call({store_target_resource_types, TargetTypes}, _From, State) -> - Reply = rd_store:store_target_resource_types(TargetTypes), - {reply, Reply, State}; + Reply = rd_store:store_target_resource_types(TargetTypes), + {reply, Reply, State}; handle_call({store_local_resource_tuples, LocalResourceTuples}, _From, State) -> - Reply = rd_store:store_local_resource_tuples(LocalResourceTuples), - {reply, Reply, State}; + Reply = rd_store:store_local_resource_tuples(LocalResourceTuples), + {reply, Reply, State}; handle_call({store_resource_tuples, Resource}, _From, State) -> - Reply = rd_store:store_resource_tuples(Resource), - {reply, Reply, State}; + Reply = rd_store:store_resource_tuples(Resource), + {reply, Reply, State}; handle_call({delete_callback_module, Module}, _From, State) -> - rd_store:delete_callback_module(Module), - {reply, ok, State}; + rd_store:delete_callback_module(Module), + {reply, ok, State}; handle_call({delete_target_resource_type, TargetType}, _From, State) -> - Reply = rd_store:delete_target_resource_type(TargetType), - {reply, Reply, State}; + Reply = rd_store:delete_target_resource_type(TargetType), + {reply, Reply, State}; handle_call({delete_local_resource_tuple, LocalResourceTuple}, _From, State) -> - Reply = rd_store:delete_local_resource_tuple(LocalResourceTuple), - {reply, Reply, State}; + Reply = rd_store:delete_local_resource_tuple(LocalResourceTuple), + {reply, Reply, State}; handle_call({delete_resource_tuple, ResourceTuple}, _From, State) -> - Reply = rd_store:delete_resource_tuple(ResourceTuple), - {reply, Reply, State}; + Reply = rd_store:delete_resource_tuple(ResourceTuple), + {reply, Reply, State}; handle_call(get_resource_types, _From, State) -> - Reply = rd_store:get_resource_types(), - {reply, Reply, State}; + Reply = rd_store:get_resource_types(), + {reply, Reply, State}; handle_call(get_local_resource_tuples, _From, State) -> - Reply = rd_store:get_local_resource_tuples(), - {reply, Reply, State}; + Reply = rd_store:get_local_resource_tuples(), + {reply, Reply, State}; handle_call(get_target_resource_types, _From, State) -> - Reply = rd_store:get_target_resource_types(), - {reply, Reply, State}; + Reply = rd_store:get_target_resource_types(), + {reply, Reply, State}; handle_call(get_deleted_resource_tuples, _From, State) -> - Reply = rd_store:get_deleted_resource_tuples(), - {reply, Reply, State}; + Reply = rd_store:get_deleted_resource_tuples(), + {reply, Reply, State}; handle_call(get_num_resource_types, _From, State) -> - Reply = rd_store:get_num_resource_types(), - {reply, Reply, State}; + Reply = rd_store:get_num_resource_types(), + {reply, Reply, State}; handle_call({get_num_resource, Type}, _From, State) -> - Reply = rd_store:get_num_resource(Type), - {reply, Reply, State}. + Reply = rd_store:get_num_resource(Type), + {reply, Reply, State}. handle_cast(trade_resources, State) -> - ResourceTuples = rd_store:get_local_resource_tuples(), - DeletedTuples = rd_store:get_deleted_resource_tuples(), - lists:foreach( - fun(Node) -> - gen_server:cast({?SERVER, Node}, - {trade_resources, {node(), {ResourceTuples, DeletedTuples}}}) - end, - nodes(known)), - rd_store:delete_deleted_resource_tuple(), - {noreply, State}; + ResourceTuples = rd_store:get_local_resource_tuples(), + DeletedTuples = rd_store:get_deleted_resource_tuples(), + lists:foreach( + fun(Node) -> + gen_server:cast({?SERVER, Node}, + {trade_resources, {node(), {ResourceTuples, DeletedTuples}}}) + end, + nodes(known)), + rd_store:delete_deleted_resource_tuple(), + {noreply, State}; handle_cast({trade_resources, {ReplyTo, {Remotes, RemoteDeletedTuples}}}, State) -> - error_logger:info_msg("trade_resources, got remotes ~p: deleted: ~p", [Remotes, RemoteDeletedTuples]), - Locals = rd_store:get_local_resource_tuples(), - LocalsDeleted = rd_store:get_deleted_resource_tuples(), - TargetTypes = rd_store:get_target_resource_types(), - FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), - error_logger:info_msg("got remotes and filtered ~p", [FilteredRemotes]), - rd_store:store_resource_tuples(FilteredRemotes), - error_logger:info_msg("trade_resources, deleting ~p", [RemoteDeletedTuples]), - [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], - make_callbacks(FilteredRemotes), - reply(ReplyTo, {Locals, LocalsDeleted}), - {noreply, State}. + error_logger:info_msg("trade_resources, got remotes ~p: deleted: ~p", [Remotes, RemoteDeletedTuples]), + Locals = rd_store:get_local_resource_tuples(), + LocalsDeleted = rd_store:get_deleted_resource_tuples(), + TargetTypes = rd_store:get_target_resource_types(), + FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), + error_logger:info_msg("got remotes and filtered ~p", [FilteredRemotes]), + rd_store:store_resource_tuples(FilteredRemotes), + error_logger:info_msg("trade_resources, deleting ~p", [RemoteDeletedTuples]), + [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], + make_callbacks(FilteredRemotes), + reply(ReplyTo, {Locals, LocalsDeleted}), + {noreply, State}. handle_info(_Info, State) -> - {noreply, State}. + {noreply, State}. terminate(_Reason, _State) -> - ok. + ok. code_change(_OldVsn, State, _Extra) -> - {ok, State}. + {ok, State}. %%%=================================================================== %%% Internal functions @@ -356,5 +356,5 @@ code_change(_OldVsn, State, _Extra) -> reply(noreply, {_LocalResources, _LocalsDeleted}) -> ok; reply(_ReplyTo, {[], []}) -> ok; -reply(ReplyTo, {LocalResources,LocalsDeleted}) -> - gen_server:cast({?SERVER, ReplyTo}, {trade_resources, {noreply, {LocalResources, LocalsDeleted}}}). +reply(ReplyTo, {LocalResources, LocalsDeleted}) -> + gen_server:cast({?SERVER, ReplyTo}, {trade_resources, {noreply, {LocalResources, LocalsDeleted}}}). diff --git a/src/rd_heartbeat.erl b/src/rd_heartbeat.erl index 77c9445..95abc97 100644 --- a/src/rd_heartbeat.erl +++ b/src/rd_heartbeat.erl @@ -9,7 +9,7 @@ -behaviour(gen_server). %% External exports --export([ start_link/1, start_link/0]). +-export([start_link/1, start_link/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -32,13 +32,13 @@ %%-------------------------------------------------------------------- -spec start_link(non_neg_integer()) -> {ok, pid()}. start_link(Frequency) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [Frequency], []). + gen_server:start_link({local, ?SERVER}, ?MODULE, [Frequency], []). %% @equiv start_link(0) start_link() -> - %% The default value is 0 which indicates no heartbeating. - {ok,Frequency} = rd_util:get_env(heartbeat_frequency, 60000), - start_link(Frequency). + %% The default value is 0 which indicates no heartbeating. + {ok, Frequency} = rd_util:get_env(heartbeat_frequency, 60000), + start_link(Frequency). %%==================================================================== %% Server functions @@ -53,8 +53,8 @@ start_link() -> %% {stop, Reason} %%-------------------------------------------------------------------- init([Frequency]) -> - ok = resource_discovery:contact_nodes(), - {ok, #state{frequency = Frequency}, Frequency}. + ok = resource_discovery:contact_nodes(), + {ok, #state{frequency = Frequency}, Frequency}. %%-------------------------------------------------------------------- %% Function: handle_call/3 @@ -67,7 +67,7 @@ init([Frequency]) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_call(_Request, _From, State) -> - {reply, ok, State}. + {reply, ok, State}. %%-------------------------------------------------------------------- %% Function: handle_cast/2 @@ -77,7 +77,7 @@ handle_call(_Request, _From, State) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_cast(_Msg, State) -> - {noreply, State}. + {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info/2 @@ -87,12 +87,12 @@ handle_cast(_Msg, State) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_info(timeout, State = #state{frequency = 0}) -> - {stop, normal, State}; + {stop, normal, State}; handle_info(timeout, State = #state{frequency = Frequency}) -> - resource_discovery:contact_nodes(), - resource_discovery:trade_resources(), - %% Wait for approximately the frequency with a random factor. - {noreply, State, random:uniform(Frequency div 2) + (Frequency div 2) + Frequency div 3}. + resource_discovery:contact_nodes(), + resource_discovery:trade_resources(), + %% Wait for approximately the frequency with a random factor. + {noreply, State, random:uniform(Frequency div 2) + (Frequency div 2) + Frequency div 3}. %%-------------------------------------------------------------------- %% Function: terminate/2 @@ -100,8 +100,8 @@ handle_info(timeout, State = #state{frequency = Frequency}) -> %% Returns: any (ignored by gen_server) %%-------------------------------------------------------------------- terminate(Reason, _State) -> - error_logger:info_msg("stoppping resource discovery hearbeat ~p", [Reason]), - ok. + error_logger:info_msg("stoppping resource discovery hearbeat ~p", [Reason]), + ok. %%-------------------------------------------------------------------- %% Func: code_change/3 @@ -109,5 +109,5 @@ terminate(Reason, _State) -> %% Returns: {ok, NewState} %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> - {ok, State}. + {ok, State}. diff --git a/src/rd_store.erl b/src/rd_store.erl index 763ebc2..a34246f 100644 --- a/src/rd_store.erl +++ b/src/rd_store.erl @@ -17,40 +17,40 @@ % Create -export([ - new/0, - delete/0 - ]). + new/0, + delete/0 +]). % Lookup -export([ - round_robin_get/1, - get_resources/1, - get_callback_modules/0, - get_local_resource_tuples/0, - get_deleted_resource_tuples/0, - get_target_resource_types/0, - get_num_resource_types/0, - get_num_resource/1, - get_resource_types/0 - ]). + round_robin_get/1, + get_resources/1, + get_callback_modules/0, + get_local_resource_tuples/0, + get_deleted_resource_tuples/0, + get_target_resource_types/0, + get_num_resource_types/0, + get_num_resource/1, + get_resource_types/0 +]). % Delete -export([ - delete_local_resource_tuple/1, - delete_target_resource_type/1, - delete_callback_module/1, - delete_resource_tuple/1, - delete_deleted_resource_tuple/0 - ]). + delete_local_resource_tuple/1, + delete_target_resource_type/1, + delete_callback_module/1, + delete_resource_tuple/1, + delete_deleted_resource_tuple/0 +]). % Store -export([ - store_local_resource_tuples/1, - store_callback_modules/1, - store_target_resource_types/1, - store_resource_tuples/1, - store_resource_tuple/1 - ]). + store_local_resource_tuples/1, + store_callback_modules/1, + store_target_resource_types/1, + store_resource_tuples/1, + store_resource_tuple/1 +]). %%-------------------------------------------------------------------- %% Macros @@ -75,10 +75,10 @@ %%----------------------------------------------------------------------- -spec new() -> ok. new() -> - ets:new(?RS, [named_table, public]), - ets:new(?LKVStore, [named_table, public]), - ok. - + ets:new(?RS, [named_table, public]), + ets:new(?LKVStore, [named_table, public]), + ok. + %%-------------------------------------------------------------------- %% @doc %% Deletes storage @@ -86,29 +86,29 @@ new() -> %%-------------------------------------------------------------------- -spec delete() -> ok. delete() -> - ets:delete(?RS), - ets:delete(?LKVStore), - ok. + ets:delete(?RS), + ets:delete(?LKVStore), + ok. %%----------------------------------------------------------------------- %% @doc Store the callback modules for the local system. %% @end %%----------------------------------------------------------------------- -spec store_callback_modules([atom()]) -> ok. -store_callback_modules([H|_] = Modules) when is_atom(H) -> - ets:insert(?LKVStore, {callback_modules, lists:usort(get_callback_modules() ++ Modules)}), - ok. - +store_callback_modules([H | _] = Modules) when is_atom(H) -> + ets:insert(?LKVStore, {callback_modules, lists:usort(get_callback_modules() ++ Modules)}), + ok. + %%----------------------------------------------------------------------- %% @doc Output the callback modules. %% @end %%----------------------------------------------------------------------- -spec get_callback_modules() -> [atom()]. get_callback_modules() -> - case ets:lookup(?LKVStore, callback_modules) of - [{callback_modules, CallBackModules}] -> CallBackModules; - [] -> [] - end. + case ets:lookup(?LKVStore, callback_modules) of + [{callback_modules, CallBackModules}] -> CallBackModules; + [] -> [] + end. %%----------------------------------------------------------------------- %% @doc Remove a callback module. @@ -116,9 +116,9 @@ get_callback_modules() -> %%----------------------------------------------------------------------- -spec delete_callback_module(atom()) -> ok. delete_callback_module(CallBackModule) -> - NewCallBackModules = lists:delete(CallBackModule, get_callback_modules()), - ets:insert(?LKVStore, {callback_modules, NewCallBackModules}), - ok. + NewCallBackModules = lists:delete(CallBackModule, get_callback_modules()), + ets:insert(?LKVStore, {callback_modules, NewCallBackModules}), + ok. %%----------------------------------------------------------------------- %% @doc Store the target types for the local system. Store an "I Want" @@ -126,10 +126,10 @@ delete_callback_module(CallBackModule) -> %% @end %%----------------------------------------------------------------------- -spec store_target_resource_types([atom()]) -> ok. -store_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> - ets:insert(?LKVStore, {target_types, lists:usort(get_target_resource_types() ++ TargetTypes)}), - ok. - +store_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> + ets:insert(?LKVStore, {target_types, lists:usort(get_target_resource_types() ++ TargetTypes)}), + ok. + %%----------------------------------------------------------------------- %% @doc Output the target types. These are the resource types we wish %% to find within our node cluster. @@ -137,10 +137,10 @@ store_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> %%----------------------------------------------------------------------- -spec get_target_resource_types() -> [atom()]. get_target_resource_types() -> - case ets:lookup(?LKVStore, target_types) of - [{target_types, TargetTypes}] -> lists:usort(TargetTypes); - [] -> [] - end. + case ets:lookup(?LKVStore, target_types) of + [{target_types, TargetTypes}] -> lists:usort(TargetTypes); + [] -> [] + end. %%----------------------------------------------------------------------- %% @doc Remove a target type. @@ -148,28 +148,28 @@ get_target_resource_types() -> %%----------------------------------------------------------------------- -spec delete_target_resource_type(atom()) -> ok. delete_target_resource_type(TargetType) -> - ets:insert(?LKVStore, {target_types, lists:delete(TargetType, get_target_resource_types())}), - ok. - + ets:insert(?LKVStore, {target_types, lists:delete(TargetType, get_target_resource_types())}), + ok. + %%----------------------------------------------------------------------- %% @doc Store the "I haves" or local_resources for resource discovery. %% @end %%----------------------------------------------------------------------- -spec store_local_resource_tuples([resource_tuple()]) -> ok. -store_local_resource_tuples([{_,_}|_] = LocalResourceTuples) -> - ets:insert(?LKVStore, {local_resources, lists:usort(get_local_resource_tuples() ++ LocalResourceTuples)}), - ok. - +store_local_resource_tuples([{_, _} | _] = LocalResourceTuples) -> + ets:insert(?LKVStore, {local_resources, lists:usort(get_local_resource_tuples() ++ LocalResourceTuples)}), + ok. + %%----------------------------------------------------------------------- %% @doc Output the local resources. %% @end %%----------------------------------------------------------------------- -spec get_local_resource_tuples() -> [resource_tuple()]. get_local_resource_tuples() -> - case ets:lookup(?LKVStore, local_resources) of - [{local_resources, LocalResources}] -> LocalResources; - [] -> [] - end. + case ets:lookup(?LKVStore, local_resources) of + [{local_resources, LocalResources}] -> LocalResources; + [] -> [] + end. %%-------------------------------------------------------------------- @@ -179,11 +179,11 @@ get_local_resource_tuples() -> %%-------------------------------------------------------------------- -spec get_deleted_resource_tuples() -> [resource_tuple()]. get_deleted_resource_tuples() -> - case ets:lookup(?LKVStore, deleted_resources) of - [{deleted_resources, DeletedResources}] -> DeletedResources; - [] -> [] - end. - + case ets:lookup(?LKVStore, deleted_resources) of + [{deleted_resources, DeletedResources}] -> DeletedResources; + [] -> [] + end. + %%----------------------------------------------------------------------- %% @doc Remove a local resource. @@ -191,19 +191,19 @@ get_deleted_resource_tuples() -> %%----------------------------------------------------------------------- -spec delete_local_resource_tuple(resource_tuple()) -> ok | {error, local_resource_not_found, resource_tuple()}. delete_local_resource_tuple(LocalResource) -> - %% first get local resource tuples - LocalResources = get_local_resource_tuples(), - %% only add to deleted cache if resource actually exist - case lists:member(LocalResource, LocalResources) of - true -> - %% store resource to be deleted in delete_cache table, so it could be removed from remote nodes resource cache - %% after syching - ets:insert(?LKVStore, {deleted_resources, lists:usort(get_deleted_resource_tuples() ++ [LocalResource])}), - %% now remove resource - ets:insert(?LKVStore, {local_resources, lists:delete(LocalResource, LocalResources)}), - ok; - false -> {error, local_resource_not_found, LocalResource} - end. + %% first get local resource tuples + LocalResources = get_local_resource_tuples(), + %% only add to deleted cache if resource actually exist + case lists:member(LocalResource, LocalResources) of + true -> + %% store resource to be deleted in delete_cache table, so it could be removed from remote nodes resource cache + %% after syching + ets:insert(?LKVStore, {deleted_resources, lists:usort(get_deleted_resource_tuples() ++ [LocalResource])}), + %% now remove resource + ets:insert(?LKVStore, {local_resources, lists:delete(LocalResource, LocalResources)}), + ok; + false -> {error, local_resource_not_found, LocalResource} + end. %%%--------------------------- %%% Network Resource Storage @@ -215,10 +215,10 @@ delete_local_resource_tuple(LocalResource) -> %%----------------------------------------------------------------------- -spec get_resources(resource_type()) -> [resource()]. get_resources(Type) -> - case ets:lookup(?RS, Type) of - [{Type, Resources}] -> Resources; - [] -> [] - end. + case ets:lookup(?RS, Type) of + [{Type, Resources}] -> Resources; + [] -> [] + end. %%----------------------------------------------------------------------- %% @doc Adds a new resource. @@ -226,15 +226,15 @@ get_resources(Type) -> %%----------------------------------------------------------------------- -spec store_resource_tuple(resource_tuple()) -> ok. store_resource_tuple({Type, Resource}) when is_atom(Type) -> - ets:insert(?RS, {Type, lists:usort(get_resources(Type) ++ [Resource])}), - ok. + ets:insert(?RS, {Type, lists:usort(get_resources(Type) ++ [Resource])}), + ok. -spec store_resource_tuples([resource_tuple()]) -> ok. store_resource_tuples([]) -> ok; -store_resource_tuples([{_,_}|_] = ResourceTuples) -> - lists:foreach(fun(ResourceTuple) -> - store_resource_tuple(ResourceTuple) - end, ResourceTuples). +store_resource_tuples([{_, _} | _] = ResourceTuples) -> + lists:foreach(fun(ResourceTuple) -> + store_resource_tuple(ResourceTuple) + end, ResourceTuples). %%----------------------------------------------------------------------- %% @doc Remove a single resource from cache. @@ -242,15 +242,15 @@ store_resource_tuples([{_,_}|_] = ResourceTuples) -> %%----------------------------------------------------------------------- -spec delete_resource_tuple(resource_tuple()) -> ok. delete_resource_tuple({Type, Resource}) -> - ets:insert(?RS, {Type, lists:delete(Resource, get_resources(Type))}), - %% delete Type if it doesnt have any resources - case get_resources(Type) of - [] -> ets:match_delete(?RS, {Type, '_'}); - _ -> do_nothing - end, - ok. - - + ets:insert(?RS, {Type, lists:delete(Resource, get_resources(Type))}), + %% delete Type if it doesnt have any resources + case get_resources(Type) of + [] -> ets:match_delete(?RS, {Type, '_'}); + _ -> do_nothing + end, + ok. + + %%-------------------------------------------------------------------- %% @doc %% clear deleted resource cache. after the network was synched @@ -258,22 +258,22 @@ delete_resource_tuple({Type, Resource}) -> %%-------------------------------------------------------------------- -spec delete_deleted_resource_tuple() -> ok. delete_deleted_resource_tuple() -> - ets:insert(?LKVStore, {deleted_resources, []}), - ok. + ets:insert(?LKVStore, {deleted_resources, []}), + ok. + - %%----------------------------------------------------------------------- %% @doc Gets resource of a particular type outputs and places it in last position. %% @end %%----------------------------------------------------------------------- -spec round_robin_get(resource_type()) -> {ok, resource()} | {error, not_found}. round_robin_get(Type) -> - case get_resources(Type) of - [Resource | RL] -> - ets:insert(?RS, {Type, RL ++ [Resource]}), - {ok, Resource}; - [] -> {error, not_found} - end. + case get_resources(Type) of + [Resource | RL] -> + ets:insert(?RS, {Type, RL ++ [Resource]}), + {ok, Resource}; + [] -> {error, not_found} + end. %%----------------------------------------------------------------------- %% @doc Outputs the number of resource types. @@ -281,7 +281,7 @@ round_robin_get(Type) -> %%----------------------------------------------------------------------- -spec get_num_resource_types() -> integer(). get_num_resource_types() -> - length(ets:match(?RS, {'$1', '_'})). + length(ets:match(?RS, {'$1', '_'})). %%----------------------------------------------------------------------- %% @doc Outputs the number of resource types. @@ -289,10 +289,10 @@ get_num_resource_types() -> %%----------------------------------------------------------------------- -spec get_num_resource(resource_type()) -> integer(). get_num_resource(Type) -> - case ets:lookup(?RS, Type) of - [{Type, Resources}] -> length(Resources); - [] -> 0 - end. + case ets:lookup(?RS, Type) of + [{Type, Resources}] -> length(Resources); + [] -> 0 + end. %%----------------------------------------------------------------------- %% @doc Outputs the types of resources. @@ -301,4 +301,4 @@ get_num_resource(Type) -> %%----------------------------------------------------------------------- -spec get_resource_types() -> [resource_type()]. get_resource_types() -> - lists:usort([E || [E] <- ets:match(?RS, {'$1', '_'})]). + lists:usort([E || [E] <- ets:match(?RS, {'$1', '_'})]). diff --git a/src/rd_sup.erl b/src/rd_sup.erl index d1aff5a..31e73fa 100644 --- a/src/rd_sup.erl +++ b/src/rd_sup.erl @@ -14,15 +14,15 @@ %% External exports %%-------------------------------------------------------------------- -export([ - start_link/0 - ]). + start_link/0 +]). %%-------------------------------------------------------------------- %% Internal exports %%-------------------------------------------------------------------- -export([ - init/1 - ]). + init/1 +]). %%-------------------------------------------------------------------- %% Macros @@ -43,7 +43,7 @@ %% @end %%-------------------------------------------------------------------- start_link() -> - supervisor:start_link({local, ?SERVER}, ?MODULE, []). + supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Server functions @@ -56,28 +56,28 @@ start_link() -> %% {error, Reason} %%-------------------------------------------------------------------- init([]) -> - RestartStrategy = one_for_one, - MaxRestarts = 1000, - MaxTimeBetRestarts = 3600, - SupFlags = {RestartStrategy, MaxRestarts, MaxTimeBetRestarts}, + RestartStrategy = one_for_one, + MaxRestarts = 1000, + MaxTimeBetRestarts = 3600, + SupFlags = {RestartStrategy, MaxRestarts, MaxTimeBetRestarts}, - ChildSpecs = - [ - {rd_core, - {rd_core, start_link, []}, - permanent, - 1000, - worker, - [rd_core]}, - {rd_heartbeat, - {rd_heartbeat, start_link, []}, - transient, - brutal_kill, - worker, - [rd_heartbeat]} - ], + ChildSpecs = + [ + {rd_core, + {rd_core, start_link, []}, + permanent, + 1000, + worker, + [rd_core]}, + {rd_heartbeat, + {rd_heartbeat, start_link, []}, + transient, + brutal_kill, + worker, + [rd_heartbeat]} + ], - {ok, {SupFlags, ChildSpecs}}. + {ok, {SupFlags, ChildSpecs}}. diff --git a/src/rd_util.erl b/src/rd_util.erl index ba87e45..78a2587 100644 --- a/src/rd_util.erl +++ b/src/rd_util.erl @@ -8,11 +8,11 @@ %% API -export([ - get_env/2, - do_until/2, - sync_ping/2, - poll_until/3 - ]). + get_env/2, + do_until/2, + sync_ping/2, + poll_until/3 +]). %%%=================================================================== %%% API @@ -22,33 +22,33 @@ %% return value from the passed in fun. -spec do_until(term(), list()) -> term() | false. do_until(_F, []) -> - false; + false; do_until(F, [Last]) -> - F(Last); -do_until(F, [H|T]) -> - case F(H) of - false -> do_until(F, T); - Return -> Return - end. - + F(Last); +do_until(F, [H | T]) -> + case F(H) of + false -> do_until(F, T); + Return -> Return + end. + %% @doc Pings a node and returns only after the net kernal distributes the nodes. -spec sync_ping(node(), timeout()) -> pang | pong. sync_ping(Node, Timeout) -> - error_logger:info_msg("pinging node: ~p", [Node]), - case net_adm:ping(Node) of - pong -> - Resp = - poll_until(fun() -> - length(get_remote_nodes(Node)) == length(nodes()) - end, - 10, Timeout div 10), - case Resp of - true -> pong; - false -> pang - end; - pang -> - pang - end. + error_logger:info_msg("pinging node: ~p", [Node]), + case net_adm:ping(Node) of + pong -> + Resp = + poll_until(fun() -> + length(get_remote_nodes(Node)) == length(nodes()) + end, + 10, Timeout div 10), + case Resp of + true -> pong; + false -> pang + end; + pang -> + pang + end. %% @doc This is a higher order function that allows for Iterations %% number of executions of Fun until false is not returned @@ -62,27 +62,26 @@ sync_ping(Node, Timeout) -> %% -spec poll_until(term(), timeout(), timeout()) -> term() | false. poll_until(Fun, 0, _PauseMS) -> - Fun(); + Fun(); poll_until(Fun, Iterations, PauseMS) -> - case Fun() of - false -> - timer:sleep(PauseMS), - case Iterations of - infinity -> poll_until(Fun, Iterations, PauseMS); - Iterations -> poll_until(Fun, Iterations - 1, PauseMS) - end; - Reply -> - Reply - end. + case Fun() of + false -> + timer:sleep(PauseMS), + case Iterations of + infinity -> poll_until(Fun, Iterations, PauseMS); + Iterations -> poll_until(Fun, Iterations - 1, PauseMS) + end; + Reply -> + Reply + end. %% @doc Get application data but provide a default. -spec get_env(atom(), term()) -> term(). get_env(Key, Default) -> - case application:get_env(resource_discovery, Key) of - {ok, Value} -> {ok, Value}; - undefined -> {ok, Default} - end. - + case application:get_env(resource_discovery, Key) of + {ok, Value} -> {ok, Value}; + undefined -> {ok, Default} + end. %%%=================================================================== @@ -91,13 +90,13 @@ get_env(Key, Default) -> get_remote_nodes(Node) -> - try - Nodes = rpc:call(Node, erlang, nodes, []), - error_logger:info_msg("contact node has ~p", [Nodes]), - Nodes - catch - _C:E -> - error_logger:info_msg("failed to connect to contact node ~p", [Node]), - throw(E) - end. + try + Nodes = rpc:call(Node, erlang, nodes, []), + error_logger:info_msg("contact node has ~p", [Nodes]), + Nodes + catch + _C:E -> + error_logger:info_msg("failed to connect to contact node ~p", [Node]), + throw(E) + end. diff --git a/src/resource_discovery.app.src b/src/resource_discovery.app.src index 523f473..934deb2 100644 --- a/src/resource_discovery.app.src +++ b/src/resource_discovery.app.src @@ -1,41 +1,41 @@ %%% -*- mode:erlang -*- {application, resource_discovery, - [ - % A quick description of the application. - {description, "Resource discovery & management"}, + [ + % A quick description of the application. + {description, "Resource discovery & management"}, - % The version of the applicaton - {vsn, "0.2.1.0"}, + % The version of the applicaton + {vsn, "0.2.1.0"}, - % All modules used by the application. - {modules, - [ - resource_discovery, - rd_core, - rd_heartbeat, - rd_store, - rd_util, - rd_sup - ]}, + % All modules used by the application. + {modules, + [ + resource_discovery, + rd_core, + rd_heartbeat, + rd_store, + rd_util, + rd_sup + ]}, - % All of the registered names the application uses. - {registered, []}, + % All of the registered names the application uses. + {registered, []}, - % Applications that are to be started prior to this one. - {applications, - [ - kernel, - stdlib - ]}, + % Applications that are to be started prior to this one. + {applications, + [ + kernel, + stdlib + ]}, - % configuration parameters - {env, [{heartbeat_frequency, 60000}]}, - - % The M F A to start this application. - {mod, {resource_discovery, - [ - {heartbeat_frequency, 60000} - ]}} - ] + % configuration parameters + {env, [{heartbeat_frequency, 60000}]}, + + % The M F A to start this application. + {mod, {resource_discovery, + [ + {heartbeat_frequency, 60000} + ]}} + ] }. diff --git a/src/resource_discovery.erl b/src/resource_discovery.erl index ccb874e..9372f1f 100644 --- a/src/resource_discovery.erl +++ b/src/resource_discovery.erl @@ -22,49 +22,49 @@ % Standard exports. -export([ - start/0, - start/2, - stop/0 - ]). + start/0, + start/2, + stop/0 +]). % Add -export([ - add_local_resource_tuples/1, - add_local_resource_tuple/1, - add_target_resource_types/1, - add_target_resource_type/1, - add_callback_modules/1, - add_callback_module/1 - ]). + add_local_resource_tuples/1, + add_local_resource_tuple/1, + add_target_resource_types/1, + add_target_resource_type/1, + add_callback_modules/1, + add_callback_module/1 +]). % Get -export([ - get_resource/1, - get_resources/1, - get_num_resource/1, - get_resource_types/0, - get_num_resource_types/0 - ]). + get_resource/1, + get_resources/1, + get_num_resource/1, + get_resource_types/0, + get_num_resource_types/0 +]). % Delete -export([ - delete_local_resource_tuple/1, - delete_target_resource_type/1, - delete_resource_tuple/1, - delete_callback_module/1, - delete_callback_modules/1 - ]). + delete_local_resource_tuple/1, + delete_target_resource_type/1, + delete_resource_tuple/1, + delete_callback_module/1, + delete_callback_modules/1 +]). % Other -export([ - trade_resources/0, - sync_resources/1, - sync_resources/0, - contact_nodes/0, - rpc_multicall/5, - rpc_multicall/4, - rpc_call/5, - rpc_call/4 - ]). + trade_resources/0, + sync_resources/1, + sync_resources/0, + contact_nodes/0, + rpc_multicall/5, + rpc_multicall/4, + rpc_call/5, + rpc_call/4 +]). -include("../include/resource_discovery.hrl"). @@ -78,7 +78,7 @@ %%==================================================================== start() -> - application:start(resource_discovery). + application:start(resource_discovery). %%-------------------------------------------------------------------- %% @doc Starts the resource discovery application. @@ -86,11 +86,11 @@ start() -> %% @end %%-------------------------------------------------------------------- start(_Type, _StartArgs) -> - % Create the storage for the local parameters; i.e. LocalTypes - % and TargetTypes. - random:seed(erlang:timestamp()), - rd_store:new(), - rd_sup:start_link(). + % Create the storage for the local parameters; i.e. LocalTypes + % and TargetTypes. + random:seed(erlang:timestamp()), + rd_store:new(), + rd_sup:start_link(). stop() -> application:stop(resource_discovery). @@ -110,45 +110,45 @@ trade_resources() -> rd_core:trade_resources(). %%----------------------------------------------------------------------- -spec sync_resources(timeout()) -> ok. sync_resources(Timeout) -> - sync_locals(), - Self = self(), - Nodes = nodes(known), - error_logger:info_msg("synching resources to nodes: ~p", [Nodes]), - LocalResourceTuples = rd_core:get_local_resource_tuples(), - DeletedTuples = rd_core:get_deleted_resource_tuples(), - TargetTypes = rd_core:get_target_resource_types(), - - Pids = [spawn(fun() -> - Self ! {'\$sync_resources\$', self(), - (catch rd_core:sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}))} - end) - || Node <- Nodes], - %% resources are synched so remove deleted tuples cache - rd_store:delete_deleted_resource_tuple(), - get_responses(Pids, Timeout). + sync_locals(), + Self = self(), + Nodes = nodes(known), + error_logger:info_msg("synching resources to nodes: ~p", [Nodes]), + LocalResourceTuples = rd_core:get_local_resource_tuples(), + DeletedTuples = rd_core:get_deleted_resource_tuples(), + TargetTypes = rd_core:get_target_resource_types(), + + Pids = [spawn(fun() -> + Self ! {'\$sync_resources\$', self(), + (catch rd_core:sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}))} + end) + || Node <- Nodes], + %% resources are synched so remove deleted tuples cache + rd_store:delete_deleted_resource_tuple(), + get_responses(Pids, Timeout). -spec sync_resources() -> ok. sync_resources() -> sync_resources(10000). sync_locals() -> - LocalResourceTuples = rd_core:get_local_resource_tuples(), - TargetTypes = rd_core:get_target_resource_types(), - FilteredLocals = rd_core:filter_resource_tuples_by_types(TargetTypes, LocalResourceTuples), - rd_core:store_resource_tuples(FilteredLocals), - rd_core:make_callbacks(FilteredLocals). + LocalResourceTuples = rd_core:get_local_resource_tuples(), + TargetTypes = rd_core:get_target_resource_types(), + FilteredLocals = rd_core:filter_resource_tuples_by_types(TargetTypes, LocalResourceTuples), + rd_core:store_resource_tuples(FilteredLocals), + rd_core:make_callbacks(FilteredLocals). get_responses([], _Timeout) -> ok; get_responses(Pids, Timeout) -> - %% XXX TODO fix the timeout by subracting elapsed time. - %% XXX TODO perhaps use the response. - receive - {'\$sync_resources\$', Pid, _Resp} -> - NewPids = lists:delete(Pid, Pids), - get_responses(NewPids, Timeout) - after - Timeout -> {error, timeout} - end. - + %% XXX TODO fix the timeout by subracting elapsed time. + %% XXX TODO perhaps use the response. + receive + {'\$sync_resources\$', Pid, _Resp} -> + NewPids = lists:delete(Pid, Pids), + get_responses(NewPids, Timeout) + after + Timeout -> {error, timeout} + end. + %%------------------------------------------------------------------------------ %% @doc Adds to the list of target types. Target types are the types %% of resources that this instance of resource_discovery will cache following @@ -157,24 +157,24 @@ get_responses(Pids, Timeout) -> %% @end %%------------------------------------------------------------------------------ -spec add_target_resource_types([resource_type()]) -> ok. -add_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> - rd_core:store_target_resource_types(TargetTypes). - +add_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> + rd_core:store_target_resource_types(TargetTypes). + -spec add_target_resource_type(resource_type()) -> ok. -add_target_resource_type(TargetType) when is_atom(TargetType) -> - add_target_resource_types([TargetType]). +add_target_resource_type(TargetType) when is_atom(TargetType) -> + add_target_resource_types([TargetType]). %%------------------------------------------------------------------------------ %% @doc Adds to the list of local resource tuples. %% @end %%------------------------------------------------------------------------------ -spec add_local_resource_tuples([resource_tuple()]) -> ok. -add_local_resource_tuples([{T,_}|_] = LocalResourceTuples) when is_atom(T) -> - rd_core:store_local_resource_tuples(LocalResourceTuples). - +add_local_resource_tuples([{T, _} | _] = LocalResourceTuples) when is_atom(T) -> + rd_core:store_local_resource_tuples(LocalResourceTuples). + -spec add_local_resource_tuple(resource_tuple()) -> ok. -add_local_resource_tuple({T,_} = LocalResourceTuple) when is_atom(T) -> - add_local_resource_tuples([LocalResourceTuple]). +add_local_resource_tuple({T, _} = LocalResourceTuple) when is_atom(T) -> + add_local_resource_tuples([LocalResourceTuple]). %%------------------------------------------------------------------------------ %% @doc Add a callback module or modules to the list of callbacks to be @@ -182,12 +182,12 @@ add_local_resource_tuple({T,_} = LocalResourceTuple) when is_atom(T) -> %% @end %%------------------------------------------------------------------------------ -spec add_callback_modules([atom()]) -> ok. -add_callback_modules([H|_] = Modules) when is_atom(H) -> - rd_core:store_callback_modules(Modules). +add_callback_modules([H | _] = Modules) when is_atom(H) -> + rd_core:store_callback_modules(Modules). -spec add_callback_module(atom()) -> ok. add_callback_module(Module) when is_atom(Module) -> - add_callback_modules([Module]). + add_callback_modules([Module]). %%------------------------------------------------------------------------------ %% @doc Replies with the cached resource. Round robins though the resources @@ -196,7 +196,7 @@ add_callback_module(Module) when is_atom(Module) -> %%------------------------------------------------------------------------------ -spec get_resource(resource_type()) -> {ok, resource()} | {error, not_found}. get_resource(Type) when is_atom(Type) -> - rd_core:round_robin_get(Type). + rd_core:round_robin_get(Type). %%------------------------------------------------------------------------------ %% @doc Returns ALL cached resources for a particular type. @@ -204,7 +204,7 @@ get_resource(Type) when is_atom(Type) -> %%------------------------------------------------------------------------------ -spec get_resources(resource_type()) -> [resource()]. get_resources(Type) -> - rd_core:all_of_type_get(Type). + rd_core:all_of_type_get(Type). %%------------------------------------------------------------------------------ %% @doc Gets a list of the types that have resources that have been cached. @@ -212,7 +212,7 @@ get_resources(Type) -> %%------------------------------------------------------------------------------ -spec get_resource_types() -> [resource_type()]. get_resource_types() -> - rd_core:get_resource_types(). + rd_core:get_resource_types(). %%------------------------------------------------------------------------------ %% @doc Removes a cached resource from the resource pool. Only returns after the @@ -220,8 +220,8 @@ get_resource_types() -> %% @end %%------------------------------------------------------------------------------ -spec delete_resource_tuple(resource_tuple()) -> ok. -delete_resource_tuple(ResourceTuple = {_,_}) -> - rd_core:delete_resource_tuple(ResourceTuple). +delete_resource_tuple(ResourceTuple = {_, _}) -> + rd_core:delete_resource_tuple(ResourceTuple). %%------------------------------------------------------------------------------ %% @doc Remove a target type and all associated resources. @@ -229,7 +229,7 @@ delete_resource_tuple(ResourceTuple = {_,_}) -> %%------------------------------------------------------------------------------ -spec delete_target_resource_type(resource_type()) -> true. delete_target_resource_type(Type) -> - rd_core:delete_target_resource_type(Type). + rd_core:delete_target_resource_type(Type). %%------------------------------------------------------------------------------ %% @doc Remove a local resource. The resource will no longer be available for @@ -238,7 +238,7 @@ delete_target_resource_type(Type) -> %%------------------------------------------------------------------------------ -spec delete_local_resource_tuple(resource_tuple()) -> ok | {error, local_resource_not_found, resource_tuple()}. delete_local_resource_tuple(LocalResourceTuple) -> - rd_core:delete_local_resource_tuple(LocalResourceTuple). + rd_core:delete_local_resource_tuple(LocalResourceTuple). %%-------------------------------------------------------------------- %% @doc @@ -246,9 +246,9 @@ delete_local_resource_tuple(LocalResourceTuple) -> %% @end %%-------------------------------------------------------------------- -spec delete_callback_modules([atom()]) -> ok. -delete_callback_modules([H|_] = Modules) when is_atom(H) -> - [rd_core:delete_callback_module(Module) || Module <- Modules], - ok. +delete_callback_modules([H | _] = Modules) when is_atom(H) -> + [rd_core:delete_callback_module(Module) || Module <- Modules], + ok. %%-------------------------------------------------------------------- %% @doc @@ -257,7 +257,7 @@ delete_callback_modules([H|_] = Modules) when is_atom(H) -> %%-------------------------------------------------------------------- -spec delete_callback_module(atom()) -> ok. delete_callback_module(Module) when is_atom(Module) -> - delete_callback_modules([Module]). + delete_callback_modules([Module]). %%------------------------------------------------------------------------------ %% @doc Gets the number of resource types locally cached. @@ -265,7 +265,7 @@ delete_callback_module(Module) when is_atom(Module) -> %%------------------------------------------------------------------------------ -spec get_num_resource_types() -> integer(). get_num_resource_types() -> - rd_core:get_num_resource_types(). + rd_core:get_num_resource_types(). %%------------------------------------------------------------------------------ %% @doc Counts the cached instances of a particular resource type. @@ -273,8 +273,8 @@ get_num_resource_types() -> %%------------------------------------------------------------------------------ -spec get_num_resource(resource_type()) -> integer(). get_num_resource(Type) -> - rd_core:get_num_resource(Type). - + rd_core:get_num_resource(Type). + %%------------------------------------------------------------------------------ %% @doc Contacts resource discoveries initial contact node. %% @@ -294,38 +294,38 @@ get_num_resource(Type) -> %% @end %%------------------------------------------------------------------------------ contact_nodes(Timeout) -> - {ok, ContactNodes} = - case lists:keysearch(contact_node, 1, init:get_arguments()) of - {value, {contact_node, [I_ContactNode]}} -> - application:set_env(resource_discovery, contact_nodes, [I_ContactNode]), - {ok, [list_to_atom(I_ContactNode)]}; - _ -> rd_util:get_env(contact_nodes, [node()]) - end, - ping_contact_nodes(ContactNodes, Timeout). + {ok, ContactNodes} = + case lists:keysearch(contact_node, 1, init:get_arguments()) of + {value, {contact_node, [I_ContactNode]}} -> + application:set_env(resource_discovery, contact_nodes, [I_ContactNode]), + {ok, [list_to_atom(I_ContactNode)]}; + _ -> rd_util:get_env(contact_nodes, [node()]) + end, + ping_contact_nodes(ContactNodes, Timeout). %% @spec contact_nodes() -> pong | pang | no_contact_node %% @equiv contact_nodes(10000) contact_nodes() -> - contact_nodes(10000). + contact_nodes(10000). ping_contact_nodes([], _Timeout) -> - error_logger:info_msg("No contact node specified. Potentially running in a standalone node", []), - {error, no_contact_node}; + error_logger:info_msg("No contact node specified. Potentially running in a standalone node", []), + {error, no_contact_node}; ping_contact_nodes(Nodes, Timeout) -> - Reply = rd_util:do_until(fun(Node) -> - case rd_util:sync_ping(Node, Timeout) of - pong -> true; - pang -> - error_logger:info_msg("ping contact node at ~p failed", [Node]), - false - end - end, - Nodes), - case Reply of - false -> {error, bad_contact_node}; - true -> ok - end. - + Reply = rd_util:do_until(fun(Node) -> + case rd_util:sync_ping(Node, Timeout) of + pong -> true; + pang -> + error_logger:info_msg("ping contact node at ~p failed", [Node]), + false + end + end, + Nodes), + case Reply of + false -> {error, bad_contact_node}; + true -> ok + end. + %%------------------------------------------------------------------------------ %% @doc Execute an rpc on a cached resource. If the result of the rpc is {badrpc, reason} the %% resource is deleted and the next resource is tried, else the result is @@ -338,24 +338,24 @@ ping_contact_nodes(Nodes, Timeout) -> %%------------------------------------------------------------------------------ -spec rpc_call(resource_type(), atom(), atom(), [term()], timeout()) -> term() | {error, not_found}. rpc_call(Type, Module, Function, Args, Timeout) -> - case get_resource(Type) of - {ok, Resource} -> - error_logger:info_msg("got a resource ~p", [Resource]), - case rpc:call(Resource, Module, Function, Args, Timeout) of - {badrpc, Reason} -> - error_logger:info_msg("got a badrpc ~p", [Reason]), - delete_resource_tuple({Type, Resource}), - rpc_call(Type, Module, Function, Args, Timeout); - Reply -> - error_logger:info_msg("result of rpc was ~p", [Reply]), - Reply - end; - {error, not_found} -> {error, not_found} - end. + case get_resource(Type) of + {ok, Resource} -> + error_logger:info_msg("got a resource ~p", [Resource]), + case rpc:call(Resource, Module, Function, Args, Timeout) of + {badrpc, Reason} -> + error_logger:info_msg("got a badrpc ~p", [Reason]), + delete_resource_tuple({Type, Resource}), + rpc_call(Type, Module, Function, Args, Timeout); + Reply -> + error_logger:info_msg("result of rpc was ~p", [Reply]), + Reply + end; + {error, not_found} -> {error, not_found} + end. -spec rpc_call(resource_type(), atom(), atom(), [term()]) -> term() | {error, no_resources}. rpc_call(Type, Module, Function, Args) -> - rpc_call(Type, Module, Function, Args, 60000). + rpc_call(Type, Module, Function, Args, 60000). %%------------------------------------------------------------------------------ %% @doc Execute an rpc on a cached resource. Any bad nodes are deleted. @@ -365,15 +365,15 @@ rpc_call(Type, Module, Function, Args) -> %%------------------------------------------------------------------------------ -spec rpc_multicall(resource_type(), atom(), atom(), [term()], timeout()) -> {term(), [node()]} | {error, no_resources}. rpc_multicall(Type, Module, Function, Args, Timeout) -> - case get_resources(Type) of - [] -> {error, no_resources}; - Resources -> - error_logger:info_msg("got resources ~p", [Resources]), - {Resl, BadNodes} = rpc:multicall(Resources, Module, Function, Args, Timeout), - [delete_resource_tuple({Type, BadNode}) || BadNode <- BadNodes], - {Resl, BadNodes} - end. + case get_resources(Type) of + [] -> {error, no_resources}; + Resources -> + error_logger:info_msg("got resources ~p", [Resources]), + {Resl, BadNodes} = rpc:multicall(Resources, Module, Function, Args, Timeout), + [delete_resource_tuple({Type, BadNode}) || BadNode <- BadNodes], + {Resl, BadNodes} + end. -spec rpc_multicall(resource_type(), atom(), atom(), [term()]) -> {term(), [node()]} | {error, no_resources}. rpc_multicall(Type, Module, Function, Args) -> - rpc_multicall(Type, Module, Function, Args, 60000). + rpc_multicall(Type, Module, Function, Args, 60000). diff --git a/src/sys.config b/src/sys.config index 6bebb04..63f01e8 100644 --- a/src/sys.config +++ b/src/sys.config @@ -1,11 +1,11 @@ %%% -*- mode:erlang -*- %%% Warning - this config file *must* end with -[ - {resource_discovery, - [ - {contact_nodes, ['rd@127.0.0.1']}, - {heartbeat_frequency, 60000}, - {log4erl_config, "etc/log4erl.conf"} - ]} +[ + {resource_discovery, + [ + {contact_nodes, ['rd@127.0.0.1']}, + {heartbeat_frequency, 60000}, + {log4erl_config, "etc/log4erl.conf"} + ]} ]. diff --git a/test/rd_store_tests.erl b/test/rd_store_tests.erl index 38fd107..af099ff 100644 --- a/test/rd_store_tests.erl +++ b/test/rd_store_tests.erl @@ -5,68 +5,68 @@ -define(TEST_VALUES, [{a, a}, {a, b}, {b, a}]). rd_store_local_resource_test_() -> - {setup, local, - fun rd_store:new/0, - fun(_Pid) -> rd_store:delete() end, - fun(_P) -> - {inorder, - [ - %% add local resources - ?_assertEqual(ok, rd_store:store_local_resource_tuples(?TEST_VALUES)), - %% check that we get the same resources from storage - ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()), - %% test for dublicate values - ?_assertEqual(ok, rd_store:store_local_resource_tuples([{a,a},{a,b}])), - %% shouln't have new resources after dublicate were attempted to add - ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()), - %% remove resource - ?_assertEqual(ok, rd_store:delete_local_resource_tuple({a, a})), - ?_assertMatch([{a, b}, {b, a}], rd_store:get_local_resource_tuples()) - ]} - end }. + {setup, local, + fun rd_store:new/0, + fun(_Pid) -> rd_store:delete() end, + fun(_P) -> + {inorder, + [ + %% add local resources + ?_assertEqual(ok, rd_store:store_local_resource_tuples(?TEST_VALUES)), + %% check that we get the same resources from storage + ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()), + %% test for dublicate values + ?_assertEqual(ok, rd_store:store_local_resource_tuples([{a, a}, {a, b}])), + %% shouln't have new resources after dublicate were attempted to add + ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()), + %% remove resource + ?_assertEqual(ok, rd_store:delete_local_resource_tuple({a, a})), + ?_assertMatch([{a, b}, {b, a}], rd_store:get_local_resource_tuples()) + ]} + end}. rd_store_target_resource_test_() -> - {setup, local, - fun rd_store:new/0, - fun(_Pid) -> rd_store:delete() end, - fun(_P) -> - {inorder, - [ - ?_assertEqual(ok, rd_store:store_target_resource_types([c, d, e])), - ?_assertMatch([c,d,e], rd_store:get_target_resource_types()), - ?_assertMatch(ok, rd_store:delete_target_resource_type(c)), - ?_assertMatch([d,e], rd_store:get_target_resource_types()) - ]} - end }. + {setup, local, + fun rd_store:new/0, + fun(_Pid) -> rd_store:delete() end, + fun(_P) -> + {inorder, + [ + ?_assertEqual(ok, rd_store:store_target_resource_types([c, d, e])), + ?_assertMatch([c, d, e], rd_store:get_target_resource_types()), + ?_assertMatch(ok, rd_store:delete_target_resource_type(c)), + ?_assertMatch([d, e], rd_store:get_target_resource_types()) + ]} + end}. rd_store_resource_test_() -> - {setup, local, - fun rd_store:new/0, - fun(_Pid) -> rd_store:delete() end, - fun(_P) -> - {inorder, - [ - ?_assertEqual(ok, rd_store:store_resource_tuple({c, c1})), - ?_assertEqual(ok, rd_store:store_resource_tuples([{d, d1},{d, d2}, {e, e1}, {e, e2}, {b, b1}])), - ?_assertMatch(2, rd_store:get_num_resource(d)), - ?_assertMatch(4, rd_store:get_num_resource_types()), - ?_assertMatch([b1], rd_store:get_resources(b)), - ?_assertMatch([d1, d2], rd_store:get_resources(d)), - ?_assertMatch([e1, e2], rd_store:get_resources(e)) - ]} - end }. + {setup, local, + fun rd_store:new/0, + fun(_Pid) -> rd_store:delete() end, + fun(_P) -> + {inorder, + [ + ?_assertEqual(ok, rd_store:store_resource_tuple({c, c1})), + ?_assertEqual(ok, rd_store:store_resource_tuples([{d, d1}, {d, d2}, {e, e1}, {e, e2}, {b, b1}])), + ?_assertMatch(2, rd_store:get_num_resource(d)), + ?_assertMatch(4, rd_store:get_num_resource_types()), + ?_assertMatch([b1], rd_store:get_resources(b)), + ?_assertMatch([d1, d2], rd_store:get_resources(d)), + ?_assertMatch([e1, e2], rd_store:get_resources(e)) + ]} + end}. rd_store_callback_test_() -> - {setup, local, - fun rd_store:new/0, - fun(_Pid) -> rd_store:delete() end, - fun(_P) -> - {inorder, - [ - ?_assertEqual(ok, rd_store:store_callback_modules([a, b])), - ?_assertEqual([a,b], rd_store:get_callback_modules()), - ?_assertEqual(ok, rd_store:delete_callback_module(a)), - ?_assertEqual([b], rd_store:get_callback_modules()) - ]} - end }. + {setup, local, + fun rd_store:new/0, + fun(_Pid) -> rd_store:delete() end, + fun(_P) -> + {inorder, + [ + ?_assertEqual(ok, rd_store:store_callback_modules([a, b])), + ?_assertEqual([a, b], rd_store:get_callback_modules()), + ?_assertEqual(ok, rd_store:delete_callback_module(a)), + ?_assertEqual([b], rd_store:get_callback_modules()) + ]} + end}. diff --git a/test/resource_discovery_tests.erl b/test/resource_discovery_tests.erl index bfe8086..f3fe466 100644 --- a/test/resource_discovery_tests.erl +++ b/test/resource_discovery_tests.erl @@ -13,190 +13,189 @@ %% resource_discovery:get_resources(b). process_test_() -> - {setup, - fun start_process/0, - fun stop_process/1, - fun run/1}. + {setup, + fun start_process/0, + fun stop_process/1, + fun run/1}. start_process() -> - resource_discovery:start(). + resource_discovery:start(). stop_process(_P) -> - resource_discovery:stop(), - ok. + resource_discovery:stop(), + ok. run(_P) -> - {inorder, + {inorder, [ - %% add local and target resources - ?_assertMatch(ok, resource_discovery:add_local_resource_tuples(?RESOURCE_TUPLES)), - ?_assertMatch(ok, resource_discovery:add_target_resource_type(b)), - ?_assertMatch(ok, resource_discovery:sync_resources()), - %% check that target resource is avilable - ?_assertMatch([a], resource_discovery:get_resources(b)), - ?_assertMatch([b], resource_discovery:get_resource_types()), - %% delete local resource, the resource should dissapear from remote caches after sych - ?_assertMatch(ok, resource_discovery:delete_local_resource_tuple({b,a})), - %% try to remove non existing resource - ?_assertMatch({error, local_resource_not_found, {b,a1}}, resource_discovery:delete_local_resource_tuple({b,a1})), - ?_assertMatch(ok, resource_discovery:sync_resources()), - %% check that it is not avialable to network anymore - ?_assertMatch([], resource_discovery:get_resources(b)), - ?_assertMatch([], resource_discovery:get_resources(a)), - ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)), - %% check that resource types with no resources is gone - ?_assertMatch([], resource_discovery:get_resource_types()), - %% add new target resources in "I want" list - ?_assertMatch(ok, resource_discovery:add_target_resource_types([e,f,n])), - ?_assertMatch(ok, resource_discovery:sync_resources()), - ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e,e1}, {e,e2}, {e,e3}, {f, f1}])), - ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({f, f1})), - ?_assertMatch(ok, resource_discovery:trade_resources()), - ?_assertMatch([e, f], resource_discovery:get_resource_types()), - ?_assertEqual(2, resource_discovery:get_num_resource_types()), - ?_assertEqual(3, resource_discovery:get_num_resource(e)), - %% number of non-existing resource - ?_assertEqual(0, resource_discovery:get_num_resource(k)), - ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{b,a}])), - ?_assertMatch(ok, resource_discovery:sync_resources()), - ?_assertMatch([a], resource_discovery:get_resources(b)), - ?_assertMatch({ok, a}, resource_discovery:get_resource(b)), - ?_assertMatch([e1, e2, e3], resource_discovery:get_resources(e)), - %% delete resource - ?_assertMatch(ok,resource_discovery:delete_resource_tuple({b,a})), - %% shouldn't exist in local cache - ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)), - ?_assertMatch(ok, resource_discovery:trade_resources()), - %% ... but deleted resource will reappear after syching - ?_assertMatch({ok, a}, resource_discovery:get_resource(b)), - %% need to delete target resource type first, then delete resource from cache - ?_assertMatch(ok, resource_discovery:delete_target_resource_type(b)), - ?_assertMatch(ok,resource_discovery:delete_resource_tuple({b,a})), - ?_assertMatch([e, f], resource_discovery:get_resource_types()), - ?_assertMatch(ok, resource_discovery:trade_resources()), - %% now it should be gone - ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)) + %% add local and target resources + ?_assertMatch(ok, resource_discovery:add_local_resource_tuples(?RESOURCE_TUPLES)), + ?_assertMatch(ok, resource_discovery:add_target_resource_type(b)), + ?_assertMatch(ok, resource_discovery:sync_resources()), + %% check that target resource is avilable + ?_assertMatch([a], resource_discovery:get_resources(b)), + ?_assertMatch([b], resource_discovery:get_resource_types()), + %% delete local resource, the resource should dissapear from remote caches after sych + ?_assertMatch(ok, resource_discovery:delete_local_resource_tuple({b, a})), + %% try to remove non existing resource + ?_assertMatch({error, local_resource_not_found, {b, a1}}, resource_discovery:delete_local_resource_tuple({b, a1})), + ?_assertMatch(ok, resource_discovery:sync_resources()), + %% check that it is not avialable to network anymore + ?_assertMatch([], resource_discovery:get_resources(b)), + ?_assertMatch([], resource_discovery:get_resources(a)), + ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)), + %% check that resource types with no resources is gone + ?_assertMatch([], resource_discovery:get_resource_types()), + %% add new target resources in "I want" list + ?_assertMatch(ok, resource_discovery:add_target_resource_types([e, f, n])), + ?_assertMatch(ok, resource_discovery:sync_resources()), + ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e, e1}, {e, e2}, {e, e3}, {f, f1}])), + ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({f, f1})), + ?_assertMatch(ok, resource_discovery:trade_resources()), + ?_assertMatch([e, f], resource_discovery:get_resource_types()), + ?_assertEqual(2, resource_discovery:get_num_resource_types()), + ?_assertEqual(3, resource_discovery:get_num_resource(e)), + %% number of non-existing resource + ?_assertEqual(0, resource_discovery:get_num_resource(k)), + ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{b, a}])), + ?_assertMatch(ok, resource_discovery:sync_resources()), + ?_assertMatch([a], resource_discovery:get_resources(b)), + ?_assertMatch({ok, a}, resource_discovery:get_resource(b)), + ?_assertMatch([e1, e2, e3], resource_discovery:get_resources(e)), + %% delete resource + ?_assertMatch(ok, resource_discovery:delete_resource_tuple({b, a})), + %% shouldn't exist in local cache + ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)), + ?_assertMatch(ok, resource_discovery:trade_resources()), + %% ... but deleted resource will reappear after syching + ?_assertMatch({ok, a}, resource_discovery:get_resource(b)), + %% need to delete target resource type first, then delete resource from cache + ?_assertMatch(ok, resource_discovery:delete_target_resource_type(b)), + ?_assertMatch(ok, resource_discovery:delete_resource_tuple({b, a})), + ?_assertMatch([e, f], resource_discovery:get_resource_types()), + ?_assertMatch(ok, resource_discovery:trade_resources()), + %% now it should be gone + ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)) ]}. - %% test call notifications %% we setup a loop to hold a state, callback will fire up resource_up/1 func, which will set a state of %% a loop process, so we can verify this state in unit test. -record(state, {value = false}). rd_notification_test_() -> - {setup, - fun start_notify_loop/0, - fun(Pid) -> stop_notify_loop(Pid) end, - fun run_notify/1}. + {setup, + fun start_notify_loop/0, + fun(Pid) -> stop_notify_loop(Pid) end, + fun run_notify/1}. start_notify_loop() -> - resource_discovery:start(), - Pid = spawn(fun() -> loop(#state{}) end), - register(notify_loop_process, Pid), - Pid. - + resource_discovery:start(), + Pid = spawn(fun() -> loop(#state{}) end), + register(notify_loop_process, Pid), + Pid. + stop_notify_loop(Pid) -> - resource_discovery:stop(), - unregister(notify_loop_process), - Pid ! stop, - ok. + resource_discovery:stop(), + unregister(notify_loop_process), + Pid ! stop, + ok. run_notify(_Pid) -> - {inorder, + {inorder, [ - %% add callback module, local and target resources - ?_assertMatch(ok, resource_discovery:add_callback_module(?MODULE)), - ?_assertMatch(ok, resource_discovery:add_target_resource_types([e,f,n])), - ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e,e1}, {f, f1}])), - %% before synch, there is not notification - ?_assertEqual(false, get_state()), - ?_assertMatch(ok, resource_discovery:sync_resources()), - %% after synch, there should be a notification - ?_assertEqual(true, get_state()), - %% now remove the cached resource - ?_assertMatch(ok,resource_discovery:delete_resource_tuple({e,e1})), - %% verify that resource is gone - ?_assertMatch({error, not_found}, resource_discovery:get_resource(e)), - %% remove notification module and synch - ?_assertMatch(ok, resource_discovery:delete_callback_module(?MODULE)), - %% reset the state of loop process - ?_assertMatch(ok, set_state(false)), - ?_assertMatch(ok, resource_discovery:sync_resources()), - %% verify that notification wasn't sent - ?_assertEqual(false, get_state()), - %% verify that resource was still cached - ?_assertMatch({ok,e1}, resource_discovery:get_resource(e)) + %% add callback module, local and target resources + ?_assertMatch(ok, resource_discovery:add_callback_module(?MODULE)), + ?_assertMatch(ok, resource_discovery:add_target_resource_types([e, f, n])), + ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e, e1}, {f, f1}])), + %% before synch, there is not notification + ?_assertEqual(false, get_state()), + ?_assertMatch(ok, resource_discovery:sync_resources()), + %% after synch, there should be a notification + ?_assertEqual(true, get_state()), + %% now remove the cached resource + ?_assertMatch(ok, resource_discovery:delete_resource_tuple({e, e1})), + %% verify that resource is gone + ?_assertMatch({error, not_found}, resource_discovery:get_resource(e)), + %% remove notification module and synch + ?_assertMatch(ok, resource_discovery:delete_callback_module(?MODULE)), + %% reset the state of loop process + ?_assertMatch(ok, set_state(false)), + ?_assertMatch(ok, resource_discovery:sync_resources()), + %% verify that notification wasn't sent + ?_assertEqual(false, get_state()), + %% verify that resource was still cached + ?_assertMatch({ok, e1}, resource_discovery:get_resource(e)) ]}. %% function which is called when event happens %% for test we only care when resource 'e' becomes available resource_up({e, R}) -> - error_logger:info_msg("resource is up ~p: ~p", [e, R]), - %% callback happend, set state in loop process, so it could be verified in test - set_state(true); + error_logger:info_msg("resource is up ~p: ~p", [e, R]), + %% callback happend, set state in loop process, so it could be verified in test + set_state(true); resource_up(Other) -> - error_logger:info_msg("resource is up, dont' care: ~p", [Other]). + error_logger:info_msg("resource is up, dont' care: ~p", [Other]). get_state() -> - notify_loop_process ! {self(), get}, - receive - Value -> Value - end. - + notify_loop_process ! {self(), get}, + receive + Value -> Value + end. + set_state(Value) -> - notify_loop_process ! {self(), {set, Value}}, - ok. + notify_loop_process ! {self(), {set, Value}}, + ok. loop(State) -> - receive - {_From, {set, Value}} -> - loop(State#state{value = Value}); - {From, get} -> - From ! State#state.value, - %% reset state back in initial state - loop(State#state{value=false}); - stop -> void - end. - + receive + {_From, {set, Value}} -> + loop(State#state{value = Value}); + {From, get} -> + From ! State#state.value, + %% reset state back in initial state + loop(State#state{value = false}); + stop -> void + end. + %% rpc_call test rd_rpc_call_test_() -> - {setup, - fun start_adder_loop/0, - fun stop_adder_loop/1, - fun rpc_run/1}. + {setup, + fun start_adder_loop/0, + fun stop_adder_loop/1, + fun rpc_run/1}. start_adder_loop() -> - resource_discovery:start(). - + resource_discovery:start(). + stop_adder_loop(_P) -> - resource_discovery:stop(). + resource_discovery:stop(). %% test function to be called by rpc call test_adder(A, B) when is_integer(A), is_integer(B) -> - A + B. + A + B. rpc_run(_Pid) -> - Node = node(), - {inorder, + Node = node(), + {inorder, [ - %% add local and target resources - ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, Node})), - ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, 'not_existing@nohost'})), - ?_assertMatch(ok, resource_discovery:add_target_resource_type(node)), - ?_assertMatch(ok, resource_discovery:sync_resources()), - %% add bad node as resource - ?_assertMatch(['not_existing@nohost', Node], resource_discovery:get_resources(node)), - ?_assertMatch(5, resource_discovery:rpc_call(node, ?MODULE, test_adder, [1,4])), - %% bad resource should be deleted now, we should only get live node - ?_assertMatch({ok, Node}, resource_discovery:get_resource(node)), - %% try using unknown_resource - ?_assertMatch({error, not_found}, resource_discovery:rpc_call(unknown_resource, ?MODULE, test_adder, [1,4])), - %% synch up so bad node is loaded again - ?_assertMatch(ok, resource_discovery:sync_resources()), - %% run multicall - ?_assertMatch({[300],[not_existing@nohost]}, resource_discovery:rpc_multicall(node, ?MODULE, test_adder, [100,200])), - ?_assertMatch({error, no_resources}, resource_discovery:rpc_multicall(unknown_resource, ?MODULE, test_adder, [400,200])) + %% add local and target resources + ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, Node})), + ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, 'not_existing@nohost'})), + ?_assertMatch(ok, resource_discovery:add_target_resource_type(node)), + ?_assertMatch(ok, resource_discovery:sync_resources()), + %% add bad node as resource + ?_assertMatch(['not_existing@nohost', Node], resource_discovery:get_resources(node)), + ?_assertMatch(5, resource_discovery:rpc_call(node, ?MODULE, test_adder, [1, 4])), + %% bad resource should be deleted now, we should only get live node + ?_assertMatch({ok, Node}, resource_discovery:get_resource(node)), + %% try using unknown_resource + ?_assertMatch({error, not_found}, resource_discovery:rpc_call(unknown_resource, ?MODULE, test_adder, [1, 4])), + %% synch up so bad node is loaded again + ?_assertMatch(ok, resource_discovery:sync_resources()), + %% run multicall + ?_assertMatch({[300], [not_existing@nohost]}, resource_discovery:rpc_multicall(node, ?MODULE, test_adder, [100, 200])), + ?_assertMatch({error, no_resources}, resource_discovery:rpc_multicall(unknown_resource, ?MODULE, test_adder, [400, 200])) ]}. From e4c3e7ca97c1b8831a56e525d96eef23e59f6621 Mon Sep 17 00:00:00 2001 From: wangrui <276361270@qq.com> Date: Fri, 17 Mar 2017 16:01:45 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rebar.config | 2 +- src/rd_core.erl | 278 ++++++++++++++-------------- src/rd_heartbeat.erl | 34 ++-- src/rd_store.erl | 228 +++++++++++------------ src/rd_sup.erl | 50 ++--- src/rd_util.erl | 108 +++++------ src/resource_discovery.app.src | 64 +++---- src/resource_discovery.erl | 294 +++++++++++++++--------------- src/sys.config | 14 +- test/rd_store_tests.erl | 116 ++++++------ test/resource_discovery_tests.erl | 281 ++++++++++++++-------------- 11 files changed, 735 insertions(+), 734 deletions(-) diff --git a/rebar.config b/rebar.config index f5494c8..5c2d31c 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ -{lib_dirs, ["deps"]}. +{lib_dirs,["deps"]}. {src_dirs, ["src", "test"]}. {excl_archive_filters, [".*"]}. {cover_enabled, true}. diff --git a/src/rd_core.erl b/src/rd_core.erl index 881e92d..3b7d9ef 100644 --- a/src/rd_core.erl +++ b/src/rd_core.erl @@ -1,5 +1,5 @@ %%%------------------------------------------------------------------- -%%% @author Martin Logan +%%% @author Martin Logan %%% @copyright 2008 Erlware %%% @doc %%% Cache and distribute resources. @@ -11,44 +11,44 @@ %% API -export([ - start_link/0, - sync_resources/2, - trade_resources/0, - filter_resource_tuples_by_types/2, - make_callbacks/1 -]). + start_link/0, + sync_resources/2, + trade_resources/0, + filter_resource_tuples_by_types/2, + make_callbacks/1 + ]). % Fetch -export([ - round_robin_get/1, - all_of_type_get/1, - get_resource_types/0, - get_num_resource_types/0, - get_num_resource/1, - get_local_resource_tuples/0, - get_target_resource_types/0, - get_deleted_resource_tuples/0 -]). + round_robin_get/1, + all_of_type_get/1, + get_resource_types/0, + get_num_resource_types/0, + get_num_resource/1, + get_local_resource_tuples/0, + get_target_resource_types/0, + get_deleted_resource_tuples/0 + ]). % Store -export([ - store_local_resource_tuples/1, - store_callback_modules/1, - store_target_resource_types/1, - store_resource_tuples/1 -]). + store_local_resource_tuples/1, + store_callback_modules/1, + store_target_resource_types/1, + store_resource_tuples/1 + ]). % Delete -export([ - delete_local_resource_tuple/1, - delete_target_resource_type/1, - delete_callback_module/1, - delete_resource_tuple/1 -]). + delete_local_resource_tuple/1, + delete_target_resource_type/1, + delete_callback_module/1, + delete_resource_tuple/1 + ]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + terminate/2, code_change/3]). -include("../include/resource_discovery.hrl"). @@ -68,7 +68,7 @@ %% @end %%-------------------------------------------------------------------- start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %%-------------------------------------------------------------------- %% @doc call each subscribed callback function for each new @@ -77,13 +77,13 @@ start_link() -> %%-------------------------------------------------------------------- -spec make_callbacks([resource_tuple()]) -> ok. make_callbacks(NewResources) -> - lists:foreach( - fun(Module) -> - lists:foreach(fun(Resource) -> - spawn(fun() -> Module:resource_up(Resource) end) end, - NewResources) - end, - rd_store:get_callback_modules()). + lists:foreach( + fun(Module) -> + lists:foreach(fun(Resource) -> + spawn(fun() -> Module:resource_up(Resource) end) end, + NewResources) + end, + rd_store:get_callback_modules()). %%-------------------------------------------------------------------- %% @doc return a list of resources that have a resource_type() found in the target @@ -92,14 +92,14 @@ make_callbacks(NewResources) -> %%-------------------------------------------------------------------- -spec filter_resource_tuples_by_types([resource_type()], [resource_tuple()]) -> [resource_tuple()]. filter_resource_tuples_by_types(TargetTypes, Resources) -> - Fun = - fun({Type, _Instance} = Resource, Acc) -> - case lists:member(Type, TargetTypes) of - true -> [Resource | Acc]; - false -> Acc - end - end, - lists:foldl(Fun, [], Resources). + Fun = + fun({Type, _Instance} = Resource, Acc) -> + case lists:member(Type, TargetTypes) of + true -> [Resource|Acc]; + false -> Acc + end + end, + lists:foldl(Fun, [], Resources). %%----------------------------------------------------------------------- @@ -107,8 +107,8 @@ filter_resource_tuples_by_types(TargetTypes, Resources) -> %% @end %%----------------------------------------------------------------------- -spec store_callback_modules([atom()]) -> no_return(). -store_callback_modules([H | _] = Modules) when is_atom(H) -> - gen_server:call(?SERVER, {store_callback_modules, Modules}). +store_callback_modules([H|_] = Modules) when is_atom(H) -> + gen_server:call(?SERVER, {store_callback_modules, Modules}). %%----------------------------------------------------------------------- %% @doc Store the target types for the local system. Store an "I Want" @@ -116,21 +116,21 @@ store_callback_modules([H | _] = Modules) when is_atom(H) -> %% @end %%----------------------------------------------------------------------- -spec store_target_resource_types([atom()]) -> no_return(). -store_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> - gen_server:call(?SERVER, {store_target_resource_types, TargetTypes}). +store_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> + gen_server:call(?SERVER, {store_target_resource_types, TargetTypes}). %%----------------------------------------------------------------------- %% @doc Store the "I haves" or local_resources for resource discovery. %% @end %%----------------------------------------------------------------------- -spec store_local_resource_tuples([resource_tuple()]) -> ok. -store_local_resource_tuples([{_, _} | _] = LocalResourceTuples) -> - gen_server:call(?SERVER, {store_local_resource_tuples, LocalResourceTuples}). +store_local_resource_tuples([{_,_}|_] = LocalResourceTuples) -> + gen_server:call(?SERVER, {store_local_resource_tuples, LocalResourceTuples}). -spec store_resource_tuples([resource_tuple()]) -> ok. store_resource_tuples(Resource) -> - gen_server:call(?SERVER, {store_resource_tuples, Resource}). + gen_server:call(?SERVER, {store_resource_tuples, Resource}). %%----------------------------------------------------------------------- %% @doc Remove a callback module. @@ -138,7 +138,7 @@ store_resource_tuples(Resource) -> %%----------------------------------------------------------------------- -spec delete_callback_module(atom()) -> true. delete_callback_module(CallBackModule) -> - gen_server:call(?SERVER, {delete_callback_module, CallBackModule}). + gen_server:call(?SERVER, {delete_callback_module, CallBackModule}). %%----------------------------------------------------------------------- %% @doc Remove a target type. @@ -146,7 +146,7 @@ delete_callback_module(CallBackModule) -> %%----------------------------------------------------------------------- -spec delete_target_resource_type(atom()) -> true. delete_target_resource_type(TargetType) -> - gen_server:call(?SERVER, {delete_target_resource_type, TargetType}). + gen_server:call(?SERVER, {delete_target_resource_type, TargetType}). %%----------------------------------------------------------------------- %% @doc Remove a local resource. @@ -154,15 +154,15 @@ delete_target_resource_type(TargetType) -> %%----------------------------------------------------------------------- -spec delete_local_resource_tuple(resource_tuple()) -> ok | {error, local_resource_not_found, resource_tuple()}. delete_local_resource_tuple(LocalResourceTuple) -> - gen_server:call(?SERVER, {delete_local_resource_tuple, LocalResourceTuple}). + gen_server:call(?SERVER, {delete_local_resource_tuple, LocalResourceTuple}). %%----------------------------------------------------------------------- %% @doc Remove a resource. %% @end %%----------------------------------------------------------------------- -spec delete_resource_tuple(resource_tuple()) -> ok. -delete_resource_tuple({_, _} = ResourceTuple) -> - gen_server:call(?SERVER, {delete_resource_tuple, ResourceTuple}). +delete_resource_tuple({_,_} = ResourceTuple) -> + gen_server:call(?SERVER, {delete_resource_tuple, ResourceTuple}). %%-------------------------------------------------------------------- %% @doc inform an rd_core server of local resources and target types. @@ -172,7 +172,7 @@ delete_resource_tuple({_, _} = ResourceTuple) -> %%-------------------------------------------------------------------- -spec trade_resources() -> ok. trade_resources() -> - gen_server:cast(?SERVER, trade_resources). + gen_server:cast(?SERVER, trade_resources). %%----------------------------------------------------------------------- %% @doc @@ -181,7 +181,7 @@ trade_resources() -> %%----------------------------------------------------------------------- -spec round_robin_get(resource_type()) -> {ok, resource()} | {error, not_found}. round_robin_get(Type) -> - gen_server:call(?SERVER, {round_robin_get, Type}). + gen_server:call(?SERVER, {round_robin_get, Type}). %%-------------------------------------------------------------------- %% @doc @@ -190,7 +190,7 @@ round_robin_get(Type) -> %%-------------------------------------------------------------------- -spec all_of_type_get(resource_type()) -> [resource()]. all_of_type_get(Type) -> - gen_server:call(?SERVER, {all_of_type_get, Type}). + gen_server:call(?SERVER, {all_of_type_get, Type}). %%----------------------------------------------------------------------- %% @doc Gets resource of a particular type outputs and places it in last position. @@ -198,11 +198,11 @@ all_of_type_get(Type) -> %%----------------------------------------------------------------------- %%-spec sync_resources(node(), {LocalResourceTuples, TargetTypes, DeletedTuples}) -> ok. sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}) -> - error_logger:info_msg("synch resources for node: ~p", [Node]), - {ok, FilteredRemotes} = gen_server:call({?SERVER, Node}, {sync_resources, {LocalResourceTuples, TargetTypes, DeletedTuples}}), - rd_store:store_resource_tuples(FilteredRemotes), - make_callbacks(FilteredRemotes), - ok. + %error_logger:info_msg("synch resources for node: ~p", [Node]), + {ok, FilteredRemotes} = gen_server:call({?SERVER, Node}, {sync_resources, {LocalResourceTuples, TargetTypes, DeletedTuples}}), + rd_store:store_resource_tuples(FilteredRemotes), + make_callbacks(FilteredRemotes), + ok. %%-------------------------------------------------------------------- %% @doc @@ -211,7 +211,7 @@ sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}) -> %%-------------------------------------------------------------------- -spec get_resource_types() -> [resource_type()]. get_resource_types() -> - gen_server:call(?SERVER, get_resource_types). + gen_server:call(?SERVER, get_resource_types). %%------------------------------------------------------------------------------ %% @doc Gets the number of resource types locally cached. @@ -219,7 +219,7 @@ get_resource_types() -> %%------------------------------------------------------------------------------ -spec get_num_resource_types() -> integer(). get_num_resource_types() -> - gen_server:call(?SERVER, get_num_resource_types). + gen_server:call(?SERVER, get_num_resource_types). %%-------------------------------------------------------------------- %% @doc @@ -228,15 +228,15 @@ get_num_resource_types() -> %%-------------------------------------------------------------------- -spec get_num_resource(resource_type()) -> integer(). get_num_resource(Type) -> - gen_server:call(?SERVER, {get_num_resource, Type}). + gen_server:call(?SERVER, {get_num_resource, Type}). -spec get_local_resource_tuples() -> [resource_tuple()]. get_local_resource_tuples() -> - gen_server:call(?SERVER, get_local_resource_tuples). + gen_server:call(?SERVER, get_local_resource_tuples). -spec get_target_resource_types() -> [atom()]. get_target_resource_types() -> - gen_server:call(?SERVER, get_target_resource_types). + gen_server:call(?SERVER, get_target_resource_types). %%-------------------------------------------------------------------- %% @doc @@ -245,7 +245,7 @@ get_target_resource_types() -> %%-------------------------------------------------------------------- -spec get_deleted_resource_tuples() -> [resource_tuple()]. get_deleted_resource_tuples() -> - gen_server:call(?SERVER, get_deleted_resource_tuples). + gen_server:call(?SERVER, get_deleted_resource_tuples). %%%=================================================================== @@ -253,101 +253,101 @@ get_deleted_resource_tuples() -> %%%=================================================================== init([]) -> - {ok, #state{}}. + {ok, #state{}}. handle_call({sync_resources, {Remotes, RemoteTargetTypes, RemoteDeletedTuples}}, _From, State) -> - error_logger:info_msg("sync_resources, got remotes: ~p deleted: ~p", [Remotes, RemoteDeletedTuples]), - LocalResourceTuples = rd_store:get_local_resource_tuples(), - TargetTypes = rd_store:get_target_resource_types(), - FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), - FilteredLocals = filter_resource_tuples_by_types(RemoteTargetTypes, LocalResourceTuples), - error_logger:info_msg("sync_resources, storing filted remotes: ~p", [FilteredRemotes]), - rd_store:store_resource_tuples(FilteredRemotes), - [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], - make_callbacks(FilteredRemotes), - {reply, {ok, FilteredLocals}, State}; + %error_logger:info_msg("sync_resources, got remotes: ~p deleted: ~p", [Remotes, RemoteDeletedTuples]), + LocalResourceTuples = rd_store:get_local_resource_tuples(), + TargetTypes = rd_store:get_target_resource_types(), + FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), + FilteredLocals = filter_resource_tuples_by_types(RemoteTargetTypes, LocalResourceTuples), + %error_logger:info_msg("sync_resources, storing filted remotes: ~p", [FilteredRemotes]), + rd_store:store_resource_tuples(FilteredRemotes), + [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], + make_callbacks(FilteredRemotes), + {reply, {ok, FilteredLocals}, State}; handle_call({round_robin_get, Type}, _From, State) -> - Reply = rd_store:round_robin_get(Type), - {reply, Reply, State}; + Reply = rd_store:round_robin_get(Type), + {reply, Reply, State}; handle_call({all_of_type_get, Type}, _From, State) -> - Reply = rd_store:get_resources(Type), - {reply, Reply, State}; + Reply = rd_store:get_resources(Type), + {reply, Reply, State}; handle_call({store_callback_modules, Modules}, _From, State) -> - rd_store:store_callback_modules(Modules), - {reply, ok, State}; + rd_store:store_callback_modules(Modules), + {reply, ok, State}; handle_call({store_target_resource_types, TargetTypes}, _From, State) -> - Reply = rd_store:store_target_resource_types(TargetTypes), - {reply, Reply, State}; + Reply = rd_store:store_target_resource_types(TargetTypes), + {reply, Reply, State}; handle_call({store_local_resource_tuples, LocalResourceTuples}, _From, State) -> - Reply = rd_store:store_local_resource_tuples(LocalResourceTuples), - {reply, Reply, State}; + Reply = rd_store:store_local_resource_tuples(LocalResourceTuples), + {reply, Reply, State}; handle_call({store_resource_tuples, Resource}, _From, State) -> - Reply = rd_store:store_resource_tuples(Resource), - {reply, Reply, State}; + Reply = rd_store:store_resource_tuples(Resource), + {reply, Reply, State}; handle_call({delete_callback_module, Module}, _From, State) -> - rd_store:delete_callback_module(Module), - {reply, ok, State}; + rd_store:delete_callback_module(Module), + {reply, ok, State}; handle_call({delete_target_resource_type, TargetType}, _From, State) -> - Reply = rd_store:delete_target_resource_type(TargetType), - {reply, Reply, State}; + Reply = rd_store:delete_target_resource_type(TargetType), + {reply, Reply, State}; handle_call({delete_local_resource_tuple, LocalResourceTuple}, _From, State) -> - Reply = rd_store:delete_local_resource_tuple(LocalResourceTuple), - {reply, Reply, State}; + Reply = rd_store:delete_local_resource_tuple(LocalResourceTuple), + {reply, Reply, State}; handle_call({delete_resource_tuple, ResourceTuple}, _From, State) -> - Reply = rd_store:delete_resource_tuple(ResourceTuple), - {reply, Reply, State}; + Reply = rd_store:delete_resource_tuple(ResourceTuple), + {reply, Reply, State}; handle_call(get_resource_types, _From, State) -> - Reply = rd_store:get_resource_types(), - {reply, Reply, State}; + Reply = rd_store:get_resource_types(), + {reply, Reply, State}; handle_call(get_local_resource_tuples, _From, State) -> - Reply = rd_store:get_local_resource_tuples(), - {reply, Reply, State}; + Reply = rd_store:get_local_resource_tuples(), + {reply, Reply, State}; handle_call(get_target_resource_types, _From, State) -> - Reply = rd_store:get_target_resource_types(), - {reply, Reply, State}; + Reply = rd_store:get_target_resource_types(), + {reply, Reply, State}; handle_call(get_deleted_resource_tuples, _From, State) -> - Reply = rd_store:get_deleted_resource_tuples(), - {reply, Reply, State}; + Reply = rd_store:get_deleted_resource_tuples(), + {reply, Reply, State}; handle_call(get_num_resource_types, _From, State) -> - Reply = rd_store:get_num_resource_types(), - {reply, Reply, State}; + Reply = rd_store:get_num_resource_types(), + {reply, Reply, State}; handle_call({get_num_resource, Type}, _From, State) -> - Reply = rd_store:get_num_resource(Type), - {reply, Reply, State}. + Reply = rd_store:get_num_resource(Type), + {reply, Reply, State}. handle_cast(trade_resources, State) -> - ResourceTuples = rd_store:get_local_resource_tuples(), - DeletedTuples = rd_store:get_deleted_resource_tuples(), - lists:foreach( - fun(Node) -> - gen_server:cast({?SERVER, Node}, - {trade_resources, {node(), {ResourceTuples, DeletedTuples}}}) - end, - nodes(known)), - rd_store:delete_deleted_resource_tuple(), - {noreply, State}; + ResourceTuples = rd_store:get_local_resource_tuples(), + DeletedTuples = rd_store:get_deleted_resource_tuples(), + lists:foreach( + fun(Node) -> + gen_server:cast({?SERVER, Node}, + {trade_resources, {node(), {ResourceTuples, DeletedTuples}}}) + end, + nodes(known)), + rd_store:delete_deleted_resource_tuple(), + {noreply, State}; handle_cast({trade_resources, {ReplyTo, {Remotes, RemoteDeletedTuples}}}, State) -> - error_logger:info_msg("trade_resources, got remotes ~p: deleted: ~p", [Remotes, RemoteDeletedTuples]), - Locals = rd_store:get_local_resource_tuples(), - LocalsDeleted = rd_store:get_deleted_resource_tuples(), - TargetTypes = rd_store:get_target_resource_types(), - FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), - error_logger:info_msg("got remotes and filtered ~p", [FilteredRemotes]), - rd_store:store_resource_tuples(FilteredRemotes), - error_logger:info_msg("trade_resources, deleting ~p", [RemoteDeletedTuples]), - [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], - make_callbacks(FilteredRemotes), - reply(ReplyTo, {Locals, LocalsDeleted}), - {noreply, State}. + %error_logger:info_msg("trade_resources, got remotes ~p: deleted: ~p", [Remotes, RemoteDeletedTuples]), + Locals = rd_store:get_local_resource_tuples(), + LocalsDeleted = rd_store:get_deleted_resource_tuples(), + TargetTypes = rd_store:get_target_resource_types(), + FilteredRemotes = filter_resource_tuples_by_types(TargetTypes, Remotes), + %error_logger:info_msg("got remotes and filtered ~p", [FilteredRemotes]), + rd_store:store_resource_tuples(FilteredRemotes), + %error_logger:info_msg("trade_resources, deleting ~p", [RemoteDeletedTuples]), + [rd_store:delete_resource_tuple(DR) || DR <- RemoteDeletedTuples], + make_callbacks(FilteredRemotes), + reply(ReplyTo, {Locals, LocalsDeleted}), + {noreply, State}. handle_info(_Info, State) -> - {noreply, State}. + {noreply, State}. terminate(_Reason, _State) -> - ok. + ok. code_change(_OldVsn, State, _Extra) -> - {ok, State}. + {ok, State}. %%%=================================================================== %%% Internal functions @@ -356,5 +356,5 @@ code_change(_OldVsn, State, _Extra) -> reply(noreply, {_LocalResources, _LocalsDeleted}) -> ok; reply(_ReplyTo, {[], []}) -> ok; -reply(ReplyTo, {LocalResources, LocalsDeleted}) -> - gen_server:cast({?SERVER, ReplyTo}, {trade_resources, {noreply, {LocalResources, LocalsDeleted}}}). +reply(ReplyTo, {LocalResources,LocalsDeleted}) -> + gen_server:cast({?SERVER, ReplyTo}, {trade_resources, {noreply, {LocalResources, LocalsDeleted}}}). diff --git a/src/rd_heartbeat.erl b/src/rd_heartbeat.erl index 95abc97..77c9445 100644 --- a/src/rd_heartbeat.erl +++ b/src/rd_heartbeat.erl @@ -9,7 +9,7 @@ -behaviour(gen_server). %% External exports --export([start_link/1, start_link/0]). +-export([ start_link/1, start_link/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -32,13 +32,13 @@ %%-------------------------------------------------------------------- -spec start_link(non_neg_integer()) -> {ok, pid()}. start_link(Frequency) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [Frequency], []). + gen_server:start_link({local, ?SERVER}, ?MODULE, [Frequency], []). %% @equiv start_link(0) start_link() -> - %% The default value is 0 which indicates no heartbeating. - {ok, Frequency} = rd_util:get_env(heartbeat_frequency, 60000), - start_link(Frequency). + %% The default value is 0 which indicates no heartbeating. + {ok,Frequency} = rd_util:get_env(heartbeat_frequency, 60000), + start_link(Frequency). %%==================================================================== %% Server functions @@ -53,8 +53,8 @@ start_link() -> %% {stop, Reason} %%-------------------------------------------------------------------- init([Frequency]) -> - ok = resource_discovery:contact_nodes(), - {ok, #state{frequency = Frequency}, Frequency}. + ok = resource_discovery:contact_nodes(), + {ok, #state{frequency = Frequency}, Frequency}. %%-------------------------------------------------------------------- %% Function: handle_call/3 @@ -67,7 +67,7 @@ init([Frequency]) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_call(_Request, _From, State) -> - {reply, ok, State}. + {reply, ok, State}. %%-------------------------------------------------------------------- %% Function: handle_cast/2 @@ -77,7 +77,7 @@ handle_call(_Request, _From, State) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_cast(_Msg, State) -> - {noreply, State}. + {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info/2 @@ -87,12 +87,12 @@ handle_cast(_Msg, State) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_info(timeout, State = #state{frequency = 0}) -> - {stop, normal, State}; + {stop, normal, State}; handle_info(timeout, State = #state{frequency = Frequency}) -> - resource_discovery:contact_nodes(), - resource_discovery:trade_resources(), - %% Wait for approximately the frequency with a random factor. - {noreply, State, random:uniform(Frequency div 2) + (Frequency div 2) + Frequency div 3}. + resource_discovery:contact_nodes(), + resource_discovery:trade_resources(), + %% Wait for approximately the frequency with a random factor. + {noreply, State, random:uniform(Frequency div 2) + (Frequency div 2) + Frequency div 3}. %%-------------------------------------------------------------------- %% Function: terminate/2 @@ -100,8 +100,8 @@ handle_info(timeout, State = #state{frequency = Frequency}) -> %% Returns: any (ignored by gen_server) %%-------------------------------------------------------------------- terminate(Reason, _State) -> - error_logger:info_msg("stoppping resource discovery hearbeat ~p", [Reason]), - ok. + error_logger:info_msg("stoppping resource discovery hearbeat ~p", [Reason]), + ok. %%-------------------------------------------------------------------- %% Func: code_change/3 @@ -109,5 +109,5 @@ terminate(Reason, _State) -> %% Returns: {ok, NewState} %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> - {ok, State}. + {ok, State}. diff --git a/src/rd_store.erl b/src/rd_store.erl index a34246f..763ebc2 100644 --- a/src/rd_store.erl +++ b/src/rd_store.erl @@ -17,40 +17,40 @@ % Create -export([ - new/0, - delete/0 -]). + new/0, + delete/0 + ]). % Lookup -export([ - round_robin_get/1, - get_resources/1, - get_callback_modules/0, - get_local_resource_tuples/0, - get_deleted_resource_tuples/0, - get_target_resource_types/0, - get_num_resource_types/0, - get_num_resource/1, - get_resource_types/0 -]). + round_robin_get/1, + get_resources/1, + get_callback_modules/0, + get_local_resource_tuples/0, + get_deleted_resource_tuples/0, + get_target_resource_types/0, + get_num_resource_types/0, + get_num_resource/1, + get_resource_types/0 + ]). % Delete -export([ - delete_local_resource_tuple/1, - delete_target_resource_type/1, - delete_callback_module/1, - delete_resource_tuple/1, - delete_deleted_resource_tuple/0 -]). + delete_local_resource_tuple/1, + delete_target_resource_type/1, + delete_callback_module/1, + delete_resource_tuple/1, + delete_deleted_resource_tuple/0 + ]). % Store -export([ - store_local_resource_tuples/1, - store_callback_modules/1, - store_target_resource_types/1, - store_resource_tuples/1, - store_resource_tuple/1 -]). + store_local_resource_tuples/1, + store_callback_modules/1, + store_target_resource_types/1, + store_resource_tuples/1, + store_resource_tuple/1 + ]). %%-------------------------------------------------------------------- %% Macros @@ -75,10 +75,10 @@ %%----------------------------------------------------------------------- -spec new() -> ok. new() -> - ets:new(?RS, [named_table, public]), - ets:new(?LKVStore, [named_table, public]), - ok. - + ets:new(?RS, [named_table, public]), + ets:new(?LKVStore, [named_table, public]), + ok. + %%-------------------------------------------------------------------- %% @doc %% Deletes storage @@ -86,29 +86,29 @@ new() -> %%-------------------------------------------------------------------- -spec delete() -> ok. delete() -> - ets:delete(?RS), - ets:delete(?LKVStore), - ok. + ets:delete(?RS), + ets:delete(?LKVStore), + ok. %%----------------------------------------------------------------------- %% @doc Store the callback modules for the local system. %% @end %%----------------------------------------------------------------------- -spec store_callback_modules([atom()]) -> ok. -store_callback_modules([H | _] = Modules) when is_atom(H) -> - ets:insert(?LKVStore, {callback_modules, lists:usort(get_callback_modules() ++ Modules)}), - ok. - +store_callback_modules([H|_] = Modules) when is_atom(H) -> + ets:insert(?LKVStore, {callback_modules, lists:usort(get_callback_modules() ++ Modules)}), + ok. + %%----------------------------------------------------------------------- %% @doc Output the callback modules. %% @end %%----------------------------------------------------------------------- -spec get_callback_modules() -> [atom()]. get_callback_modules() -> - case ets:lookup(?LKVStore, callback_modules) of - [{callback_modules, CallBackModules}] -> CallBackModules; - [] -> [] - end. + case ets:lookup(?LKVStore, callback_modules) of + [{callback_modules, CallBackModules}] -> CallBackModules; + [] -> [] + end. %%----------------------------------------------------------------------- %% @doc Remove a callback module. @@ -116,9 +116,9 @@ get_callback_modules() -> %%----------------------------------------------------------------------- -spec delete_callback_module(atom()) -> ok. delete_callback_module(CallBackModule) -> - NewCallBackModules = lists:delete(CallBackModule, get_callback_modules()), - ets:insert(?LKVStore, {callback_modules, NewCallBackModules}), - ok. + NewCallBackModules = lists:delete(CallBackModule, get_callback_modules()), + ets:insert(?LKVStore, {callback_modules, NewCallBackModules}), + ok. %%----------------------------------------------------------------------- %% @doc Store the target types for the local system. Store an "I Want" @@ -126,10 +126,10 @@ delete_callback_module(CallBackModule) -> %% @end %%----------------------------------------------------------------------- -spec store_target_resource_types([atom()]) -> ok. -store_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> - ets:insert(?LKVStore, {target_types, lists:usort(get_target_resource_types() ++ TargetTypes)}), - ok. - +store_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> + ets:insert(?LKVStore, {target_types, lists:usort(get_target_resource_types() ++ TargetTypes)}), + ok. + %%----------------------------------------------------------------------- %% @doc Output the target types. These are the resource types we wish %% to find within our node cluster. @@ -137,10 +137,10 @@ store_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> %%----------------------------------------------------------------------- -spec get_target_resource_types() -> [atom()]. get_target_resource_types() -> - case ets:lookup(?LKVStore, target_types) of - [{target_types, TargetTypes}] -> lists:usort(TargetTypes); - [] -> [] - end. + case ets:lookup(?LKVStore, target_types) of + [{target_types, TargetTypes}] -> lists:usort(TargetTypes); + [] -> [] + end. %%----------------------------------------------------------------------- %% @doc Remove a target type. @@ -148,28 +148,28 @@ get_target_resource_types() -> %%----------------------------------------------------------------------- -spec delete_target_resource_type(atom()) -> ok. delete_target_resource_type(TargetType) -> - ets:insert(?LKVStore, {target_types, lists:delete(TargetType, get_target_resource_types())}), - ok. - + ets:insert(?LKVStore, {target_types, lists:delete(TargetType, get_target_resource_types())}), + ok. + %%----------------------------------------------------------------------- %% @doc Store the "I haves" or local_resources for resource discovery. %% @end %%----------------------------------------------------------------------- -spec store_local_resource_tuples([resource_tuple()]) -> ok. -store_local_resource_tuples([{_, _} | _] = LocalResourceTuples) -> - ets:insert(?LKVStore, {local_resources, lists:usort(get_local_resource_tuples() ++ LocalResourceTuples)}), - ok. - +store_local_resource_tuples([{_,_}|_] = LocalResourceTuples) -> + ets:insert(?LKVStore, {local_resources, lists:usort(get_local_resource_tuples() ++ LocalResourceTuples)}), + ok. + %%----------------------------------------------------------------------- %% @doc Output the local resources. %% @end %%----------------------------------------------------------------------- -spec get_local_resource_tuples() -> [resource_tuple()]. get_local_resource_tuples() -> - case ets:lookup(?LKVStore, local_resources) of - [{local_resources, LocalResources}] -> LocalResources; - [] -> [] - end. + case ets:lookup(?LKVStore, local_resources) of + [{local_resources, LocalResources}] -> LocalResources; + [] -> [] + end. %%-------------------------------------------------------------------- @@ -179,11 +179,11 @@ get_local_resource_tuples() -> %%-------------------------------------------------------------------- -spec get_deleted_resource_tuples() -> [resource_tuple()]. get_deleted_resource_tuples() -> - case ets:lookup(?LKVStore, deleted_resources) of - [{deleted_resources, DeletedResources}] -> DeletedResources; - [] -> [] - end. - + case ets:lookup(?LKVStore, deleted_resources) of + [{deleted_resources, DeletedResources}] -> DeletedResources; + [] -> [] + end. + %%----------------------------------------------------------------------- %% @doc Remove a local resource. @@ -191,19 +191,19 @@ get_deleted_resource_tuples() -> %%----------------------------------------------------------------------- -spec delete_local_resource_tuple(resource_tuple()) -> ok | {error, local_resource_not_found, resource_tuple()}. delete_local_resource_tuple(LocalResource) -> - %% first get local resource tuples - LocalResources = get_local_resource_tuples(), - %% only add to deleted cache if resource actually exist - case lists:member(LocalResource, LocalResources) of - true -> - %% store resource to be deleted in delete_cache table, so it could be removed from remote nodes resource cache - %% after syching - ets:insert(?LKVStore, {deleted_resources, lists:usort(get_deleted_resource_tuples() ++ [LocalResource])}), - %% now remove resource - ets:insert(?LKVStore, {local_resources, lists:delete(LocalResource, LocalResources)}), - ok; - false -> {error, local_resource_not_found, LocalResource} - end. + %% first get local resource tuples + LocalResources = get_local_resource_tuples(), + %% only add to deleted cache if resource actually exist + case lists:member(LocalResource, LocalResources) of + true -> + %% store resource to be deleted in delete_cache table, so it could be removed from remote nodes resource cache + %% after syching + ets:insert(?LKVStore, {deleted_resources, lists:usort(get_deleted_resource_tuples() ++ [LocalResource])}), + %% now remove resource + ets:insert(?LKVStore, {local_resources, lists:delete(LocalResource, LocalResources)}), + ok; + false -> {error, local_resource_not_found, LocalResource} + end. %%%--------------------------- %%% Network Resource Storage @@ -215,10 +215,10 @@ delete_local_resource_tuple(LocalResource) -> %%----------------------------------------------------------------------- -spec get_resources(resource_type()) -> [resource()]. get_resources(Type) -> - case ets:lookup(?RS, Type) of - [{Type, Resources}] -> Resources; - [] -> [] - end. + case ets:lookup(?RS, Type) of + [{Type, Resources}] -> Resources; + [] -> [] + end. %%----------------------------------------------------------------------- %% @doc Adds a new resource. @@ -226,15 +226,15 @@ get_resources(Type) -> %%----------------------------------------------------------------------- -spec store_resource_tuple(resource_tuple()) -> ok. store_resource_tuple({Type, Resource}) when is_atom(Type) -> - ets:insert(?RS, {Type, lists:usort(get_resources(Type) ++ [Resource])}), - ok. + ets:insert(?RS, {Type, lists:usort(get_resources(Type) ++ [Resource])}), + ok. -spec store_resource_tuples([resource_tuple()]) -> ok. store_resource_tuples([]) -> ok; -store_resource_tuples([{_, _} | _] = ResourceTuples) -> - lists:foreach(fun(ResourceTuple) -> - store_resource_tuple(ResourceTuple) - end, ResourceTuples). +store_resource_tuples([{_,_}|_] = ResourceTuples) -> + lists:foreach(fun(ResourceTuple) -> + store_resource_tuple(ResourceTuple) + end, ResourceTuples). %%----------------------------------------------------------------------- %% @doc Remove a single resource from cache. @@ -242,15 +242,15 @@ store_resource_tuples([{_, _} | _] = ResourceTuples) -> %%----------------------------------------------------------------------- -spec delete_resource_tuple(resource_tuple()) -> ok. delete_resource_tuple({Type, Resource}) -> - ets:insert(?RS, {Type, lists:delete(Resource, get_resources(Type))}), - %% delete Type if it doesnt have any resources - case get_resources(Type) of - [] -> ets:match_delete(?RS, {Type, '_'}); - _ -> do_nothing - end, - ok. - - + ets:insert(?RS, {Type, lists:delete(Resource, get_resources(Type))}), + %% delete Type if it doesnt have any resources + case get_resources(Type) of + [] -> ets:match_delete(?RS, {Type, '_'}); + _ -> do_nothing + end, + ok. + + %%-------------------------------------------------------------------- %% @doc %% clear deleted resource cache. after the network was synched @@ -258,22 +258,22 @@ delete_resource_tuple({Type, Resource}) -> %%-------------------------------------------------------------------- -spec delete_deleted_resource_tuple() -> ok. delete_deleted_resource_tuple() -> - ets:insert(?LKVStore, {deleted_resources, []}), - ok. - + ets:insert(?LKVStore, {deleted_resources, []}), + ok. + %%----------------------------------------------------------------------- %% @doc Gets resource of a particular type outputs and places it in last position. %% @end %%----------------------------------------------------------------------- -spec round_robin_get(resource_type()) -> {ok, resource()} | {error, not_found}. round_robin_get(Type) -> - case get_resources(Type) of - [Resource | RL] -> - ets:insert(?RS, {Type, RL ++ [Resource]}), - {ok, Resource}; - [] -> {error, not_found} - end. + case get_resources(Type) of + [Resource | RL] -> + ets:insert(?RS, {Type, RL ++ [Resource]}), + {ok, Resource}; + [] -> {error, not_found} + end. %%----------------------------------------------------------------------- %% @doc Outputs the number of resource types. @@ -281,7 +281,7 @@ round_robin_get(Type) -> %%----------------------------------------------------------------------- -spec get_num_resource_types() -> integer(). get_num_resource_types() -> - length(ets:match(?RS, {'$1', '_'})). + length(ets:match(?RS, {'$1', '_'})). %%----------------------------------------------------------------------- %% @doc Outputs the number of resource types. @@ -289,10 +289,10 @@ get_num_resource_types() -> %%----------------------------------------------------------------------- -spec get_num_resource(resource_type()) -> integer(). get_num_resource(Type) -> - case ets:lookup(?RS, Type) of - [{Type, Resources}] -> length(Resources); - [] -> 0 - end. + case ets:lookup(?RS, Type) of + [{Type, Resources}] -> length(Resources); + [] -> 0 + end. %%----------------------------------------------------------------------- %% @doc Outputs the types of resources. @@ -301,4 +301,4 @@ get_num_resource(Type) -> %%----------------------------------------------------------------------- -spec get_resource_types() -> [resource_type()]. get_resource_types() -> - lists:usort([E || [E] <- ets:match(?RS, {'$1', '_'})]). + lists:usort([E || [E] <- ets:match(?RS, {'$1', '_'})]). diff --git a/src/rd_sup.erl b/src/rd_sup.erl index 31e73fa..d1aff5a 100644 --- a/src/rd_sup.erl +++ b/src/rd_sup.erl @@ -14,15 +14,15 @@ %% External exports %%-------------------------------------------------------------------- -export([ - start_link/0 -]). + start_link/0 + ]). %%-------------------------------------------------------------------- %% Internal exports %%-------------------------------------------------------------------- -export([ - init/1 -]). + init/1 + ]). %%-------------------------------------------------------------------- %% Macros @@ -43,7 +43,7 @@ %% @end %%-------------------------------------------------------------------- start_link() -> - supervisor:start_link({local, ?SERVER}, ?MODULE, []). + supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Server functions @@ -56,28 +56,28 @@ start_link() -> %% {error, Reason} %%-------------------------------------------------------------------- init([]) -> - RestartStrategy = one_for_one, - MaxRestarts = 1000, - MaxTimeBetRestarts = 3600, - SupFlags = {RestartStrategy, MaxRestarts, MaxTimeBetRestarts}, + RestartStrategy = one_for_one, + MaxRestarts = 1000, + MaxTimeBetRestarts = 3600, + SupFlags = {RestartStrategy, MaxRestarts, MaxTimeBetRestarts}, - ChildSpecs = - [ - {rd_core, - {rd_core, start_link, []}, - permanent, - 1000, - worker, - [rd_core]}, - {rd_heartbeat, - {rd_heartbeat, start_link, []}, - transient, - brutal_kill, - worker, - [rd_heartbeat]} - ], + ChildSpecs = + [ + {rd_core, + {rd_core, start_link, []}, + permanent, + 1000, + worker, + [rd_core]}, + {rd_heartbeat, + {rd_heartbeat, start_link, []}, + transient, + brutal_kill, + worker, + [rd_heartbeat]} + ], - {ok, {SupFlags, ChildSpecs}}. + {ok, {SupFlags, ChildSpecs}}. diff --git a/src/rd_util.erl b/src/rd_util.erl index 78a2587..4205a77 100644 --- a/src/rd_util.erl +++ b/src/rd_util.erl @@ -8,11 +8,11 @@ %% API -export([ - get_env/2, - do_until/2, - sync_ping/2, - poll_until/3 -]). + get_env/2, + do_until/2, + sync_ping/2, + poll_until/3 + ]). %%%=================================================================== %%% API @@ -22,66 +22,67 @@ %% return value from the passed in fun. -spec do_until(term(), list()) -> term() | false. do_until(_F, []) -> - false; + false; do_until(F, [Last]) -> - F(Last); -do_until(F, [H | T]) -> - case F(H) of - false -> do_until(F, T); - Return -> Return - end. + F(Last); +do_until(F, [H|T]) -> + case F(H) of + false -> do_until(F, T); + Return -> Return + end. %% @doc Pings a node and returns only after the net kernal distributes the nodes. -spec sync_ping(node(), timeout()) -> pang | pong. sync_ping(Node, Timeout) -> - error_logger:info_msg("pinging node: ~p", [Node]), - case net_adm:ping(Node) of - pong -> - Resp = - poll_until(fun() -> - length(get_remote_nodes(Node)) == length(nodes()) - end, - 10, Timeout div 10), - case Resp of - true -> pong; - false -> pang - end; - pang -> - pang - end. + %%error_logger:info_msg("pinging node: ~p", [Node]), + case net_adm:ping(Node) of + pong -> + Resp = + poll_until(fun() -> + length(get_remote_nodes(Node)) == length(nodes()) + end, + 10, Timeout div 10), + case Resp of + true -> pong; + false -> pang + end; + pang -> + pang + end. %% @doc This is a higher order function that allows for Iterations -%% number of executions of Fun until false is not returned +%% number of executions of Fun until false is not returned %% from the Fun pausing for PauseMS after each execution. %%
 %% Variables:
 %%  Fun - A fun to execute per iteration.
-%%  Iterations - The maximum number of iterations to try getting Reply out of Fun.  
+%%  Iterations - The maximum number of iterations to try getting Reply out of Fun.
 %%  PauseMS - The number of miliseconds to wait inbetween each iteration.
 %%  Return - What ever the fun returns.
 %% 
-spec poll_until(term(), timeout(), timeout()) -> term() | false. poll_until(Fun, 0, _PauseMS) -> - Fun(); + Fun(); poll_until(Fun, Iterations, PauseMS) -> - case Fun() of - false -> - timer:sleep(PauseMS), - case Iterations of - infinity -> poll_until(Fun, Iterations, PauseMS); - Iterations -> poll_until(Fun, Iterations - 1, PauseMS) - end; - Reply -> - Reply - end. + case Fun() of + false -> + timer:sleep(PauseMS), + case Iterations of + infinity -> poll_until(Fun, Iterations, PauseMS); + Iterations -> poll_until(Fun, Iterations - 1, PauseMS) + end; + Reply -> + Reply + end. %% @doc Get application data but provide a default. -spec get_env(atom(), term()) -> term(). get_env(Key, Default) -> - case application:get_env(resource_discovery, Key) of - {ok, Value} -> {ok, Value}; - undefined -> {ok, Default} - end. + case application:get_env(resource_discovery, Key) of + {ok, Value} -> {ok, Value}; + undefined -> {ok, Default} + end. + %%%=================================================================== @@ -90,13 +91,12 @@ get_env(Key, Default) -> get_remote_nodes(Node) -> - try - Nodes = rpc:call(Node, erlang, nodes, []), - error_logger:info_msg("contact node has ~p", [Nodes]), - Nodes - catch - _C:E -> - error_logger:info_msg("failed to connect to contact node ~p", [Node]), - throw(E) - end. - + try + Nodes = rpc:call(Node, erlang, nodes, []), + %%error_logger:info_msg("contact node has ~p", [Nodes]), + Nodes + catch + _C:E -> + error_logger:info_msg("failed to connect to contact node ~p", [Node]), + throw(E) + end. diff --git a/src/resource_discovery.app.src b/src/resource_discovery.app.src index 934deb2..523f473 100644 --- a/src/resource_discovery.app.src +++ b/src/resource_discovery.app.src @@ -1,41 +1,41 @@ %%% -*- mode:erlang -*- {application, resource_discovery, - [ - % A quick description of the application. - {description, "Resource discovery & management"}, + [ + % A quick description of the application. + {description, "Resource discovery & management"}, - % The version of the applicaton - {vsn, "0.2.1.0"}, + % The version of the applicaton + {vsn, "0.2.1.0"}, - % All modules used by the application. - {modules, - [ - resource_discovery, - rd_core, - rd_heartbeat, - rd_store, - rd_util, - rd_sup - ]}, + % All modules used by the application. + {modules, + [ + resource_discovery, + rd_core, + rd_heartbeat, + rd_store, + rd_util, + rd_sup + ]}, - % All of the registered names the application uses. - {registered, []}, + % All of the registered names the application uses. + {registered, []}, - % Applications that are to be started prior to this one. - {applications, - [ - kernel, - stdlib - ]}, + % Applications that are to be started prior to this one. + {applications, + [ + kernel, + stdlib + ]}, - % configuration parameters - {env, [{heartbeat_frequency, 60000}]}, - - % The M F A to start this application. - {mod, {resource_discovery, - [ - {heartbeat_frequency, 60000} - ]}} - ] + % configuration parameters + {env, [{heartbeat_frequency, 60000}]}, + + % The M F A to start this application. + {mod, {resource_discovery, + [ + {heartbeat_frequency, 60000} + ]}} + ] }. diff --git a/src/resource_discovery.erl b/src/resource_discovery.erl index 9372f1f..49ff058 100644 --- a/src/resource_discovery.erl +++ b/src/resource_discovery.erl @@ -1,7 +1,7 @@ %%%------------------------------------------------------------------- %%% File : resource_discovery.erl %%% Author : Martin J. Logan -%%% @doc +%%% @doc %%% Resource Discovery has 3 major types. They are listed here. %%% @type resource_tuple() = {resource_type(), resource()}. The type %%% of a resource followed by the actual resource. Local @@ -10,7 +10,7 @@ %%% @type resource_type() = atom(). The name of a resource, how it is identified. For example %%% a type of service that you have on the network may be identified by it's node name %%% in which case you might have a resource type of 'my_service' of which there may be -%%% many node names representing resources such as {my_service, myservicenode@myhost}. +%%% many node names representing resources such as {my_service, myservicenode@myhost}. %%% @type resource() = term(). Either a concrete resource or a reference to one like a pid(). %%% @end %%%------------------------------------------------------------------- @@ -22,49 +22,49 @@ % Standard exports. -export([ - start/0, - start/2, - stop/0 -]). + start/0, + start/2, + stop/0 + ]). % Add -export([ - add_local_resource_tuples/1, - add_local_resource_tuple/1, - add_target_resource_types/1, - add_target_resource_type/1, - add_callback_modules/1, - add_callback_module/1 -]). + add_local_resource_tuples/1, + add_local_resource_tuple/1, + add_target_resource_types/1, + add_target_resource_type/1, + add_callback_modules/1, + add_callback_module/1 + ]). % Get -export([ - get_resource/1, - get_resources/1, - get_num_resource/1, - get_resource_types/0, - get_num_resource_types/0 -]). + get_resource/1, + get_resources/1, + get_num_resource/1, + get_resource_types/0, + get_num_resource_types/0 + ]). % Delete -export([ - delete_local_resource_tuple/1, - delete_target_resource_type/1, - delete_resource_tuple/1, - delete_callback_module/1, - delete_callback_modules/1 -]). + delete_local_resource_tuple/1, + delete_target_resource_type/1, + delete_resource_tuple/1, + delete_callback_module/1, + delete_callback_modules/1 + ]). % Other -export([ - trade_resources/0, - sync_resources/1, - sync_resources/0, - contact_nodes/0, - rpc_multicall/5, - rpc_multicall/4, - rpc_call/5, - rpc_call/4 -]). + trade_resources/0, + sync_resources/1, + sync_resources/0, + contact_nodes/0, + rpc_multicall/5, + rpc_multicall/4, + rpc_call/5, + rpc_call/4 + ]). -include("../include/resource_discovery.hrl"). @@ -78,7 +78,7 @@ %%==================================================================== start() -> - application:start(resource_discovery). + application:start(resource_discovery). %%-------------------------------------------------------------------- %% @doc Starts the resource discovery application. @@ -86,11 +86,11 @@ start() -> %% @end %%-------------------------------------------------------------------- start(_Type, _StartArgs) -> - % Create the storage for the local parameters; i.e. LocalTypes - % and TargetTypes. - random:seed(erlang:timestamp()), - rd_store:new(), - rd_sup:start_link(). + % Create the storage for the local parameters; i.e. LocalTypes + % and TargetTypes. + random:seed(erlang:timestamp()), + rd_store:new(), + rd_sup:start_link(). stop() -> application:stop(resource_discovery). @@ -110,44 +110,44 @@ trade_resources() -> rd_core:trade_resources(). %%----------------------------------------------------------------------- -spec sync_resources(timeout()) -> ok. sync_resources(Timeout) -> - sync_locals(), - Self = self(), - Nodes = nodes(known), - error_logger:info_msg("synching resources to nodes: ~p", [Nodes]), - LocalResourceTuples = rd_core:get_local_resource_tuples(), - DeletedTuples = rd_core:get_deleted_resource_tuples(), - TargetTypes = rd_core:get_target_resource_types(), - - Pids = [spawn(fun() -> - Self ! {'\$sync_resources\$', self(), - (catch rd_core:sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}))} - end) - || Node <- Nodes], - %% resources are synched so remove deleted tuples cache - rd_store:delete_deleted_resource_tuple(), - get_responses(Pids, Timeout). + sync_locals(), + Self = self(), + Nodes = nodes(known), + %%error_logger:info_msg("synching resources to nodes: ~p", [Nodes]), + LocalResourceTuples = rd_core:get_local_resource_tuples(), + DeletedTuples = rd_core:get_deleted_resource_tuples(), + TargetTypes = rd_core:get_target_resource_types(), + + Pids = [spawn(fun() -> + Self ! {'\$sync_resources\$', self(), + (catch rd_core:sync_resources(Node, {LocalResourceTuples, TargetTypes, DeletedTuples}))} + end) + || Node <- Nodes], + %% resources are synched so remove deleted tuples cache + rd_store:delete_deleted_resource_tuple(), + get_responses(Pids, Timeout). -spec sync_resources() -> ok. sync_resources() -> sync_resources(10000). sync_locals() -> - LocalResourceTuples = rd_core:get_local_resource_tuples(), - TargetTypes = rd_core:get_target_resource_types(), - FilteredLocals = rd_core:filter_resource_tuples_by_types(TargetTypes, LocalResourceTuples), - rd_core:store_resource_tuples(FilteredLocals), - rd_core:make_callbacks(FilteredLocals). + LocalResourceTuples = rd_core:get_local_resource_tuples(), + TargetTypes = rd_core:get_target_resource_types(), + FilteredLocals = rd_core:filter_resource_tuples_by_types(TargetTypes, LocalResourceTuples), + rd_core:store_resource_tuples(FilteredLocals), + rd_core:make_callbacks(FilteredLocals). get_responses([], _Timeout) -> ok; get_responses(Pids, Timeout) -> - %% XXX TODO fix the timeout by subracting elapsed time. - %% XXX TODO perhaps use the response. - receive - {'\$sync_resources\$', Pid, _Resp} -> - NewPids = lists:delete(Pid, Pids), - get_responses(NewPids, Timeout) - after - Timeout -> {error, timeout} - end. + %% XXX TODO fix the timeout by subracting elapsed time. + %% XXX TODO perhaps use the response. + receive + {'\$sync_resources\$', Pid, _Resp} -> + NewPids = lists:delete(Pid, Pids), + get_responses(NewPids, Timeout) + after + Timeout -> {error, timeout} + end. %%------------------------------------------------------------------------------ %% @doc Adds to the list of target types. Target types are the types @@ -157,24 +157,24 @@ get_responses(Pids, Timeout) -> %% @end %%------------------------------------------------------------------------------ -spec add_target_resource_types([resource_type()]) -> ok. -add_target_resource_types([H | _] = TargetTypes) when is_atom(H) -> - rd_core:store_target_resource_types(TargetTypes). +add_target_resource_types([H|_] = TargetTypes) when is_atom(H) -> + rd_core:store_target_resource_types(TargetTypes). -spec add_target_resource_type(resource_type()) -> ok. add_target_resource_type(TargetType) when is_atom(TargetType) -> - add_target_resource_types([TargetType]). + add_target_resource_types([TargetType]). %%------------------------------------------------------------------------------ -%% @doc Adds to the list of local resource tuples. +%% @doc Adds to the list of local resource tuples. %% @end %%------------------------------------------------------------------------------ -spec add_local_resource_tuples([resource_tuple()]) -> ok. -add_local_resource_tuples([{T, _} | _] = LocalResourceTuples) when is_atom(T) -> - rd_core:store_local_resource_tuples(LocalResourceTuples). +add_local_resource_tuples([{T,_}|_] = LocalResourceTuples) when is_atom(T) -> + rd_core:store_local_resource_tuples(LocalResourceTuples). -spec add_local_resource_tuple(resource_tuple()) -> ok. -add_local_resource_tuple({T, _} = LocalResourceTuple) when is_atom(T) -> - add_local_resource_tuples([LocalResourceTuple]). +add_local_resource_tuple({T,_} = LocalResourceTuple) when is_atom(T) -> + add_local_resource_tuples([LocalResourceTuple]). %%------------------------------------------------------------------------------ %% @doc Add a callback module or modules to the list of callbacks to be @@ -182,12 +182,12 @@ add_local_resource_tuple({T, _} = LocalResourceTuple) when is_atom(T) -> %% @end %%------------------------------------------------------------------------------ -spec add_callback_modules([atom()]) -> ok. -add_callback_modules([H | _] = Modules) when is_atom(H) -> - rd_core:store_callback_modules(Modules). +add_callback_modules([H|_] = Modules) when is_atom(H) -> + rd_core:store_callback_modules(Modules). -spec add_callback_module(atom()) -> ok. add_callback_module(Module) when is_atom(Module) -> - add_callback_modules([Module]). + add_callback_modules([Module]). %%------------------------------------------------------------------------------ %% @doc Replies with the cached resource. Round robins though the resources @@ -196,7 +196,7 @@ add_callback_module(Module) when is_atom(Module) -> %%------------------------------------------------------------------------------ -spec get_resource(resource_type()) -> {ok, resource()} | {error, not_found}. get_resource(Type) when is_atom(Type) -> - rd_core:round_robin_get(Type). + rd_core:round_robin_get(Type). %%------------------------------------------------------------------------------ %% @doc Returns ALL cached resources for a particular type. @@ -204,7 +204,7 @@ get_resource(Type) when is_atom(Type) -> %%------------------------------------------------------------------------------ -spec get_resources(resource_type()) -> [resource()]. get_resources(Type) -> - rd_core:all_of_type_get(Type). + rd_core:all_of_type_get(Type). %%------------------------------------------------------------------------------ %% @doc Gets a list of the types that have resources that have been cached. @@ -212,7 +212,7 @@ get_resources(Type) -> %%------------------------------------------------------------------------------ -spec get_resource_types() -> [resource_type()]. get_resource_types() -> - rd_core:get_resource_types(). + rd_core:get_resource_types(). %%------------------------------------------------------------------------------ %% @doc Removes a cached resource from the resource pool. Only returns after the @@ -220,16 +220,16 @@ get_resource_types() -> %% @end %%------------------------------------------------------------------------------ -spec delete_resource_tuple(resource_tuple()) -> ok. -delete_resource_tuple(ResourceTuple = {_, _}) -> - rd_core:delete_resource_tuple(ResourceTuple). +delete_resource_tuple(ResourceTuple = {_,_}) -> + rd_core:delete_resource_tuple(ResourceTuple). %%------------------------------------------------------------------------------ -%% @doc Remove a target type and all associated resources. +%% @doc Remove a target type and all associated resources. %% @end %%------------------------------------------------------------------------------ -spec delete_target_resource_type(resource_type()) -> true. delete_target_resource_type(Type) -> - rd_core:delete_target_resource_type(Type). + rd_core:delete_target_resource_type(Type). %%------------------------------------------------------------------------------ %% @doc Remove a local resource. The resource will no longer be available for @@ -238,7 +238,7 @@ delete_target_resource_type(Type) -> %%------------------------------------------------------------------------------ -spec delete_local_resource_tuple(resource_tuple()) -> ok | {error, local_resource_not_found, resource_tuple()}. delete_local_resource_tuple(LocalResourceTuple) -> - rd_core:delete_local_resource_tuple(LocalResourceTuple). + rd_core:delete_local_resource_tuple(LocalResourceTuple). %%-------------------------------------------------------------------- %% @doc @@ -246,9 +246,9 @@ delete_local_resource_tuple(LocalResourceTuple) -> %% @end %%-------------------------------------------------------------------- -spec delete_callback_modules([atom()]) -> ok. -delete_callback_modules([H | _] = Modules) when is_atom(H) -> - [rd_core:delete_callback_module(Module) || Module <- Modules], - ok. +delete_callback_modules([H|_] = Modules) when is_atom(H) -> + [rd_core:delete_callback_module(Module) || Module <- Modules], + ok. %%-------------------------------------------------------------------- %% @doc @@ -257,7 +257,7 @@ delete_callback_modules([H | _] = Modules) when is_atom(H) -> %%-------------------------------------------------------------------- -spec delete_callback_module(atom()) -> ok. delete_callback_module(Module) when is_atom(Module) -> - delete_callback_modules([Module]). + delete_callback_modules([Module]). %%------------------------------------------------------------------------------ %% @doc Gets the number of resource types locally cached. @@ -265,7 +265,7 @@ delete_callback_module(Module) when is_atom(Module) -> %%------------------------------------------------------------------------------ -spec get_num_resource_types() -> integer(). get_num_resource_types() -> - rd_core:get_num_resource_types(). + rd_core:get_num_resource_types(). %%------------------------------------------------------------------------------ %% @doc Counts the cached instances of a particular resource type. @@ -273,7 +273,7 @@ get_num_resource_types() -> %%------------------------------------------------------------------------------ -spec get_num_resource(resource_type()) -> integer(). get_num_resource(Type) -> - rd_core:get_num_resource(Type). + rd_core:get_num_resource(Type). %%------------------------------------------------------------------------------ %% @doc Contacts resource discoveries initial contact node. @@ -294,41 +294,41 @@ get_num_resource(Type) -> %% @end %%------------------------------------------------------------------------------ contact_nodes(Timeout) -> - {ok, ContactNodes} = - case lists:keysearch(contact_node, 1, init:get_arguments()) of - {value, {contact_node, [I_ContactNode]}} -> - application:set_env(resource_discovery, contact_nodes, [I_ContactNode]), - {ok, [list_to_atom(I_ContactNode)]}; - _ -> rd_util:get_env(contact_nodes, [node()]) - end, - ping_contact_nodes(ContactNodes, Timeout). + {ok, ContactNodes} = + case lists:keysearch(contact_node, 1, init:get_arguments()) of + {value, {contact_node, [I_ContactNode]}} -> + application:set_env(resource_discovery, contact_nodes, [I_ContactNode]), + {ok, [list_to_atom(I_ContactNode)]}; + _ -> rd_util:get_env(contact_nodes, [node()]) + end, + ping_contact_nodes(ContactNodes, Timeout). %% @spec contact_nodes() -> pong | pang | no_contact_node %% @equiv contact_nodes(10000) contact_nodes() -> - contact_nodes(10000). + contact_nodes(10000). ping_contact_nodes([], _Timeout) -> - error_logger:info_msg("No contact node specified. Potentially running in a standalone node", []), - {error, no_contact_node}; + error_logger:info_msg("No contact node specified. Potentially running in a standalone node", []), + {error, no_contact_node}; ping_contact_nodes(Nodes, Timeout) -> - Reply = rd_util:do_until(fun(Node) -> - case rd_util:sync_ping(Node, Timeout) of - pong -> true; - pang -> - error_logger:info_msg("ping contact node at ~p failed", [Node]), - false - end - end, - Nodes), - case Reply of - false -> {error, bad_contact_node}; - true -> ok - end. + Reply = rd_util:do_until(fun(Node) -> + case rd_util:sync_ping(Node, Timeout) of + pong -> true; + pang -> + error_logger:info_msg("ping contact node at ~p failed", [Node]), + false + end + end, + Nodes), + case Reply of + false -> {error, bad_contact_node}; + true -> ok + end. %%------------------------------------------------------------------------------ -%% @doc Execute an rpc on a cached resource. If the result of the rpc is {badrpc, reason} the -%% resource is deleted and the next resource is tried, else the result is +%% @doc Execute an rpc on a cached resource. If the result of the rpc is {badrpc, reason} the +%% resource is deleted and the next resource is tried, else the result is %% returned to the user. %%
 %% Varibles:
@@ -338,42 +338,42 @@ ping_contact_nodes(Nodes, Timeout) ->
 %%------------------------------------------------------------------------------
 -spec rpc_call(resource_type(), atom(), atom(), [term()], timeout()) -> term() | {error, not_found}.
 rpc_call(Type, Module, Function, Args, Timeout) ->
-  case get_resource(Type) of
-    {ok, Resource} ->
-      error_logger:info_msg("got a resource ~p", [Resource]),
-      case rpc:call(Resource, Module, Function, Args, Timeout) of
-        {badrpc, Reason} ->
-          error_logger:info_msg("got a badrpc ~p", [Reason]),
-          delete_resource_tuple({Type, Resource}),
-          rpc_call(Type, Module, Function, Args, Timeout);
-        Reply ->
-          error_logger:info_msg("result of rpc was ~p", [Reply]),
-          Reply
-      end;
-    {error, not_found} -> {error, not_found}
-  end.
+    case get_resource(Type) of
+	{ok, Resource} ->
+	    %%error_logger:info_msg("got a resource ~p", [Resource]),
+	    case rpc:call(Resource, Module, Function, Args, Timeout) of
+		{badrpc, Reason} ->
+		    error_logger:info_msg("got a badrpc ~p", [Reason]),
+		    delete_resource_tuple({Type, Resource}),
+		    rpc_call(Type, Module, Function, Args, Timeout);
+		Reply ->
+		    error_logger:info_msg("result of rpc was ~p", [Reply]),
+		    Reply
+	    end;
+        {error, not_found} -> {error, not_found}
+    end.
 
 -spec rpc_call(resource_type(), atom(), atom(), [term()]) -> term() | {error, no_resources}.
 rpc_call(Type, Module, Function, Args) ->
-  rpc_call(Type, Module, Function, Args, 60000).
+    rpc_call(Type, Module, Function, Args, 60000).
 
 %%------------------------------------------------------------------------------
-%% @doc Execute an rpc on a cached resource.  Any bad nodes are deleted. 
-%%      resource is deleted and the next resource is tried, else the result is 
+%% @doc Execute an rpc on a cached resource.  Any bad nodes are deleted.
+%%      resource is deleted and the next resource is tried, else the result is
 %%      returned to the user.
 %% @end
 %%------------------------------------------------------------------------------
 -spec rpc_multicall(resource_type(), atom(), atom(), [term()], timeout()) -> {term(), [node()]} | {error, no_resources}.
 rpc_multicall(Type, Module, Function, Args, Timeout) ->
-  case get_resources(Type) of
-    [] -> {error, no_resources};
-    Resources ->
-      error_logger:info_msg("got resources ~p", [Resources]),
-      {Resl, BadNodes} = rpc:multicall(Resources, Module, Function, Args, Timeout),
-      [delete_resource_tuple({Type, BadNode}) || BadNode <- BadNodes],
-      {Resl, BadNodes}
-  end.
+    case get_resources(Type) of
+        [] -> {error, no_resources};
+	Resources ->
+	    %%error_logger:info_msg("got resources ~p", [Resources]),
+	    {Resl, BadNodes} = rpc:multicall(Resources, Module, Function, Args, Timeout),
+	    [delete_resource_tuple({Type, BadNode}) || BadNode <- BadNodes],
+	    {Resl, BadNodes}
+    end.
 
 -spec rpc_multicall(resource_type(), atom(), atom(), [term()]) -> {term(), [node()]} | {error, no_resources}.
 rpc_multicall(Type, Module, Function, Args) ->
-  rpc_multicall(Type, Module, Function, Args, 60000).
+    rpc_multicall(Type, Module, Function, Args, 60000).
diff --git a/src/sys.config b/src/sys.config
index 63f01e8..6bebb04 100644
--- a/src/sys.config
+++ b/src/sys.config
@@ -1,11 +1,11 @@
 %%% -*- mode:erlang -*-
 %%% Warning - this config file *must* end with 
 
-[
-  {resource_discovery,
-    [
-      {contact_nodes, ['rd@127.0.0.1']},
-      {heartbeat_frequency, 60000},
-      {log4erl_config, "etc/log4erl.conf"}
-    ]}
+[ 
+  {resource_discovery, 
+   [
+    {contact_nodes, ['rd@127.0.0.1']},
+    {heartbeat_frequency, 60000},
+    {log4erl_config, "etc/log4erl.conf"}
+   ]}
 ].
diff --git a/test/rd_store_tests.erl b/test/rd_store_tests.erl
index af099ff..38fd107 100644
--- a/test/rd_store_tests.erl
+++ b/test/rd_store_tests.erl
@@ -5,68 +5,68 @@
 -define(TEST_VALUES, [{a, a}, {a, b}, {b, a}]).
 
 rd_store_local_resource_test_() ->
-  {setup, local,
-    fun rd_store:new/0,
-    fun(_Pid) -> rd_store:delete() end,
-    fun(_P) ->
-      {inorder,
-        [
-          %% add local resources
-          ?_assertEqual(ok, rd_store:store_local_resource_tuples(?TEST_VALUES)),
-          %% check that we get the same resources from storage
-          ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()),
-          %% test for dublicate values
-          ?_assertEqual(ok, rd_store:store_local_resource_tuples([{a, a}, {a, b}])),
-          %% shouln't have new resources after dublicate were attempted to add
-          ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()),
-          %% remove resource
-          ?_assertEqual(ok, rd_store:delete_local_resource_tuple({a, a})),
-          ?_assertMatch([{a, b}, {b, a}], rd_store:get_local_resource_tuples())
-        ]}
-    end}.
+    {setup, local,
+     fun rd_store:new/0,
+     fun(_Pid) -> rd_store:delete() end,
+     fun(_P) ->
+	     {inorder,
+	      [
+	       %% add local resources
+	       ?_assertEqual(ok, rd_store:store_local_resource_tuples(?TEST_VALUES)),
+	       %% check that we get the same resources from storage
+	       ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()),
+	       %% test for dublicate values
+	       ?_assertEqual(ok, rd_store:store_local_resource_tuples([{a,a},{a,b}])),
+	       %% shouln't have new resources after dublicate were attempted to add
+	       ?_assertEqual(?TEST_VALUES, rd_store:get_local_resource_tuples()),
+	       %% remove resource
+	       ?_assertEqual(ok, rd_store:delete_local_resource_tuple({a, a})),
+	       ?_assertMatch([{a, b}, {b, a}], rd_store:get_local_resource_tuples())
+	      ]}
+     end }.
 
 rd_store_target_resource_test_() ->
-  {setup, local,
-    fun rd_store:new/0,
-    fun(_Pid) -> rd_store:delete() end,
-    fun(_P) ->
-      {inorder,
-        [
-          ?_assertEqual(ok, rd_store:store_target_resource_types([c, d, e])),
-          ?_assertMatch([c, d, e], rd_store:get_target_resource_types()),
-          ?_assertMatch(ok, rd_store:delete_target_resource_type(c)),
-          ?_assertMatch([d, e], rd_store:get_target_resource_types())
-        ]}
-    end}.
+    {setup, local,
+     fun rd_store:new/0,
+     fun(_Pid) -> rd_store:delete() end,
+     fun(_P) ->
+	     {inorder,
+	      [
+	       ?_assertEqual(ok, rd_store:store_target_resource_types([c, d, e])),
+	       ?_assertMatch([c,d,e], rd_store:get_target_resource_types()),
+	       ?_assertMatch(ok, rd_store:delete_target_resource_type(c)),
+	       ?_assertMatch([d,e], rd_store:get_target_resource_types())
+	      ]}
+     end }.
 
 
 rd_store_resource_test_() ->
-  {setup, local,
-    fun rd_store:new/0,
-    fun(_Pid) -> rd_store:delete() end,
-    fun(_P) ->
-      {inorder,
-        [
-          ?_assertEqual(ok, rd_store:store_resource_tuple({c, c1})),
-          ?_assertEqual(ok, rd_store:store_resource_tuples([{d, d1}, {d, d2}, {e, e1}, {e, e2}, {b, b1}])),
-          ?_assertMatch(2, rd_store:get_num_resource(d)),
-          ?_assertMatch(4, rd_store:get_num_resource_types()),
-          ?_assertMatch([b1], rd_store:get_resources(b)),
-          ?_assertMatch([d1, d2], rd_store:get_resources(d)),
-          ?_assertMatch([e1, e2], rd_store:get_resources(e))
-        ]}
-    end}.
+    {setup, local,
+     fun rd_store:new/0,
+     fun(_Pid) -> rd_store:delete() end,
+     fun(_P) ->
+	     {inorder,
+	      [
+	       ?_assertEqual(ok, rd_store:store_resource_tuple({c, c1})),
+	       ?_assertEqual(ok, rd_store:store_resource_tuples([{d, d1},{d, d2}, {e, e1}, {e, e2}, {b, b1}])),
+	       ?_assertMatch(2, rd_store:get_num_resource(d)),
+	       ?_assertMatch(4, rd_store:get_num_resource_types()),
+	       ?_assertMatch([b1], rd_store:get_resources(b)),
+	       ?_assertMatch([d1, d2], rd_store:get_resources(d)),
+	       ?_assertMatch([e1, e2], rd_store:get_resources(e))
+	      ]}
+     end }.
 
 rd_store_callback_test_() ->
-  {setup, local,
-    fun rd_store:new/0,
-    fun(_Pid) -> rd_store:delete() end,
-    fun(_P) ->
-      {inorder,
-        [
-          ?_assertEqual(ok, rd_store:store_callback_modules([a, b])),
-          ?_assertEqual([a, b], rd_store:get_callback_modules()),
-          ?_assertEqual(ok, rd_store:delete_callback_module(a)),
-          ?_assertEqual([b], rd_store:get_callback_modules())
-        ]}
-    end}.
+    {setup, local,
+     fun rd_store:new/0,
+     fun(_Pid) -> rd_store:delete() end,
+     fun(_P) ->
+	     {inorder,
+	      [
+	       ?_assertEqual(ok, rd_store:store_callback_modules([a, b])),
+	       ?_assertEqual([a,b], rd_store:get_callback_modules()),
+	       ?_assertEqual(ok, rd_store:delete_callback_module(a)),
+	       ?_assertEqual([b], rd_store:get_callback_modules())	       
+	      ]}
+     end }.
diff --git a/test/resource_discovery_tests.erl b/test/resource_discovery_tests.erl
index f3fe466..bfe8086 100644
--- a/test/resource_discovery_tests.erl
+++ b/test/resource_discovery_tests.erl
@@ -13,189 +13,190 @@
 %% resource_discovery:get_resources(b).
 
 process_test_() ->
-  {setup,
-    fun start_process/0,
-    fun stop_process/1,
-    fun run/1}.
+    {setup,
+     fun start_process/0,
+     fun stop_process/1,
+     fun run/1}.
 
 start_process() ->
-  resource_discovery:start().
+    resource_discovery:start().
 stop_process(_P) ->
-  resource_discovery:stop(),
-  ok.
+    resource_discovery:stop(),
+    ok.
 
 run(_P) ->
-  {inorder,
+    {inorder,
     [
-      %% add local and target resources
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuples(?RESOURCE_TUPLES)),
-      ?_assertMatch(ok, resource_discovery:add_target_resource_type(b)),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      %% check that target resource is avilable
-      ?_assertMatch([a], resource_discovery:get_resources(b)),
-      ?_assertMatch([b], resource_discovery:get_resource_types()),
-      %% delete local resource, the resource should dissapear from remote caches after sych
-      ?_assertMatch(ok, resource_discovery:delete_local_resource_tuple({b, a})),
-      %% try to remove non existing resource
-      ?_assertMatch({error, local_resource_not_found, {b, a1}}, resource_discovery:delete_local_resource_tuple({b, a1})),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      %% check that it is not avialable to network anymore
-      ?_assertMatch([], resource_discovery:get_resources(b)),
-      ?_assertMatch([], resource_discovery:get_resources(a)),
-      ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)),
-      %% check that resource types with no resources is gone
-      ?_assertMatch([], resource_discovery:get_resource_types()),
-      %% add new target resources in "I want" list
-      ?_assertMatch(ok, resource_discovery:add_target_resource_types([e, f, n])),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e, e1}, {e, e2}, {e, e3}, {f, f1}])),
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({f, f1})),
-      ?_assertMatch(ok, resource_discovery:trade_resources()),
-      ?_assertMatch([e, f], resource_discovery:get_resource_types()),
-      ?_assertEqual(2, resource_discovery:get_num_resource_types()),
-      ?_assertEqual(3, resource_discovery:get_num_resource(e)),
-      %% number of non-existing resource
-      ?_assertEqual(0, resource_discovery:get_num_resource(k)),
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{b, a}])),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      ?_assertMatch([a], resource_discovery:get_resources(b)),
-      ?_assertMatch({ok, a}, resource_discovery:get_resource(b)),
-      ?_assertMatch([e1, e2, e3], resource_discovery:get_resources(e)),
-      %% delete resource
-      ?_assertMatch(ok, resource_discovery:delete_resource_tuple({b, a})),
-      %% shouldn't exist in local cache
-      ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)),
-      ?_assertMatch(ok, resource_discovery:trade_resources()),
-      %% ... but deleted resource will reappear after syching
-      ?_assertMatch({ok, a}, resource_discovery:get_resource(b)),
-      %% need to delete target resource type first, then delete resource from cache
-      ?_assertMatch(ok, resource_discovery:delete_target_resource_type(b)),
-      ?_assertMatch(ok, resource_discovery:delete_resource_tuple({b, a})),
-      ?_assertMatch([e, f], resource_discovery:get_resource_types()),
-      ?_assertMatch(ok, resource_discovery:trade_resources()),
-      %% now it should be gone
-      ?_assertMatch({error, not_found}, resource_discovery:get_resource(b))
+     %% add local and target resources
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuples(?RESOURCE_TUPLES)),
+     ?_assertMatch(ok, resource_discovery:add_target_resource_type(b)),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     %% check that target resource is avilable
+     ?_assertMatch([a], resource_discovery:get_resources(b)),
+     ?_assertMatch([b], resource_discovery:get_resource_types()),
+     %% delete local resource, the resource should dissapear from remote caches after sych
+     ?_assertMatch(ok, resource_discovery:delete_local_resource_tuple({b,a})),
+     %% try to remove non existing resource
+     ?_assertMatch({error, local_resource_not_found, {b,a1}}, resource_discovery:delete_local_resource_tuple({b,a1})),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     %% check that it is not avialable to network anymore
+     ?_assertMatch([], resource_discovery:get_resources(b)),
+     ?_assertMatch([], resource_discovery:get_resources(a)),
+     ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)),
+     %% check that resource types with no resources is gone  
+     ?_assertMatch([], resource_discovery:get_resource_types()),
+     %% add new target resources in "I want" list
+     ?_assertMatch(ok, resource_discovery:add_target_resource_types([e,f,n])),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e,e1}, {e,e2}, {e,e3}, {f, f1}])),
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({f, f1})),
+     ?_assertMatch(ok, resource_discovery:trade_resources()),
+     ?_assertMatch([e, f], resource_discovery:get_resource_types()),
+     ?_assertEqual(2, resource_discovery:get_num_resource_types()),
+     ?_assertEqual(3, resource_discovery:get_num_resource(e)),
+     %% number of non-existing resource 
+     ?_assertEqual(0, resource_discovery:get_num_resource(k)),
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{b,a}])),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     ?_assertMatch([a], resource_discovery:get_resources(b)),
+     ?_assertMatch({ok, a}, resource_discovery:get_resource(b)),
+     ?_assertMatch([e1, e2, e3], resource_discovery:get_resources(e)),
+     %% delete resource
+     ?_assertMatch(ok,resource_discovery:delete_resource_tuple({b,a})),
+     %% shouldn't exist in local cache
+     ?_assertMatch({error, not_found}, resource_discovery:get_resource(b)),
+     ?_assertMatch(ok, resource_discovery:trade_resources()),
+     %% ... but deleted resource will reappear after syching
+     ?_assertMatch({ok, a}, resource_discovery:get_resource(b)),
+     %% need to delete target resource type first, then delete resource from cache
+     ?_assertMatch(ok, resource_discovery:delete_target_resource_type(b)),
+     ?_assertMatch(ok,resource_discovery:delete_resource_tuple({b,a})),
+     ?_assertMatch([e, f], resource_discovery:get_resource_types()),
+     ?_assertMatch(ok, resource_discovery:trade_resources()),
+     %% now it should be gone
+     ?_assertMatch({error, not_found}, resource_discovery:get_resource(b))
     ]}.
 
 
+
 %% test call notifications
 %% we setup a loop to hold a state, callback will fire up resource_up/1 func, which will set a state of 
 %% a loop process, so we can verify this state in unit test.
 
 -record(state, {value = false}).
 rd_notification_test_() ->
-  {setup,
-    fun start_notify_loop/0,
-    fun(Pid) -> stop_notify_loop(Pid) end,
-    fun run_notify/1}.
+    {setup,
+     fun start_notify_loop/0,
+     fun(Pid) -> stop_notify_loop(Pid) end,
+     fun run_notify/1}.
 
 start_notify_loop() ->
-  resource_discovery:start(),
-  Pid = spawn(fun() -> loop(#state{}) end),
-  register(notify_loop_process, Pid),
-  Pid.
-
+    resource_discovery:start(),
+    Pid = spawn(fun() -> loop(#state{}) end),
+    register(notify_loop_process, Pid),
+    Pid.
+			 
 stop_notify_loop(Pid) ->
-  resource_discovery:stop(),
-  unregister(notify_loop_process),
-  Pid ! stop,
-  ok.
+    resource_discovery:stop(),
+    unregister(notify_loop_process),
+    Pid ! stop,
+    ok.
 
 run_notify(_Pid) ->
-  {inorder,
+    {inorder,
     [
-      %% add callback module, local and target resources
-      ?_assertMatch(ok, resource_discovery:add_callback_module(?MODULE)),
-      ?_assertMatch(ok, resource_discovery:add_target_resource_types([e, f, n])),
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e, e1}, {f, f1}])),
-      %% before synch, there is not notification
-      ?_assertEqual(false, get_state()),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      %% after synch, there should be a notification
-      ?_assertEqual(true, get_state()),
-      %% now remove the cached resource
-      ?_assertMatch(ok, resource_discovery:delete_resource_tuple({e, e1})),
-      %% verify that resource is gone
-      ?_assertMatch({error, not_found}, resource_discovery:get_resource(e)),
-      %% remove notification module and synch
-      ?_assertMatch(ok, resource_discovery:delete_callback_module(?MODULE)),
-      %% reset the state of loop process
-      ?_assertMatch(ok, set_state(false)),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      %% verify that notification wasn't sent
-      ?_assertEqual(false, get_state()),
-      %% verify that resource was still cached
-      ?_assertMatch({ok, e1}, resource_discovery:get_resource(e))
+     %% add callback module, local and target resources
+     ?_assertMatch(ok, resource_discovery:add_callback_module(?MODULE)),
+     ?_assertMatch(ok, resource_discovery:add_target_resource_types([e,f,n])),
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuples([{e,e1}, {f, f1}])),
+     %% before synch, there is not notification
+     ?_assertEqual(false, get_state()),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     %% after synch, there should be a notification
+     ?_assertEqual(true, get_state()),
+     %% now remove the cached resource
+     ?_assertMatch(ok,resource_discovery:delete_resource_tuple({e,e1})),
+     %% verify that resource is gone
+     ?_assertMatch({error, not_found}, resource_discovery:get_resource(e)),
+     %% remove notification module and synch 
+     ?_assertMatch(ok, resource_discovery:delete_callback_module(?MODULE)),
+     %% reset the state of loop process
+     ?_assertMatch(ok, set_state(false)),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     %% verify that notification wasn't sent
+     ?_assertEqual(false, get_state()),
+     %% verify that resource was still cached
+     ?_assertMatch({ok,e1}, resource_discovery:get_resource(e))
     ]}.
 
 
 %% function which is called when event happens
 %% for test we only care when resource 'e' becomes available
 resource_up({e, R}) ->
-  error_logger:info_msg("resource is up ~p: ~p", [e, R]),
-  %% callback happend, set state in loop process, so it could be verified in test
-  set_state(true);
+    error_logger:info_msg("resource is up ~p: ~p", [e, R]),
+    %% callback happend, set state in loop process, so it could be verified in test
+    set_state(true);   
 resource_up(Other) ->
-  error_logger:info_msg("resource is up, dont' care: ~p", [Other]).
+    error_logger:info_msg("resource is up, dont' care: ~p", [Other]).
 
 get_state() ->
-  notify_loop_process ! {self(), get},
-  receive
-    Value -> Value
-  end.
-
+    notify_loop_process ! {self(), get},
+    receive
+	Value -> Value
+    end.
+	     
 set_state(Value) ->
-  notify_loop_process ! {self(), {set, Value}},
-  ok.
+    notify_loop_process ! {self(), {set, Value}},
+    ok.
 
 loop(State) ->
-  receive
-    {_From, {set, Value}} ->
-      loop(State#state{value = Value});
-    {From, get} ->
-      From ! State#state.value,
-      %% reset state back in initial state
-      loop(State#state{value = false});
-    stop -> void
-  end.
-
+    receive
+	{_From, {set, Value}} -> 
+	    loop(State#state{value = Value});
+	{From, get} -> 
+	    From ! State#state.value,
+	    %% reset state back in initial state
+	    loop(State#state{value=false});
+	stop -> void
+    end.
+	       
 
 %% rpc_call test
 rd_rpc_call_test_() ->
-  {setup,
-    fun start_adder_loop/0,
-    fun stop_adder_loop/1,
-    fun rpc_run/1}.
+    {setup,
+     fun start_adder_loop/0,
+     fun stop_adder_loop/1,
+     fun rpc_run/1}.
 
 start_adder_loop() ->
-  resource_discovery:start().
-
+    resource_discovery:start().
+	 
 stop_adder_loop(_P) ->
-  resource_discovery:stop().
+    resource_discovery:stop().
 
 %% test function to be called by rpc call
 test_adder(A, B) when is_integer(A), is_integer(B) ->
-  A + B.
+    A + B.
 
 rpc_run(_Pid) ->
-  Node = node(),
-  {inorder,
+    Node = node(),
+    {inorder,
     [
-      %% add local and target resources
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, Node})),
-      ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, 'not_existing@nohost'})),
-      ?_assertMatch(ok, resource_discovery:add_target_resource_type(node)),
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      %% add bad node as resource
-      ?_assertMatch(['not_existing@nohost', Node], resource_discovery:get_resources(node)),
-      ?_assertMatch(5, resource_discovery:rpc_call(node, ?MODULE, test_adder, [1, 4])),
-      %% bad resource should be deleted now, we should only get live node
-      ?_assertMatch({ok, Node}, resource_discovery:get_resource(node)),
-      %% try using unknown_resource
-      ?_assertMatch({error, not_found}, resource_discovery:rpc_call(unknown_resource, ?MODULE, test_adder, [1, 4])),
-      %% synch up so bad node is loaded again
-      ?_assertMatch(ok, resource_discovery:sync_resources()),
-      %% run multicall
-      ?_assertMatch({[300], [not_existing@nohost]}, resource_discovery:rpc_multicall(node, ?MODULE, test_adder, [100, 200])),
-      ?_assertMatch({error, no_resources}, resource_discovery:rpc_multicall(unknown_resource, ?MODULE, test_adder, [400, 200]))
+     %% add local and target resources
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, Node})),
+     ?_assertMatch(ok, resource_discovery:add_local_resource_tuple({node, 'not_existing@nohost'})),
+     ?_assertMatch(ok, resource_discovery:add_target_resource_type(node)),
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     %% add bad node as resource
+     ?_assertMatch(['not_existing@nohost', Node], resource_discovery:get_resources(node)),
+     ?_assertMatch(5, resource_discovery:rpc_call(node, ?MODULE, test_adder, [1,4])),
+     %% bad resource should be deleted now, we should only get live node
+     ?_assertMatch({ok, Node}, resource_discovery:get_resource(node)),
+     %% try using unknown_resource
+     ?_assertMatch({error, not_found}, resource_discovery:rpc_call(unknown_resource, ?MODULE, test_adder, [1,4])),
+     %% synch up so bad node is loaded again
+     ?_assertMatch(ok, resource_discovery:sync_resources()),
+     %% run multicall
+     ?_assertMatch({[300],[not_existing@nohost]}, resource_discovery:rpc_multicall(node, ?MODULE, test_adder, [100,200])),
+     ?_assertMatch({error, no_resources}, resource_discovery:rpc_multicall(unknown_resource, ?MODULE, test_adder, [400,200]))
     ]}.