summaryrefslogtreecommitdiff
path: root/src/mem3_cache.erl
diff options
context:
space:
mode:
authorAdam Kocoloski <adam@cloudant.com>2010-06-30 16:23:38 -0400
committerAdam Kocoloski <adam@cloudant.com>2010-08-12 01:22:33 -0400
commit48c8fde34591f782be7af77575eaa02dab8659b3 (patch)
treebb54c0d61a660b9ba019f9b187e901ede7132bfa /src/mem3_cache.erl
parent8a09581aa2252f53047fa0e9e95591eaae4556c9 (diff)
standardize mem3 naming. app is horribly broken for now
Diffstat (limited to 'src/mem3_cache.erl')
-rw-r--r--src/mem3_cache.erl91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/mem3_cache.erl b/src/mem3_cache.erl
new file mode 100644
index 00000000..8f5c372a
--- /dev/null
+++ b/src/mem3_cache.erl
@@ -0,0 +1,91 @@
+-module(mem3_cache).
+-behaviour(gen_server).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ code_change/3]).
+
+-export([start_link/0]).
+
+-include("mem3.hrl").
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ ets:new(partitions, [bag, protected, named_table, {keypos,#shard.dbname}]),
+ ets:new(memnodes, [bag, protected, named_table]),
+ cache_dbs(),
+ Self = self(),
+ couch_db_update_notifier:start_link(fun({updated, <<"dbs">>}) ->
+ Self ! rebuild_dbs_cache;
+ (_) -> ok end),
+ {ok, nil}.
+
+handle_call(_Msg, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(rebuild_dbs_cache, State) ->
+ receive rebuild_dbs_cache ->
+ handle_info(rebuild_dbs_cache, State)
+ after 0 -> ok end,
+ T0 = now(),
+ ?LOG_INFO("rebuilding dbs DB cache", []),
+ ets:delete_all_objects(partitions),
+ ets:delete_all_objects(memnodes),
+ cache_dbs(),
+ ?LOG_INFO("rebuild of dbs DB cache complete in ~p ms",
+ [round(timer:now_diff(now(),T0)/1000)]),
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+cache_dbs() ->
+ try couch_db:open(<<"dbs">>, []) of
+ {ok, Db} ->
+ Bt = Db#db.id_tree,
+ FoldFun = fun(#full_doc_info{id=Id, deleted=false} = FullDocInfo, _, _) ->
+ {ok, Doc} = couch_db:open_doc_int(Db, FullDocInfo, []),
+ {Props} = couch_doc:to_json_obj(Doc, []),
+ cache_map(Id, Props),
+ cache_nodes(Id, Props),
+ {ok, true};
+ (_, _, _) ->
+ {ok, nil}
+ end,
+ couch_btree:foldl(Bt, FoldFun, nil),
+ couch_db:close(Db)
+ catch exit:{noproc,{gen_server,call,[couch_server|_]}} ->
+ timer:sleep(1000),
+ exit(couch_server_is_dead)
+ end.
+
+cache_map(Id, Props) ->
+ Map = couch_util:get_value(<<"map">>, Props, []),
+ lists:foreach(fun({[{<<"node">>,Node},{<<"b">>,Beg},{<<"e">>,End}]}) ->
+ Part = #shard{
+ name = partitions:shard_name(Beg, Id),
+ dbname = Id,
+ node = to_atom(Node),
+ range = [Beg,End]
+ },
+ ets:insert(partitions, Part)
+ end, Map).
+
+cache_nodes(Id, Props) ->
+ Nodes = couch_util:get_value(<<"nodes">>, Props, []),
+ lists:foreach(fun({[{<<"order">>,Order},{<<"node">>, Node},{<<"options">>,Opts}]}) ->
+ ets:insert(memnodes, {Id, {Order, to_atom(Node), Opts}})
+ end, Nodes).
+
+to_atom(Node) when is_binary(Node) ->
+ list_to_atom(binary_to_list(Node));
+to_atom(Node) when is_atom(Node) ->
+ Node.
+
+%{ok, ets:insert(dbs_cache, {Id, Props})};