summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Mazzoli <francesco@rabbitmq.com>2012-01-31 13:34:37 +0000
committerFrancesco Mazzoli <francesco@rabbitmq.com>2012-01-31 13:34:37 +0000
commite41c5d956a41761b2469871a4aab9094d12d1fba (patch)
tree21174b56654095d9d9ee1dea8bbc02355161b4ec
parentd229865f237ac90339a32e3e5eca4a0a502d90c0 (diff)
downloadrabbitmq-server-e41c5d956a41761b2469871a4aab9094d12d1fba.tar.gz
Change fash guid generation function to use phash + rotating blocks.
-rw-r--r--src/rabbit_guid.erl24
1 files changed, 17 insertions, 7 deletions
diff --git a/src/rabbit_guid.erl b/src/rabbit_guid.erl
index 262487a5..4fe6eaee 100644
--- a/src/rabbit_guid.erl
+++ b/src/rabbit_guid.erl
@@ -80,20 +80,30 @@ fresh() ->
Serial = gen_server:call(?SERVER, serial, infinity),
{Serial, node(), make_ref()}.
+advance_blocks({B1, B2, B3, B4}, I) ->
+ B5 = erlang:phash2({B1, I}),
+ {{(B2 bxor B5), (B3 bxor B5), (B4 bxor B5), B5}, I+1}.
+
+blocks_to_binary({B1, B2, B3, B4}) ->
+ <<B1:32/integer,B2:32/integer, B3:32/integer,B4:32/integer>>.
+
%% generate a GUID. This function should be used when performance is a
%% priority and predictability is not an issue. Otherwise, use gen_secure/0.
gen() ->
%% We hash a fresh GUID and then XOR it with a process-local counter
%% to get a new GUID each time.
- {S, I} =
+ {BS, I} =
case get(guid) of
- undefined -> G = fresh(),
- <<S0:128/integer>> = erlang:md5(term_to_binary(G)),
- {S0, 0};
- {S0, I0} -> {S0, I0+1}
+ undefined ->
+ G = fresh(),
+ <<B1:32/integer,B2:32/integer, B3:32/integer,B4:32/integer>> =
+ erlang:md5(term_to_binary(G)),
+ {{B1,B2,B3,B4}, 0};
+ {BS0, I0} ->
+ advance_blocks(BS0, I0)
end,
- put(guid, {S, I}),
- <<(S bxor I):128>>.
+ put(guid, {BS, I}),
+ blocks_to_binary(BS).
%% generate a non-predictable GUID.
%%