Skip to content

Commit

Permalink
Merge pull request #769 from basho/merge-2.0-gdce213c-to-2.1
Browse files Browse the repository at this point in the history
Merge 2.0 gdce213c to 2.1

Reviewed-by: jonmeredith
  • Loading branch information
borshop committed Aug 12, 2015
2 parents 0c89aee + 2f55206 commit 138fc50
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 9 deletions.
2 changes: 1 addition & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{riak_sysmon, ".*", {git, "git://github.com/basho/riak_sysmon.git", {branch, "2.1"}}},
{riak_ensemble, ".*", {git, "git://github.com/basho/riak_ensemble", {branch, "2.1"}}},
{pbkdf2, ".*", {git, "git://github.com/basho/erlang-pbkdf2.git", {tag, "2.0.0"}}},
{eleveldb, ".*", {git, "git://github.com/basho/eleveldb.git", {tag, "2.1.0"}}},
{eleveldb, ".*", {git, "git://github.com/basho/eleveldb.git", {tag, "2.1.3"}}},
{exometer_core, ".*", {git, "git://github.com/basho/exometer_core.git", {tag, "1.0.0-basho2"}}},
{clique, "0.3.2", {git, "git://github.com/basho/clique.git", {tag, "0.3.2"}}}
]}.
21 changes: 18 additions & 3 deletions src/riak_core.erl
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,30 @@ standard_join(Node, Rejoin, Auto) when is_atom(Node) ->
{error, not_reachable}
end.

%% `init:get_status/0' will return a 2-tuple reflecting the init
%% status on this node; the first element is one of `starting',
%% `started', or `stopping'. We only want to allow join actions if all
%% applications have finished starting to avoid ring status race
%% conditions.
init_complete({started, _}) ->
true;
init_complete(_) ->
false.

standard_join(Node, Ring, Rejoin, Auto) ->
{ok, MyRing} = riak_core_ring_manager:get_raw_ring(),

InitComplete = init_complete(init:get_status()),

SameSize = (riak_core_ring:num_partitions(MyRing) =:=
riak_core_ring:num_partitions(Ring)),
Singleton = ([node()] =:= riak_core_ring:all_members(MyRing)),
case {Rejoin or Singleton, SameSize} of
{false, _} ->
case {InitComplete, Rejoin or Singleton, SameSize} of
{false, _, _} ->
{error, node_still_starting};
{_, false, _} ->
{error, not_single_node};
{_, false} ->
{_, _, false} ->
{error, different_ring_sizes};
_ ->
GossipVsn = riak_core_gossip:gossip_version(),
Expand Down
2 changes: 1 addition & 1 deletion src/riak_core_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ start(_StartType, _StartArgs) ->

%% add these defaults now to supplement the set that may have been
%% configured in app.config
riak_core_bucket:append_bucket_defaults(riak_core_bucket_type:defaults()),
riak_core_bucket:append_bucket_defaults(riak_core_bucket_type:defaults(default_type)),

%% Spin up the supervisor; prune ring files as necessary
case riak_core_sup:start_link() of
Expand Down
30 changes: 26 additions & 4 deletions src/riak_core_bucket_type.erl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
-include("riak_core_bucket_type.hrl").

-export([defaults/0,
defaults/1,
create/2,
status/1,
activate/1,
Expand All @@ -118,6 +119,28 @@
%% @doc The hardcoded defaults for all bucket types.
-spec defaults() -> bucket_type_props().
defaults() ->
custom_type_defaults().

%% @doc The hardcoded defaults for the legacy, default bucket
%% type. These find their way into the `default_bucket_props'
%% environment variable
-spec defaults(default_type) -> bucket_type_props().
defaults(default_type) ->
default_type_defaults().

default_type_defaults() ->
common_defaults() ++
[{dvv_enabled, false},
{allow_mult, false}].

custom_type_defaults() ->
common_defaults() ++
%% @HACK dvv is a riak_kv only thing, yet there is nowhere else
%% to put it (except maybe fixups?)
[{dvv_enabled, true},
{allow_mult, true}].

common_defaults() ->
[{linkfun, {modfun, riak_kv_wm_link_walker, mapreduce_linkfun}},
{old_vclock, 86400},
{young_vclock, 20},
Expand All @@ -132,13 +155,9 @@ defaults() ->
{basic_quorum, false},
{notfound_ok, true},
{n_val,3},
{allow_mult, true},
{last_write_wins,false},
{precommit, []},
{postcommit, []},
%% @HACK this is a riak_kv only thing, yet there is nowhere else
%% to put it (except maybe fixups?)
{dvv_enabled, true},
{chash_keyfun, {riak_core_util, chash_std_keyfun}}].

%% @doc Create the type. The type is not activated (available to nodes) at this time. This
Expand Down Expand Up @@ -188,6 +207,9 @@ get(BucketType) when is_binary(BucketType) ->
%% @doc Reset the properties of the bucket. This only affects properties that
%% can be set using {@link update/2} and can only be performed on an active
%% type.
%%
%% This is not currently hooked into `riak-admin' but can be invoked
%% from the console.
-spec reset(bucket_type()) -> ok | {error, term()}.
reset(BucketType) ->
update(BucketType, defaults()).
Expand Down
64 changes: 64 additions & 0 deletions src/riak_core_util.erl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
safe_rpc/5,
rpc_every_member/4,
rpc_every_member_ann/4,
keydelete/2,
multi_keydelete/2,
multi_keydelete/3,
compose/1,
compose/2,
pmap/2,
pmap/3,
multi_rpc/4,
Expand Down Expand Up @@ -307,6 +312,46 @@ ensure_started(App) ->
ok
end.

%% @doc Returns a copy of `TupleList' where the first occurrence of a tuple whose
%% first element compares equal to `Key' is deleted, if there is such a tuple.
%% Equivalent to `lists:keydelete(Key, 1, TupleList)'.
-spec keydelete(atom(), [tuple()]) -> [tuple()].
keydelete(Key, TupleList) ->
lists:keydelete(Key, 1, TupleList).

%% @doc Returns a copy of `TupleList' where the first occurrence of a tuple whose
%% first element compares equal to any key in `KeysToDelete' is deleted, if
%% there is such a tuple.
-spec multi_keydelete([atom()], [tuple()]) -> [tuple()].
multi_keydelete(KeysToDelete, TupleList) ->
multi_keydelete(KeysToDelete, 1, TupleList).

%% @doc Returns a copy of `TupleList' where the Nth occurrence of a tuple whose
%% first element compares equal to any key in `KeysToDelete' is deleted, if
%% there is such a tuple.
-spec multi_keydelete([atom()], non_neg_integer(), [tuple()]) -> [tuple()].
multi_keydelete(KeysToDelete, N, TupleList) ->
lists:foldl(
fun(Key, Acc) -> lists:keydelete(Key, N, Acc) end,
TupleList,
KeysToDelete).

%% @doc Function composition: returns a function that is the composition of
%% `F' and `G'.
-spec compose(fun(), fun()) -> fun().
compose(F, G) when is_function(F), is_function(G) ->
fun(X) ->
F(G(X))
end.

%% @doc Function composition: returns a function that is the composition of all
%% functions in the `Funs' list.
-spec compose([fun()]) -> fun().
compose([Fun]) ->
Fun;
compose([Fun|Funs]) ->
lists:foldl(fun compose/2, Fun, Funs).

%% @doc Invoke function `F' over each element of list `L' in parallel,
%% returning the results in the same order as the input list.
-spec pmap(F, L1) -> L2 when
Expand Down Expand Up @@ -742,6 +787,25 @@ incr_counter(CounterPid) ->
decr_counter(CounterPid) ->
CounterPid ! down.

multi_keydelete_test_() ->
Languages = [{lisp, 1958},
{ml, 1973},
{erlang, 1986},
{haskell, 1990},
{ocaml, 1996},
{clojure, 2007},
{elixir, 2012}],
?_assertMatch(
[{lisp, _}, {ml, _}, {erlang, _}, {haskell, _}],
multi_keydelete([ocaml, clojure, elixir], Languages)).

compose_test_() ->
Upper = fun string:to_upper/1,
Reverse = fun lists:reverse/1,
Strip = fun(S) -> string:strip(S, both, $!) end,
Composed = compose([Upper, Reverse, Strip]),
?_assertEqual("DLROW OLLEH", Composed("Hello world!")).

pmap_test_() ->
Fgood = fun(X) -> 2 * X end,
Fbad = fun(3) -> throw(die_on_3);
Expand Down
7 changes: 7 additions & 0 deletions src/riak_core_vnode.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
-export([reply/2,
monitor/1]).
-export([get_mod_index/1,
get_modstate/1,
set_forwarding/2,
trigger_handoff/2,
trigger_handoff/3,
Expand Down Expand Up @@ -1059,6 +1060,12 @@ mod_set_forwarding(Forward, State=#state{mod=Mod, modstate=ModState}) ->
%% Test API
%% ===================================================================

%% @doc Reveal the underlying module state for testing
-spec(get_modstate(pid()) -> {atom(), #state{}}).
get_modstate(Pid) ->
{_StateName, State} = gen_fsm:sync_send_all_state_event(Pid, current_state),
{State#state.mod, State#state.modstate}.

-ifdef(TEST).

%% Start the garbage collection server
Expand Down

0 comments on commit 138fc50

Please sign in to comment.