You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by be...@apache.org on 2014/02/13 17:35:49 UTC

[16/23] goldrush commit: updated refs/heads/import-master to 71e6321

Protect params table and extend per module supervision


Project: http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/commit/18042453
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/tree/18042453
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/diff/18042453

Branch: refs/heads/import-master
Commit: 1804245358b731f7f9419e4bcc3b0a63278a98aa
Parents: 457e980
Author: Pedram Nimreezi <de...@deadzen.com>
Authored: Thu Nov 7 16:02:21 2013 -0500
Committer: Pedram Nimreezi <de...@deadzen.com>
Committed: Thu Nov 7 16:02:21 2013 -0500

----------------------------------------------------------------------
 src/glc.erl            | 122 ++++++++++++++++++++++------
 src/glc_code.erl       |  32 ++++----
 src/gr_counter.erl     |  26 +++---
 src/gr_counter_mgr.erl | 170 --------------------------------------
 src/gr_counter_sup.erl |  42 ++++++++++
 src/gr_manager.erl     | 168 ++++++++++++++++++++++++++++++++++++++
 src/gr_manager_sup.erl |  42 ++++++++++
 src/gr_param.erl       | 194 ++++++++++++++++++++++++++++++++++++++++++++
 src/gr_param_sup.erl   |  42 ++++++++++
 src/gr_sup.erl         |   8 +-
 10 files changed, 619 insertions(+), 227 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/glc.erl
----------------------------------------------------------------------
diff --git a/src/glc.erl b/src/glc.erl
index 1dc0928..ff0a6e6 100644
--- a/src/glc.erl
+++ b/src/glc.erl
@@ -87,7 +87,7 @@
 
 -record(module, {
     'query' :: term(),
-    tables :: [{atom(), ets:tid()}],
+    tables :: [{atom(), atom()}],
     qtree :: term()
 }).
 
@@ -167,7 +167,7 @@ union(Queries) ->
 %% function. The name of the query module is expected to be unique.
 -spec compile(atom(), list()) -> {ok, atom()}.
 compile(Module, Query) ->
-    {ok, ModuleData} = module_data(Query),
+    {ok, ModuleData} = module_data(Module, Query),
     case glc_code:compile(Module, ModuleData) of
         {ok, Module} ->
             {ok, Module}
@@ -186,27 +186,73 @@ handle(Module, Event) ->
 %% is expected to be associated with an existing query module. Calling this
 %% function will result in a runtime error.
 -spec delete(atom()) -> ok.
-delete(_Module) ->
+delete(Module) ->
+    Params = params_name(Module),
+    Counts = counts_name(Module),
+    ManageParams = manage_params_name(Module),
+    ManageCounts = manage_counts_name(Module),
+
+    [ begin 
+        supervisor:terminate_child(Sup, Name),
+        supervisor:delete_child(Sup, Name)
+      end || {Sup, Name} <- 
+        [{gr_manager_sup, ManageParams}, {gr_manager_sup, ManageCounts},
+         {gr_param_sup, Params}, {gr_counter_sup, Counts}]
+    ],
+
+    code:soft_purge(Module),
+    code:delete(Module),
     ok.
 
 
 %% @private Map a query to a module data term.
--spec module_data(term()) -> {ok, #module{}}.
-module_data(Query) ->
+-spec module_data(atom(), term()) -> {ok, #module{}}.
+module_data(Module, Query) ->
     %% terms in the query which are not valid arguments to the
     %% erl_syntax:abstract/1 functions are stored in ETS.
     %% the terms are only looked up once they are necessary to
     %% continue evaluation of the query.
-    Params = ets:new(params, [set,protected]),
+
     %% query counters are stored in a shared ETS table. this should
-    %% be an optional feature. enable by defaults to simplify tests.
-    %% the abstract_tables/1 function expects a list of name-tid pairs.
+    %% be an optional feature. enabled by defaults to simplify tests.
+    %% the abstract_tables/1 function expects a list of name-atom pairs.
     %% tables are referred to by name in the generated code. the table/1
-    %% function maps names to tids.
-    Tables = [{params,Params}],
+    %% function maps names to registered processes response for those tables.
+    Tables = module_tables(Module),
     Query2 = glc_lib:reduce(Query),
     {ok, #module{'query'=Query, tables=Tables, qtree=Query2}}.
 
+%% @private Create a data managed supervised process for params, counter tables
+module_tables(Module) ->
+    Params = params_name(Module),
+    Counts = counts_name(Module),
+    ManageParams = manage_params_name(Module),
+    ManageCounts = manage_counts_name(Module),
+    Counters = [{input,0}, {filter,0}, {output,0}],
+
+    supervisor:start_child(gr_param_sup, 
+        {Params, {gr_param, start_link, [Params]}, 
+        transient, brutal_kill, worker, [Params]}),
+    supervisor:start_child(gr_counter_sup, 
+        {Counts, {gr_counter, start_link, [Counts]}, 
+        transient, brutal_kill, worker, [Counts]}),
+    supervisor:start_child(gr_manager_sup, 
+        {ManageParams, {gr_manager, start_link, [ManageParams, Params, []]},
+        transient, brutal_kill, worker, [ManageParams]}),
+    supervisor:start_child(gr_manager_sup, {ManageCounts, 
+        {gr_manager, start_link, [ManageCounts, Counts, Counters]},
+        transient, brutal_kill, worker, [ManageCounts]}),
+    [{params,Params}, {counters, Counts}].
+
+reg_name(Module, Name) ->
+    list_to_atom("gr_" ++ atom_to_list(Module) ++ Name).
+
+params_name(Module) -> reg_name(Module, "_params").
+counts_name(Module) -> reg_name(Module, "_counters").
+manage_params_name(Module) -> reg_name(Module, "_params_mgr").
+manage_counts_name(Module) -> reg_name(Module, "_counters_mgr").
+
+
 
 %% @todo Move comment.
 %% @private Map a query to a simplified query tree term.
@@ -244,21 +290,6 @@ setup_query(Module, Query) ->
     ?assert(erlang:function_exported(Module, handle, 1)),
     {compiled, Module}.
 
-nullquery_compiles_test() ->
-    {compiled, Mod} = setup_query(testmod1, glc:null(false)),
-    ?assertError(badarg, Mod:table(noexists)).
-
-params_table_exists_test() ->
-    {compiled, Mod} = setup_query(testmod2, glc:null(false)),
-    ?assert(is_integer(Mod:table(params))),
-    ?assertMatch([_|_], ets:info(Mod:table(params))).
-
-nullquery_exists_test() ->
-    {compiled, Mod} = setup_query(testmod3, glc:null(false)),
-    ?assert(erlang:function_exported(Mod, info, 1)),
-    ?assertError(badarg, Mod:info(invalid)),
-    ?assertEqual({null, false}, Mod:info('query')).
-
 events_test_() ->
     {foreach,
         fun() ->
@@ -274,6 +305,27 @@ events_test_() ->
                 error_logger:tty(true)
         end,
         [
+            {"null query compiles",
+                fun() ->
+                    {compiled, Mod} = setup_query(testmod1, glc:null(false)),
+                    ?assertError(badarg, Mod:table(noexists))
+                end
+            },
+            {"params table exists",
+                fun() ->
+                    {compiled, Mod} = setup_query(testmod2, glc:null(false)),
+                    ?assert(is_atom(Mod:table(params))),
+                    ?assertMatch([_|_], gr_param:info(Mod:table(params)))
+                end
+            },
+            {"null query exists",
+                fun() ->
+                    {compiled, Mod} = setup_query(testmod3, glc:null(false)),
+                    ?assert(erlang:function_exported(Mod, info, 1)),
+                    ?assertError(badarg, Mod:info(invalid)),
+                    ?assertEqual({null, false}, Mod:info('query'))
+                end
+            },
             {"init counters test",
                 fun() ->
                     {compiled, Mod} = setup_query(testmod4, glc:null(false)),
@@ -381,6 +433,26 @@ events_test_() ->
                     ?assertEqual(1, Mod:info(output)),
                     ?assertEqual(1, receive Msg -> Msg after 0 -> notcalled end)
                 end
+            },
+            {"delete test",
+                fun() ->
+                    {compiled, Mod} = setup_query(testmod13, glc:null(false)),
+                    ?assert(is_atom(Mod:table(params))),
+                    ?assertMatch([_|_], gr_param:info(Mod:table(params))),
+                    ?assert(is_list(code:which(Mod))),
+                    ?assert(is_pid(whereis(params_name(Mod)))),
+                    ?assert(is_pid(whereis(counts_name(Mod)))),
+                    ?assert(is_pid(whereis(manage_params_name(Mod)))),
+                    ?assert(is_pid(whereis(manage_counts_name(Mod)))),
+
+                    glc:delete(Mod),
+                    
+                    ?assertEqual(non_existing, code:which(Mod)),
+                    ?assertEqual(undefined, whereis(params_name(Mod))),
+                    ?assertEqual(undefined, whereis(counts_name(Mod))),
+                    ?assertEqual(undefined, whereis(manage_params_name(Mod))),
+                    ?assertEqual(undefined, whereis(manage_counts_name(Mod)))
+                end
             }
         ]
     }.

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/glc_code.erl
----------------------------------------------------------------------
diff --git a/src/glc_code.erl b/src/glc_code.erl
index 2e2c7c9..1111bd9 100644
--- a/src/glc_code.erl
+++ b/src/glc_code.erl
@@ -9,7 +9,7 @@
 
 -record(module, {
     'query' :: term(),
-    tables :: [{atom(), ets:tid()}],
+    tables :: [{atom(), atom()}],
     qtree :: term()
 }).
 
@@ -20,7 +20,8 @@
     fields = [] :: [{atom(), syntaxTree()}],
     fieldc = 0 :: non_neg_integer(),
     paramvars = [] :: [{term(), syntaxTree()}],
-    paramstab = undefined :: ets:tid()
+    paramstab = undefined :: atom(),
+    countstab = undefined :: atom()
 }).
 
 -type nextFun() :: fun((#state{}) -> [syntaxTree()]).
@@ -47,6 +48,7 @@ abstract_module(Module, Data) ->
 -spec abstract_module_(atom(), #module{}) -> [?erl:syntaxTree()].
 abstract_module_(Module, #module{tables=Tables, qtree=Tree}=Data) ->
     {_, ParamsTable} = lists:keyfind(params, 1, Tables),
+    {_, CountsTable} = lists:keyfind(counters, 1, Tables),
     AbstractMod = [
      %% -module(Module)
      ?erl:attribute(?erl:atom(module), [?erl:atom(Module)]),
@@ -94,12 +96,11 @@ abstract_module_(Module, #module{tables=Tables, qtree=Tree}=Data) ->
         [?erl:clause([?erl:variable("Event")], none,
          abstract_filter(Tree, #state{
             event=?erl:variable("Event"),
-            paramstab=ParamsTable}))])
+            paramstab=ParamsTable,
+            countstab=CountsTable}))])
     ],
     %% Transform Term -> Key to Key -> Term
-    ParamsList = [{K, V} || {V, K} <- ets:tab2list(ParamsTable)],
-    ets:delete_all_objects(ParamsTable),
-    ets:insert(ParamsTable, ParamsList),
+    gr_param:transform(ParamsTable),
     AbstractMod.
 
 %% @private Return the clauses of the table/1 function.
@@ -258,22 +259,21 @@ abstract_getparam(Term, OnBound, #state{paramvars=Params}=State) ->
 
 
 -spec abstract_getparam_(term(), nextFun(), #state{}) -> [syntaxTree()].
-abstract_getparam_(Term, OnBound, #state{paramstab=Table,
+abstract_getparam_(Term, OnBound, #state{paramstab=ParamsTable,
         paramvars=Params}=State) ->
-    Key = case ets:lookup(Table, Term) of
+    Key = case gr_param:lookup(ParamsTable, Term) of
         [{_, Key2}] ->
             Key2;
         [] ->
-            Key2 = ets:info(Table, size),
-            ets:insert(Table, {Term, Key2}),
+            Key2 = gr_param:size(ParamsTable),
+            gr_param:insert(ParamsTable, {Term, Key2}),
             Key2
     end,
     [?erl:match_expr(
         param_variable(Key),
-        abstract_apply(ets, lookup_element,
+        abstract_apply(gr_param, lookup_element,
             [abstract_apply(table, [?erl:atom(params)]),
-             ?erl:abstract(Key),
-             ?erl:abstract(2)]))
+             ?erl:abstract(Key)]))
     ] ++ OnBound(State#state{paramvars=[{Term, param_variable(Key)}|Params]}).
 
 %% @private Generate a variable name for the value of a field.
@@ -317,7 +317,8 @@ param_variable(Key) ->
 -spec abstract_count(atom()) -> syntaxTree().
 abstract_count(Counter) ->
     abstract_apply(gr_counter, update,
-        [?erl:abstract(Counter),
+        [abstract_apply(table, [?erl:atom(counters)]),
+         ?erl:abstract(Counter),
          ?erl:abstract({2,1})]).
 
 
@@ -326,7 +327,8 @@ abstract_count(Counter) ->
 -spec abstract_getcount(atom()) -> [syntaxTree()].
 abstract_getcount(Counter) ->
     [abstract_apply(gr_counter, check,
-        [?erl:abstract(Counter)])].
+        [abstract_apply(table, [?erl:atom(counters)]),
+         ?erl:abstract(Counter)])].
 
 
 %% abstract code util functions

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_counter.erl
----------------------------------------------------------------------
diff --git a/src/gr_counter.erl b/src/gr_counter.erl
index f11550b..76f7dd5 100644
--- a/src/gr_counter.erl
+++ b/src/gr_counter.erl
@@ -17,9 +17,9 @@
 -behaviour(gen_server).
 
 %% API
--export([start_link/0, 
-         check/0, check/1,
-         update/2]).
+-export([start_link/1, 
+         check/1, check/2,
+         update/3]).
 
 %% gen_server callbacks
 -export([init/1,
@@ -29,21 +29,19 @@
          terminate/2,
          code_change/3]).
 
--define(SERVER, ?MODULE).
-
 -record(state, {init=true, table_id}).
 
 %%%===================================================================
 %%% API
 %%%===================================================================
-check() ->
-    gen_server:call(?MODULE, check).
+check(Server) ->
+    gen_server:call(Server, check).
 
-check(Counter) ->
-    gen_server:call(?MODULE, {check, Counter}).
+check(Server, Counter) ->
+    gen_server:call(Server, {check, Counter}).
 
-update(Counter, Value) ->
-    gen_server:cast(?MODULE, {update, Counter, Value}).
+update(Server, Counter, Value) ->
+    gen_server:cast(Server, {update, Counter, Value}).
 
 %%--------------------------------------------------------------------
 %% @doc
@@ -52,8 +50,8 @@ update(Counter, Value) ->
 %% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
 %% @end
 %%--------------------------------------------------------------------
-start_link() ->
-    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+start_link(Name) ->
+    gen_server:start_link({local, Name}, ?MODULE, [], []).
 
 %%%===================================================================
 %%% gen_server callbacks
@@ -94,7 +92,7 @@ handle_call({check, Counter}, _From, State) ->
     TableId = State#state.table_id,
     {reply, ets:lookup_element(TableId, Counter, 2), State};
 handle_call(_Request, _From, State) ->
-    Reply = ok,
+    Reply = {error, unhandled_message},
     {reply, Reply, State}.
 
 %%--------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_counter_mgr.erl
----------------------------------------------------------------------
diff --git a/src/gr_counter_mgr.erl b/src/gr_counter_mgr.erl
deleted file mode 100644
index 5c9cabc..0000000
--- a/src/gr_counter_mgr.erl
+++ /dev/null
@@ -1,170 +0,0 @@
-%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
-%%
-%% Permission to use, copy, modify, and/or distribute this software for any
-%% purpose with or without fee is hereby granted, provided that the above
-%% copyright notice and this permission notice appear in all copies.
-%%
-%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--module(gr_counter_mgr).
-
--behaviour(gen_server).
-
-%% API
--export([start_link/0]).
-
-%% gen_server callbacks
--export([init/1,
-         handle_call/3,
-         handle_cast/2,
-         handle_info/2,
-         terminate/2,
-         code_change/3]).
-
--define(SERVER, ?MODULE).
-
--record(state, {table_id}).
-
--define(CTR, gr_counter).
-
-%%%===================================================================
-%%% API
-%%%===================================================================
-
-setup(Data) ->
-    gen_server:cast(?MODULE, {setup, Data}).
-
-%%--------------------------------------------------------------------
-%% @doc
-%% Starts the server
-%%
-%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
-%% @end
-%%--------------------------------------------------------------------
-start_link() ->
-    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
-
-%%%===================================================================
-%%% gen_server callbacks
-%%%===================================================================
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Initializes the server
-%%
-%% @spec init(Args) -> {ok, State} |
-%%                     {ok, State, Timeout} |
-%%                     ignore |
-%%                     {stop, Reason}
-%% @end
-%%--------------------------------------------------------------------
-init([]) ->
-    process_flag(trap_exit, true),
-    setup([{input,0}, {filter,0}, {output,0}]),
-    {ok, #state{}}.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Handling call messages
-%%
-%% @spec handle_call(Request, From, State) ->
-%%                                   {reply, Reply, State} |
-%%                                   {reply, Reply, State, Timeout} |
-%%                                   {noreply, State} |
-%%                                   {noreply, State, Timeout} |
-%%                                   {stop, Reason, Reply, State} |
-%%                                   {stop, Reason, State}
-%% @end
-%%--------------------------------------------------------------------
-handle_call(_Request, _From, State) ->
-    Reply = ok,
-    {reply, Reply, State}.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Handling cast messages
-%%
-%% @spec handle_cast(Msg, State) -> {noreply, State} |
-%%                                  {noreply, State, Timeout} |
-%%                                  {stop, Reason, State}
-%% @end
-%%--------------------------------------------------------------------
-handle_cast({setup, Data}, State) ->
-    Ctr = whereis(?CTR),
-    link(Ctr),
-    TableId = ets:new(?MODULE, [set, private]),
-    ets:insert(TableId, Data),
-    ets:setopts(TableId, {heir, self(), Data}),
-    ets:give_away(TableId, Ctr, Data),
-    {noreply, State#state{table_id=TableId}};
-handle_cast(_Msg, State) ->
-    {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Handling all non call/cast messages
-%%
-%% @spec handle_info(Info, State) -> {noreply, State} |
-%%                                   {noreply, State, Timeout} |
-%%                                   {stop, Reason, State}
-%% @end
-%%--------------------------------------------------------------------
-handle_info({'EXIT', _Pid, killed}, State) ->
-    {noreply, State};
-handle_info({'ETS-TRANSFER', TableId, _Pid, Data}, State) ->
-    Ctr = wait_for_ctr(),
-    link(Ctr),
-    ets:give_away(TableId, Ctr, Data),
-    {noreply, State#state{table_id=TableId}}.
-
-wait_for_ctr() -> 
-    case whereis(?CTR) of
-        undefined -> 
-            timer:sleep(1),
-            wait_for_ctr();
-        Pid -> Pid
-    end.
-
-
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% This function is called by a gen_server when it is about to
-%% terminate. It should be the opposite of Module:init/1 and do any
-%% necessary cleaning up. When it returns, the gen_server terminates
-%% with Reason. The return value is ignored.
-%%
-%% @spec terminate(Reason, State) -> void()
-%% @end
-%%--------------------------------------------------------------------
-terminate(_Reason, _State) ->
-    ok.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Convert process state when code is changed
-%%
-%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% @end
-%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
-
-%%%===================================================================
-%%% Internal functions
-%%%===================================================================
-
-
-

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_counter_sup.erl
----------------------------------------------------------------------
diff --git a/src/gr_counter_sup.erl b/src/gr_counter_sup.erl
new file mode 100644
index 0000000..234919b
--- /dev/null
+++ b/src/gr_counter_sup.erl
@@ -0,0 +1,42 @@
+%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(gr_counter_sup).
+
+-behaviour(supervisor).
+
+-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().
+-type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+%% ===================================================================
+%% API functions
+%% ===================================================================
+%% @hidden
+-spec start_link() -> startlink_ret().
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% ===================================================================
+%% Supervisor callbacks
+%% ===================================================================
+%% @hidden
+-spec init([]) -> {ok, { {one_for_one, 50, 10}, [supervisor:child_spec()]} }.
+init(_Args) ->
+    {ok, { {one_for_one, 50, 10}, []} }.

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_manager.erl
----------------------------------------------------------------------
diff --git a/src/gr_manager.erl b/src/gr_manager.erl
new file mode 100644
index 0000000..c64f74e
--- /dev/null
+++ b/src/gr_manager.erl
@@ -0,0 +1,168 @@
+%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% 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).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/3]).
+
+%% gen_server callbacks
+-export([init/1,
+         handle_call/3,
+         handle_cast/2,
+         handle_info/2,
+         terminate/2,
+         code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {table_id :: ets:tid(), managee :: atom()}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+setup(Name, Data) ->
+    gen_server:cast(Name, {setup, Data}).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
+%% @end
+%%--------------------------------------------------------------------
+start_link(Name, Managee, Data) ->
+    gen_server:start_link({local, Name}, ?MODULE, [Managee, Data], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+init([Managee, Data]) ->
+    process_flag(trap_exit, true),
+    setup(self(), Data),
+    {ok, #state{managee=Managee}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @spec handle_call(Request, From, State) ->
+%%                                   {reply, Reply, State} |
+%%                                   {reply, Reply, State, Timeout} |
+%%                                   {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, Reply, State} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_call(_Request, _From, State) ->
+    Reply = {error, unhandled_message},
+    {reply, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @spec handle_cast(Msg, State) -> {noreply, State} |
+%%                                  {noreply, State, Timeout} |
+%%                                  {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_cast({setup, Data}, State = #state{managee=Managee}) ->
+    ManageePid = whereis(Managee),
+    link(ManageePid),
+    TableId = ets:new(?MODULE, [set, private]),
+    ets:insert(TableId, Data),
+    ets:setopts(TableId, {heir, self(), Data}),
+    ets:give_away(TableId, ManageePid, Data),
+    {noreply, State#state{table_id=TableId}};
+handle_cast(_Msg, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_info({'EXIT', _Pid, _Reason}, State) ->
+    {noreply, State};
+handle_info({'ETS-TRANSFER', TableId, _Pid, Data}, State = #state{managee=Managee}) ->
+    ManageePid = wait_for_pid(Managee),
+    link(ManageePid),
+    ets:give_away(TableId, ManageePid, Data),
+    {noreply, State#state{table_id=TableId}}.
+
+wait_for_pid(Managee) -> 
+    case whereis(Managee) of
+        undefined -> 
+            timer:sleep(1),
+            wait_for_pid(Managee);
+        Pid -> Pid
+    end.
+
+
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+
+

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_manager_sup.erl
----------------------------------------------------------------------
diff --git a/src/gr_manager_sup.erl b/src/gr_manager_sup.erl
new file mode 100644
index 0000000..49c21cd
--- /dev/null
+++ b/src/gr_manager_sup.erl
@@ -0,0 +1,42 @@
+%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% 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_sup).
+
+-behaviour(supervisor).
+
+-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().
+-type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+%% ===================================================================
+%% API functions
+%% ===================================================================
+%% @hidden
+-spec start_link() -> startlink_ret().
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% ===================================================================
+%% Supervisor callbacks
+%% ===================================================================
+%% @hidden
+-spec init([]) -> {ok, { {one_for_one, 50, 10}, [supervisor:child_spec()]} }.
+init(_Args) ->
+    {ok, { {one_for_one, 50, 10}, []} }.

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_param.erl
----------------------------------------------------------------------
diff --git a/src/gr_param.erl b/src/gr_param.erl
new file mode 100644
index 0000000..700d6c3
--- /dev/null
+++ b/src/gr_param.erl
@@ -0,0 +1,194 @@
+%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% 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).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/1, 
+         list/1, size/1, insert/2, 
+         lookup/2, lookup_element/2,
+         info/1, update/2, transform/1]).
+
+%% gen_server callbacks
+-export([init/1,
+         handle_call/3,
+         handle_cast/2,
+         handle_info/2,
+         terminate/2,
+         code_change/3]).
+
+-record(state, {init=true, table_id}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+list(Server) ->
+    gen_server:call(Server, list).
+
+size(Server) ->
+    gen_server:call(Server, size).
+
+insert(Server, Data) ->
+    gen_server:call(Server, {insert, Data}).
+
+lookup(Server, Term) ->
+    gen_server:call(Server, {lookup, Term}).
+
+lookup_element(Server, Term) ->
+    gen_server:call(Server, {lookup_element, Term}).
+
+info(Server) ->
+    gen_server:call(Server, info).
+
+update(Counter, Value) ->
+    gen_server:cast(?MODULE, {update, Counter, Value}).
+
+%% @doc Transform Term -> Key to Key -> Term
+transform(Server) ->
+    gen_server:call(Server, transform).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
+%% @end
+%%--------------------------------------------------------------------
+start_link(Name) ->
+    gen_server:start_link({local, Name}, ?MODULE, [], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+init([]) ->
+    {ok, #state{}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @spec handle_call(Request, From, State) ->
+%%                                   {reply, Reply, State} |
+%%                                   {reply, Reply, State, Timeout} |
+%%                                   {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, Reply, State} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_call(list, _From, State) ->
+    TableId = State#state.table_id,
+    {reply, ets:tab2list(TableId), State};
+handle_call(size, _From, State) ->
+    TableId = State#state.table_id,
+    {reply, ets:info(TableId, size), State};
+handle_call({insert, Data}, _From, State) ->
+    TableId = State#state.table_id,
+    {reply, ets:insert(TableId, Data), State};
+handle_call({lookup, Term}, _From, State) ->
+    TableId = State#state.table_id,
+    {reply, ets:lookup(TableId, Term), State};
+handle_call({lookup_element, Term}, _From, State) ->
+    TableId = State#state.table_id,
+    {reply, ets:lookup_element(TableId, Term, 2), State};
+handle_call(info, _From, State) ->
+    TableId = State#state.table_id,
+    {reply, ets:info(TableId), State};
+handle_call(transform, _From, State) ->
+    TableId = State#state.table_id,
+    ParamsList = [{K, V} || {V, K} <- ets:tab2list(TableId)],
+    ets:delete_all_objects(TableId),
+    ets:insert(TableId, ParamsList),
+    {reply, ok, State};
+handle_call(_Request, _From, State) ->
+    Reply = {error, unhandled_message},
+    {reply, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @spec handle_cast(Msg, State) -> {noreply, State} |
+%%                                  {noreply, State, Timeout} |
+%%                                  {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_cast({update, Counter, Value}, State) ->
+    TableId = State#state.table_id,
+    ets:update_counter(TableId, Counter, Value),
+    {noreply, State};
+handle_cast(_Msg, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_info({'ETS-TRANSFER', TableId, _Pid, _Data}, State) ->
+    {noreply, State#state{table_id=TableId}};
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_param_sup.erl
----------------------------------------------------------------------
diff --git a/src/gr_param_sup.erl b/src/gr_param_sup.erl
new file mode 100644
index 0000000..25d240f
--- /dev/null
+++ b/src/gr_param_sup.erl
@@ -0,0 +1,42 @@
+%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% 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).
+
+-behaviour(supervisor).
+
+-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().
+-type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+%% ===================================================================
+%% API functions
+%% ===================================================================
+%% @hidden
+-spec start_link() -> startlink_ret().
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% ===================================================================
+%% Supervisor callbacks
+%% ===================================================================
+%% @hidden
+-spec init([]) -> {ok, { {one_for_one, 50, 10}, [supervisor:child_spec()]} }.
+init(_Args) ->
+    {ok, { {one_for_one, 50, 10}, []} }.

http://git-wip-us.apache.org/repos/asf/couchdb-goldrush/blob/18042453/src/gr_sup.erl
----------------------------------------------------------------------
diff --git a/src/gr_sup.erl b/src/gr_sup.erl
index b207d4c..dab4d7c 100644
--- a/src/gr_sup.erl
+++ b/src/gr_sup.erl
@@ -1,4 +1,5 @@
 %% Copyright (c) 2012, Magnus Klaar <kl...@ninenines.eu>
+%% Copyright (c) 2013, Pedram Nimreezi <de...@deadzen.com>
 %%
 %% Permission to use, copy, modify, and/or distribute this software for any
 %% purpose with or without fee is hereby granted, provided that the above
@@ -25,6 +26,7 @@ start_link() ->
     supervisor:start_link({local, ?MODULE}, ?MODULE, []).
 
 init([]) ->
-    Counter = ?CHILD(gr_counter, worker),
-    CounterMgr = ?CHILD(gr_counter_mgr, worker),
-    {ok, {{one_for_one, 5, 10}, [Counter, CounterMgr]}}.
+    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]}}.