Skip to content

Instantly share code, notes, and snippets.

@lrascao
Last active August 29, 2015 14:22
Show Gist options
  • Save lrascao/3600d821503bdb9cea7b to your computer and use it in GitHub Desktop.
Save lrascao/3600d821503bdb9cea7b to your computer and use it in GitHub Desktop.
Mnesia ramblings
-module(master).
-include("record.hrl").
-export([start/0, read/1, write/2, frag_dist/0]).
% mnesia:table_info(book_info, frag_properties).
start() ->
mnesia:start(),
net_adm:ping('lr2@Luis-Rascao-MPT'),
{atomic, ok} = mnesia:create_table(book_info,
[{ram_copies, ['lr1@Luis-Rascao-MPT']},
{index, [name]},
{frag_properties, [{node_pool, [node()]},
{n_fragments, 4},
{hash_module, mnesia_frag_hash2}]},
{attributes, record_info(fields, book_info)}]).
read(Id) ->
F = fun(I) ->
mnesia:read(book_info, I)
end,
mnesia:activity(transaction, F, [Id], mnesia_frag).
write(Id, Name) ->
F = fun(I, N) ->
mnesia:write(book_info, #book_info{id = I, name = N}, write)
end,
mnesia:activity(transaction, F, [Id, Name], mnesia_frag).
frag_dist() ->
FragProperties = mnesia:table_info(book_info, frag_properties),
NFragments = proplists:get_value(n_fragments, FragProperties),
L = lists:map(fun(Fragment) ->
FragId = list_to_atom(atom_to_list(book_info_frag) ++ integer_to_list(Fragment)),
NodeFrag = mnesia:table_info(FragId, where_to_read),
{NodeFrag, FragId}
end, lists:seq(2, NFragments)),
lists:map(fun(Node) ->
Frags = proplists:get_all_values(Node, L),
{Node, Frags}
end, proplists:get_keys(L)).
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
%%
%%%----------------------------------------------------------------------
%%% Purpose : Implements hashing functionality for fragmented tables
%%%----------------------------------------------------------------------
%header_doc_include
-module(mnesia_frag_hash2).
%% Fragmented Table Hashing callback functions
-export([
init_state/2,
add_frag/1,
del_frag/1,
key_to_frag_number/2,
match_spec_to_frag_numbers/2
]).
%header_doc_include
%%-behaviour(mnesia_frag_hash).
%impl_doc_include
-record(hash_state,
{n_fragments,
next_n_to_split,
n_doubles,
function}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_state(_Tab, State) when State == undefined ->
#hash_state{n_fragments = 1,
next_n_to_split = 1,
n_doubles = 0,
function = phash2}.
convert_old_state({hash_state, N, P, L}) ->
#hash_state{n_fragments = N,
next_n_to_split = P,
n_doubles = L,
function = phash}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
add_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
P = SplitN + 1,
NewN = N + 1,
State2 = case power2(L) + 1 of
P2 when P2 == P ->
State#hash_state{n_fragments = NewN,
n_doubles = L + 1,
next_n_to_split = 1};
_ ->
State#hash_state{n_fragments = NewN,
next_n_to_split = P}
end,
{State2, [SplitN], [NewN]};
add_frag(OldState) ->
State = convert_old_state(OldState),
add_frag(State).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
del_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
P = SplitN - 1,
if
P < 1 ->
L2 = L - 1,
MergeN = power2(L2),
State2 = State#hash_state{n_fragments = N - 1,
next_n_to_split = MergeN,
n_doubles = L2},
{State2, [N], [MergeN]};
true ->
MergeN = P,
State2 = State#hash_state{n_fragments = N - 1,
next_n_to_split = MergeN},
{State2, [N], [MergeN]}
end;
del_frag(OldState) ->
State = convert_old_state(OldState),
del_frag(State).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
key_to_frag_number(State, Key) ->
FragNumber = key_to_frag_number0(State, Key),
io:format("frag #: ~p~n", [FragNumber]),
FragNumber.
key_to_frag_number0(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
A = erlang:phash(Key, power2(L + 1)),
if
A > N ->
A - power2(L);
true ->
A
end;
key_to_frag_number0(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
A = erlang:phash2(Key, power2(L + 1)) + 1,
if
A > N ->
A - power2(L);
true ->
A
end;
key_to_frag_number0(OldState, Key) ->
State = convert_old_state(OldState),
key_to_frag_number(State, Key).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
match_spec_to_frag_numbers(#hash_state{n_fragments = N} = State, MatchSpec) ->
case MatchSpec of
[{HeadPat, _, _}] when is_tuple(HeadPat), tuple_size(HeadPat) > 2 ->
KeyPat = element(2, HeadPat),
case has_var(KeyPat) of
false ->
[key_to_frag_number(State, KeyPat)];
true ->
lists:seq(1, N)
end;
_ ->
lists:seq(1, N)
end;
match_spec_to_frag_numbers(OldState, MatchSpec) ->
State = convert_old_state(OldState),
match_spec_to_frag_numbers(State, MatchSpec).
power2(Y) ->
1 bsl Y. % trunc(math:pow(2, Y)).
%impl_doc_include
has_var(Pat) ->
mnesia:has_var(Pat).
-record(book_info, {id, name}).
-module(slave).
-include("record.hrl").
-export([start/0, read/1, write/2, frag_dist/0]).
% mnesia:table_info(book_info, where_to_read).
% mnesia:table_info(book_info, frag_dist).
start() ->
mnesia:start(),
mnesia:change_config(extra_db_nodes, ['lr1@Luis-Rascao-MPT']),
{atomic, ok} = mnesia:change_table_frag(book_info, {add_node, node()}),
{atomic, ok} = mnesia:change_table_frag(book_info, {add_frag, [node()]}),
{atomic, ok} = mnesia:change_table_frag(book_info, {add_frag, [node()]}),
{atomic, ok} = mnesia:change_table_frag(book_info, {add_frag, [node()]}),
{atomic, ok} = mnesia:change_table_frag(book_info, {add_frag, [node()]}),
% mnesia:add_table_copy(book_info, node(), ram_copies),
ok.
read(Id) ->
F = fun(I) ->
mnesia:read(book_info, I)
end,
mnesia:activity(transaction, F, [Id], mnesia_frag).
write(Id, Name) ->
F = fun(I, N) ->
mnesia:write(book_info, #book_info{id = I, name = N}, write)
end,
mnesia:activity(transaction, F, [Id, Name], mnesia_frag).
frag_dist() ->
FragProperties = mnesia:table_info(book_info, frag_properties),
NFragments = proplists:get_value(n_fragments, FragProperties),
L = lists:map(fun(Fragment) ->
FragId = list_to_atom(atom_to_list(book_info_frag) ++ integer_to_list(Fragment)),
NodeFrag = mnesia:table_info(FragId, where_to_read),
{NodeFrag, FragId}
end, lists:seq(2, NFragments)),
lists:map(fun(Node) ->
Frags = proplists:get_all_values(Node, L),
{Node, Frags}
end, proplists:get_keys(L)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment