Pārlūkot izejas kodu

Add support for event fields that are notfound, and begin some documentation

develop-sidejob
Pedram Nimreezi pirms 11 gadiem
vecāks
revīzija
088a095717
15 mainītis faili ar 486 papildinājumiem un 28 dzēšanām
  1. +1
    -1
      Makefile
  2. +0
    -0
      README.md
  3. +188
    -0
      README.org
  4. +130
    -0
      priv/edoc.css
  5. +2
    -0
      rebar.config
  6. +60
    -10
      src/glc.erl
  7. +26
    -2
      src/glc_code.erl
  8. +24
    -5
      src/glc_lib.erl
  9. +11
    -2
      src/glc_ops.erl
  10. +1
    -1
      src/gr_counter.erl
  11. +18
    -3
      src/gr_manager.erl
  12. +6
    -1
      src/gr_manager_sup.erl
  13. +1
    -1
      src/gr_param.erl
  14. +7
    -1
      src/gr_param_sup.erl
  15. +11
    -1
      src/gr_sup.erl

+ 1
- 1
Makefile Parādīt failu

@ -27,7 +27,7 @@ ct:
build-plt:
@$(DIALYZER) --build_plt --output_plt .$(APPNAME)_dialyzer.plt \
--apps kernel stdlib sasl inets crypto public_key ssl
--apps kernel stdlib sasl inets crypto public_key ssl compiler syntax_tools
dialyze:
@$(DIALYZER) --src src --plt .$(APPNAME)_dialyzer.plt --no_native \

+ 0
- 0
README.md Parādīt failu


+ 188
- 0
README.org Parādīt failu

@ -0,0 +1,188 @@
# Goldrush #
Goldrush is a small Erlang app that provides fast event stream processing
# Features #
* Event processing compiled to a query module
- per module protected event processing statistics
- query module logic can be combined for any/all filters
- query module logic can be reduced to efficiently match event processing
* Complex event processing logic
- match input events with greater than (gt) logic
- match input events with less than (lt) logic
- match input events with equal to (eq) logic
- match input events with wildcard (wc) logic
- match input events with notfound (nf) logic
- match no input events (null blackhole) logic
- match all input events (null passthrough) logic
* Handle output events
- Once a query has been composed the output action can be overriden
with an erlang function. The function will be applied to each
output event from the query.
# Usage #
To use goldrush in your application, you need to define it as a rebar dep or
include it in erlang's path.
Before composing modules, you'll need to define a query. The query syntax is
matches any number of `{erlang, terms}' and is composed as follows:
* Simple Logic
- Simple logic is defined as any logic matching a single event filter
Select all events where 'a' exists and is greater than 0.
#+BEGIN_EXAMPLE
glc:gt(a, 0).
#+END_EXAMPLE
Select all events where 'a' exists and is equal to 0.
#+BEGIN_EXAMPLE
glc:eq(a, 0).
#+END_EXAMPLE
Select all events where 'a' exists and is less than 0.
#+BEGIN_EXAMPLE
glc:lt(a, 0).
#+END_EXAMPLE
Select all events where 'a' exists.
#+BEGIN_EXAMPLE
glc:wc(a).
#+END_EXAMPLE
Select all events where 'a' does not exist.
#+BEGIN_EXAMPLE
glc:nf(a, 0).
#+END_EXAMPLE
Select no input events. User as a black hole query.
#+BEGIN_EXAMPLE
glc:null(false).
#+END_EXAMPLE
Select all input events. Used as a passthrough query.
#+BEGIN_EXAMPLE
glc:null(true).
#+END_EXAMPLE
* Combined Logic
- Combined logic is defined as logic matching multiple event filters
Select all events where both 'a' `and' 'b' exists and are greater than 0.
#+BEGIN_EXAMPLE
glc:all([glc:gt(a, 0), glc:gt(b, 0)]).
#+END_EXAMPLE
Select all events where 'a' `or' 'b' exists and are greater than 0.
#+BEGIN_EXAMPLE
glc:any([glc:gt(a, 0), glc:gt(b, 0)]).
#+END_EXAMPLE
Select all events where 'a' `and' 'b' exists where 'a' is greater than 1 and 'b' is less than 2.
#+BEGIN_EXAMPLE
glc:all([glc:gt(a, 1), glc:lt(b, 2)]).
#+END_EXAMPLE
Select all events where 'a' `or' 'b' exists where 'a' is greater than 1 and 'b' is less than 2.
#+BEGIN_EXAMPLE
glc:any([glc:gt(a, 1), glc:lt(b, 2)]).
#+END_EXAMPLE
* Reduced Logic
- Reduced logic is defined as logic which can be simplified to improve efficiency.
Select all events where 'a' is equal to 1, 'b' is equal to 2 and 'c' is equal to 3 and collapse any duplicate logic.
#+BEGIN_EXAMPLE
glc_lib:reduce(
glc:all([
glc:any([glc:eq(a, 1), glc:eq(b, 2)]),
glc:any([glc:eq(a, 1), glc:eq(c, 3)])])).
#+END_EXAMPLE
The previous example will produce and is equivalent to:
#+BEGIN_EXAMPLE
glc:all([glc:eq(a, 1), glc:eq(b, 2), glc:eq(c, 3)]).
#+END_EXAMPLE
# Composing Modules #
To compose a module you will take your Query defined above and compile it.
#+BEGIN_EXAMPLE
glc:compile(Module, Query).
#+END_EXAMPLE
# Handling Events #
At this point you will be able to handle an event using a compiled query.
Begin by constructing an event list.
#+BEGIN_EXAMPLE
Event = gre:make([{'a', 2}], [list]).
#+END_EXAMPLE
Now pass it to your query module to be handled.
#+BEGIN_EXAMPLE
glc:handle(Module, Event).
#+END_EXAMPLE
* Handling output events
- You can override the output action with an erlang function.
Write all input events as info reports to the error logger.
#+BEGIN_EXAMPLE
glc:with(glc:null(true), fun(E) ->
error_logger:info_report(gre:pairs(E)) end).
#+END_EXAMPLE
Write all input events where `error_level' exists and is less than 5 as info reports to the error logger.
#+BEGIN_EXAMPLE
glc:with(glc:lt(error_level, 5), fun(E) ->
error_logger:info_report(gre:pairs(E)) end).
#+END_EXAMPLE
# Event Processing Statistics #
Return the number of input events for this query module.
#+BEGIN_EXAMPLE
glc:input(Module).
#+END_EXAMPLE
Return the number of output events for this query module.
#+BEGIN_EXAMPLE
glc:output(Module).
#+END_EXAMPLE
Return the number of filtered events for this query module.
#+BEGIN_EXAMPLE
glc:filter(Module).
#+END_EXAMPLE
## How to build ##
`$ ./rebar compile`
or
`$ make`
## CHANGELOG ##
### 0.1.6 ###
- Add notfound event matching
### 0.1.5 ###
- Rewrite to make highly crash resilient
- per module supervision
- statistics data recovery
- Add wildcard event matching
- Add reset counters

+ 130
- 0
priv/edoc.css Parādīt failu

@ -0,0 +1,130 @@
/* Baseline rhythm */
body {
font-size: 16px;
font-family: Helvetica, sans-serif;
margin: 8px;
}
p {
font-size: 1em; /* 16px */
line-height: 1.5em; /* 24px */
margin: 0 0 1.5em 0;
}
h1 {
font-size: 1.5em; /* 24px */
line-height: 1em; /* 24px */
margin-top: 1em;
margin-bottom: 0em;
}
h2 {
font-size: 1.375em; /* 22px */
line-height: 1.0909em; /* 24px */
margin-top: 1.0909em;
margin-bottom: 0em;
}
h3 {
font-size: 1.25em; /* 20px */
line-height: 1.2em; /* 24px */
margin-top: 1.2em;
margin-bottom: 0em;
}
h4 {
font-size: 1.125em; /* 18px */
line-height: 1.3333em; /* 24px */
margin-top: 1.3333em;
margin-bottom: 0em;
}
.class-for-16px {
font-size: 1em; /* 16px */
line-height: 1.5em; /* 24px */
margin-top: 1.5em;
margin-bottom: 0em;
}
.class-for-14px {
font-size: 0.875em; /* 14px */
line-height: 1.7143em; /* 24px */
margin-top: 1.7143em;
margin-bottom: 0em;
}
ul {
margin: 0 0 1.5em 0;
}
/* Customizations */
body {
color: #333;
}
tt, code, pre {
font-family: "Andale Mono", "Inconsolata", "Monaco", "DejaVu Sans Mono", monospaced;
}
tt, code { font-size: 0.875em }
pre {
font-size: 0.875em; /* 14px */
line-height: 1.7143em; /* 24px */
margin: 0 1em 1.7143em;
padding: 0 1em;
background: #eee;
}
.navbar img, hr { display: none }
table {
border-collapse: collapse;
}
h1 {
border-left: 0.5em solid #fa0;
padding-left: 0.5em;
}
h2.indextitle {
font-size: 1.25em; /* 20px */
line-height: 1.2em; /* 24px */
margin: -8px -8px 0.6em;
background-color: #fa0;
color: white;
padding: 0.3em;
}
ul.index {
list-style: none;
margin-left: 0em;
padding-left: 0;
}
ul.index li {
display: inline;
padding-right: 0.75em
}
div.spec p {
margin-bottom: 0;
padding-left: 1.25em;
background-color: #eee;
}
h3.function {
border-left: 0.5em solid #fa0;
padding-left: 0.5em;
background: #fc9;
}
a, a:visited, a:hover, a:active { color: #C60 }
h2 a, h3 a { color: #333 }
i {
font-size: 0.875em; /* 14px */
line-height: 1.7143em; /* 24px */
margin-top: 1.7143em;
margin-bottom: 0em;
font-style: normal;
}

+ 2
- 0
rebar.config Parādīt failu

@ -4,3 +4,5 @@
%% warn_missing_spec,
warn_export_all
]}.
{edoc_opts, [{stylesheet_file, "./priv/edoc.css"}]}.

+ 60
- 10
src/glc.erl Parādīt failu

@ -44,7 +44,7 @@
%% %% Select all events where both 'a' and 'b' exists and are greater than 0.
%% glc:all([glc:gt(a, 0), glc:gt(b, 0)]).
%% %% Select all events where 'a' or 'b' exists and are greater than 0.
%% glc:any([glc:get(a, 0), glc:gt(b, 0)]).
%% glc:any([glc:gt(a, 0), glc:gt(b, 0)]).
%% '''
%%
%% === Handling output events ===
@ -74,7 +74,8 @@
lt/2,
eq/2,
gt/2,
wc/1
wc/1,
nf/1
]).
-export([
@ -85,6 +86,9 @@
]).
-export([
input/1,
output/1,
filter/1,
union/1
]).
@ -110,6 +114,10 @@ gt(Key, Term) ->
wc(Key) ->
glc_ops:wc(Key).
-spec nf(atom()) -> glc_ops:op().
nf(Key) ->
glc_ops:nf(Key).
%% @doc Filter the input using multiple filters.
%%
%% For an input to be considered valid output the all filters specified
@ -192,6 +200,22 @@ compile(Module, Query, Reset) ->
handle(Module, Event) ->
Module:handle(Event).
%% @doc The number of input events for this query module.
-spec input(atom()) -> non_neg_integer().
input(Module) ->
Module:info(input).
%% @doc The number of output events for this query module.
-spec output(atom()) -> non_neg_integer().
output(Module) ->
Module:info(output).
%% @doc The number of filtered events for this query module.
-spec filter(atom()) -> non_neg_integer().
filter(Module) ->
Module:info(filter).
%% @doc Release a compiled query.
%%
%% This releases all resources allocated by a compiled query. The query name
@ -392,9 +416,35 @@ events_test_() ->
?assertEqual(1, Mod:info(output))
end
},
{"opfilter wildcard test",
fun() ->
{compiled, Mod} = setup_query(testmod8, glc:wc(a)),
glc:handle(Mod, gre:make([{b, 2}], [list])),
?assertEqual(1, Mod:info(input)),
?assertEqual(1, Mod:info(filter)),
?assertEqual(0, Mod:info(output)),
glc:handle(Mod, gre:make([{a, 2}], [list])),
?assertEqual(2, Mod:info(input)),
?assertEqual(1, Mod:info(filter)),
?assertEqual(1, Mod:info(output))
end
},
{"opfilter notfound test",
fun() ->
{compiled, Mod} = setup_query(testmod9, glc:nf(a)),
glc:handle(Mod, gre:make([{a, 2}], [list])),
?assertEqual(1, Mod:info(input)),
?assertEqual(1, Mod:info(filter)),
?assertEqual(0, Mod:info(output)),
glc:handle(Mod, gre:make([{b, 2}], [list])),
?assertEqual(2, Mod:info(input)),
?assertEqual(1, Mod:info(filter)),
?assertEqual(1, Mod:info(output))
end
},
{"opfilter greater than test",
fun() ->
{compiled, Mod} = setup_query(testmod8, glc:gt(a, 1)),
{compiled, Mod} = setup_query(testmod10, glc:gt(a, 1)),
glc:handle(Mod, gre:make([{'a', 2}], [list])),
?assertEqual(1, Mod:info(input)),
?assertEqual(0, Mod:info(filter)),
@ -406,7 +456,7 @@ events_test_() ->
},
{"opfilter less than test",
fun() ->
{compiled, Mod} = setup_query(testmod9, glc:lt(a, 1)),
{compiled, Mod} = setup_query(testmod11, glc:lt(a, 1)),
glc:handle(Mod, gre:make([{'a', 0}], [list])),
?assertEqual(1, Mod:info(input)),
?assertEqual(0, Mod:info(filter)),
@ -419,7 +469,7 @@ events_test_() ->
},
{"allholds op test",
fun() ->
{compiled, Mod} = setup_query(testmod10,
{compiled, Mod} = setup_query(testmod12,
glc:all([glc:eq(a, 1), glc:eq(b, 2)])),
glc:handle(Mod, gre:make([{'a', 1}], [list])),
glc:handle(Mod, gre:make([{'a', 2}], [list])),
@ -437,7 +487,7 @@ events_test_() ->
},
{"anyholds op test",
fun() ->
{compiled, Mod} = setup_query(testmod11,
{compiled, Mod} = setup_query(testmod13,
glc:any([glc:eq(a, 1), glc:eq(b, 2)])),
glc:handle(Mod, gre:make([{'a', 2}], [list])),
glc:handle(Mod, gre:make([{'b', 1}], [list])),
@ -452,7 +502,7 @@ events_test_() ->
{"with function test",
fun() ->
Self = self(),
{compiled, Mod} = setup_query(testmod12,
{compiled, Mod} = setup_query(testmod14,
glc:with(glc:eq(a, 1), fun(Event) -> Self ! gre:fetch(a, Event) end)),
glc:handle(Mod, gre:make([{a,1}], [list])),
?assertEqual(1, Mod:info(output)),
@ -461,7 +511,7 @@ events_test_() ->
},
{"delete test",
fun() ->
{compiled, Mod} = setup_query(testmod13, glc:null(false)),
{compiled, Mod} = setup_query(testmod15, glc:null(false)),
?assert(is_atom(Mod:table(params))),
?assertMatch([_|_], gr_param:info(Mod:table(params))),
?assert(is_list(code:which(Mod))),
@ -481,7 +531,7 @@ events_test_() ->
},
{"reset counters test",
fun() ->
{compiled, Mod} = setup_query(testmod14,
{compiled, Mod} = setup_query(testmod16,
glc:any([glc:eq(a, 1), glc:eq(b, 2)])),
glc:handle(Mod, gre:make([{'a', 2}], [list])),
glc:handle(Mod, gre:make([{'b', 1}], [list])),
@ -510,7 +560,7 @@ events_test_() ->
{"ets data recovery test",
fun() ->
Self = self(),
{compiled, Mod} = setup_query(testmod15,
{compiled, Mod} = setup_query(testmod17,
glc:with(glc:eq(a, 1), fun(Event) -> Self ! gre:fetch(a, Event) end)),
glc:handle(Mod, gre:make([{a,1}], [list])),
?assertEqual(1, Mod:info(output)),

+ 26
- 2
src/glc_code.erl Parādīt failu

@ -1,5 +1,24 @@
%% @doc Code generation functions.
-module(glc_code).
-compile({nowarn_unused_function, {abstract_module,2}}).
-compile({nowarn_unused_function, {abstract_tables,1}}).
-compile({nowarn_unused_function, {abstract_reset,0}}).
-compile({nowarn_unused_function, {abstract_filter,2}}).
-compile({nowarn_unused_function, {abstract_filter_,4}}).
-compile({nowarn_unused_function, {abstract_opfilter,6}}).
-compile({nowarn_unused_function, {abstract_all,4}}).
-compile({nowarn_unused_function, {abstract_any,4}}).
-compile({nowarn_unused_function, {abstract_with,2}}).
-compile({nowarn_unused_function, {abstract_getkey,4}}).
-compile({nowarn_unused_function, {abstract_getkey_,4}}).
-compile({nowarn_unused_function, {abstract_getparam,3}}).
-compile({nowarn_unused_function, {abstract_getparam_,3}}).
-compile({nowarn_unused_function, {param_variable,1}}).
-compile({nowarn_unused_function, {field_variable,1}}).
-compile({nowarn_unused_function, {field_variable_,1}}).
-compile({nowarn_unused_function, {compile_forms,2}}).
-compile({nowarn_unused_function, {load_binary,2}}).
-export([
compile/2
@ -165,7 +184,7 @@ abstract_filter(Cond, State) ->
%% @private Return a list of expressions to apply a filter.
%% A filter expects two continuation functions which generates the expressions
%% to apply when the filter matches or fails to match. The state passed to the
%% functions will be contain all variable bindings to previously accessed
%% functions will contain all the variable bindings of previously accessed
%% fields and parameters.
-spec abstract_filter_(glc_ops:op(), nextFun(), nextFun(), #state{}) ->
syntaxTree().
@ -177,6 +196,11 @@ abstract_filter_({Key, '*'}, OnMatch, OnNomatch, State) ->
abstract_getkey(Key,
_OnMatch=fun(#state{}=State2) -> OnMatch(State2) end,
_OnNomatch=fun(State2) -> OnNomatch(State2) end, State);
abstract_filter_({Key, '!'}, OnMatch, OnNomatch, State) ->
abstract_getkey(Key,
_OnNomatch=fun(State2) -> OnNomatch(State2) end,
_OnMatch=fun(#state{}=State2) -> OnMatch(State2) end,
State);
abstract_filter_({Key, Op, Value}, OnMatch, OnNomatch, State)
when Op =:= '>'; Op =:= '='; Op =:= '<' ->
Op2 = case Op of '=' -> '=:='; Op -> Op end,
@ -353,7 +377,7 @@ abstract_getcount(Counter) ->
?erl:abstract(Counter)])].
%% @private Return an expression to reset a counter.
-spec abstract_resetcount(atom()) -> [syntaxTree()].
-spec abstract_resetcount(atom() | [filter | input | output]) -> [syntaxTree()].
abstract_resetcount(Counter) ->
[abstract_apply(gr_counter, reset_counters,
[abstract_apply(table, [?erl:atom(counters)]),

+ 24
- 5
src/glc_lib.erl Parādīt failu

@ -74,7 +74,9 @@ matches({Key, '*'}, Event) ->
case gre:find(Key, Event) of
{true, _} -> true;
false -> false
end.
end;
matches({Key, '!'}, Event) ->
not matches({Key, '*'}, Event).
%% @private Repeatedly apply a function to a query.
%% This is used for query transformation functions that must be applied
@ -87,6 +89,7 @@ repeat(Query, Fun) ->
%% @doc Return the output action of a query.
-spec onoutput(glc_ops:op()) -> output | no_return().
onoutput({_, '<', _}) ->
output;
onoutput({_, '=', _}) ->
@ -95,10 +98,13 @@ onoutput({_, '>', _}) ->
output;
onoutput({_, '*'}) ->
output;
onoutput({_, '!'}) ->
output;
onoutput(Query) ->
erlang:error(badarg, [Query]).
%% @doc Modify the output action of a query.
-spec onoutput(Action :: any(), Query :: glc_ops:op()) -> no_return().
onoutput(Action, Query) ->
erlang:error(badarg, [Action, Query]).
@ -238,6 +244,7 @@ deleteall(Filter, []) ->
%% @private Test if a term is a valid filter.
-spec is_valid(glc_ops:op()) -> boolean().
is_valid({Field, '<', _Term}) when is_atom(Field) ->
true;
is_valid({Field, '=', _Term}) when is_atom(Field) ->
@ -246,6 +253,8 @@ is_valid({Field, '>', _Term}) when is_atom(Field) ->
true;
is_valid({Field, '*'}) when is_atom(Field) ->
true;
is_valid({Field, '!'}) when is_atom(Field) ->
true;
is_valid({null, true}) ->
true;
is_valid({null, false}) ->
@ -256,6 +265,7 @@ is_valid(_Other) ->
%% @private Assert that a term is a valid filter.
%% If the term is a valid filter. The original term will be returned.
%% If the term is not a valid filter. A `badarg' error is thrown.
-spec valid(glc_ops:op()) -> boolean() | no_return().
valid(Term) ->
is_valid(Term) orelse erlang:error(badarg, [Term]),
Term.
@ -279,6 +289,13 @@ any_one_test() ->
glc_lib:reduce(glc:any([glc:eq(a, 1)]))
).
all_two_test() ->
?assertEqual(glc_lib:reduce(glc:all([glc:wc(a), glc:nf(b)])),
glc_lib:reduce(glc:any([
glc:all([glc:wc(a)]),
glc:all([glc:wc(a), glc:nf(b)])]))
).
any_sort_test() ->
?assertEqual(glc:any([glc:eq(a, 1), glc:eq(b, 2)]),
glc_lib:reduce(glc:any([glc:eq(b, 2), glc:eq(a, 1)]))
@ -317,11 +334,12 @@ any_equiv_test() ->
any_required_test() ->
?assertEqual(
glc:all([
glc:any([glc:eq(b, 2), glc:eq(c, 3)]),
glc:any([glc:nf(d), glc:eq(b, 2), glc:eq(c, 3)]),
glc:eq(a, 1)
]),
glc_lib:reduce(
glc:any([
glc:all([glc:eq(a, 1), glc:nf(d)]),
glc:all([glc:eq(a, 1), glc:eq(b, 2)]),
glc:all([glc:eq(a, 1), glc:eq(c, 3)])]))
).
@ -340,21 +358,22 @@ delete_from_all_test() ->
?assertEqual(
glc:all([glc:eq(b,2)]),
deleteall(
glc:all([glc:eq(a, 1),glc:eq(b,2)]), [glc:eq(a, 1)])
glc:all([glc:eq(a, 1),glc:eq(b,2)]), [glc:eq(a, 1), glc:nf(a)])
).
delete_from_any_test() ->
?assertEqual(
glc:any([glc:eq(b,2)]),
deleteall(
glc:any([glc:eq(a, 1),glc:eq(b,2)]), [glc:eq(a, 1)])
glc:any([glc:eq(a, 1),glc:eq(b,2)]), [glc:eq(a, 1), glc:wc(a)])
).
default_is_output_test_() ->
[?_assertEqual(output, glc_lib:onoutput(glc:lt(a, 1))),
?_assertEqual(output, glc_lib:onoutput(glc:eq(a, 1))),
?_assertEqual(output, glc_lib:onoutput(glc:gt(a, 1))),
?_assertEqual(output, glc_lib:onoutput(glc:wc(a)))
?_assertEqual(output, glc_lib:onoutput(glc:wc(a))),
?_assertEqual(output, glc_lib:onoutput(glc:nf(a)))
].
-ifdef(PROPER).

+ 11
- 2
src/glc_ops.erl Parādīt failu

@ -5,7 +5,8 @@
lt/2,
eq/2,
gt/2,
wc/1
wc/1,
nf/1
]).
-export([
@ -24,6 +25,7 @@
{atom(), '=', term()} |
{atom(), '>', term()} |
{atom(), '*'} |
{atom(), '!'} |
{any, [op(), ...]} |
{all, [op(), ...]} |
{null, true|false}.
@ -51,13 +53,20 @@ gt(Key, Term) when is_atom(Key) ->
gt(Key, Term) ->
erlang:error(badarg, [Key, Term]).
%% @doc Test that a field value is exists.
%% @doc Test that a field exists.
-spec wc(atom()) -> op().
wc(Key) when is_atom(Key) ->
{Key, '*'};
wc(Key) ->
erlang:error(badarg, [Key]).
%% @doc Test that a field is not found.
-spec nf(atom()) -> op().
nf(Key) when is_atom(Key) ->
{Key, '!'};
nf(Key) ->
erlang:error(badarg, [Key]).
%% @doc Filter the input using multiple filters.
%%
%% For an input to be considered valid output the all filters specified

+ 1
- 1
src/gr_counter.erl Parādīt failu

@ -75,7 +75,7 @@ reset_counters(Server, Counter) ->
%% @doc
%% Starts the server
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @spec start_link(Name) -> {ok, Pid} | ignore | {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link(Name) ->

+ 18
- 3
src/gr_manager.erl Parādīt failu

@ -12,8 +12,17 @@
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-module(gr_manager).
%% @doc Process table manager for goldrush.
%%
%% Manager responsible for the processes, which serve as heir of the
%% {@link gr_counter:start_link/0. <em>Counter</em>} and
%% {@link gr_param:start_link/0. <em>Param</em>} ets table processes.
%% This process creates the table and initial data then assigns itself
%% to inherit the ets table if any process responsible for it is killed.
%% It then waits to give it back while that process is recreated by its
%% supervisor.
-module(gr_manager).
-behaviour(gen_server).
%% API
@ -29,12 +38,14 @@
-define(SERVER, ?MODULE).
-record(state, {table_id :: ets:tid(), managee :: atom()}).
-record(state, {table_id :: ets:tab(), managee :: atom()}).
%%%===================================================================
%%% API
%%%===================================================================
%% Setup the initial data for the ets table
-spec setup(atom() | pid(), term()) -> ok.
setup(Name, Data) ->
gen_server:cast(Name, {setup, Data}).
@ -42,7 +53,8 @@ setup(Name, Data) ->
%% @doc
%% Starts the server
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @spec start_link(Name, Managee, Data) -> {ok, Pid} | ignore |
%% {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link(Name, Managee, Data) ->
@ -125,6 +137,9 @@ handle_info({'ETS-TRANSFER', TableId, _Pid, Data}, State = #state{managee=Manage
ets:give_away(TableId, ManageePid, Data),
{noreply, State#state{table_id=TableId}}.
%% @doc Wait for a registered process to be associated to a process identifier.
%% @spec wait_for_pid(Managee) -> ManageePid
-spec wait_for_pid(atom()) -> pid().
wait_for_pid(Managee) when is_atom(Managee), Managee =/= undefined ->
case whereis(Managee) of
undefined ->

+ 6
- 1
src/gr_manager_sup.erl Parādīt failu

@ -12,8 +12,13 @@
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%% @doc Table manager supervisor for all goldrush ets process tables.
%%
%% Manager supervisor responsible for the {@link gr_manager:start_link/3.
%% <em>Manager</em>} processes, which serve as heir of the
%% {@link gr_counter:start_link/0. <em>Counter</em>} and
%% {@link gr_param:start_link/0. <em>Param</em>} ets table processes.
-module(gr_manager_sup).
-behaviour(supervisor).
-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().

+ 1
- 1
src/gr_param.erl Parādīt failu

@ -89,7 +89,7 @@ transform(Server) ->
%% @doc
%% Starts the server
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @spec start_link(Name) -> {ok, Pid} | ignore | {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link(Name) ->

+ 7
- 1
src/gr_param_sup.erl Parādīt failu

@ -12,8 +12,14 @@
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-module(gr_param_sup).
%% @doc Second level supervisor for goldrush.
%%
%% Supervisor for the {@link gr_param:start_link/0.
%% <em>Param</em>}, process table responsible for params
%% {@link gr_param:start_link/0. <em>Counter</em>} and
%% their {@link gr_counter:start_link/0. <em>Manager</em>} supervisors.
-module(gr_param_sup).
-behaviour(supervisor).
-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().

+ 11
- 1
src/gr_sup.erl Parādīt failu

@ -13,20 +13,30 @@
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%% @doc Top level supervisor for goldrush.
%%
%% Main supervisor responsible for the {@link gr_counter_sup:start_link/0.
%% <em>Counter</em>}, {@link gr_param_sup:start_link/0. <em>Param</em>} and
%% their {@link gr_manager_sup:start_link/0. <em>Manager</em>} supervisors.
-module(gr_sup).
-behaviour(supervisor).
-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().
-type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.
-export([start_link/0]).
-export([init/1]).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
-spec start_link() -> startlink_ret().
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-spec init([]) -> {ok, { {one_for_one, 50, 10}, [supervisor:child_spec()]} }.
init([]) ->
CounterSup = ?CHILD(gr_counter_sup, supervisor),
ParamSup = ?CHILD(gr_param_sup, supervisor),
MgrSup = ?CHILD(gr_manager_sup, supervisor),
{ok, {{one_for_one, 5, 10}, [CounterSup, ParamSup, MgrSup]}}.
{ok, {{one_for_one, 50, 10}, [CounterSup, ParamSup, MgrSup]}}.

Notiek ielāde…
Atcelt
Saglabāt