Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:19
dht_ring
dht_ring-1.0.0-git.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File dht_ring-1.0.0-git.patch of Package dht_ring
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3d6f1af --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2008-2014 JackNyfe, Inc. <info@jacknyfe.com> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/Makefile b/Makefile index 22db18a..cf6a3ae 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,30 @@ -all: - ./rebar compile +.PHONY: all get-deps compile clean test-unit test-ct check distclean + +REBAR := $(shell which ./rebar || which rebar) + +all: get-deps compile + +compile: + $(REBAR) compile + +get-deps: + $(REBAR) get-deps + +test-unit: all + $(REBAR) eunit skip_deps=true + +test-ct: all + $(REBAR) ct skip_deps=true + +check: test-unit test-ct clean: - ./rebar clean + $(REBAR) clean + rm -rf ./ebin + rm -rf ./logs + rm -f ./erl_crash.dump + rm -rf ./.eunit + rm -f ./test/*.beam + +distclean: clean + rm -rf ./deps diff --git a/rebar.config b/rebar.config index a6a2e1d..0b722b7 100644 --- a/rebar.config +++ b/rebar.config @@ -1,8 +1,35 @@ %%% vim: set ts=4 sts=4 sw=4 et: -{deps_dir, "../../deps"}. +{deps_dir, "deps"}. + +{eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}. +{eunit_compile_opts, [export_all]}. +{cover_enabled, true}. +{cover_export_enabled, true}. + +{erl_opts, [ + bin_opt_info, + + warn_unused_vars, + warn_export_all, + warn_shadow_vars, + warn_unused_import, + warn_unused_function, + warn_bif_clash, + warn_unused_record, + warn_deprecated_function, + warn_obsolete_guard, + strict_validation, + warn_export_vars, + warn_exported_vars, + warn_untyped_record, + + {parse_transform, lager_transform}, + {lager_truncation_size, 4096} +]}. {deps, [ % let it always be the first - {lager, "2.0.0", {git, "https://github.com/EchoTeam/lager", "6ee1113ec0d8cd9dde4feacf1e1bade749f35057"}} + {lager, "2.0.1", + {git, "git://github.com/basho/lager.git", {tag, "2.0.1"}}} ]}. diff --git a/src/dht_ring.erl b/src/dht_ring.erl index 152c93f..6b76a0c 100644 --- a/src/dht_ring.erl +++ b/src/dht_ring.erl @@ -1,7 +1,3 @@ -%%% -%%% Copyright (c) 2008-2013 JackNyfe. All rights reserved. -%%% THIS SOFTWARE IS PROPRIETARY AND CONFIDENTIAL. DO NOT REDISTRIBUTE. -%%% %%% vim: ts=4 sts=4 sw=4 expandtab: -module(dht_ring). @@ -71,10 +67,10 @@ node_shares(Ring) -> (_, Acc) -> Acc end, 0, Partitions) end, - lists:flatten([io_lib:format("\t~p weight ~p share ~p%~n", + lists:flatten([io_lib:format("\t~p weight ~p share ~.2f%~n", [Node, Weight, Share]) || {Node, _, Weight} <- get_config(Ring), - Share <- [100 * NodePartitions(Node) div 65536]]). + Share <- [100 * NodePartitions(Node) / 65536]]). partitions(Ring) -> partitions_from_ring(gen_server:call(Ring, {ring})). diff --git a/test/dht_ring_test.erl b/test/dht_ring_test.erl new file mode 100644 index 0000000..3645ac8 --- /dev/null +++ b/test/dht_ring_test.erl @@ -0,0 +1,136 @@ +-module(dht_ring_test). + +-compile(export_all). + +-include_lib("eunit/include/eunit.hrl"). + + +run_test_() -> + [{"Basic test with three peers", fun basic_test/0}, + {"Test with one peer", fun vacuous_test/0}, + {"Dynamic ring", fun dynamic_test/0}]. + +check_distribution(Nodes, Expected) -> + {ok, RingServer} = dht_ring:start_link(Nodes), + + true = (length(Nodes) == length(dht_ring:nodes(RingServer))), + + KeysQty = length(Expected), + + true = KeysQty >= 1, + + Keys = lists:seq(1, KeysQty), + + [?assertMatch(E, dht_ring:lookup(RingServer, integer_to_list(Key))) || {Key, E} <- lists:zip(Keys, Expected)]. + +basic_test() -> + check_distribution( + [{a, a, 5}, {b, b, 3}, {c, c, 2}], + [ + [{a,a},{b,b},{c,c}], + [{a,a},{c,c},{b,b}], + [{c,c},{a,a},{b,b}], + [{a,a},{b,b},{c,c}], + [{a,a},{b,b},{c,c}], + [{c,c},{a,a},{b,b}], + [{a,a},{b,b},{c,c}], + [{c,c},{a,a},{b,b}], + [{b,b},{a,a},{c,c}], + [{b,b},{a,a},{c,c}] + ] + ). + +vacuous_test() -> + check_distribution([{n, n, 1}], lists:duplicate(10, [{n, n}])). + +dynamic_test() -> + A = {a, a, 5}, + B = {b, b, 3}, + C = {c, c, 10}, + {ok, Ring} = dht_ring:start_link([A]), + {ok, Ring0} = dht_ring:start_link([]), + {ok, RingA} = dht_ring:start_link([A]), + {ok, RingAB} = dht_ring:start_link([A, B]), + {ok, RingAC} = dht_ring:start_link([A, C]), + {ok, RingABC} = dht_ring:start_link([A, B, C]), + + {error, already_there, [a]} = dht_ring:add(Ring, [A]), + + Keys = lists:seq(1, 10), + + true = (length(dht_ring:nodes(Ring)) == 1), + ok = dht_ring:add(Ring, [B]), + true = (length(dht_ring:nodes(Ring)) == 2), + + Tests = [ + { "A+B vs AB", compare_rings(Ring, RingAB, Keys) }, + + { "A+B vs AB config", compare_configs(Ring, RingAB) }, + + begin + ok = dht_ring:add(Ring, [C]), + true = (length(dht_ring:nodes(Ring)) == 3), + { "A+B+C vs ABC", compare_rings(Ring, RingABC, Keys) } + end, + + { "A+B+C vs ABC config", compare_configs(Ring, RingABC) }, + + % Check if 'nodes/1' returns the right thing + { "nodes in A+B+C", + begin + Nodes = lists:keysort(1, dht_ring:nodes(Ring)), + if + Nodes == [{a, a}, {b, b}, {c, c}] -> pass; + true -> {fail, Nodes} + end + end + }, + + begin + {error, unknown_nodes, [d, e]} = dht_ring:delete(Ring, [d, e]), + ok = dht_ring:delete(Ring, [b]), + { "A+C vs AC", compare_rings(Ring, RingAC, Keys) } + end, + + { "A+C vs AC config", compare_configs(Ring, RingAC) }, + + begin + ok = dht_ring:delete(Ring, [a, c]), + {"empty rings lookups", compare_rings(Ring, Ring0, Keys) } + end, + + begin + ok = dht_ring:add(Ring, A), + { "0,add{A} vs A", compare_configs(Ring, RingA) } + end, + + begin + ok = dht_ring:delete(Ring, a), + { "A,delete{A} vs 0", compare_configs(Ring, Ring0) } + end + ], + + case [ Result || {_, Status} = Result <- Tests, Status =/= pass ] of + [] -> pass; + Else -> {fail, Else} + end. + +compare_rings(Ring1, Ring2, Keys) -> + Results = [ {Key, dht_ring:lookup(Ring1, Key) == dht_ring:lookup(Ring2, Key)} + || Key <- Keys + ], + + case [ Key || {Key, false} <- Results ] of + [] -> pass; + FailedKeys -> {fail, FailedKeys} + end. + + +compare_configs(Ring1, Ring2) -> + Config1 = dht_ring:get_config(Ring1), + Config2 = dht_ring:get_config(Ring2), + + case lists:keysort(1, Config1) == lists:keysort(1, Config2) of + true -> pass; + _ -> {fail, Config1, Config2} + end. diff --git a/test/test_dht_ring.erl b/test/test_dht_ring.erl deleted file mode 100644 index 42eaf92..0000000 --- a/test/test_dht_ring.erl +++ /dev/null @@ -1,156 +0,0 @@ --module(test_dht_ring). --compile(export_all). - -start() -> - {ok, RingServer} = dht_ring:start_link([{undef, undef, 1000}]), - lists:foreach( - fun(X) -> dht_ring:lookup(RingServer, integer_to_list(X)) end, - lists:seq(1, 10) - ). - -test(Nodes, KeysQty, Expected) -> - {ok, RingServer} = dht_ring:start_link(Nodes), - - true = (length(Nodes) == length(dht_ring:nodes(RingServer))), - true = KeysQty >= 1, - - Keys = lists:seq(1, KeysQty), - - Results = lists:map( - fun(X) -> dht_ring:lookup(RingServer, integer_to_list(X)) end, - Keys - ), - - lists:foreach( - fun({K, E, G}) -> - if - E /= G -> io:format("FAIL: key=~p expected=~p got=~p~n", [K, E, G]); - true -> ok - end - end, - lists:zip3(Keys, Expected, Results) - ). - -test_dynamic() -> - A = {a, a, 5}, - B = {b, b, 3}, - C = {c, c, 10}, - {ok, Ring} = dht_ring:start_link([A]), - {ok, Ring0} = dht_ring:start_link([]), - {ok, RingA} = dht_ring:start_link([A]), - {ok, RingAB} = dht_ring:start_link([A, B]), - {ok, RingAC} = dht_ring:start_link([A, C]), - {ok, RingABC} = dht_ring:start_link([A, B, C]), - - {error, already_there, [a]} = dht_ring:add(Ring, [A]), - - Keys = lists:seq(1, 10), - - true = (length(dht_ring:nodes(Ring)) == 1), - ok = dht_ring:add(Ring, [B]), - true = (length(dht_ring:nodes(Ring)) == 2), - - Tests = [ - { "A+B vs AB", compare_rings(Ring, RingAB, Keys) }, - - { "A+B vs AB config", compare_configs(Ring, RingAB) }, - - begin - ok = dht_ring:add(Ring, [C]), - true = (length(dht_ring:nodes(Ring)) == 3), - { "A+B+C vs ABC", compare_rings(Ring, RingABC, Keys) } - end, - - { "A+B+C vs ABC config", compare_configs(Ring, RingABC) }, - - % Check if 'nodes/1' returns the right thing - { "nodes in A+B+C", - begin - Nodes = lists:keysort(1, dht_ring:nodes(Ring)), - if - Nodes == [{a, a}, {b, b}, {c, c}] -> pass; - true -> {fail, Nodes} - end - end - }, - - begin - {error, unknown_nodes, [d, e]} = dht_ring:delete(Ring, [d, e]), - ok = dht_ring:delete(Ring, [b]), - { "A+C vs AC", compare_rings(Ring, RingAC, Keys) } - end, - - { "A+C vs AC config", compare_configs(Ring, RingAC) }, - - begin - ok = dht_ring:delete(Ring, [a, c]), - {"empty rings lookups", compare_rings(Ring, Ring0, Keys) } - end, - - begin - ok = dht_ring:add(Ring, A), - { "0,add{A} vs A", compare_configs(Ring, RingA) } - end, - - begin - ok = dht_ring:delete(Ring, a), - { "A,delete{A} vs 0", compare_configs(Ring, Ring0) } - end - ], - - case [ Result || {_, Status} = Result <- Tests, Status =/= pass ] of - [] -> pass; - Else -> {fail, Else} - end. - -compare_rings(Ring1, Ring2, Keys) -> - Results = [ {Key, dht_ring:lookup(Ring1, Key) == dht_ring:lookup(Ring2, Key)} - || Key <- Keys - ], - - case [ Key || {Key, false} <- Results ] of - [] -> pass; - FailedKeys -> {fail, FailedKeys} - end. - - -compare_configs(Ring1, Ring2) -> - Config1 = dht_ring:get_config(Ring1), - Config2 = dht_ring:get_config(Ring2), - - case lists:keysort(1, Config1) == lists:keysort(1, Config2) of - true -> pass; - _ -> {fail, Config1, Config2} - end. - - -test() -> - test( - [{a, a, 5}, {b, b, 3}, {c, c, 2}], - 10, - [ - [{a,a},{b,b},{c,c}], - [{a,a},{c,c},{b,b}], - [{c,c},{a,a},{b,b}], - [{a,a},{b,b},{c,c}], - [{a,a},{b,b},{c,c}], - [{c,c},{a,a},{b,b}], - [{a,a},{b,b},{c,c}], - [{c,c},{a,a},{b,b}], - [{b,b},{a,a},{c,c}], - [{b,b},{a,a},{c,c}] - ] - ), - - test( - [{n, n, 1}], - 10, - lists:duplicate(10, [{n, n}]) - ), - - test_dynamic(). - -profile() -> - eprof:start(), - eprof:profile([], ?MODULE, start, []), - eprof:analyse().
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor