diff options
Diffstat (limited to 'src/mem3.erl')
-rw-r--r-- | src/mem3.erl | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/src/mem3.erl b/src/mem3.erl index 4f7c6ade..e6ee5bf8 100644 --- a/src/mem3.erl +++ b/src/mem3.erl @@ -1,7 +1,7 @@ -module(mem3). --author('Brad Anderson <brad@cloudant.com>'). --export([start/0, stop/0, restart/0, state/0]). +-export([start/0, stop/0, restart/0, state/0, nodes/0, shards/1, shards/2, + choose_shards/2]). -include("mem3.hrl"). @@ -22,7 +22,7 @@ restart() -> %% key and the nodes holding that state as the value. Also reports member %% nodes which fail to respond and nodes which are connected but are not %% cluster members. Useful for debugging. --spec state() -> [{mem_state() | bad_nodes | non_member_nodes, [node()]}]. +-spec state() -> [{any | bad_nodes | non_member_nodes, [node()]}]. state() -> {ok, Nodes} = mem3:nodes(), AllNodes = erlang:nodes([this, visible]), @@ -30,4 +30,52 @@ state() -> Dict = lists:foldl(fun({Node, {ok,State}}, D) -> orddict:append(State, Node, D) end, orddict:new(), Replies), - [{non_member_nodes, AllNodes -- Nodes}, {bad_nodes, BadNodes} | Dict].
\ No newline at end of file + [{non_member_nodes, AllNodes -- Nodes}, {bad_nodes, BadNodes} | Dict]. + +-spec nodes() -> [node()]. +nodes() -> + mem3_nodes:get_nodelist(). + +-spec shards(DbName::binary()) -> [#shard{}]. +shards(DbName) -> + case ets:lookup(partitions, DbName) of + [] -> + % TODO fall back to checking dbs.couch directly + erlang:error(database_does_not_exist); + Else -> + Else + end. + +-spec shards(DbName::binary(), DocId::binary()) -> [#shard{}]. +shards(DbName, DocId) -> + HashKey = mem3_util:hash(DocId), + Head = #shard{ + name = '_', + node = '_', + dbname = DbName, + range = ['$1','$2'], + ref = '_' + }, + % TODO these conditions assume A < B, which we don't require + Conditions = [{'<', '$1', HashKey}, {'=<', HashKey, '$2'}], + case ets:select(partitions, [{Head, Conditions, ['$_']}]) of + [] -> + % TODO fall back to checking dbs.couch directly + erlang:error(database_does_not_exist); + Shards -> + Shards + end. + +choose_shards(DbName, Options) -> + try shards(DbName) + catch error:database_does_not_exist -> + Nodes = mem3:nodes(), + NodeCount = length(Nodes), + N = mem3_util:n_val(couch_util:get_value(n, Options), NodeCount), + Q = mem3_util:to_integer(couch_util:get_value(q, Options, + couch_config:get("cluster", "q", "8"))), + % rotate to a random entry in the nodelist for even distribution + {A, B} = lists:split(crypto:rand_uniform(1,length(Nodes)+1), Nodes), + RotatedNodes = B ++ A, + mem3_util:create_partition_map(DbName, N, Q, RotatedNodes) + end. |