Permalink
Browse files

add global counter

  • Loading branch information...
stolen committed Jun 28, 2014
1 parent b45e5e6 commit 0f14927644194222993f0da72004bdbfc212637c
Showing with 71 additions and 2 deletions.
  1. +7 −2 src/erdico.erl
  2. +64 −0 src/erdico_counter.erl
View
@@ -27,7 +27,9 @@ stop(_) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init(root) ->
{ok, _} = start_cowboy(),
{ok, {{one_for_one, 10, 5}, []}}.
Counter = {counter, {erdico_counter, start_link, []},
permanent, 1000, worker, [erdico_counter]},
{ok, {{one_for_one, 10, 5}, [Counter]}}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Internals
@@ -37,4 +39,7 @@ start_cowboy() ->
Host = {'_', [DefPath]}, % No virtualhosts
Dispatch = cowboy_router:compile([Host]),
Env = [{env, [{dispatch, Dispatch}]}],
cowboy:start_http(?MODULE, 10, [{port, 2080}], Env).
cowboy:start_http(?MODULE, 10, [{port, conf(port, 2080)}], Env).
conf(Key, Default) ->
application:get_env(?MODULE, Key, Default).
View
@@ -0,0 +1,64 @@
-module(erdico_counter).
-export([start_link/0, inc/0, inc/1]).
-behavior(gen_server).
-export([init/1, handle_info/2, handle_cast/2, handle_call/3, terminate/2, code_change/3]).
%% API
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
inc() ->
inc(1).
inc(Inc) ->
Master = global:whereis_name(?MODULE),
gen_server:call(Master, {inc, Inc}).
% Start: choose role
init([]) ->
ok = global:sync(),
{ok, capture_or_monitor()}.
% Become master or monitor existing one
capture_or_monitor() ->
case global:register_name(?MODULE, self()) of
yes -> {master, 0};
no -> {slave, set_monitor()}
end.
% Monitor master
set_monitor() ->
Master = global:whereis_name(?MODULE),
erlang:monitor(process, Master).
% When master goes down, try to change him
handle_info({'DOWN', Ref, process, _Master, _Info}, {slave, Ref}) ->
{noreply, capture_or_monitor()};
% Dummy
handle_info(_, State) ->
{noreply, State}.
% Dummy
handle_cast(_, State) ->
{noreply, State}.
% When client asks to increment master's number, do it
handle_call({inc, Inc}, _From, {master, Count}) when is_integer(Inc) ->
NextCount = Count + Inc,
{reply, {ok, NextCount}, {master, NextCount}};
% Refuse to increment on slave
handle_call({inc, _}, _From, {slave, _} = State) ->
{reply, {error, slave}, State};
% Default: return error
handle_call(_, _From, State) ->
{reply, {error, not_implemented}, State}.
% Dummy
code_change(_, State, _) ->
{ok, State}.
% Dummy
terminate(_, _) ->
ok.

0 comments on commit 0f14927

Please sign in to comment.