1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
16
%% $Id: mnesia_frag_hash.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
18
%%%----------------------------------------------------------------------
19
%%% Purpose : Implements hashing functionality for fragmented tables
20
%%%----------------------------------------------------------------------
23
-module(mnesia_frag_hash).
24
-behaviour(mnesia_frag_hash).
26
%% Fragmented Table Hashing callback functions
32
match_spec_to_frag_numbers/2
38
-record(hash_state, {n_fragments, next_n_to_split, n_doubles}).
40
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42
init_state(_Tab, State) when State == undefined ->
43
#hash_state{n_fragments = 1,
47
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49
add_frag(State) when record(State, hash_state) ->
50
SplitN = State#hash_state.next_n_to_split,
52
L = State#hash_state.n_doubles,
53
NewN = State#hash_state.n_fragments + 1,
54
State2 = case trunc(math:pow(2, L)) + 1 of
56
State#hash_state{n_fragments = NewN,
60
State#hash_state{n_fragments = NewN,
63
{State2, [SplitN], [NewN]}.
65
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67
del_frag(State) when record(State, hash_state) ->
68
P = State#hash_state.next_n_to_split - 1,
69
L = State#hash_state.n_doubles,
70
N = State#hash_state.n_fragments,
74
MergeN = trunc(math:pow(2, L2)),
75
State2 = State#hash_state{n_fragments = N - 1,
76
next_n_to_split = MergeN,
78
{State2, [N], [MergeN]};
81
State2 = State#hash_state{n_fragments = N - 1,
82
next_n_to_split = MergeN},
83
{State2, [N], [MergeN]}
86
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88
key_to_frag_number(State, Key) when record(State, hash_state) ->
89
L = State#hash_state.n_doubles,
90
A = erlang:phash(Key, trunc(math:pow(2, L))),
91
P = State#hash_state.next_n_to_split,
94
erlang:phash(Key, trunc(math:pow(2, L + 1)));
99
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101
match_spec_to_frag_numbers(State, MatchSpec) when record(State, hash_state) ->
103
[{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
104
KeyPat = element(2, HeadPat),
105
case has_var(KeyPat) of
107
[key_to_frag_number(State, KeyPat)];
109
lists:seq(1, State#hash_state.n_fragments)
112
lists:seq(1, State#hash_state.n_fragments)