Merge branch '1.3.x' Conflicts: src/mem3.erl src/mem3_cache.erl src/mem3_nodes.erl src/mem3_rep.erl src/mem3_sup.erl src/mem3_sync.erl src/mem3_sync_event.erl
BugzID: 13780 Project: http://git-wip-us.apache.org/repos/asf/couchdb-mem3/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mem3/commit/d39a7915 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mem3/tree/d39a7915 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mem3/diff/d39a7915 Branch: refs/heads/import Commit: d39a79156950a2993ac988da84c59f79caadf572 Parents: 87cbec9 4704323 Author: Adam Kocoloski <a...@cloudant.com> Authored: Fri Jun 1 12:03:55 2012 -0400 Committer: Adam Kocoloski <a...@cloudant.com> Committed: Fri Jun 1 12:03:55 2012 -0400 ---------------------------------------------------------------------- README.md | 8 +- src/mem3.app.src | 3 +- src/mem3.erl | 39 ++--- src/mem3_cache.erl | 118 --------------- src/mem3_nodes.erl | 69 +++++---- src/mem3_rep.erl | 134 ++++++++++++----- src/mem3_shards.erl | 332 +++++++++++++++++++++++++++++++++++++++++++ src/mem3_sup.erl | 3 +- src/mem3_sync.erl | 64 ++++++--- src/mem3_sync_event.erl | 4 +- src/mem3_sync_nodes.erl | 116 +++++++++++++++ src/mem3_util.erl | 23 +-- 12 files changed, 661 insertions(+), 252 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-mem3/blob/d39a7915/src/mem3.app.src ---------------------------------------------------------------------- diff --cc src/mem3.app.src index 8844778,6ff46f1..bdc2d49 --- a/src/mem3.app.src +++ b/src/mem3.app.src @@@ -3,11 -3,12 +3,12 @@@ {vsn, git}, {mod, {mem3_app, []}}, {registered, [ - mem3_cache, mem3_events, mem3_nodes, + mem3_shards, mem3_sync, + mem3_sync_nodes, mem3_sup ]}, - {applications, [kernel, stdlib, sasl, crypto, mochiweb, couch]} + {applications, [kernel, stdlib, sasl, crypto, mochiweb, couch, twig]} ]}. http://git-wip-us.apache.org/repos/asf/couchdb-mem3/blob/d39a7915/src/mem3.erl ---------------------------------------------------------------------- diff --cc src/mem3.erl index 77e6372,f7934e1..aad85e4 --- a/src/mem3.erl +++ b/src/mem3.erl @@@ -15,13 -15,13 +15,14 @@@ -module(mem3). -export([start/0, stop/0, restart/0, nodes/0, node_info/2, shards/1, shards/2, - choose_shards/2, n/1, dbname/1, ushards/1]). + choose_shards/2, n/1, dbname/1, ushards/1, ushards/2]). + -export([get_shard/3, local_shards/1, fold_shards/2]). -export([sync_security/0, sync_security/1]). -export([compare_nodelists/0, compare_shards/1]). --export([group_by_proximity/1]). +-export([quorum/1, group_by_proximity/1]). -include("mem3.hrl"). +-include_lib("couch/include/couch_db.hrl"). start() -> application:start(mem3). @@@ -104,38 -97,39 +98,31 @@@ shards(DbName, DocId) when is_list(DbNa shards(DbName, DocId) when is_list(DocId) -> shards(DbName, list_to_binary(DocId)); shards(DbName, DocId) -> - HashKey = mem3_util:hash(DocId), - Head = #shard{ - name = '_', - node = '_', - dbname = DbName, - range = ['$1','$2'], - ref = '_' - }, - Conditions = [{'=<', '$1', HashKey}, {'=<', HashKey, '$2'}], - try ets:select(partitions, [{Head, Conditions, ['$_']}]) of - [] -> - mem3_util:load_shards_from_disk(DbName, DocId); - Shards -> - Shards - catch error:badarg -> - mem3_util:load_shards_from_disk(DbName, DocId) - end. + mem3_shards:for_docid(DbName, DocId). +-spec ushards(DbName::iodata()) -> [#shard{}]. ushards(DbName) -> - {L,S,D} = group_by_proximity(live_shards(DbName)), - % Prefer shards in the local zone over shards in a different zone, - % but sort each group separately to ensure a consistent choice between - % nodes in the same zone. - Shards = lists:sort(L ++ S) ++ lists:sort(D), - lists:usort(fun(#shard{name=A}, #shard{name=B}) -> - A =< B - end, Shards). - -live_shards(DbName) -> Nodes = [node()|erlang:nodes()], - [S || #shard{node=Node} = S <- shards(DbName), lists:member(Node, Nodes)]. + ZoneMap = zone_map(Nodes), + ushards(live_shards(DbName, Nodes), ZoneMap). -group_by_proximity(Shards) -> - {Local, Remote} = lists:partition(fun(S) -> S#shard.node =:= node() end, - Shards), - LocalZone = mem3:node_info(node(), <<"zone">>), - Fun = fun(S) -> mem3:node_info(S#shard.node, <<"zone">>) =:= LocalZone end, - {SameZone, DifferentZone} = lists:partition(Fun, Remote), - {Local, SameZone, DifferentZone}. +ushards(Shards0, ZoneMap) -> + {L,S,D} = group_by_proximity(Shards0, ZoneMap), + % Prefer shards in the local zone over shards in a different zone, + % but sort each zone separately to ensure a consistent choice between + % nodes in the same zone. + Shards = choose_ushards(L ++ S) ++ choose_ushards(D), + lists:ukeysort(#shard.range, Shards). + get_shard(DbName, Node, Range) -> + mem3_shards:get(DbName, Node, Range). + + local_shards(DbName) -> + mem3_shards:local(DbName). + + fold_shards(Fun, Acc) -> + mem3_shards:fold(Fun, Acc). + sync_security() -> mem3_sync_security:go(). @@@ -208,41 -202,3 +195,41 @@@ apportion(Shares, Acc, Remaining) - N = Remaining rem length(Acc), [H|T] = lists:nthtail(N, Acc), apportion(Shares, lists:sublist(Acc, N) ++ [H+1|T], Remaining - 1). + +live_shards(DbName, Nodes) -> + [S || #shard{node=Node} = S <- shards(DbName), lists:member(Node, Nodes)]. + +zone_map(Nodes) -> + [{Node, node_info(Node, <<"zone">>)} || Node <- Nodes]. + +group_by_proximity(Shards) -> + Nodes = [N || #shard{node=N} <- lists:ukeysort(#shard.node, Shards)], + group_by_proximity(Shards, zone_map(Nodes)). + +group_by_proximity(Shards, ZoneMap) -> + {Local, Remote} = lists:partition(fun(S) -> S#shard.node =:= node() end, + Shards), + LocalZone = proplists:get_value(node(), ZoneMap), + Fun = fun(S) -> proplists:get_value(S#shard.node, ZoneMap) =:= LocalZone end, + {SameZone, DifferentZone} = lists:partition(Fun, Remote), + {Local, SameZone, DifferentZone}. + +choose_ushards(Shards) -> + Groups = group_by_range(lists:sort(Shards)), + Fun = fun(Group, {N, Acc}) -> + {N+1, [lists:nth(1 + N rem length(Group), Group) | Acc]} end, + {_, Result} = lists:foldl(Fun, {0, []}, Groups), + Result. + +group_by_range(Shards) -> + Groups0 = lists:foldl(fun(#shard{range=Range}=Shard, Dict) -> + orddict:append(Range, Shard, Dict) end, orddict:new(), Shards), + {_, Groups} = lists:unzip(Groups0), + Groups. + +% quorum functions + +quorum(#db{name=DbName}) -> + quorum(DbName); +quorum(DbName) -> - n(DbName) div 2 + 1. ++ n(DbName) div 2 + 1. http://git-wip-us.apache.org/repos/asf/couchdb-mem3/blob/d39a7915/src/mem3_nodes.erl ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-mem3/blob/d39a7915/src/mem3_sup.erl ---------------------------------------------------------------------- diff --cc src/mem3_sup.erl index 07b9498,ae38d7d..bad651a --- a/src/mem3_sup.erl +++ b/src/mem3_sup.erl @@@ -22,10 -22,10 +22,11 @@@ start_link() - init(_Args) -> Children = [ child(mem3_events), - child(mem3_cache), child(mem3_nodes), + child(mem3_sync_nodes), % Order important? child(mem3_sync), - child(mem3_shards) ++ child(mem3_shards), + child(mem3_rep_manager) ], {ok, {{one_for_one,10,1}, Children}}.