summaryrefslogtreecommitdiff
path: root/deps/ale
diff options
context:
space:
mode:
authorUlf Wiger <ulf@feuerlabs.com>2015-10-28 21:23:05 +0100
committerUlf Wiger <ulf@feuerlabs.com>2015-11-20 13:46:13 -0800
commit1b44c2448344a10ae63904a796b6211c40a3f212 (patch)
treece8f7dda870a5c454ffbe9e2c0bc7035b34f0f4b /deps/ale
parent34aa86b5a2e97650fe6299ccf794d5eb5d052d91 (diff)
downloadrvi_core-1b44c2448344a10ae63904a796b6211c40a3f212.tar.gz
Lots of changes to make dlink_bt (simulated) and dlink_tls runtime tests pass
* Introduced high-level logging (rvi_log) * Upgraded to new lager version, customized debug output * Thread rvi_log IDs between nodes and components * Introduce simplified protocol for dlink_tls * Use msgpack encoding for dlink_tls * dlink_bt can use TCP instead of Bluetooth for testing purposes * Bug fixes and additions to the test suite
Diffstat (limited to 'deps/ale')
-rw-r--r--deps/ale/.gitignore3
-rw-r--r--deps/ale/README.md153
-rw-r--r--deps/ale/rebar.config7
-rw-r--r--deps/ale/rebar.config.script7
-rw-r--r--deps/ale/src/.gitignore2
-rw-r--r--deps/ale/src/ale.app.src18
-rw-r--r--deps/ale/src/ale.erl437
-rw-r--r--deps/ale/src/ale_srv.erl590
-rw-r--r--deps/ale/src/ale_sup.erl95
-rw-r--r--deps/ale/sys.config39
-rw-r--r--deps/ale/test/.gitignore4
-rw-r--r--deps/ale/test/Makefile34
-rw-r--r--deps/ale/test/ale_SUITE.erl361
13 files changed, 1750 insertions, 0 deletions
diff --git a/deps/ale/.gitignore b/deps/ale/.gitignore
new file mode 100644
index 0000000..d588e7a
--- /dev/null
+++ b/deps/ale/.gitignore
@@ -0,0 +1,3 @@
+rel/
+logs/
+*~ \ No newline at end of file
diff --git a/deps/ale/README.md b/deps/ale/README.md
new file mode 100644
index 0000000..e3c7b5e
--- /dev/null
+++ b/deps/ale/README.md
@@ -0,0 +1,153 @@
+ale
+=====
+
+ale, a [lager](https://github.com/basho/lager) extension, makes it possible for several processes to trace the same modules.
+
+
+### Dependencies
+
+To build ale you will need a working installation of Erlang R15B (or
+later).<br/>
+Information on building and installing [Erlang/OTP](http://www.erlang.org)
+can be found [here](https://github.com/erlang/otp/wiki/Installation)
+([more info](https://github.com/erlang/otp/blob/master/INSTALL.md)).
+
+ale is built using rebar that can be found [here](https://github.com/rebar/rebar), with building instructions [here](https://github.com/rebar/rebar/wiki/Building-rebar). rebar's dynamic configuration mechanism, described [here](https://github.com/rebar/rebar/wiki/Dynamic-configuration), is used so the environment variable `REBAR_DEPS` should be set to the directory where your erlang applications are located.
+
+ale also requires [lager](https://github.com/basho/lager) to be installed.
+
+### Downloading
+
+Clone the repository in a suitable location:
+
+```sh
+$ git clone git://github.com/tonyrog/ale.git
+```
+### Functionality
+#### Concepts
+
+ale extends lager by using a server that keeps track of all trace request thus making it possible for several processes to add the same traces while only adding one to lager and likewise not removing it from lager until all processes have removed it.<br/>
+Available api is:
+<ul>
+<li> trace(on | off, ModuleOrPidOrFilter::atom() | pid() | tuple() | list(tuple)), Loglevel::atom()) - prints trace output on console as long as calling process hasn't terminated.</li>
+<li> trace(on | off, ModuleOrPidOrFilter::atom() | pid() | tuple() | list(tuple)), Loglevel::atom(), File::string()) - prints trace output to File as long as calling process hasn't terminated. File must exist.</li>
+<li> trace_gl(on | off, ModuleOrPidOrFilter::atom() | pid() | tuple() | list(tuple)), Loglevel::atom()) - prints trace output on console as long as calling process' group leader hasn't terminated. Suitable for calls from a shell.</li>
+<li> trace_gl(on | off, ModuleOrPidOrFilter::atom() | pid() | tuple() | list(tuple)), Loglevel::atom(), File::string()) - prints trace output to File as long as calling process' group leader hasn't terminated. Suitable for calls from a shell. File must exist.</li>
+</ul>
+Filter is a tuple {tag, Tag} that lager uses to determine what to output. <br/>
+LogLevel is debug | info | notice | warning | error | critical | alert | emergency. <br/>
+See lager documentations for more details.<br/>
+Examples:<br/>
+<code>
+ale:trace(on, sz_master, debug).<br/>
+ale:trace(on, self(), debug).<br/>
+ale:trace_gl(on, sz_node, info, "/tmp/ale.log").<br/>
+ale:trace(off, sz_master, debug)<br/>
+ale:trace(on, [{module, ale}, {function, start}], debug).<br/>
+</code>
+
+There are also some shortcut functions:
+<ul>
+<li> debug(ModuleOrPidOrList::atom() | pid() | tuple() | list(atom())) - calls trace(on, ModuleOrPidOrList, debug).</li>
+<li> info(ModuleOrPidOrList::atom() | pid() | tuple() | list(atom())) - calls trace(on, ModuleOrPidOrList, info).</li>
+<li> error(ModuleOrPidOrList::atom() | pid() | tuple() | list(atom())) - calls trace(on, ModuleOrPidOrList, error).</li>
+<li> warning(ModuleOrPidOrList::atom() | pid() | tuple() | list(atom())) - calls trace(on, ModuleOrPidOrList, warning).</li>
+</ul><br/>
+These can be called with lists of modules.
+
+#### Config Files
+
+Arguments to all applicable erlang applications are specified in an erlang configuration file.<br/>
+Traces can be added to the ale part of the configuration file. These traces will be active as long as ale i running.<br/>
+Example:<br/>
+<code>
+ {init_traces, [<br/>
+ {[{module, sz_master}], debug}, <br/>
+ {[{module, sz_node}], info, "/tmp/ale.log"}<br/>
+ ]}<br/>
+</code>
+
+An example can be found in ["sys.config"](https://github.com/tonyrog/ale/raw/master/sys.config).<br/>
+
+
+#### Tips
+
+If you start tracing using the non-groupleader function calls from the shell you can stop it by 'crashing' the shell, for ex with a=b. Might be handy if you get more output than expected ;-)
+
+### Building
+
+Rebar will compile all needed dependencies.<br/>
+Compile:
+
+```sh
+$ cd ale
+$ rebar compile
+...
+==> ale (compile)
+```
+
+### Running
+
+There is a quick way to run the application for testing:
+
+```sh
+$ erl -sname ale -config sys -pa <path>/ale/ebin
+>ale:start().
+```
+(Instead of specifing the path to the ebin directory you can set the environment ERL_LIBS.)
+
+Stop:
+
+```sh
+>halt().
+```
+
+### Release
+
+To generate a proper release follow the instructions in
+ [Release Handling](https://github.com/basho/rebar/wiki/Release-handling) or look in the [Rebar tutorial](http://www.metabrew.com/article/erlang-rebar-tutorial-generating-releases-upgrades).
+
+<b>Before</b> the last step you have to update the file "ale/rel/files/sys.config" with your own settings.
+You probably also have to update "ale/rel/reltool.config" with the correct path to your application (normally "{lib_dirs, ["../.."]}") and all apps you need.
+```
+ {app, sasl, [{incl_cond, include}]},
+ {app, stdlib, [{incl_cond, include}]},
+ {app, kernel, [{incl_cond, include}]},
+ {app, lager, [{incl_cond, include}]}
+ {app, ale, [{incl_cond, include}]}
+```
+
+
+And then you run:
+```
+$ rebar generate
+```
+
+Before generating a new version of a release the old version should be (re)moved.
+
+Start node:
+
+```sh
+$ cd rel
+$ ale/bin/ale start
+```
+
+(If you want to have access to the erlang node use
+```
+console
+```
+instead of
+```
+start
+```
+.)
+
+### Documentation
+
+ale is documented using edoc. To generate the documentation do:
+
+```sh
+$ cd ale
+$ rebar doc
+```
+You get the resulting html-files in ale/doc subdirectory.
diff --git a/deps/ale/rebar.config b/deps/ale/rebar.config
new file mode 100644
index 0000000..5c774b2
--- /dev/null
+++ b/deps/ale/rebar.config
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+%% Config file for ale application
+{deps_dir, ["deps"]}.
+{deps, [{lager, ".*"}]}.
+{erl_opts, [debug_info, fail_on_warning]}.
+{sub_dirs, ["src"]}.
+{ct_extra_params, ""}.
diff --git a/deps/ale/rebar.config.script b/deps/ale/rebar.config.script
new file mode 100644
index 0000000..70787ad
--- /dev/null
+++ b/deps/ale/rebar.config.script
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+case os:getenv("REBAR_DEPS") of
+ false ->
+ CONFIG;
+ Dir ->
+ lists:keystore(deps_dir, 1, CONFIG, {deps_dir, Dir})
+end.
diff --git a/deps/ale/src/.gitignore b/deps/ale/src/.gitignore
new file mode 100644
index 0000000..b92b763
--- /dev/null
+++ b/deps/ale/src/.gitignore
@@ -0,0 +1,2 @@
+depend.mk
+*~
diff --git a/deps/ale/src/ale.app.src b/deps/ale/src/ale.app.src
new file mode 100644
index 0000000..e3bafac
--- /dev/null
+++ b/deps/ale/src/ale.app.src
@@ -0,0 +1,18 @@
+%% -*- erlang -*-
+%%
+%% Application source file for ale
+%%
+{application, ale,
+ [
+ {description, "ALE - a lager extension"},
+ {vsn, git},
+ {registered, []},
+ {applications, [
+ kernel,
+ stdlib,
+ sasl,
+ lager
+ ]},
+ {mod, { ale, []}},
+ {env, []}
+ ]}.
diff --git a/deps/ale/src/ale.erl b/deps/ale/src/ale.erl
new file mode 100644
index 0000000..2a99727
--- /dev/null
+++ b/deps/ale/src/ale.erl
@@ -0,0 +1,437 @@
+%%%---- BEGIN COPYRIGHT --------------------------------------------------------
+%%%
+%%% Copyright (C) 2007 - 2012, Rogvall Invest AB, <tony@rogvall.se>
+%%%
+%%% This software is licensed as described in the file COPYRIGHT, which
+%%% you should have received as part of this distribution. The terms
+%%% are also available at http://www.rogvall.se/docs/copyright.txt.
+%%%
+%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
+%%% copies of the Software, and permit persons to whom the Software is
+%%% furnished to do so, under the terms of the COPYRIGHT file.
+%%%
+%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+%%% KIND, either express or implied.
+%%%
+%%%---- END COPYRIGHT ----------------------------------------------------------
+%%%-------------------------------------------------------------------
+%%% @author Malotte W Lönne <malotte@malotte.net>
+%%% @copyright (C) 2012, Tony Rogvall
+%%% @doc
+%%% ale application.
+%%% A lager extension.
+%%%
+%%% Created : 2012 by Malotte W Lönne
+%%% @end
+%%%-------------------------------------------------------------------
+
+-module(ale).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2,
+ stop/1]).
+
+%% Shortcut API
+-export([start/0,
+ stop/0]).
+
+%% Start/Stop traces
+-export([trace/3,
+ trace_gl/3,
+ trace/4,
+ trace_gl/4,
+ debug/1,
+ debug_gl/1,
+ info/1,
+ info_gl/1,
+ warning/1,
+ warning_gl/1,
+ error/1,
+ error_gl/1,
+ clear/0]).
+
+%% Info requests
+-export([i/0]).
+
+-define(SRV, ale_srv).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the application.<br/>
+%% Arguments are ignored, instead the options for the application server are
+%% retreived from the application environment (sys.config).
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec start(StartType:: normal |
+ {takeover, Node::atom()} |
+ {failover, Node::atom()},
+ StartArgs::term()) ->
+ {ok, Pid::pid()} |
+ {ok, Pid::pid(), State::term()} |
+ {error, Reason::term()}.
+
+start(_StartType, _StartArgs) ->
+ error_logger:info_msg("~p: start: arguments ignored.\n", [?MODULE]),
+ Opts = case application:get_env(options) of
+ undefined -> [];
+ {ok, O} -> O
+ end,
+ Traces = case application:get_env(init_traces) of
+ undefined -> [];
+ {ok, T} -> T
+ end,
+ Args = [{options, Opts},{init_traces, Traces}],
+ ale_sup:start_link(Args).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Stops the application.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec stop(State::term()) -> ok | {error, Error::term()}.
+
+stop(_State) ->
+ ok.
+
+-type log_level() :: debug |
+ info |
+ notice |
+ warning |
+ error |
+ critical |
+ alert |
+ emergency.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Controls tracing.
+%% For details see lager documentation.
+%% @end
+%%--------------------------------------------------------------------
+-spec trace(OnOrOff:: on | off,
+ ModuleOrPidOrFilter::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(tuple()),
+ Level::log_level()) ->
+ ok | {error, Error::term()}.
+
+trace(OnOrOff, ModulOrPidOrFilter, Level) ->
+ trace(OnOrOff, ModulOrPidOrFilter, Level, console).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Controls tracing.
+%% For details see lager documentation.
+%% @end
+%%--------------------------------------------------------------------
+-spec trace(OnOrOff:: on | off,
+ ModuleOrPidOrFilter::atom() |
+ pid() |
+ tuple() |
+ list(tuple()),
+ Level::log_level(),
+ File::string() | console) ->
+ ok | {error, Error::term()}.
+
+trace(OnOrOff, Module, Level, File)
+ when is_atom(OnOrOff), is_atom(Module), is_atom(Level) ->
+ call({trace, OnOrOff, [{module, Module}], Level, self(), File});
+trace(OnOrOff, Pid, Level, File)
+ when is_atom(OnOrOff), is_pid(Pid), is_atom(Level) ->
+ call({trace, OnOrOff, [{pid, pid_to_list(Pid)}], Level, self(), File});
+trace(OnOrOff, Filter, Level, File)
+ when is_atom(OnOrOff), is_tuple(Filter),is_atom(Level) ->
+ call({trace, OnOrOff, [Filter], Level, self(), File});
+trace(OnOrOff, FilterList, Level, File)
+ when is_atom(OnOrOff), is_list(FilterList),is_atom(Level) ->
+ call({trace, OnOrOff, FilterList, Level, self(), File}).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Controls tracing.
+%% This variant uses the groupleader() instead of self() to monitor
+%% client. Suitable for calls from an erlang shell.
+%% For details see lager documentation.
+%% @end
+%%--------------------------------------------------------------------
+-spec trace_gl(OnOrOff:: on | off,
+ ModuleOrPidOrFilter::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(tuple()),
+ Level::log_level()) ->
+ ok | {error, Error::term()}.
+
+trace_gl(OnOrOff, Module, Level) ->
+ trace_gl(OnOrOff, Module, Level, console).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Controls tracing.
+%% This variant uses the groupleader() instead of self() to monitor
+%% client. Suitable for calls from an erlang shell.
+%% For details see lager documentation.
+%% @end
+%%--------------------------------------------------------------------
+-spec trace_gl(OnOrOff:: on | off,
+ ModuleOrPidOrFilter::atom() |
+ pid() |
+ tuple() |
+ list(tuple()),
+ Level::log_level(),
+ File::string() | console) ->
+ ok | {error, Error::term()}.
+
+trace_gl(OnOrOff, Module, Level, File)
+ when is_atom(OnOrOff), is_atom(Module), is_atom(Level) ->
+ call({trace, OnOrOff, [{module, Module}], Level, group_leader(), File});
+trace_gl(OnOrOff, Pid, Level, File)
+ when is_atom(OnOrOff), is_pid(Pid), is_atom(Level) ->
+ call({trace, OnOrOff, [{pid, pid_to_list(Pid)}], Level,
+ group_leader(), File});
+trace_gl(OnOrOff, Filter, Level, File)
+ when is_atom(OnOrOff), is_tuple(Filter), is_atom(Level) ->
+ call({trace, OnOrOff, [Filter], Level, group_leader(), File});
+trace_gl(OnOrOff, FilterList, Level, File)
+ when is_atom(OnOrOff), is_list(FilterList), is_atom(Level) ->
+ call({trace, OnOrOff, FilterList, Level, group_leader(), File}).
+
+
+call({trace, _OnOrOff, _FilterList, _Level, _Client, console} = Trace) ->
+ gen_server:call(?SRV, Trace);
+call({trace, _OnOrOff, _FilterList, _Level, _Client, File} = Trace)
+ when is_list(File) ->
+ %% Do we want this check ??
+ case filelib:is_regular(File) of
+ true ->
+ gen_server:call(?SRV, Trace);
+ false ->
+ {error, non_existing_file}
+ end.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Lists existing traces and clients.
+%% @end
+%%--------------------------------------------------------------------
+-spec i() -> list(tuple()).
+
+i() ->
+ gen_server:call(?SRV, i).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace(on, X, debug).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec debug(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+debug(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, debug).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace_gl(on, X, debug).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec debug_gl(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+debug_gl(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, debug, gl).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace(on, X, info).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec info(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+info(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, info).
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace_gl(on, X, info).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec info_gl(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+info_gl(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, info, gl).
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace(on, X, warning).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec warning(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+warning(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, warning).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace_gl(on, X, warning).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec warning_gl(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+warning_gl(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, warning, gl).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace(on, X, error).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec error(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+error(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, error).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Shortcut to trace_gl(on, X, error).
+%% For details see {@link trace/3}.
+%% Can be called with a list of modules.
+%% @end
+%%--------------------------------------------------------------------
+-spec error_gl(ModuleOrPidOrList::atom() |
+ string() |
+ pid() |
+ tuple() |
+ list(atom())) ->
+ ok | {error, Error::term()}.
+
+error_gl(ModulOrPidOrList) ->
+ trace_i(ModulOrPidOrList, error, gl).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Removes all traces for all clients.
+%% @end
+%%--------------------------------------------------------------------
+-spec clear() -> ok.
+
+clear() ->
+ gen_server:call(?SRV, clear).
+
+
+%%--------------------------------------------------------------------
+%% Test functions
+%%--------------------------------------------------------------------
+%% @private
+start() ->
+ app_ctrl([kernel, stdlib, compiler, syntax_tools, sasl, lager, ale],start).
+
+%% @private
+stop() ->
+ app_ctrl([ale, lager],stop).
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+%% @private
+app_ctrl([], _F) ->
+ ok;
+app_ctrl([App|Apps], F) ->
+ error_logger:info_msg("~p: ~p\n", [F,App]),
+ case application:F(App) of
+ {error,{not_started,App1}} ->
+ case F of
+ start ->
+ app_ctrl([App1,App|Apps], F);
+ stop ->
+ app_ctrl(Apps, F)
+ end;
+ {error,{already_started,App}} ->
+ app_ctrl(Apps, F);
+ ok ->
+ app_ctrl(Apps, F);
+ Error ->
+ Error
+ end.
+
+%% @private
+trace_i(Module, Level) ->
+ trace_i(Module, Level, self).
+
+trace_i(Module, Level, Type)
+ when is_atom(Module), is_atom(Level) ->
+ trace_i([Module], Level, Type);
+trace_i([], _Level, _Type) ->
+ ok;
+trace_i([Module | Rest], Level, self)
+ when is_atom(Module), is_atom(Level) ->
+ trace(on, Module, Level),
+ trace_i(Rest, Level, self);
+trace_i([Module | Rest], Level, gl)
+ when is_atom(Module), is_atom(Level) ->
+ trace_gl(on, Module, Level),
+ trace_i(Rest, Level, gl);
+trace_i([Filter | _Rest] = FilterList, Level, self)
+ when is_tuple(Filter), is_atom(Level) ->
+ trace(on, FilterList, Level);
+trace_i([Filter | _Rest] = FilterList, Level, gl)
+ when is_tuple(Filter), is_atom(Level) ->
+ trace_gl(on, FilterList, Level).
+
diff --git a/deps/ale/src/ale_srv.erl b/deps/ale/src/ale_srv.erl
new file mode 100644
index 0000000..f6a56fe
--- /dev/null
+++ b/deps/ale/src/ale_srv.erl
@@ -0,0 +1,590 @@
+%%%---- BEGIN COPYRIGHT --------------------------------------------------------
+%%%
+%%% Copyright (C) 2007 - 2012, Rogvall Invest AB, <tony@rogvall.se>
+%%%
+%%% This software is licensed as described in the file COPYRIGHT, which
+%%% you should have received as part of this distribution. The terms
+%%% are also available at http://www.rogvall.se/docs/copyright.txt.
+%%%
+%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
+%%% copies of the Software, and permit persons to whom the Software is
+%%% furnished to do so, under the terms of the COPYRIGHT file.
+%%%
+%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+%%% KIND, either express or implied.
+%%%
+%%%---- END COPYRIGHT ----------------------------------------------------------
+%%%-------------------------------------------------------------------
+%%% @author Malotte Westman Lönne <malotte@malotte.net>
+%%% @copyright (C) 2012, Tony Rogvall
+%%% @doc
+%%% ale server.
+%%%
+%%% Created: 2012 by Malotte W Lönne
+%%% @end
+%%%-------------------------------------------------------------------
+-module(ale_srv).
+
+-behaviour(gen_server).
+
+-include_lib("lager/include/log.hrl").
+
+
+%% API
+-export([start_link/1,
+ stop/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%% Testing
+-export([start/0,
+ start/1,
+ traces/0,
+ clients/0,
+ dump/0,
+ debug/1]).
+
+-record(trace_item,
+ {
+ trace,
+ lager_ref,
+ client
+ }).
+
+-record(client_item,
+ {
+ pid,
+ monitor
+ }).
+
+-record(ctx,
+ {
+ trace_list = [],
+ client_list = [],
+ debug %% Debug of own process
+ }).
+
+-define(dbg(Format, Args),
+ lager:debug("~s(~p): " ++ Format, [?MODULE, self() | Args])).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server that will keep track of traces.
+%% @end
+%%--------------------------------------------------------------------
+-spec start_link(Options::list(tuple())) ->
+ {ok, Pid::pid()} |
+ ignore |
+ {error, Error::term()}.
+
+start_link(Args) ->
+ ?dbg("start_link: starting, args ~p",[Args]),
+ Opts = proplists:get_value(options, Args, []),
+ F = case proplists:get_value(linked,Opts,true) of
+ true -> start_link;
+ false -> start
+ end,
+ gen_server:F({local, ?MODULE}, ?MODULE, Args, []).
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Stops the server.
+%% @end
+%%--------------------------------------------------------------------
+-spec stop() -> ok | {error, Error::term()}.
+
+stop() ->
+ ?dbg("start_link: stopping",[]),
+ gen_server:call(?MODULE, stop).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Lists existing traces.
+%% @end
+%%--------------------------------------------------------------------
+-spec traces() -> list(tuple()).
+
+traces() ->
+ gen_server:call(?MODULE, traces).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Lists existing clients.
+%% @end
+%%--------------------------------------------------------------------
+-spec clients() -> list(tuple()).
+
+clients() ->
+ gen_server:call(?MODULE, clients).
+
+
+%%--------------------------------------------------------------------
+%% Test functions
+%% @private
+start() ->
+ start([]).
+%% @private
+start(Args) ->
+ gen_server:start({local, ?MODULE}, ?MODULE, Args, []).
+
+%% @private
+dump() ->
+ gen_server:call(?MODULE, dump).
+
+%% @private
+debug(TrueOrFalse) ->
+ gen_server:call(?MODULE, {debug, TrueOrFalse}).
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec init(list(tuple())) ->
+ {ok, Ctx::#ctx{}} |
+ {stop, Reason::term()}.
+
+init(Args) ->
+ Opts = proplists:get_value(options, Args, []),
+ {ok,Debug} = set_debug(proplists:get_value(debug, Opts, false), undefined),
+ ?dbg("init: args ~p",[Args]),
+ InitTraces = proplists:get_value(init_traces, Args, []),
+ TL =
+ lists:foldl(fun({Filter, Level}, TraceList) ->
+ {_Result, TmpL} =
+ add_trace({Filter, Level, console},
+ self(), TraceList),
+ TmpL;
+ ({Filter, Level, File}, TraceList) ->
+ %% Do we want this check ??
+ case filelib:is_regular(File) of
+ true ->
+ {_Result, TmpL} =
+ add_trace({Filter, Level, File},
+ self(), TraceList),
+ TmpL;
+ false ->
+ error_logger:error_msg(
+ "ale: non existing file ~p, " ++
+ "no trace added.~n", [File]),
+ TraceList
+ end
+ end,
+ [], InitTraces),
+ {ok, #ctx {debug = Debug, trace_list = TL}}.
+
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages.
+%% Request can be the following:
+%% <ul>
+%% <li> trace</li>
+%% <li> dump</li>
+%% <li> stop</li>
+%% </ul>
+%%
+%% @end
+%%--------------------------------------------------------------------
+-type call_request()::
+ {trace,
+ OnOrOff:: on | off,
+ Filter::list(tuple()),
+ Level::atom(),
+ Pid::pid()} |
+ dump |
+ {debug, TrueOrFalse::boolean()} |
+ clear |
+ stop.
+
+-spec handle_call(Request::call_request(),
+ From::{pid(), Tag::term()},
+ Ctx::#ctx{}) ->
+ {reply, Reply::term(), Ctx::#ctx{}} |
+ {noreply, Ctx::#ctx{}} |
+ {stop, Reason::atom(), Reply::term(), Ctx::#ctx{}}.
+
+
+handle_call({trace, on, Filter, Level, Client, File} = _T, _From,
+ Ctx=#ctx {trace_list = TL, client_list = CL})
+ when is_list(Filter) ->
+ ?dbg("handle_call: trace on ~p.",[_T]),
+ case add_trace({Filter, Level, File}, Client, TL) of
+ {ok, NewTL} ->
+ NewCL = monitor_client(Client, CL),
+ {reply, ok, Ctx#ctx {trace_list = NewTL, client_list = NewCL}};
+ {Error, TL} ->
+ {reply, Error, Ctx}
+ end;
+handle_call({trace, off, Filter, Level, Client, File} = _T, _From,
+ Ctx=#ctx {trace_list = TL, client_list = CL})
+ when is_list(Filter) ->
+ ?dbg("handle_call: trace off ~p.",[_T]),
+ case remove_trace({Filter, Level, File}, Client, TL) of
+ {ok, NewTL} ->
+ NewCL = demonitor_client(Client, NewTL, CL),
+ {reply, ok, Ctx#ctx {trace_list = NewTL, client_list = NewCL}};
+ {E, TL} ->
+ {reply, E, Ctx}
+ end;
+
+handle_call(traces, _From, Ctx=#ctx {trace_list = TL}) ->
+ ?dbg("handle_call: traces.",[]),
+ {reply, TL, Ctx};
+
+handle_call(clients, _From, Ctx=#ctx {client_list = CL}) ->
+ ?dbg("handle_call: clients.",[]),
+ {reply, CL, Ctx};
+
+handle_call(i, _From, Ctx=#ctx {trace_list = TL, client_list = CL}) ->
+ ?dbg("handle_call: i.",[]),
+ PrettyTraceList = {'Trace list:',
+ lists:map(
+ fun(#trace_item {client = C, trace = {F, L, B}}) ->
+ lists:flatten(
+ io_lib:format(
+ "Client ~p, filter ~p, level ~p, backend ~p.",
+ [C, F, L, B]))
+ end, TL)},
+ PrettyClientList = {'Client list:',
+ lists:map(
+ fun(#client_item {pid = P}) ->
+ lists:flatten(io_lib:format("Client ~p.", [P]))
+ end, CL)},
+ {reply, {PrettyTraceList, PrettyClientList}, Ctx};
+
+handle_call(dump, _From, Ctx=#ctx {trace_list = TL, client_list = CL}) ->
+ lists:foreach(fun(#trace_item {client = C, trace = T, lager_ref = LR}) ->
+ io:format("Client ~p, trace ~p, ref ~w.\n",
+ [C, T, LR])
+ end, TL),
+ lists:foreach(fun(#client_item {pid = P, monitor = M}) ->
+ io:format("Client ~p, monitor ~p.\n",
+ [P, M])
+ end, CL),
+ {reply, ok, Ctx};
+
+handle_call({debug, TrueOrFalse}, _From, Ctx=#ctx {debug = Dbg}) ->
+ case set_debug(TrueOrFalse, Dbg) of
+ {ok, NewDbg} ->
+ {reply, ok, Ctx#ctx { debug = NewDbg }};
+ Error ->
+ {reply, Error, Ctx}
+ end;
+
+handle_call(clear, _From, Ctx=#ctx {trace_list = TL, client_list = CL}) ->
+ lists:foldl(fun(#trace_item {trace = Trace, client = Client}, Rest) ->
+ remove_trace(Trace, Client, TL),
+ Rest
+ end, [], TL),
+ ?dbg("clear: traces removed.",[]),
+ lists:foreach(fun( #client_item {monitor = Mon}) ->
+ erlang:demonitor(Mon, [flush])
+ end, CL),
+ ?dbg("clear: clients removed.",[]),
+ {reply, ok, Ctx#ctx {trace_list = [], client_list = []}};
+
+handle_call(stop, _From, Ctx) ->
+ ?dbg("handle_call: stop.",[]),
+ {stop, normal, ok, Ctx};
+
+handle_call(_Request, _From, Ctx) ->
+ ?dbg("handle_call: unknown request ~p.", [_Request]),
+ {reply, {error,bad_call}, Ctx}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-type cast_msg()::
+ term().
+
+-spec handle_cast(Msg::cast_msg(), Ctx::#ctx{}) ->
+ {noreply, Ctx::#ctx{}} |
+ {stop, Reason::term(), Ctx::#ctx{}}.
+
+handle_cast(_Msg, Ctx) ->
+ ?dbg("handle_cast: unknown msg ~p", [_Msg]),
+ {noreply, Ctx}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-type info()::
+ {'DOWN', Ref::reference(), process, Pid::pid(), Reason::term()} |
+ term().
+
+-spec handle_info(Info::info(), Ctx::#ctx{}) ->
+ {noreply, Ctx::#ctx{}} |
+ {noreply, Ctx::#ctx{}, Timeout::timeout()} |
+ {stop, Reason::term(), Ctx::#ctx{}}.
+
+handle_info({'DOWN', MonRef, process, _Pid, Reason},
+ Ctx=#ctx {trace_list = TL, client_list = CL}) ->
+ ?dbg("handle_info: DOWN for process ~p received, reason ~p.",
+ [_Pid, Reason]),
+ %% See if we have this client
+ {NewCL, NewTL} =
+ case lists:keytake(MonRef, #client_item.monitor, CL) of
+ false ->
+ %% Ignore
+ ?dbg("handle_info: client not found.",[]),
+ {CL, TL};
+ {value, #client_item {pid = Pid}, Rest} ->
+ %% Remove all traces for this client
+ ?dbg("handle_info: client found, removing traces.",[]),
+ {Rest, remove_traces(Pid, TL, [])}
+
+ end,
+ {noreply, Ctx#ctx {trace_list = NewTL, client_list = NewCL}};
+
+handle_info(_Info, Ctx) ->
+ ?dbg("handle_info: unknown info ~p received.", [_Info]),
+ {noreply, Ctx}.
+
+%%--------------------------------------------------------------------
+%% @private
+%%--------------------------------------------------------------------
+-spec terminate(Reason::term(), Ctx::#ctx{}) ->
+ no_return().
+
+terminate(_Reason,
+ _Ctx=#ctx {trace_list = TL, client_list = CL, debug = Dbg}) ->
+ ?dbg("terminate: Reason = ~p.",[_Reason]),
+ lists:foldl(fun(#trace_item {trace = Trace, client = Client}, Rest) ->
+ remove_trace(Trace, Client, TL),
+ Rest
+ end, [], TL),
+ ?dbg("terminate: traces removed.",[]),
+ lists:foreach(fun( #client_item {monitor = Mon}) ->
+ erlang:demonitor(Mon, [flush])
+ end, CL),
+ ?dbg("terminate: clients removed.",[]),
+ stop_debug(Dbg),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process ctx when code is changed.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec code_change(OldVsn::term(), Ctx::#ctx{}, Extra::term()) ->
+ {ok, NewCtx::#ctx{}}.
+
+code_change(_OldVsn, Ctx, _Extra) ->
+ ?dbg("code_change: old version ~p.",[_OldVsn]),
+ {ok, Ctx}.
+
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%% @private
+%%--------------------------------------------------------------------
+-spec add_trace({Filter::term(), Level::atom(), File::string() | console},
+ Client::pid(), TL::list(tuple())) ->
+ list(tuple()).
+
+add_trace(Trace = {Filter, Level, File}, Client, TL) ->
+ %% See if we already are tracing this.
+ ?dbg("add_trace: trace ~p for client ~p",[Trace, Client]),
+ case lists:keyfind(Trace, #trace_item.trace, TL) of
+ false ->
+ %% Create new trace in lager
+ ?dbg("add_trace: trace ~p not found.",[Trace]),
+ Res =
+ case File of
+ console ->
+ lager:trace_console(Filter, Level);
+ _F ->
+ lager:trace_file(File, Filter,Level)
+ end,
+ case Res of
+ {ok, LagerRef} ->
+ ?dbg("add_trace: trace added in lager, ref ~p.",[LagerRef]),
+ {ok,
+ [#trace_item {trace = Trace,
+ lager_ref = LagerRef,
+ client = Client}
+ | TL]};
+ {error, _Reason} = E->
+ ?dbg("add_trace: lager call failed, reason ~p.",[_Reason]),
+ {E, TL}
+ end;
+ #trace_item {trace = Trace, client = Client} ->
+ %% Trace already exists, ignore
+ ?dbg("add_trace: trace ~p found.",[Trace]),
+ {ok, TL};
+ #trace_item {trace = Trace, lager_ref = LagerRef, client = _Other} ->
+ %% Trace exists in lager, just add a post locally
+ ?dbg("add_trace: trace ~p found for client ~p.",
+ [Trace, _Other]),
+ {ok,
+ [#trace_item {trace = Trace, lager_ref = LagerRef, client = Client}
+ | TL]}
+ end.
+
+%%--------------------------------------------------------------------
+%% @private
+%%--------------------------------------------------------------------
+-spec remove_trace({Filter::term(), Level::atom(), File::string()},
+ Client::pid(), TL::list(tuple())) ->
+ list(tuple()).
+
+remove_trace(Trace, Client, TL) ->
+ %% See if we are tracing this.
+ ?dbg("remove_trace: trace ~p for client ~p.",[Trace, Client]),
+ case lists:keytake(Trace, #trace_item.trace, TL) of
+ false ->
+ %% Ignore ??
+ ?dbg("remove_trace: trace ~p not found in ~p.",[Trace, TL]),
+ {ok, TL};
+ {value,
+ #trace_item {trace = Trace, lager_ref = LagerRef, client = Client},
+ Rest} ->
+ %% See if it was the last trace of this
+ case lists:keyfind(Trace, #trace_item.trace, Rest) of
+ false ->
+ %% Last trace, remove in lager and locally
+ ?dbg("remove_trace: last trace ~p found.",[Trace]),
+ case lager:stop_trace(LagerRef) of
+ ok ->
+ {ok, Rest};
+ {error, _Reason} = E ->
+ ?dbg("add_trace: lager call failed, reason ~p.",
+ [_Reason]),
+ {E, TL}
+ end;
+ #trace_item {} ->
+ %% We still need this trace in lager,
+ %% only remove locally
+ ?dbg("remove_trace: more traces ~p exist.",[Trace]),
+ {ok, Rest}
+ end;
+ {value, #trace_item {trace = Trace, client = _Other}, _Rest} ->
+ ?dbg("remove_trace: trace ~p found for client ~p.",
+ [Trace, _Other]),
+ {ok, TL}
+ end.
+
+%%--------------------------------------------------------------------
+%% @private
+%%--------------------------------------------------------------------
+-spec monitor_client(Client::pid(), CL::list(pid())) ->
+ list(pid()).
+
+monitor_client(Client, CL) ->
+ %% See if we already have this client
+ case lists:keyfind(Client, #client_item.pid, CL) of
+ false ->
+ %% Monitor the client
+ ?dbg("monitor_client: new client pid ~p.",[Client]),
+ Mon = erlang:monitor(process, Client),
+ [#client_item {pid = Client, monitor = Mon} | CL];
+ #client_item {pid = Client} ->
+ ?dbg("monitor_client: old client pid ~p.",[Client]),
+ CL
+ end.
+
+%%--------------------------------------------------------------------
+%% @private
+%%--------------------------------------------------------------------
+-spec demonitor_client(Client::pid(), CL::list(pid()), TL::list(tuple())) ->
+ list(pid()).
+
+demonitor_client(Client, TL, CL) ->
+ %% See if we have this client
+ case lists:keytake(Client, #client_item.pid, CL) of
+ false ->
+ %% Ignore
+ ?dbg("demonitor_client: client pid ~p not found.",[Client]),
+ CL;
+ {value, #client_item {pid = Client, monitor = Mon}, Rest} ->
+ %% See if this client has any traces left
+ case lists:keyfind(Client, #trace_item.client, TL) of
+ false ->
+ %% No more traces
+ %% Demonitor the client
+ ?dbg("demonitor_client: last trace for client ~p.",
+ [Client]),
+ erlang:demonitor(Mon, [flush]),
+ Rest;
+ #trace_item {} ->
+ %% Continue monitoring
+ ?dbg("demonitor_client: more traces for client ~p.",
+ [Client]),
+ CL
+ end
+ end.
+
+
+%%--------------------------------------------------------------------
+%% @private
+%%--------------------------------------------------------------------
+-spec remove_traces(Client::pid(), TL::list(tuple()), NewTL::list(tuple())) ->
+ list(tuple()).
+
+remove_traces(_Client, [], NewTL) ->
+ ?dbg("remove_traces: all traces for client ~p removed.",[_Client]),
+ NewTL;
+remove_traces(Client,
+ [#trace_item {trace = Trace, lager_ref = LagerRef, client = Client}
+ | RestTL], NewTL) ->
+ %% See if it was the last trace of this
+ case lists:keytake(Trace, #trace_item.trace, RestTL) of
+ false ->
+ %% Last trace, remove in lager and locally
+ ?dbg("remove_traces:last trace for client ~p found.",
+ [Client]),
+ lager:stop_trace(LagerRef),
+ remove_traces(Client, RestTL, NewTL);
+ {value, _TraceItem, _RestOfRest} ->
+ %% We still need this trace in lager,
+ %% only remove locally
+ ?dbg("remove_traces: more traces for client ~p found.",
+ [Client]),
+ remove_traces(Client, RestTL, NewTL)
+ end;
+remove_traces(Client, [Item | RestTL], NewTL) ->
+ %% Not this client
+ ?dbg("remove_traces: traces for other client found.",[]),
+ remove_traces(Client, RestTL, [Item | NewTL]).
+
+
+%% Internal debugging
+stop_debug(undefined) ->
+ undefined;
+stop_debug(Dbg) ->
+ lager:stop_trace(Dbg),
+ undefined.
+
+%% enable/disable module debug
+set_debug(false, Dbg) ->
+ NewDbg = stop_debug(Dbg),
+ lager:set_loglevel(lager_console_backend, info),
+ {ok, NewDbg};
+set_debug(true, undefined) ->
+ lager:trace_console([{module,?MODULE}], debug);
+set_debug(true, Dbg) ->
+ {ok, Dbg}.
+
diff --git a/deps/ale/src/ale_sup.erl b/deps/ale/src/ale_sup.erl
new file mode 100644
index 0000000..cfd0fce
--- /dev/null
+++ b/deps/ale/src/ale_sup.erl
@@ -0,0 +1,95 @@
+%%%---- BEGIN COPYRIGHT --------------------------------------------------------
+%%%
+%%% Copyright (C) 2007 - 2012, Rogvall Invest AB, <tony@rogvall.se>
+%%%
+%%% This software is licensed as described in the file COPYRIGHT, which
+%%% you should have received as part of this distribution. The terms
+%%% are also available at http://www.rogvall.se/docs/copyright.txt.
+%%%
+%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
+%%% copies of the Software, and permit persons to whom the Software is
+%%% furnished to do so, under the terms of the COPYRIGHT file.
+%%%
+%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+%%% KIND, either express or implied.
+%%%
+%%%---- END COPYRIGHT ----------------------------------------------------------
+%%%-------------------------------------------------------------------
+%%% @author Malotte W Lönne <malotte@malotte.net>
+%%% @copyright (C) 2012, Tony Rogvall
+%%% @doc
+%%% ale application supervisor.
+%%% @end
+%%% Created : 2012 by Malotte W Lönne
+%%%-------------------------------------------------------------------
+
+-module(ale_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/1,
+ stop/1]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+%% Helper macro for declaring children of supervisor
+-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
+
+
+%% ===================================================================
+%% API functions
+%% ===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the supervisor. <br/>
+%% Arguments are sent on to the supervisor.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec start_link(Args::list(term())) ->
+ {ok, Pid::pid()} |
+ ignore |
+ {error, Error::term()}.
+
+start_link(Args) ->
+ error_logger:info_msg("~p: start_link: args = ~p\n", [?MODULE, Args]),
+ try supervisor:start_link({local, ?MODULE}, ?MODULE, Args) of
+ {ok, Pid} ->
+ {ok, Pid, {normal, Args}};
+ Error ->
+ error_logger:error_msg("~p: start_link: Failed to start process, "
+ "reason ~p\n", [?MODULE, Error]),
+ Error
+ catch
+ error:Reason ->
+ error_logger:error_msg("~p: start_link: Try failed, reason ~p\n",
+ [?MODULE,Reason]),
+ Reason
+ end.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Stops the supervisor.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec stop(StartArgs::list(term())) -> ok | {error, Error::term()}.
+
+stop(_StartArgs) ->
+ exit(stopped).
+
+%% ===================================================================
+%% Supervisor callbacks
+%% ===================================================================
+%% @private
+init(Args) ->
+ error_logger:info_msg("~p: init: args = ~p,\n pid = ~p\n",
+ [?MODULE, Args, self()]),
+ AS = ale_srv,
+ Ale = {AS, {AS, start_link, [Args]}, permanent, 5000, worker, [AS]},
+ error_logger:info_msg("~p: About to start ~p\n", [?MODULE,Ale]),
+ {ok, { {one_for_one, 0, 300}, [Ale]} }.
+
diff --git a/deps/ale/sys.config b/deps/ale/sys.config
new file mode 100644
index 0000000..35c3f7c
--- /dev/null
+++ b/deps/ale/sys.config
@@ -0,0 +1,39 @@
+%% -*- erlang -*-
+%%
+%% ale
+%% Configuration file for included erlang applications.
+[
+ %% SASL config
+ {sasl, [
+ {sasl_error_logger, {file, "log/sasl-error.log"}},
+ {errlog_type, error},
+ {error_logger_mf_dir, "log/sasl"}, % Log directory
+ {error_logger_mf_maxbytes, 10485760}, % 10 MB max file size
+ {error_logger_mf_maxfiles, 5} % 5 files max
+ ]},
+ %% Lager config, see lager documentation
+ {lager, [
+ {handlers,
+ [
+ {lager_console_backend, debug},
+ {lager_file_backend,
+ [
+ {"log/lager/error.log", error, 10485760, "$D0", 5},
+ {"log/lager/console.log", info, 10485760, "$D0", 5}
+ ]}
+ ]}
+ ]},
+ %% Ale config.
+ %% For format of trace filter and level, see lager doc.
+ {ale, [
+ {options, []},
+ %% {options, [{debug, true}]},
+ %% traces - list({list(Filter:tuple()), Level}) %% to console
+ %% list({list(Filter:tuple()), Level, File}) %% to file
+ %% Filter for ex {module, Module}
+ {init_traces, [
+ %% {[{module, sz_master}], debug},
+ %% {[{module, sz_node}], info, "/tmp/ale.log"}
+ ]}
+ ]}
+].
diff --git a/deps/ale/test/.gitignore b/deps/ale/test/.gitignore
new file mode 100644
index 0000000..5d9033f
--- /dev/null
+++ b/deps/ale/test/.gitignore
@@ -0,0 +1,4 @@
+*.beam
+*.html
+ct*
+*~ \ No newline at end of file
diff --git a/deps/ale/test/Makefile b/deps/ale/test/Makefile
new file mode 100644
index 0000000..eb05b29
--- /dev/null
+++ b/deps/ale/test/Makefile
@@ -0,0 +1,34 @@
+#
+# Make the ale test modules
+#
+
+MODULES = \
+ ale_SUITE
+
+
+EBIN = .
+ERLC = erlc
+
+ERLDIR := $(shell erl -noshell -eval "io:format([126,115,126,110],[code:root_dir()])" -s erlang halt)
+
+override ERLC_FLAGS = -Wall -I ../include
+
+debug: ERLC_FLAGS += +debug_info -Ddebug
+
+OBJS = $(MODULES:%=$(EBIN)/%.beam)
+
+all: $(OBJS)
+
+debug: all
+
+depend:
+ edep -MM -o ../ebin $(ERLC_FLAGS) $(MODULES:%=%.erl) > depend.mk
+
+clean:
+ rm -f $(OBJS)
+
+
+-include depend.mk
+
+./%.beam: %.erl
+ erlc -o ../ebin $(ERLC_FLAGS) $<
diff --git a/deps/ale/test/ale_SUITE.erl b/deps/ale/test/ale_SUITE.erl
new file mode 100644
index 0000000..b0b48e6
--- /dev/null
+++ b/deps/ale/test/ale_SUITE.erl
@@ -0,0 +1,361 @@
+%%%---- BEGIN COPYRIGHT --------------------------------------------------------
+%%%
+%%% Copyright (C) 2007 - 2012, Rogvall Invest AB, <tony@rogvall.se>
+%%%
+%%% This software is licensed as described in the file COPYRIGHT, which
+%%% you should have received as part of this distribution. The terms
+%%% are also available at http://www.rogvall.se/docs/copyright.txt.
+%%%
+%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
+%%% copies of the Software, and permit persons to whom the Software is
+%%% furnished to do so, under the terms of the COPYRIGHT file.
+%%%
+%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+%%% KIND, either express or implied.
+%%%
+%%%---- END COPYRIGHT ----------------------------------------------------------
+%%%-------------------------------------------------------------------
+%%% @author Marina Westman Lönne <malotte@malotte.net>
+%%% @copyright (C) 2012, Tony Rogvall
+%%% @doc
+%%% Test suite for ale.
+%%% @end
+%%% Created : 2012 by Marina Westman Lönne <malotte@malotte.net>
+%%%-------------------------------------------------------------------
+-module(ale_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% COMMON TEST CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Returns list of tuples to set default properties
+%% for the suite.
+%% @spec suite() -> Info
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{minutes,10}}].
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Returns the list of groups and test cases that
+%% are to be executed.
+%%
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [start_of_ale_app,
+ start_with_it_console,
+ start_with_it_file,
+ start_with_it_no_file,
+ add_trace,
+ add_trace_gl,
+ add_trace_pid,
+ add_trace_and_die,
+ add_trace_wrong_level,
+ remove_non_existing_trace].
+%% break].
+
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Initialization before the whole suite
+%%
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ start_system(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Cleanup after the whole suite
+%%
+%% @spec end_per_suite(Config) -> _
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ application:stop(ale),
+ stop_system(),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Initialization before each test case
+%%
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(TC, Config) ->
+ ct:pal("Init testcase: ~p", [TC]),
+ tc_init(TC, Config).
+
+tc_init(start_with_it_file, Config) ->
+ os:cmd("touch ./ale.log"),
+ Config;
+tc_init(_Any, Config) ->
+ Config.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Cleanup after each test case
+%%
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1} | {fail,Reason}
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(TC, Config) ->
+ ct:pal("End testcase: ~p", [TC]),
+ tc_end(TC, Config).
+
+tc_end(start_of_ale_app, _Config) ->
+ application:stop(ale),
+ ct:pal("Stopped ale."),
+ ok;
+tc_end(start_with_it_file, Config) ->
+ os:cmd("rm ./ale.log"),
+ tc_end(any, Config);
+tc_end(_Any, _Config) ->
+ ale_srv:stop(),
+ ct:pal("Stopped ale server."),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Start of ale application.
+%% @end
+%%--------------------------------------------------------------------
+-spec start_of_ale_app(Config::list(tuple())) -> ok.
+
+start_of_ale_app(_Config) ->
+ ale:start(),
+ ok = ale_srv:dump(),
+ ct:pal("Ale up and running"),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Start of ale with init trace to console.
+%% @end
+%%--------------------------------------------------------------------
+-spec start_with_it_console(Config::list(tuple())) -> ok.
+
+start_with_it_console(_Config) ->
+ {ok, Pid} = ale_srv:start([{init_traces,
+ [{[{module, ale_SUITE}], debug}]}]),
+ ok = ale_srv:dump(),
+ [{trace_item, {[{module, ale_SUITE}], debug, console}, _LagRef, Pid}] =
+ ale_srv:traces(),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Start of ale with init trace to file.
+%% @end
+%%--------------------------------------------------------------------
+-spec start_with_it_file(Config::list(tuple())) -> ok.
+
+start_with_it_file(_Config) ->
+ {ok, Pid} = ale_srv:start([{init_traces,
+ [{[{module, ale_SUITE}], debug, "./ale.log"}]}]),
+ ok = ale_srv:dump(),
+ [{trace_item, {[{module, ale_SUITE}], debug, _File}, _LagRef, Pid}] =
+ ale_srv:traces(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Start of ale with init trace refering to non-existing file.
+%% @end
+%%--------------------------------------------------------------------
+-spec start_with_it_no_file(Config::list(tuple())) -> ok.
+
+start_with_it_no_file(_Config) ->
+ {ok, _Pid} = ale_srv:start([{init_traces,
+ [{[{module, ale_SUITE}], debug, "./ale.log"}]}]),
+ ok = ale_srv:dump(),
+ [] = ale_srv:traces(),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Add/remove trace on module.
+%% @end
+%%--------------------------------------------------------------------
+-spec add_trace(Config::list(tuple())) -> ok.
+
+add_trace(_Config) ->
+ Self = self(),
+ {ok, _Pid} = ale_srv:start(),
+ ok = ale_srv:dump(),
+ ok = ale:trace(on, ale_SUITE, debug),
+ [{trace_item, {[{module, ale_SUITE}], debug, console}, _LagRef, Self}] =
+ ale_srv:traces(),
+ ok = ale:trace(off, ale_SUITE, debug),
+ [] = ale_srv:traces(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Add/remove trace on module with groupleader.
+%% @end
+%%--------------------------------------------------------------------
+-spec add_trace_gl(Config::list(tuple())) -> ok.
+
+add_trace_gl(_Config) ->
+ GL = group_leader(),
+ {ok, _Pid} = ale_srv:start(),
+ ok = ale:trace_gl(on, ale_SUITE, info),
+ ok = ale_srv:dump(),
+ [{trace_item, {[{module, ale_SUITE}], info, console}, _LagRef, GL}] =
+ ale_srv:traces(),
+ ok = ale:trace_gl(off, ale_SUITE, info),
+ [] = ale_srv:traces(),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Add/remove trace on pid.
+%% @end
+%%--------------------------------------------------------------------
+-spec add_trace_pid(Config::list(tuple())) -> ok.
+
+add_trace_pid(_Config) ->
+ Self = self(),
+ SelfStr = pid_to_list(Self),
+ {ok, _Pid} = ale_srv:start(),
+ ok = ale:trace(on, Self, debug),
+ ok = ale_srv:dump(),
+ [{trace_item, {[{pid, SelfStr}], debug, console}, _LagRef, Self}] =
+ ale_srv:traces(),
+ ok = ale:trace(off, Self, debug),
+ [] = ale_srv:traces(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Have tmp processes add trace and die.
+%% @end
+%%--------------------------------------------------------------------
+-spec add_trace_and_die(Config::list(tuple())) -> ok.
+
+add_trace_and_die(_Config) ->
+ {ok, _AlePid} = ale_srv:start(),
+ TmpPid = proc_lib:spawn(?MODULE, trace_starter, []),
+ timer:sleep(100),
+ ok = ale_srv:dump(),
+ [{trace_item, {[{module, ale_SUITE}], debug, console}, _LagRef, TmpPid}] =
+ ale_srv:traces(),
+ TmpPid ! die,
+ timer:sleep(100),
+ [] = ale_srv:traces(),
+ ok.
+
+trace_starter() ->
+ ok = ale:trace(on, ale_SUITE, debug),
+ receive
+ die ->
+ ct:pal("Told to die")
+ after
+ 1000 ->
+ ct:fail("Timeout")
+ end.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Add trace with incorrect level.
+%% @end
+%%--------------------------------------------------------------------
+-spec add_trace_wrong_level(Config::list(tuple())) -> ok.
+
+add_trace_wrong_level(_Config) ->
+ {ok, _AlePid} = ale_srv:start(),
+ {error, E} = ale:trace(on, ale_SUITE, wrong),
+ ok = ale_srv:dump(),
+ ct:pal("Error ~p", [E]),
+ [] = ale_srv:traces(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Remove non existing trace.
+%% @end
+%%--------------------------------------------------------------------
+-spec remove_non_existing_trace(Config::list(tuple())) -> ok.
+
+remove_non_existing_trace(_Config) ->
+ {ok, _AlePid} = ale_srv:start(),
+ %% Is ok OK??
+ ok = ale:trace(off, ale_SUITE, debug),
+ ok = ale_srv:dump(),
+ [] = ale_srv:traces(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Dummy test case to have a test environment running.
+%% Stores Config in ets table.
+%% @end
+%%--------------------------------------------------------------------
+-spec break(Config::list(tuple())) -> ok.
+
+break(Config) ->
+ ets:new(config, [set, public, named_table]),
+ ets:insert(config, Config),
+ test_server:break("Break for test development\n" ++
+ "Get Config by ets:tab2list(config)"),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% Help functions
+%%--------------------------------------------------------------------
+start_system() ->
+ app_ctrl([kernel, stdlib, compiler, syntax_tools, sasl, lager],start).
+
+stop_system() ->
+ app_ctrl([lager], stop).
+
+app_ctrl([], _F) ->
+ ok;
+app_ctrl([App|Apps], F) ->
+ error_logger:info_msg("~p: ~p\n", [F,App]),
+ case application:F(App) of
+ {error,{not_started,App1}} ->
+ case F of
+ start ->
+ app_ctrl([App1,App|Apps], F);
+ stop ->
+ app_ctrl(Apps, F)
+ end;
+ {error,{already_started,App}} ->
+ app_ctrl(Apps, F);
+ ok ->
+ app_ctrl(Apps, F);
+ Error ->
+ Error
+ end.