From 28e2a1a202fcf35f11d14b33a6a0280f64d7c746 Mon Sep 17 00:00:00 2001 From: Matt Mullins Date: Sun, 19 Dec 2010 22:26:36 -0600 Subject: [PATCH 1/1] Basic structure of the IRC modules. Nothing does anything, and I still need to make sure my pid accounting works properly, but at least it kind of has the supervisory structure I'm going to want. I made lots of TODO notes in comments. --- ebin/erlbot.app | 3 +++ src/erlbot.erl | 14 ++++++++++++++ src/erlbot_sup.erl | 25 +++++++++++++++++++++++++ src/irc_channel_sup.erl | 22 ++++++++++++++++++++++ src/irc_conn.erl | 42 +++++++++++++++++++++++++++++++++++++++++ src/irc_pid_cache.erl | 28 +++++++++++++++++++++++++++ src/irc_sup.erl | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ src/irc_user_sup.erl | 24 ++++++++++++++++++++++++ src/pid_cache.erl | 22 ++++++++++++++++++++++ 9 files changed, 230 insertions(+) create mode 100644 ebin/erlbot.app create mode 100644 src/erlbot.erl create mode 100644 src/erlbot_sup.erl create mode 100644 src/irc_channel_sup.erl create mode 100644 src/irc_conn.erl create mode 100644 src/irc_pid_cache.erl create mode 100644 src/irc_sup.erl create mode 100644 src/irc_user_sup.erl create mode 100644 src/pid_cache.erl diff --git a/ebin/erlbot.app b/ebin/erlbot.app new file mode 100644 index 0000000..b293147 --- /dev/null +++ b/ebin/erlbot.app @@ -0,0 +1,3 @@ +{application, erlbot, + [{mod, {erlbot, []}} + ]}. diff --git a/src/erlbot.erl b/src/erlbot.erl new file mode 100644 index 0000000..39a30b3 --- /dev/null +++ b/src/erlbot.erl @@ -0,0 +1,14 @@ +-module(erlbot). +-behavior(application). + +-export([ + start/2, + stop/1 + ]). + +% TODO: probably should take in a config file through _Args +start(_Type, _Args) -> + erlbot_sup:start_link(). + +stop(_State) -> + ok. diff --git a/src/erlbot_sup.erl b/src/erlbot_sup.erl new file mode 100644 index 0000000..380c45d --- /dev/null +++ b/src/erlbot_sup.erl @@ -0,0 +1,25 @@ +-module(erlbot_sup). +-behavior(supervisor). + +-export([ + start_link/0 + ]). +-export([ + init/1 + ]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, ok). + +init(_Args) -> + Children = [child("tamu", "irc.tamu.edu", 6667, "moko|bot")], + RestartStrategy = {one_for_one, 0, 1}, % TODO: change to 4 per hour + {ok, {RestartStrategy, Children}}. + +child(Instance, Host, Port, Nick) -> + {{irc, Instance}, + {irc_sup, start_link, [Instance, Host, Port, Nick]}, + permanent, + brutal_kill, + supervisor, + [irc_sup]}. diff --git a/src/irc_channel_sup.erl b/src/irc_channel_sup.erl new file mode 100644 index 0000000..dfebef1 --- /dev/null +++ b/src/irc_channel_sup.erl @@ -0,0 +1,22 @@ +-module(irc_channel_sup). +-behavior(supervisor). + +-export([ + start_link/1 + ]). + +-export([init/1]). + +start_link(Instance) -> + supervisor:start_link(?MODULE, Instance). + +init(Instance) -> + Child = {?MODULE, + {irc_channel, start_link, [Instance]}, + transient, + brutal_kill, + worker, + [irc_channel]}, + RestartStrategy = {simple_one_for_one, 0, 1}, + {ok, {RestartStrategy, [Child]}}. + diff --git a/src/irc_conn.erl b/src/irc_conn.erl new file mode 100644 index 0000000..f2a3ec9 --- /dev/null +++ b/src/irc_conn.erl @@ -0,0 +1,42 @@ +-module(irc_conn). +-behavior(gen_server). + +-export([ + start_link/5 + ]). + +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3 + ]). + +-record(irc_state, {sup, instance, host, port, nick}). + +start_link(Supervisor, Instance, Host, Port, Nick) -> + gen_server:start_link(?MODULE, + {Supervisor, Instance, Host, Port, Nick}, []). + +init({Supervisor, Instance, Host, Port, Nick}) -> + State = #irc_state{ + sup=Supervisor, instance=Instance, host=Host, + port=Port, nick=Nick}, + {ok, State}. + +handle_call(_Request, _From, _State) -> + {reply, ok, _State}. + +handle_cast(_Request, _State) -> + {noreply, _State}. + +handle_info(_Message, _State) -> + {noreply, _State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. diff --git a/src/irc_pid_cache.erl b/src/irc_pid_cache.erl new file mode 100644 index 0000000..df5b2fd --- /dev/null +++ b/src/irc_pid_cache.erl @@ -0,0 +1,28 @@ +-module(irc_pid_cache). + +-export([ + insert_channel/3, + get_channel/2, + delete_channel/2, + insert_user/3, + get_user/2, + delete_user/2 + ]). + +insert_channel(Instance, Channel, Pid) -> + pid_cache:insert({irc_channel, Instance, Channel}, Pid). + +get_channel(Instance, Channel) -> + pid_cache:get({irc_channel, Instance, Channel}). + +delete_channel(Instance, Channel) -> + pid_cache:delete({irc_channel, Instance, Channel}). + +insert_user(Instance, User, Pid) -> + pid_cache:insert({irc_user, Instance, User}, Pid). + +get_user(Instance, User) -> + pid_cache:get({irc_user, Instance, User}). + +delete_user(Instance, User) -> + pid_cache:delete({irc_user, Instance, User}). diff --git a/src/irc_sup.erl b/src/irc_sup.erl new file mode 100644 index 0000000..207efe0 --- /dev/null +++ b/src/irc_sup.erl @@ -0,0 +1,50 @@ +-module(irc_sup). +-behavior(supervisor). + +-export([ + start_link/4, + get_channel_sup/1, + get_user_sup/1 + ]). +-export([init/1]). + +start_link(Instance, Host, Port, Nick) -> + supervisor:start_link(?MODULE, + {Instance, Host, Port, Nick}). + +get_channel_sup(Pid) -> + get_sup(Pid, channels). + +get_user_sup(Pid) -> + get_sup(Pid, users). + +% TODO: should this crash and burn if the child isn't running? +% i.e. can this become a race condition with the actual +% respawning of a process? +get_sup(Pid, Type) -> + case supervisor:start_child(Pid, + data_child(Type, ok, [])) + of + {error, {already_started, Child}} -> + Child + end. + +init({Instance, Host, Port, Nick}) -> + Connection = {connection, + {irc_conn, start_link, [self(), Instance, Host, Port, Nick]}, + transient, 5, worker, [irc_conn]}, + Children = [data_child(channels, irc_channel_sup, [Instance]), + data_child(users, irc_user_sup, [Instance]), + Connection + ], + RestartStrategy = {one_for_all, 0, 1}, % TODO + {ok, {RestartStrategy, Children}}. + +data_child(Id, Module, Args) -> + {Id, + {Module, start_link, Args}, + permanent, + 5, + supervisor, + [Module]}. + diff --git a/src/irc_user_sup.erl b/src/irc_user_sup.erl new file mode 100644 index 0000000..57c7155 --- /dev/null +++ b/src/irc_user_sup.erl @@ -0,0 +1,24 @@ +% TODO: combine with irc_channel_sup + +-module(irc_user_sup). +-behavior(supervisor). + +-export([ + start_link/1 + ]). + +-export([init/1]). + +start_link(Instance) -> + supervisor:start_link(?MODULE, Instance). + +init(Instance) -> + Child = {?MODULE, + {irc_user, start_link, [Instance]}, + transient, + brutal_kill, + worker, + [irc_user]}, + RestartStrategy = {simple_one_for_one, 0, 1}, + {ok, {RestartStrategy, [Child]}}. + diff --git a/src/pid_cache.erl b/src/pid_cache.erl new file mode 100644 index 0000000..b9432fd --- /dev/null +++ b/src/pid_cache.erl @@ -0,0 +1,22 @@ +-module(pid_cache). + +-export([ + init/0, + insert/2, + get/1, + delete/1 + ]). + +init() -> + ets:new(?MODULE, [set, public]). + +insert(Key, Value) -> + ets:insert(?MODULE, {Key, Value}). + +get(Key) -> + case ets:lookup(?MODULE, Key) of + [{Key, Pid}] -> Pid + end. + +delete(Key) -> + ets:delete(?MODULE, Key). -- 2.11.0