Packages
Chatter is extracted from the ScaleSmall project as a standalone piece. This may be used independently to broadcast messages to a set of nodes. It uses a mixture of UDP multicast and TCP to deliver messages and tries to minimize network traffic while doing so.
Current section
Files
Jump to
Current section
Files
lib/planner.ex
defmodule Chatter.Planner do
alias Chatter.NetID
alias Chatter.BroadcastID
alias Chatter.PeerDB
@spec plan( list(NetID.t ) ) :: list(list(NetID.t))
def plan(netid_list)
do
:ok = NetID.validate_list!(netid_list)
group_mcast_peers(netid_list) |> build_tree([])
end
@spec build_tree(list, list) :: list
def build_tree([], acc), do: acc
def build_tree(list, acc)
when is_list(list) and is_list(acc)
do
len = length(list)
take_n = div(len, 2)
{next, remainder} = list |> Enum.shuffle |> Enum.split(take_n)
new_acc = [remainder|acc]
build_tree(next, new_acc) |> Enum.reverse
end
@spec group_mcast_peers( list(NetID.t ) ) :: list(list(NetID.t))
def group_mcast_peers(netid_list)
do
:ok = NetID.validate_list!(netid_list)
{result, _set} = Enum.reduce(netid_list, {[], Enum.into(netid_list, HashSet.new)}, fn(x,acc) ->
{result_list, netid_set} = acc
if HashSet.member?(netid_set, x)
do
netid_set = HashSet.delete(netid_set, x)
case PeerDB.get_seen_id_list_(x)
do
{:ok, seen_ids} ->
{mcast_group, netid_set} = Enum.reduce(seen_ids, {[x], netid_set}, fn(x2,acc2) ->
{result_list2, netid_set} = acc2
id = BroadcastID.origin(x2)
if HashSet.member?(netid_set, id)
do
{[id|result_list2], HashSet.delete(netid_set, id)}
else
acc2
end
end)
{[(mcast_group |> Enum.shuffle)|result_list], netid_set}
{:error, :not_found} ->
{[[x]|result_list], netid_set}
end
else
acc
end
end)
result
end
end