实现资源探测

实现资源探测

-record(state.
(target_resource_types,
local_resource tuples,
found_resource_tuples)).
定义了3个字段:target_resource_types就是上述的“需求”列表,所需资源的类型的列表;local_resource_tuples则是“供给”列表,这张列表以资源元组的形式保存着本地节点上的所有资源;found_resource_tuples用于缓存探测到的可以需求的资源实例。

-module(resource_discovery).
-author("chen").
-behaviour(gen_server).

%% API
-export([
  start_link/0,
  add_target_resource_type/1,
  fetch_resources/1,
  trade_resources/0,
  add_local_resource/2]).
-export([init/1, handle_cast/2, handle_call/3]).

-define(SERVER, ?MODULE).

-record(state, {
  target_resource_types,
  local_resource_tuples,
  found_resource_tuples
}).



start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) ->
  {ok, #state{target_resource_types = [],
    local_resource_tuples = dict:new(),
    found_resource_tuples = dict:new()}}.

add_target_resource_type(Type) ->
  gen_server:cast(?SERVER, {add_target_resource_type, Type}).
add_local_resource(Type, Instance) ->
  gen_server:cast(?SERVER, {add_local_resource, {Type, Instance}}).
trade_resources() ->
  gen_server:cast(?SERVER, trade_resources).

fetch_resources(Type) ->
  gen_server:call(?SERVER, {fetch_resources, Type}).

handle_cast({add_target_resource_type, Type}, State) ->
  TargetTypes = State#state.target_resource_types,
  NewTargetTypes = [Type | lists:delete(Type, TargetTypes)],
  {noreply, State#state{target_resource_types = NewTargetTypes}};

handle_cast({add_local_resource, {Type, Instance}}, State) ->
  ResourceTuples = State#state.local_resource_tuples,
  NewResourceTuples = add_resource(Type, Instance, ResourceTuples),
  {noreply, State#state{local_resource_tuples  = NewResourceTuples}};

handle_cast({trade_resources, {ReplyTo, Remotes}},
    #state{local_resource_tuples = Locals,
      target_resource_types = TargetTypes,
      found_resource_tuples = OldFound} = State) ->
  FilteredRemotes = resources_for_types(TargetTypes, Remotes),
  NewFound = add_resources(FilteredRemotes, OldFound),
  case ReplyTo of
    noreply ->
      ok;
    _ ->
      gen_server:cast({?SERVER, ReplyTo},
        {trade_resources, {noreply, Locals}})
  end,
  {noreply, State#state{found_resource_tuples = NewFound}};

handle_cast(trade_resources, State) ->
  ResourceTuples = State#state.local_resource_tuples,
  AllNodes = [node() | nodes()],
  lists:foreach(
    fun(Node) ->
      gen_server:cast({?SERVER, Node}, {trade_resources, {node(), ResourceTuples}})
    end,
    AllNodes),
  {noreply, state}.


add_resource(Type, Resource, ResourceTuples) ->
  case dict:find(Type, ResourceTuples) of
    {ok, ResourceList} ->
      NewList = [Resource | lists:delete(Resource, ResourceList)],
      dict:store(Type, NewList, ResourceTuples);
    error ->
      dict:store(Type, [Resource], ResourceTuples)
  end.



handle_call({fetch_resources, Type}, _From, State) ->
  {reply, dict:find(Type, State#state.found_resource_tuples), State}.

add_resources([{Type, Resource} | T], ResourceTuples) ->
  add_resources(T, add_resource(Type, Resource, ResourceTuples));
add_resources([], ResourceTuples) ->
  ResourceTuples.
resources_for_types(Types, ResourceTuples) ->
  Fun =
    fun(Type, Acc) ->
      case dict:find(Type, ResourceTuples) of
        {ok, List} ->
          [{Type, Instance} || Instance <- List] ++ Acc;
        error
          ->
          Acc
      end
    end,
  lists:foldl(Fun, [], Types).

 首先,从服务器状态中提取当前所有目标资源的类型。然后,将接收到的资源类型加入当前
的列表。。

 trade_resources消息会促使本地节点上的资源探测服务器异步地向Erlang集群内所
有互联节点上的资源探测服务器发起广播(也包括本地节点自身,这种对称性使你无须额外的代
码便可以更新本地的资源匹配情况。)这些广播消息的格式为{trade_resources,[ReplyTo,Resources]},其中ReplyTo是发送方所处节点的节点名(由node()给出)Resources是一个数据结构(一个dict),内含发送方打算公布的所有资源元组。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值