Refactoring process tree.

master
Alexander Markevych 2012-07-24 16:58:42 +03:00
parent fdc5ae9480
commit d9b32e67d8
14 changed files with 731 additions and 640 deletions

View File

@ -1,11 +1,17 @@
{application,erlmines,
[{description,[]},
{vsn,"0.0.1"},
{registered,[erlmines_app,erlmines_sup,erlmines]},
{registered,[erlmines_app,erlmines_sup,connection_sup,connection_disp]},
{applications,[kernel,stdlib]},
{mod,{erlmines_app,[]}},
{env,[]},
{modules,[clientserver,connection,connection_channels,
connection_incoming_split_buffer,connection_peers,
connection_reliable_packet_buffer,erlmines,
erlmines_app,erlmines_sup]}]}.
{modules,[erlmines_app,
erlmines_sup,
erlmines,
connection_sup,
connection_disp,
peer_channels,
peer_packet_buffers,
peer_mgr,
peer_reliable_packet_buffer,
clientserver]}]}.

View File

@ -1,3 +1,4 @@
#!/bin/bash
#erl -noshell -pa ./ebin -eval 'application:start(erlmines)'
erl -smp auto -pa ./ebin -eval 'application:start(erlmines)'

View File

@ -9,6 +9,26 @@
-define(U16, 16/unsigned-little-integer).
-define(U32, 32/unsigned-little-integer).
%% @type udp_server_option() =
%% {option(), port(), max_restarts(), time(), shutdown(),recv_length(), recv_timeout()}.
%% A data structure holding the options.
%% @type option() = [term()].
%% @type port() = integer().
%% @type max_restarts() = integer().
%% @type time() = integer().
%% @type shutdown() = integer().
%% @type recv_length() = integer().
%% @type recv_timeout() = integer() | infinity.
-record(udp_server_option, {
option = [binary],
port = 4000,
max_restarts = 3,
time = 60,
shutdown = 2000,
recv_length = 0,
recv_timeout = infinity
}).
-record(buffered_packet, {
data, % Data of the packet, including headers
time, % Seconds from buffering the packet or re-sending

View File

@ -1,93 +0,0 @@
%%
%% erlmines - The minetest server written in Erlang
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection).
-include("connection.hrl").
-export([readPeerId/1,readChannel/1]).
-export([makePacket/5,
makeOriginalPacket/1,
makeSplitPacket/3,
makeAutoSplitPacket/3,
makeReliablePacket/2,
test/0]).
ceiling(X) ->
T = trunc(X),
case X - T == 0 of
true -> T;
false -> T + 1
end.
readPeerId(PacketData) ->
<<_P:?U32,SenderPeerId:?U16,_Other/binary>> = PacketData,
SenderPeerId.
readChannel(PacketData) ->
<<_P:?U32,_S:?U16,Channel:?U8,_Other/binary>> = PacketData,
Channel.
% This adds the base headers to the data and makes a packet out of it
makePacket(Address, Data, ProtocolId,SenderPeerId,Channel)->
#buffered_packet{
address=Address,
data = <<ProtocolId:?U32,SenderPeerId:?U16,Channel:?U8,Data/binary>>
}.
% Add the TYPE_ORIGINAL header to the data
makeOriginalPacket(Data) ->
#original_packet{ data = <<?TYPE_ORIGINAL:?U8,Data/binary>> }.
% Split data in chunks and add TYPE_SPLIT headers to them
makeSplitPacket(Data,ChunkSizeMax,SeqNum) ->
ChunkHeaderSize = 7,
MaxDataSize = ChunkSizeMax - ChunkHeaderSize,
ChunkCount=ceiling(byte_size(Data)/MaxDataSize),
Chunks = makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, 0, Data),
Chunks.
makeSplitPacketList(_MaxDataSize, _SeqNum, ChunkCount, ChunkCount, _Data) ->[];
makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, ChunkNum, Data) ->
DataSize = byte_size(Data),
ChunkDataSize = case MaxDataSize - DataSize < 0 of
true -> MaxDataSize;
false -> DataSize
end,
<<ChunkData:ChunkDataSize/binary,Tile/binary>> = Data,
%%ChunkNum1 = ChunkNum+1,
[<<?TYPE_SPLIT:?U8, SeqNum:?U16, ChunkCount:?U16, ChunkNum:?U16,ChunkData/binary>>|makeSplitPacketList(MaxDataSize,SeqNum,ChunkCount,ChunkNum+1,Tile)].
test() ->
makeSplitPacket(list_to_binary([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]),9,65500).
% Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
% Increments split_seqnum if a split packet is made
makeAutoSplitPacket(_Data,_ChunkSizeMax,_SplitSeqNum) ->
todo.
% core::list<SharedBuffer<u8> > makeAutoSplitPacket(
% SharedBuffer<u8> data,
% u32 chunksize_max,
% u16 &split_seqnum)
%{
% u32 original_header_size = 1;
% core::list<SharedBuffer<u8> > list;
% if(data.getSize() + original_header_size > chunksize_max)
% {
% list = makeSplitPacket(data, chunksize_max, split_seqnum);
% split_seqnum++;
% return list;
% }
% else
% {
% list.push_back(makeOriginalPacket(data));
% }
% return list;
%}
%
% Add the TYPE_RELIABLE header to the data
makeReliablePacket(Data, SeqNum) ->
#reliable_packet{ data = <<?TYPE_RELIABLE:?U8,SeqNum:?U16,Data/binary>> }.

View File

@ -0,0 +1,181 @@
%%
%% erlmines - The minetest server written in Erlang
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection_disp).
-behaviour(gen_server).
-export([start_link/0
, init/1
, handle_call/3
, handle_cast/2
, handle_info/2
, terminate/2
, code_change/3
]).
-export([set_socket/2, readPeerId/1,readChannel/1]).
-export([makePacket/5,
makeOriginalPacket/1,
makeSplitPacket/3,
makeAutoSplitPacket/3,
makeReliablePacket/2,
test/0]).
-include("connection.hrl").
%% Client API
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%% Server functions
init(_Args) ->
erlang:process_flag(trap_exit, true),
io:format("===connection:init===~n",[]),
case gen_udp:open(30000,[binary]) of
{ok,Socket} -> {ok, [Socket]};
{error, Reason} -> {stop, Reason}
end.
set_socket(Peer, Socket) when is_pid(Peer) andalso is_port(Socket) ->
gen_tcp:controlling_process(Socket, Peer),
gen_server:call(Peer, {set_socket, Socket}).
handle_call({msg,Msg},From,State) ->
io:format("===connection:handle_call===~p, ~p, ~p~n",[Msg,From,State]),
{reply, ok, State};
handle_call({set_socket, Socket}, _From, State) ->
inet:setopts(Socket, [{packet,raw},{active,once}]),
{reply, ok, State}.
handle_cast(calc, State) ->
io:format("result 2+2=4~n"),
{noreply, State};
handle_cast(calcbad, State) ->
io:format("result 1/0~n"),
1 / 0,
{noreply, State};
handle_cast(_Msg, State) ->
io:format("===connection:handle_cast===~n",[]),
{noreply,State}.
handle_info({udp, Socket, _IP, _InPortNo, _Bin} = UdpMsg, State) ->
inet:setopts(Socket, [{active,once}]),
process_packet(UdpMsg),
%%{ok, Decoder1, Frames} = decode(Bin, Decoder),
%%[Consumer ! Frame || Frame <- Frames],
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
process_packet({udp,_Socket,Host,Port,Bin}) ->
io:format("========================================~n",[]),
io:format("Host = ~p, Port = ~p~n",[Host,Port]),
<<_ProtocolId:?U32, SenderPeerId:?U16, Channel:?U8,
PacketType:?U8, Data/binary>> = Bin,
case PacketType of
?TYPE_CONTROL -> Type = "TYPE_CONTROL (0)",
type_control(Data);
?TYPE_ORIGINAL -> Type = "TYPE_ORIGINAL(1)",
type_original(Data);
?TYPE_SPLIT -> Type = "TYPE_SPLIT(2)",
type_split(Data);
?TYPE_RELIABLE -> Type = "TYPE_RELIABLE(2)",
type_reliable(Data)
end,
%io:format("ProtocolId: ~p, SenderPeerId:~p, Channel:~p, PacketType: ~p,~n Data:~p~n",[ProtocolId,SenderPeerId,Channel,Type,Data]).
io:format("SenderPeerId:~p, Channel:~p, PacketType: ~p,~n Data:~p~n",
[SenderPeerId,Channel,Type,Data]).
type_control(<<_ControlType:?U8,_Data/binary>>)-> ok.
type_original(_Data)-> ok.
type_split(<<_SeqNum:?U16,_ChunkCount:?U16,_ChunkNum:?U16,_Data/binary>>)-> ok.
type_reliable(<<_SeqNum:?U16,_Data/binary>>)-> ok.
ceiling(X) ->
T = trunc(X),
case X - T == 0 of
true -> T;
false -> T + 1
end.
readPeerId(PacketData) ->
<<_P:?U32,SenderPeerId:?U16,_Other/binary>> = PacketData,
SenderPeerId.
readChannel(PacketData) ->
<<_P:?U32,_S:?U16,Channel:?U8,_Other/binary>> = PacketData,
Channel.
% This adds the base headers to the data and makes a packet out of it
makePacket(Address, Data, ProtocolId,SenderPeerId,Channel)->
#buffered_packet{
address=Address,
data = <<ProtocolId:?U32,SenderPeerId:?U16,Channel:?U8,Data/binary>>
}.
% Add the TYPE_ORIGINAL header to the data
makeOriginalPacket(Data) ->
#original_packet{ data = <<?TYPE_ORIGINAL:?U8,Data/binary>> }.
% Split data in chunks and add TYPE_SPLIT headers to them
makeSplitPacket(Data,ChunkSizeMax,SeqNum) ->
ChunkHeaderSize = 7,
MaxDataSize = ChunkSizeMax - ChunkHeaderSize,
ChunkCount=ceiling(byte_size(Data)/MaxDataSize),
Chunks = makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, 0, Data),
Chunks.
makeSplitPacketList(_MaxDataSize, _SeqNum, ChunkCount, ChunkCount, _Data) ->[];
makeSplitPacketList(MaxDataSize, SeqNum, ChunkCount, ChunkNum, Data) ->
DataSize = byte_size(Data),
ChunkDataSize = case MaxDataSize - DataSize < 0 of
true -> MaxDataSize;
false -> DataSize
end,
<<ChunkData:ChunkDataSize/binary,Tile/binary>> = Data,
%%ChunkNum1 = ChunkNum+1,
[<<?TYPE_SPLIT:?U8, SeqNum:?U16, ChunkCount:?U16, ChunkNum:?U16,ChunkData/binary>>|makeSplitPacketList(MaxDataSize,SeqNum,ChunkCount,ChunkNum+1,Tile)].
test() ->
makeSplitPacket(list_to_binary([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]),9,65500).
% Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
% Increments split_seqnum if a split packet is made
makeAutoSplitPacket(_Data,_ChunkSizeMax,_SplitSeqNum) ->
todo.
% core::list<SharedBuffer<u8> > makeAutoSplitPacket(
% SharedBuffer<u8> data,
% u32 chunksize_max,
% u16 &split_seqnum)
%{
% u32 original_header_size = 1;
% core::list<SharedBuffer<u8> > list;
% if(data.getSize() + original_header_size > chunksize_max)
% {
% list = makeSplitPacket(data, chunksize_max, split_seqnum);
% split_seqnum++;
% return list;
% }
% else
% {
% list.push_back(makeOriginalPacket(data));
% }
% return list;
%}
%
% Add the TYPE_RELIABLE header to the data
makeReliablePacket(Data, SeqNum) ->
#reliable_packet{ data = <<?TYPE_RELIABLE:?U8,SeqNum:?U16,Data/binary>> }.

View File

@ -0,0 +1,31 @@
%%
%% erlmines - The minetest server written in Erlang
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_Args) ->
io:format("===connection_sup:init===~n",[]),
RestartStrategy = one_for_one, % one_for_one | one_for_all | rest_for_one
MaxRestarts = 10,
MaxSecondsBetweenRestarts = 60,
SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
Restart = permanent, % permanent | transient | temporary
Shutdown = 2000, % brutal_kill | int() >= 0 | infinity
Type = worker, % worker | supervisor
Connection = {connection_dispatcher, % used to identify the child spec internally by the supervisor
{connection_disp, start_link, []}, % StartFun = {M, F, A}
Restart, Shutdown, Type,
[connection_disp]}, % Modules = [Module] | dynamic
{ok, {SupFlags, [Connection]}}.

View File

@ -1,12 +0,0 @@
{application, erlmines,
[
{description, ""},
{vsn, "0.0.1"},
{registered, [erlmines_app, erlmines_sup, erlmines]},
{applications, [
kernel,
stdlib
]},
{mod, { erlmines_app, []}},
{env, []}
]}.

View File

@ -1,7 +1,6 @@
-module(erlmines).
-behaviour(gen_server).
-include("connection.hrl").
-export([start_link/0]).
-export([init/1
@ -12,90 +11,35 @@
, code_change/3
]).
%% @type udp_server_option() =
%% {option(), port(), max_restarts(), time(), shutdown(),recv_length(), recv_timeout()}.
%% A data structure holding the options.
%% @type option() = [term()].
%% @type port() = integer().
%% @type max_restarts() = integer().
%% @type time() = integer().
%% @type shutdown() = integer().
%% @type recv_length() = integer().
%% @type recv_timeout() = integer() | infinity.
-record(udp_server_option, {
option = [binary],
port = 4000,
max_restarts = 3,
time = 60,
shutdown = 2000,
recv_length = 0,
recv_timeout = infinity
}).
%% Client API
start_link() ->
gen_server:start_link(?MODULE, [], []).
gen_server:start_link({local,?MODULE}, ?MODULE, [], []).
%% Server functions
init([]) ->
case gen_udp:open(30000,[binary]) of
{ok,Socket} -> {ok, [Socket]};
{error, Reason} -> {stop, Reason}
end.
init(_Args) ->
io:format("===erlmines:init===~n",[]),
erlang:process_flag(trap_exit, true),
io:format("erlmines has started (~w)~n", [self()]),
{ok,[]}.
handle_call(_Request,From,State) ->
error_logger:info_report("handle_call"),
%% io:format("handle_call ========================================~n",[]),
handle_call(_Msg, _From, State) ->
{reply, ok, State}.
handle_cast({udp,Socket,Host,Port,Bin} = Message,State) ->
error_logger:info_report("handle_cast1"),
%% io:format("handle_cast ========================================~n",[]),
%% io:format("Data= ~p~n",[Bin]),
{noreply,State};
handle_cast(_Msg, State) ->
error_logger:info_report("handle_cast2"),
%% io:format("handle_cast ~n",[]),
%% io:format("Data= ~p~n",[Bin]),
%error_logger:info_report("handle_cast"),
{noreply,State}.
handle_info(UdpMsg,State) ->
process_packet(UdpMsg),
handle_info(_Msg, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
io:format("===erlmines:terminate===~n",[]),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
process_packet({udp,Socket,Host,Port,Bin}) ->
io:format("========================================~n",[]),
% io:format("Host = ~p, Port = ~p~n",[Host,Port]),
<<ProtocolId:?U32, SenderPeerId:?U16, Channel:?U8,
PacketType:?U8, Data/binary>> = Bin,
case PacketType of
?TYPE_CONTROL -> Type = "TYPE_CONTROL (0)",
type_control(Data);
?TYPE_ORIGINAL -> Type = "TYPE_ORIGINAL(1)",
type_original(Data);
?TYPE_SPLIT -> Type = "TYPE_SPLIT(2)",
type_split(Data);
?TYPE_RELIABLE -> Type = "TYPE_RELIABLE(2)",
type_reliable(Data)
end,
%io:format("ProtocolId: ~p, SenderPeerId:~p, Channel:~p, PacketType: ~p,~n Data:~p~n",[ProtocolId,SenderPeerId,Channel,Type,Data]).
io:format("SenderPeerId:~p, Channel:~p, PacketType: ~p,~n Data:~p~n",
[SenderPeerId,Channel,Type,Data]).
type_control(<<ControlType:?U8,Data/binary>>)-> ok.
type_original(Data)-> ok.
type_split(<<SeqNum:?U16,ChunkCount:?U16,ChunkNum:?U16,Data/binary>>)-> ok.
type_reliable(<<SeqNum:?U16,Data/binary>>)-> ok.

View File

@ -7,8 +7,8 @@
-behaviour(application).
-export([start/2, stop/1]).
start(_Type, StartArgs) ->
erlmines_sup:start_link(StartArgs).
start(normal, _Args) ->
erlmines_sup:start_link().
stop(_State) ->
ok.

View File

@ -6,34 +6,47 @@
-behaviour(supervisor).
-export([start/0, start_link/1, init/1]).
-export([start_link/0, init/1,
shutdown/0
% start_shell/0
]).
start() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
start_link(Args) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, Args).
%start_shell() ->
% {ok, Pid} = supervisor:start_link(erlmines_sup, []),
% unlink(Pid).
init([]) ->
init(_Args) ->
io:format("===erlmines_sup:init===~n",[]),
RestartStrategy = one_for_one, % one_for_one | one_for_all | rest_for_one
MaxRestarts = 10,
MaxSecondsBetweenRestarts = 60,
SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
Restart = permanent, % permanent | transient | temporary
Shutdown = 2000, % brutal_kill | int() >= 0 | infinity
Type = worker, % worker | supervisor
Shutdown = infinity, % brutal_kill | int() >= 0 | infinity
Type = supervisor, % worker | supervisor
AChild = {erlmines_sup, % used to identify the child spec internally by the supervisor
{erlmines, start_link, []}, % StartFun = {M, F, A}
% Erlmines = {erlmines_main, % used to identify the child spec internally by the supervisor
% {erlmines, start_link, []}, % StartFun = {M, F, A}
% Restart, Shutdown, Type,
% [erlmines]},
Connection_sup = {erlmines_connection_sup,
{connection_sup, start_link, []},
Restart, Shutdown, Type,
[erlmines]}, % Modules = [Module] | dynamic
[connection_sup]},
{ok, {SupFlags, [AChild]}}.
%%{ok, {SupFlags, [Erlmines, Connection_sup]}}.
%, ?SUPERVISOR_LINK(connection_sup)]}}.
{ok, {SupFlags, [Connection_sup]}}.
% {ok, {{one_for_one, 100, 300},
% [{erlmines_sup,
% {erlmines, start_link, []},
% permanent, 10000, worker, [erlmines]}
% ]}}.
% supervisor can be shutdown by calling exit(SupPid,shutdown)
% or, if it's linked to its parent, by parent calling exit/1.
shutdown() ->
exit(whereis(?MODULE), shutdown).
% or
% exit(normal).

View File

@ -2,7 +2,7 @@
%% erlmines - The minetest server written in Erlang
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection_channels).
-module(peer_channels).
-compile(export_all).

View File

@ -2,7 +2,7 @@
%% erlmines - The minetest server written in Erlang
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection_peers).
-module(peer_mgr).
-compile(export_all).

View File

@ -3,7 +3,7 @@
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection_incoming_split_buffer).
-module(peer_packet_buffers).
-include("connection.hrl").
-export([init/1, insert/3, removeUnreliableTimedOuts/1]).

View File

@ -2,7 +2,7 @@
%% erlmines - The minetest server written in Erlang
%% Copyright (C) 2012 hummermania, Markevych Alexander <rabota.pmr@gmail.com>
%%
-module(connection_reliable_packet_buffer).
-module(peer_reliable_packet_buffer).
-include("connection.hrl").
-export([init/1, insert/2, findPacket/2, print/1, empty/1,