From 5dbbb70bb9dc1fc6af6d97c911eae83a98f5cbe7 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 23 Feb 2012 16:12:12 -0600 Subject: [PATCH 01/61] Add the riak_kv_yessir_backend.erl storage manager for simulation purposes. %% @doc riak_kv_yessir_backend is a backend for benchmarking Riak without %% any disk I/O or RAM constraints. %% %% Riak: "Store this key/value pair." %% Backend: "Yes, sir!" %% Riak: "Get me that key/value pair." %% Backend: "Yes, sir!" %% %% This backend uses zero disk resources and uses constant memory. %% %% * All put requests are immediately acknowledged 'ok'. No %% data about the put request is stored. %% * All get requests are fulfilled by creating a constant binary for %% the value. No attempt is made to correlate get keys with %% previously-put keys or to correlate get values with previously-put %% values. %% - Get operation keys that are formatted in with the convention %% <<"integer.anything">> will use integer as the returned binary's %% Size. %% %% This backend is the Riak storage manager equivalent of: %% %% * cat > /dev/null %% * cat < /dev/zero --- src/riak_kv_yessir_backend.erl | 224 +++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 src/riak_kv_yessir_backend.erl diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl new file mode 100644 index 0000000000..b894174774 --- /dev/null +++ b/src/riak_kv_yessir_backend.erl @@ -0,0 +1,224 @@ +%% ------------------------------------------------------------------- +%% +%% riak_fs_backend: storage engine based on basic filesystem access +%% +%% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved. +%% +%% This file is provided to you under the Apache License, +%% Version 2.0 (the "License"); you may not use this file +%% except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, +%% software distributed under the License is distributed on an +%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%% KIND, either express or implied. See the License for the +%% specific language governing permissions and limitations +%% under the License. +%% +%% ------------------------------------------------------------------- + +%% @doc riak_kv_yessir_backend is a backend for benchmarking Riak without +%% any disk I/O or RAM constraints. +%% +%% Riak: "Store this key/value pair." +%% Backend: "Yes, sir!" +%% Riak: "Get me that key/value pair." +%% Backend: "Yes, sir!" +%% +%% This backend uses zero disk resources and uses constant memory. +%% +%% * All put requests are immediately acknowledged 'ok'. No +%% data about the put request is stored. +%% * All get requests are fulfilled by creating a constant binary for +%% the value. No attempt is made to correlate get keys with +%% previously-put keys or to correlate get values with previously-put +%% values. +%% - Get operation keys that are formatted in with the convention +%% <<"integer.anything">> will use integer as the returned binary's +%% Size. +%% +%% This backend is the Riak storage manager equivalent of: +%% +%% * cat > /dev/null +%% * cat < /dev/zero +%% +%% TODO list: +%% +%% * Add configuration option for random percent of not_found replies for get +%% - Anything non-zero would trigger read-repair, which could be useful +%% for some simulations. +%% * Is there a need for simulations for get to return different vclocks? + +-module(riak_kv_yessir_backend). +-behavior(riak_kv_backend). + +%% KV Backend API +-export([api_version/0, + capabilities/1, + capabilities/2, + start/2, + stop/1, + get/3, + put/5, + delete/4, + drop/1, + fold_buckets/4, + fold_keys/4, + fold_objects/4, + is_empty/1, + status/1, + callback/3]). + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). +-endif. + +-define(API_VERSION, 1). +-define(CAPABILITIES, [async_fold]). + +-record(state, { + default_get = <<>>, + op_get = 0, + op_put = 0, + op_delete = 0 + }). +-type state() :: #state{}. +-type config() :: [{atom(), term()}]. + +%% =================================================================== +%% Public API +%% =================================================================== + +%% @doc Return the major version of the +%% current API. +-spec api_version() -> {ok, integer()}. +api_version() -> + {ok, ?API_VERSION}. + +%% @doc Return the capabilities of the backend. +-spec capabilities(state()) -> {ok, [atom()]}. +capabilities(_) -> + {ok, ?CAPABILITIES}. + +%% @doc Return the capabilities of the backend. +-spec capabilities(riak_object:bucket(), state()) -> {ok, [atom()]}. +capabilities(_, _) -> + {ok, ?CAPABILITIES}. + +%% @doc Start this backend, yes, sir! +-spec start(integer(), config()) -> {ok, state()} | {error, term()}. +start(_Partition, Config) -> + DefaultLen = case app_helper:get_prop_or_env( + default_size, Config, yessir_backend) of + undefined -> 1024; + N -> N + end, + {ok, #state{default_get = <<42:(DefaultLen*8)>>}}. + +%% @doc Stop this backend, yes, sir! +-spec stop(state()) -> ok. +stop(_State) -> + ok. + +%% @doc Get a fake object, yes, sir! +-spec get(riak_object:bucket(), riak_object:key(), state()) -> + {ok, any(), state()}. +get(Bucket, Key, #state{op_get = Gets} = S) -> + Bin = case get_binsize(Key) of + undefined -> S#state.default_get; + N -> <<42:(N*8)>> + end, + O = riak_object:increment_vclock(riak_object:new(Bucket, Key, Bin), + <<"yessir!">>, 1), + {ok, term_to_binary(O), S#state{op_get = Gets + 1}}. + +%% @doc Store an object, yes, sir! +-type index_spec() :: {add, Index, SecondaryKey} | {remove, Index, SecondaryKey}. +-spec put(riak_object:bucket(), riak_object:key(), [index_spec()], binary(), state()) -> + {ok, state()}. +put(_Bucket, _PKey, _IndexSpecs, _Val, #state{op_put = Puts} = S) -> + {ok, S#state{op_put = Puts + 1}}. + +%% @doc Delete an object, yes, sir! +-spec delete(riak_object:bucket(), riak_object:key(), [index_spec()], state()) -> + {ok, state()}. +delete(_Bucket, _Key, _IndexSpecs, #state{op_delete = Deletes} = S) -> + {ok, S#state{op_delete = Deletes + 1}}. + +%% @doc Fold over all the buckets, yes, sir! +-spec fold_buckets(riak_kv_backend:fold_buckets_fun(), + any(), + [], + state()) -> {ok, any()}. +fold_buckets(_FoldBucketsFun, Acc, _Opts, _S) -> + {ok, Acc}. + +%% @doc Fold over all the keys for one or all buckets, yes, sir! +-spec fold_keys(riak_kv_backend:fold_keys_fun(), + any(), + [{atom(), term()}], + state()) -> {ok, term()}. +fold_keys(_FoldKeysFun, Acc, _Opts, _S) -> + {ok, Acc}. + +%% @doc Fold over all the objects for one or all buckets, yes, sir! +-spec fold_objects(riak_kv_backend:fold_objects_fun(), + any(), + [{atom(), term()}], + state()) -> {ok, any()}. +fold_objects(_FoldObjectsFun, Acc, _Opts, _S) -> + {ok, Acc}. + +%% @doc Delete all objects from this backend, yes, sir! +-spec drop(state()) -> {ok, state()}. +drop(S) -> + {ok, S}. + +%% @doc Returns true if this bitcasks backend contains any +%% non-tombstone values; otherwise returns false. +-spec is_empty(state()) -> false. +is_empty(_S) -> + false. + +-spec status(state()) -> [{atom(), term()}]. +status(#state{op_put = Puts, op_get = Gets, op_delete = Deletes}) -> + [{puts, Puts}, {gets, Gets}, {deletes, Deletes}]. + +%% @doc Register an asynchronous callback +-spec callback(reference(), any(), state()) -> {ok, state()}. +callback(_Ref, _Whatever, S) -> + {ok, S}. + + +%% =================================================================== +%% Internal functions +%% =================================================================== + +get_binsize(<> = Bin) when $0 =< X, X =< $9-> + get_binsize(Bin, 0); +get_binsize(_) -> + undefined. + +get_binsize(<>, Val) when $0 =< X, X =< $9-> + get_binsize(Rest, (Val * 10) + (X - $0)); +get_binsize(_, Val) -> + Val. + +%% +%% Test +%% +-ifdef(TEST). +simple_test() -> + Config = [], + riak_kv_backend:standard_test(?MODULE, Config). + +-ifdef(EQC). +eqc_test() -> + Cleanup = fun(_State,_Olds) -> ok end, + Config = [], + ?assertEqual(true, backend_eqc:test(?MODULE, false, Config, Cleanup)). +-endif. % EQC +-endif. % TEST From 910bd446f9f29621135d082e9b4429ef7cec6048 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 23 Feb 2012 16:59:14 -0600 Subject: [PATCH 02/61] Fix cut-and-paste-o, comment out broken tests --- src/riak_kv_yessir_backend.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index b894174774..47b4b94c69 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -1,6 +1,6 @@ %% ------------------------------------------------------------------- %% -%% riak_fs_backend: storage engine based on basic filesystem access +%% riak_kv_yessir_backend: simulation backend for Riak %% %% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved. %% @@ -210,6 +210,7 @@ get_binsize(_, Val) -> %% %% Test %% +-ifdef(USE_BROKEN_TESTS). -ifdef(TEST). simple_test() -> Config = [], @@ -222,3 +223,4 @@ eqc_test() -> ?assertEqual(true, backend_eqc:test(?MODULE, false, Config, Cleanup)). -endif. % EQC -endif. % TEST +-endif. % USE_BROKEN_TESTS From 6a09c407483c26331262901f6c7322c737dc7c0a Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 23 Feb 2012 17:03:27 -0600 Subject: [PATCH 03/61] Add variable latency todo --- src/riak_kv_yessir_backend.erl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index 47b4b94c69..e684c00545 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -51,6 +51,10 @@ %% - Anything non-zero would trigger read-repair, which could be useful %% for some simulations. %% * Is there a need for simulations for get to return different vclocks? +%% * Add variable latency before responding. This callback API is +%% synchronous, but adding constant- & uniform- & pareto-distributed +%% delays would simulate disk I/O latencies because all other backend +%% APIs are also synchronous. -module(riak_kv_yessir_backend). -behavior(riak_kv_backend). From eff200c65125d6c9e884975c4581f0d4dc79a5d3 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Fri, 15 Jun 2012 14:41:14 -0500 Subject: [PATCH 04/61] Add 'yessir.' prefix to get_binsize/1 check --- src/riak_kv_yessir_backend.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index e684c00545..0563430760 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -37,8 +37,8 @@ %% previously-put keys or to correlate get values with previously-put %% values. %% - Get operation keys that are formatted in with the convention -%% <<"integer.anything">> will use integer as the returned binary's -%% Size. +%% <<"yessir.{integer}.anything">> will use integer (interpreted in +%% base 10) as the returned binary's Size. %% %% This backend is the Riak storage manager equivalent of: %% @@ -201,8 +201,8 @@ callback(_Ref, _Whatever, S) -> %% Internal functions %% =================================================================== -get_binsize(<> = Bin) when $0 =< X, X =< $9-> - get_binsize(Bin, 0); +get_binsize(<<"yessir.", Rest/binary>>) -> + get_binsize(Rest, 0); get_binsize(_) -> undefined. From 514c3b4c82d0fc20cf0db052776b59590404f758 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Sun, 24 Jun 2012 14:10:10 -0400 Subject: [PATCH 05/61] Add PB service deregistration on stop. --- src/riak_kv_app.erl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/riak_kv_app.erl b/src/riak_kv_app.erl index ae774d6ee3..c62d03fe2e 100644 --- a/src/riak_kv_app.erl +++ b/src/riak_kv_app.erl @@ -25,6 +25,13 @@ -behaviour(application). -export([start/2,stop/1]). +-define(SERVICES, [{riak_kv_pb_object, 3, 6}, %% ClientID stuff + {riak_kv_pb_object, 9, 14}, %% Object requests + {riak_kv_pb_bucket, 15, 22}, %% Bucket requests + {riak_kv_pb_mapred, 23, 24}, %% MapReduce requests + {riak_kv_pb_index, 25, 26} %% Secondary index requests + ]). + %% @spec start(Type :: term(), StartArgs :: term()) -> %% {ok,Pid} | ignore | {error,Error} %% @doc The application:start callback for riak. @@ -129,12 +136,7 @@ start(_Type, _StartArgs) -> {bucket_validator, riak_kv_bucket} ]), - ok = riak_api_pb_service:register([{riak_kv_pb_object, 3, 6}, %% ClientID stuff - {riak_kv_pb_object, 9, 14}, %% Object requests - {riak_kv_pb_bucket, 15, 22}, %% Bucket requests - {riak_kv_pb_mapred, 23, 24}, %% MapReduce requests - {riak_kv_pb_index, 25, 26} %% Secondary index requests - ]), + ok = riak_api_pb_service:register(?SERVICES), %% Add routes to webmachine [ webmachine_router:add_route(R) @@ -147,6 +149,7 @@ start(_Type, _StartArgs) -> %% @spec stop(State :: term()) -> ok %% @doc The application:stop callback for riak. stop(_State) -> + ok = riak_api_pb_service:deregister(?SERVICES), ok. %% 719528 days from Jan 1, 0 to Jan 1, 1970 From 0851e60aa2367c9dc8491f7e64198e4372c33080 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Mon, 2 Jul 2012 11:47:29 -0400 Subject: [PATCH 06/61] Add chat bot notification. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 07c357d311..6dc62f0c58 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: erlang notifications: + webhooks: http://basho-engbot.herokuapp.com/travis?key=ad9a6e51d706903e1fd0963c7b8e064b93e85b56 email: eng@basho.com before_script: - "ulimit -n 4096" From a915c848c2c650e5136950c363ef79c3c57c6ae7 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Mon, 2 Jul 2012 17:03:57 +0100 Subject: [PATCH 07/61] Use a sliding one minute window not a EWMA meter Remove dep on basho_metrics --- rebar.config | 2 -- src/riak_kv_stat.erl | 44 ++++++++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/rebar.config b/rebar.config index 6e71da8a67..67455688de 100644 --- a/rebar.config +++ b/rebar.config @@ -21,7 +21,5 @@ {sext, ".*", {git, "git://github.com/esl/sext", "master"}}, {riak_pipe, ".*", {git, "git://github.com/basho/riak_pipe.git", "master"}}, - {basho_metrics, ".*", {git, "git://github.com/basho/basho_metrics.git", - "master"}}, {riak_api, ".*", {git, "git://github.com/basho/riak_api.git", "master"}} ]}. diff --git a/src/riak_kv_stat.erl b/src/riak_kv_stat.erl index 2e1c45328b..3921ace097 100644 --- a/src/riak_kv_stat.erl +++ b/src/riak_kv_stat.erl @@ -232,18 +232,18 @@ code_change(_OldVsn, State, _Extra) -> %% @doc Update the given stat update1(vnode_get) -> - folsom_metrics:notify_existing_metric({?APP, vnode_gets}, 1, meter); + folsom_metrics:notify_existing_metric({?APP, vnode_gets}, 1, spiral); update1(vnode_put) -> - folsom_metrics:notify_existing_metric({?APP, vnode_puts}, 1, meter); + folsom_metrics:notify_existing_metric({?APP, vnode_puts}, 1, spiral); update1(vnode_index_read) -> - folsom_metrics:notify_existing_metric({?APP, vnode_index_reads}, 1, meter); + folsom_metrics:notify_existing_metric({?APP, vnode_index_reads}, 1, spiral); update1({vnode_index_write, PostingsAdded, PostingsRemoved}) -> - folsom_metrics:notify_existing_metric({?APP, vnode_index_writes}, 1, meter), - folsom_metrics:notify_existing_metric({?APP, vnode_index_writes_postings}, PostingsAdded, meter), - folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes_postings}, PostingsRemoved, meter); + folsom_metrics:notify_existing_metric({?APP, vnode_index_writes}, 1, spiral), + folsom_metrics:notify_existing_metric({?APP, vnode_index_writes_postings}, PostingsAdded, spiral), + folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes_postings}, PostingsRemoved, spiral); update1({vnode_index_delete, Postings}) -> - folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes}, Postings, meter), - folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes_postings}, Postings, meter); + folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes}, Postings, spiral), + folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes_postings}, Postings, spiral); update1({get_fsm, Bucket, Microsecs, undefined, undefined, PerBucket}) -> folsom_metrics:notify_existing_metric({?APP, node_gets_total}, {inc, 1}, counter), folsom_metrics:notify_existing_metric({?APP, node_get_fsm_time}, Microsecs, histogram), @@ -260,11 +260,11 @@ update1({put_fsm_time, Bucket, Microsecs, PerBucket}) -> do_put_bucket(PerBucket, {Bucket, Microsecs}); update1(pbc_connect) -> folsom_metrics:notify_existing_metric({?APP, pbc_connects_active}, {inc, 1}, counter), - folsom_metrics:notify_existing_metric({?APP, pbc_connects}, 1, meter); + folsom_metrics:notify_existing_metric({?APP, pbc_connects}, 1, spiral); update1(pbc_disconnect) -> folsom_metrics:notify_existing_metric({?APP, pbc_connects_active}, {dec, 1}, counter); update1(read_repairs) -> - folsom_metrics:notify_existing_metric({?APP, read_repairs}, 1, meter); + folsom_metrics:notify_existing_metric({?APP, read_repairs}, 1, spiral); update1(coord_redir) -> folsom_metrics:notify_existing_metric({?APP, coord_redirs_total}, {inc, 1}, counter); update1(mapper_start) -> @@ -331,7 +331,7 @@ get_stat(Name, histogram) -> get_stat(Name, _Type) -> folsom_metrics:get_metric_value(Name). -backwards_compat(Name, meter, Stats) -> +backwards_compat(Name, spiral, Stats) -> [{Name, trunc(proplists:get_value(one, Stats))}, {join(Name, total), proplists:get_value(count, Stats)}]; backwards_compat(mapper_count, counter, Stats) -> @@ -365,29 +365,29 @@ join(Atom1, Atom2) -> binary_to_atom(<>, latin1). stats() -> - [{vnode_gets, meter}, - {vnode_puts, meter}, - {vnode_index_reads, meter}, - {vnode_index_writes, meter}, - {vnode_index_writes_postings, meter}, - {vnode_index_deletes, meter}, - {vnode_index_deletes_postings, meter}, + [{vnode_gets, spiral}, + {vnode_puts, spiral}, + {vnode_index_reads, spiral}, + {vnode_index_writes, spiral}, + {vnode_index_writes_postings, spiral}, + {vnode_index_deletes, spiral}, + {vnode_index_deletes_postings, spiral}, {node_gets_total, counter}, {node_get_fsm_siblings, histogram}, {node_get_fsm_objsize, histogram}, {node_get_fsm_time, histogram}, {node_puts_total, counter}, {node_put_fsm_time, histogram}, - {pbc_connects, meter}, + {pbc_connects, spiral}, {pbc_connects_active, counter}, - {read_repairs, meter}, + {read_repairs, spiral}, {coord_redirs_total, counter}, {mapper_count, counter}, {precommit_fail, counter}, {postcommit_fail, counter}]. -register_stat(Name, meter) -> - folsom_metrics:new_meter(Name); +register_stat(Name, spiral) -> + folsom_metrics:new_spiral(Name); register_stat(Name, counter) -> folsom_metrics:new_counter(Name); register_stat(Name, histogram) -> From 155d749b7fc2e918e0507f5c0ea3d724e45ca036 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Sat, 7 Jul 2012 07:18:11 +0100 Subject: [PATCH 08/61] Track node gets and puts with a spiral stat When using the `slide_uniform` sample type for the node puts / gets histogram, the one minute count will be inaccurate for very small and somewhat large numbers of readings. `Folsom` (actually `bear`) only calculates the histogram when there are 5 or more readings. The `slide_uniform` sample type holds a maximum number of 1028 readings per second by default, so nodes with greater throughput than that will show lower than actual one minute counts. Using `spiral` for the get / put count solves these issues. --- src/riak_kv_stat.erl | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/riak_kv_stat.erl b/src/riak_kv_stat.erl index 3921ace097..1c2a5828b0 100644 --- a/src/riak_kv_stat.erl +++ b/src/riak_kv_stat.erl @@ -245,17 +245,17 @@ update1({vnode_index_delete, Postings}) -> folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes}, Postings, spiral), folsom_metrics:notify_existing_metric({?APP, vnode_index_deletes_postings}, Postings, spiral); update1({get_fsm, Bucket, Microsecs, undefined, undefined, PerBucket}) -> - folsom_metrics:notify_existing_metric({?APP, node_gets_total}, {inc, 1}, counter), + folsom_metrics:notify_existing_metric({?APP, node_gets}, 1, spiral), folsom_metrics:notify_existing_metric({?APP, node_get_fsm_time}, Microsecs, histogram), do_get_bucket(PerBucket, {Bucket, Microsecs, undefined, undefined}); update1({get_fsm, Bucket, Microsecs, NumSiblings, ObjSize, PerBucket}) -> - folsom_metrics:notify_existing_metric({?APP, node_gets_total}, {inc, 1}, counter), + folsom_metrics:notify_existing_metric({?APP, node_gets}, 1, spiral), folsom_metrics:notify_existing_metric({?APP, node_get_fsm_time}, Microsecs, histogram), folsom_metrics:notify_existing_metric({?APP, node_get_fsm_siblings}, NumSiblings, histogram), folsom_metrics:notify_existing_metric({?APP, node_get_fsm_objsize}, ObjSize, histogram), do_get_bucket(PerBucket, {Bucket, Microsecs, NumSiblings, ObjSize}); update1({put_fsm_time, Bucket, Microsecs, PerBucket}) -> - folsom_metrics:notify_existing_metric({?APP, node_puts_total}, {inc, 1}, counter), + folsom_metrics:notify_existing_metric({?APP, node_puts}, 1, spiral), folsom_metrics:notify_existing_metric({?APP, node_put_fsm_time}, Microsecs, histogram), do_put_bucket(PerBucket, {Bucket, Microsecs}); update1(pbc_connect) -> @@ -282,14 +282,14 @@ do_get_bucket(false, _) -> ok; do_get_bucket(true, {Bucket, Microsecs, NumSiblings, ObjSize}=Args) -> BucketAtom = binary_to_atom(Bucket, latin1), - case (catch folsom_metrics:notify_existing_metric({?APP, join(node_gets_total, BucketAtom)}, {inc, 1}, counter)) of + case (catch folsom_metrics:notify_existing_metric({?APP, join(node_gets, BucketAtom)}, 1, spiral)) of ok -> [folsom_metrics:notify_existing_metric({?APP, join(Stat, BucketAtom)}, Arg, histogram) || {Stat, Arg} <- [{node_get_fsm_time, Microsecs}, {node_get_fsm_siblings, NumSiblings}, {node_get_fsm_objsize, ObjSize}], Arg /= undefined]; {'EXIT', _} -> - folsom_metrics:new_counter({?APP, join(node_gets_total, BucketAtom)}), + folsom_metrics:new_spiral({?APP, join(node_gets, BucketAtom)}), [register_stat({?APP, join(Stat, BucketAtom)}, histogram) || Stat <- [node_get_fsm_time, node_get_fsm_siblings, node_get_fsm_objsize]], @@ -301,11 +301,11 @@ do_put_bucket(false, _) -> ok; do_put_bucket(true, {Bucket, Microsecs}=Args) -> BucketAtom = binary_to_atom(Bucket, latin1), - case (catch folsom_metrics:notify_existing_metric({?APP, join(node_puts_total, BucketAtom)}, {inc, 1}, counter)) of + case (catch folsom_metrics:notify_existing_metric({?APP, join(node_puts, BucketAtom)}, 1, spiral)) of ok -> folsom_metrics:notify_existing_metric({?APP, join(node_put_fsm_time, BucketAtom)}, Microsecs, histogram); {'EXIT', _} -> - register_stat({?APP, join(node_puts_total, BucketAtom)}, counter), + register_stat({?APP, join(node_puts, BucketAtom)}, spiral), register_stat({?APP, join(node_put_fsm_time, BucketAtom)}, histogram), do_put_bucket(true, Args) end. @@ -340,14 +340,6 @@ backwards_compat(pbc_connects_active, counter, Stats) -> {pbc_active, Stats}; backwards_compat(Name, counter, Stats) -> {Name, Stats}; -backwards_compat(node_get_fsm_time, histogram, Stats) -> - Histogram = proplists:get_value(histogram, Stats), - Cnt = lists:foldl(fun({_Bin, Val}, Sum) -> Sum + Val end, 0, Histogram), - [{node_gets, Cnt} | backwards_compat_histo(node_get_fsm_time, Stats)]; -backwards_compat(node_put_fsm_time, histogram, Stats) -> - Histogram = proplists:get_value(histogram, Stats), - Cnt = lists:foldl(fun({_Bin, Val}, Sum) -> Sum + Val end, 0, Histogram), - [{node_puts, Cnt} | backwards_compat_histo(node_put_fsm_time, Stats)]; backwards_compat(Name, histogram, Stats) -> backwards_compat_histo(Name, Stats). @@ -372,11 +364,11 @@ stats() -> {vnode_index_writes_postings, spiral}, {vnode_index_deletes, spiral}, {vnode_index_deletes_postings, spiral}, - {node_gets_total, counter}, + {node_gets, spiral}, {node_get_fsm_siblings, histogram}, {node_get_fsm_objsize, histogram}, {node_get_fsm_time, histogram}, - {node_puts_total, counter}, + {node_puts, spiral}, {node_put_fsm_time, histogram}, {pbc_connects, spiral}, {pbc_connects_active, counter}, From 336e617607be4b90dfb23428be93c506afa56168 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 10 Jul 2012 16:33:27 -0400 Subject: [PATCH 09/61] When converting riak_object to JSON, treat usermeta as a struct even if it's empty. This prevents the case in the Java client where a "map" is expected for the usermeta, but instead the JSON form contains an empty list. Along with basho/riak_pb#10, this resolves the regression in the Java client integration suite. --- src/riak_object.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/riak_object.erl b/src/riak_object.erl index a4f215f5b6..5707c94de8 100644 --- a/src/riak_object.erl +++ b/src/riak_object.erl @@ -418,10 +418,13 @@ from_json(Obj) -> jsonify_metadata(MD) -> MDJS = fun({LastMod, Now={_,_,_}}) -> - % convert Now to JS-readable time string + %% convert Now to JS-readable time string {LastMod, list_to_binary( httpd_util:rfc1123_date( calendar:now_to_local_time(Now)))}; + %% When the user metadata is empty, it should still be a struct + ({?MD_USERMETA, []}) -> + {?MD_USERMETA, {struct, []}}; ({<<"Links">>, Links}) -> {<<"Links">>, [ [B, K, T] || {{B, K}, T} <- Links ]}; ({Name, List=[_|_]}) -> From 001487e3843ca5f6b6e467f6a7d164696910ca33 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 11 Jul 2012 11:29:50 +0100 Subject: [PATCH 10/61] Use the pb stats from riak_api Riak_api does not depend on riak_kv so couldn't call riak_kv_stat:update/1. Riak_api has its own stats, use them and make them backwards compatible. --- src/riak_kv_stat.erl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/riak_kv_stat.erl b/src/riak_kv_stat.erl index 1c2a5828b0..d23bc24f7e 100644 --- a/src/riak_kv_stat.erl +++ b/src/riak_kv_stat.erl @@ -258,11 +258,6 @@ update1({put_fsm_time, Bucket, Microsecs, PerBucket}) -> folsom_metrics:notify_existing_metric({?APP, node_puts}, 1, spiral), folsom_metrics:notify_existing_metric({?APP, node_put_fsm_time}, Microsecs, histogram), do_put_bucket(PerBucket, {Bucket, Microsecs}); -update1(pbc_connect) -> - folsom_metrics:notify_existing_metric({?APP, pbc_connects_active}, {inc, 1}, counter), - folsom_metrics:notify_existing_metric({?APP, pbc_connects}, 1, spiral); -update1(pbc_disconnect) -> - folsom_metrics:notify_existing_metric({?APP, pbc_connects_active}, {dec, 1}, counter); update1(read_repairs) -> folsom_metrics:notify_existing_metric({?APP, read_repairs}, 1, spiral); update1(coord_redir) -> @@ -316,6 +311,7 @@ do_put_bucket(true, {Bucket, Microsecs}=Args) -> produce_stats() -> lists:append( [lists:flatten([backwards_compat(Name, Type, get_stat({?APP, Name}, Type)) || {Name, Type} <- stats()]), + backwards_compat_pb(riak_api_stat:produce_stats()), cpu_stats(), mem_stats(), disk_stats(), @@ -331,6 +327,10 @@ get_stat(Name, histogram) -> get_stat(Name, _Type) -> folsom_metrics:get_metric_value(Name). +backwards_compat_pb({riak_api, Stats}) -> + [{pbc_active, proplists:get_value(pbc_connects_active, Stats)} | + backwards_compat(pbc_connects, spiral, proplists:get_value(pbc_connects, Stats))]. + backwards_compat(Name, spiral, Stats) -> [{Name, trunc(proplists:get_value(one, Stats))}, {join(Name, total), proplists:get_value(count, Stats)}]; @@ -370,8 +370,6 @@ stats() -> {node_get_fsm_time, histogram}, {node_puts, spiral}, {node_put_fsm_time, histogram}, - {pbc_connects, spiral}, - {pbc_connects_active, counter}, {read_repairs, spiral}, {coord_redirs_total, counter}, {mapper_count, counter}, From a1067e4b6839be3cc51f3fdf2c058e802ecbdf37 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 19 Jun 2012 08:00:48 -0600 Subject: [PATCH 11/61] Add Referer header validation --- src/riak_kv_wm_buckets.erl | 3 +++ src/riak_kv_wm_index.erl | 4 ++++ src/riak_kv_wm_keylist.erl | 3 +++ src/riak_kv_wm_link_walker.erl | 4 ++++ src/riak_kv_wm_mapred.erl | 5 ++++- src/riak_kv_wm_object.erl | 4 ++++ src/riak_kv_wm_props.erl | 4 ++++ src/riak_kv_wm_stats.erl | 4 ++++ src/riak_kv_wm_utils.erl | 37 +++++++++++++++++++++++++++++++++- 9 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/riak_kv_wm_buckets.erl b/src/riak_kv_wm_buckets.erl index 4f05a7cacf..e604924316 100644 --- a/src/riak_kv_wm_buckets.erl +++ b/src/riak_kv_wm_buckets.erl @@ -35,6 +35,7 @@ -export([ init/1, service_available/2, + forbidden/2, content_types_provided/2, encodings_provided/2, produce_bucket_list/2 @@ -87,6 +88,8 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. %% @spec content_types_provided(reqdata(), context()) -> %% {[{ContentType::string(), Producer::atom()}], reqdata(), context()} diff --git a/src/riak_kv_wm_index.erl b/src/riak_kv_wm_index.erl index 0e74f8b145..0af983969d 100644 --- a/src/riak_kv_wm_index.erl +++ b/src/riak_kv_wm_index.erl @@ -33,6 +33,7 @@ -export([ init/1, service_available/2, + forbidden/2, malformed_request/2, content_types_provided/2, encodings_provided/2, @@ -74,6 +75,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + %% @spec malformed_request(reqdata(), context()) -> %% {boolean(), reqdata(), context()} %% @doc Determine whether query parameters are badly-formed. diff --git a/src/riak_kv_wm_keylist.erl b/src/riak_kv_wm_keylist.erl index 76b4f96949..3ec48e69d6 100644 --- a/src/riak_kv_wm_keylist.erl +++ b/src/riak_kv_wm_keylist.erl @@ -45,6 +45,7 @@ -export([ init/1, service_available/2, + forbidden/2, content_types_provided/2, encodings_provided/2, produce_bucket_body/2 @@ -100,6 +101,8 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. %% @spec content_types_provided(reqdata(), context()) -> diff --git a/src/riak_kv_wm_link_walker.erl b/src/riak_kv_wm_link_walker.erl index 64f1387e4a..14efa777f7 100644 --- a/src/riak_kv_wm_link_walker.erl +++ b/src/riak_kv_wm_link_walker.erl @@ -122,6 +122,7 @@ init/1, malformed_request/2, service_available/2, + forbidden/2, allowed_methods/2, content_types_provided/2, resource_exists/2, @@ -250,6 +251,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + %% @spec allowed_methods(reqdata(), context()) -> %% {[method()], reqdata(), context()} %% @doc Get the list of methods this resource supports. diff --git a/src/riak_kv_wm_mapred.erl b/src/riak_kv_wm_mapred.erl index b8631542b3..198142c53d 100644 --- a/src/riak_kv_wm_mapred.erl +++ b/src/riak_kv_wm_mapred.erl @@ -24,7 +24,7 @@ -module(riak_kv_wm_mapred). --export([init/1, service_available/2, allowed_methods/2, known_content_type/2]). +-export([init/1, service_available/2, allowed_methods/2, known_content_type/2, forbidden/2]). -export([malformed_request/2, process_post/2, content_types_provided/2]). -export([nop/2]). @@ -50,6 +50,9 @@ service_available(RD, State) -> {false, RD, State} end. +forbidden(RD, State) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, State}. + allowed_methods(RD, State) -> {['GET','HEAD','POST'], RD, State}. diff --git a/src/riak_kv_wm_object.erl b/src/riak_kv_wm_object.erl index fe8be9000d..b5bf9a1448 100644 --- a/src/riak_kv_wm_object.erl +++ b/src/riak_kv_wm_object.erl @@ -99,6 +99,7 @@ -export([ init/1, service_available/2, + forbidden/2, allowed_methods/2, allow_missing_post/2, malformed_request/2, @@ -189,6 +190,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + %% @spec allowed_methods(reqdata(), context()) -> %% {[method()], reqdata(), context()} %% @doc Get the list of methods this resource supports. diff --git a/src/riak_kv_wm_props.erl b/src/riak_kv_wm_props.erl index 168f3a6297..76e8426e81 100644 --- a/src/riak_kv_wm_props.erl +++ b/src/riak_kv_wm_props.erl @@ -51,6 +51,7 @@ -export([ init/1, service_available/2, + forbidden/2, allowed_methods/2, malformed_request/2, content_types_provided/2, @@ -108,6 +109,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + %% @spec allowed_methods(reqdata(), context()) -> %% {[method()], reqdata(), context()} %% @doc Get the list of methods this resource supports. diff --git a/src/riak_kv_wm_stats.erl b/src/riak_kv_wm_stats.erl index 2bd189c18b..1b47c5fbd1 100644 --- a/src/riak_kv_wm_stats.erl +++ b/src/riak_kv_wm_stats.erl @@ -29,6 +29,7 @@ encodings_provided/2, content_types_provided/2, service_available/2, + forbidden/2, produce_body/2, pretty_print/2 ]). @@ -75,6 +76,9 @@ service_available(ReqData, Ctx) -> {true, ReqData, Ctx} end. +forbidden(RD, Ctx) -> + {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + produce_body(ReqData, Ctx) -> Body = mochijson2:encode({struct, get_stats()}), {Body, ReqData, Ctx}. diff --git a/src/riak_kv_wm_utils.erl b/src/riak_kv_wm_utils.erl index 78c1e45215..2f05b782fb 100644 --- a/src/riak_kv_wm_utils.erl +++ b/src/riak_kv_wm_utils.erl @@ -35,7 +35,8 @@ encode_value/1, accept_value/2, any_to_list/1, - any_to_bool/1 + any_to_bool/1, + is_valid_referer/1 ]). -include_lib("webmachine/include/webmachine.hrl"). @@ -232,3 +233,37 @@ any_to_bool(V) when is_integer(V) -> V /= 0; any_to_bool(V) when is_boolean(V) -> V. + + + +%% @doc Validate that the Referer matches up with scheme, host and port of the +%% machine that received the request. +is_valid_referer(RD) -> + OriginTuple = {wrq:scheme(RD), string:join(wrq:host_tokens(RD), "."), wrq:port(RD)}, + case referer_tuple(RD) of + undefined -> + true; + {invalid, Url} -> + lager:debug("WM unparsable referer: ~s\n", [Url]), + false; + OriginTuple -> + true; + RefererTuple -> + lager:debug("WM referrer not origin. Origin ~p != Referer ~p\n", [OriginTuple, RefererTuple]), + false + end. + +referer_tuple(RD) -> + case wrq:get_req_header("Referer", RD) of + undefined -> + undefined; + Url -> + case http_uri:parse(Url) of + {ok, {Scheme, _, Host, Port, _, _}} -> %R15+ + {Scheme, Host, Port}; + {Scheme, _, Host, Port, _, _} -> % R14 and below + {Scheme, Host, Port}; + {error, _} -> + {invalid, Url} + end + end. From 46ac4a18af9cfaeb3e310bef310456c63c0f0e80 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 11 Jul 2012 15:28:46 -0600 Subject: [PATCH 12/61] Add check for "null" origin header --- src/riak_kv_wm_buckets.erl | 2 +- src/riak_kv_wm_index.erl | 2 +- src/riak_kv_wm_keylist.erl | 2 +- src/riak_kv_wm_link_walker.erl | 2 +- src/riak_kv_wm_mapred.erl | 2 +- src/riak_kv_wm_object.erl | 2 +- src/riak_kv_wm_props.erl | 2 +- src/riak_kv_wm_stats.erl | 2 +- src/riak_kv_wm_utils.erl | 13 ++++++++++++- 9 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/riak_kv_wm_buckets.erl b/src/riak_kv_wm_buckets.erl index e604924316..a4942f0711 100644 --- a/src/riak_kv_wm_buckets.erl +++ b/src/riak_kv_wm_buckets.erl @@ -89,7 +89,7 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. %% @spec content_types_provided(reqdata(), context()) -> %% {[{ContentType::string(), Producer::atom()}], reqdata(), context()} diff --git a/src/riak_kv_wm_index.erl b/src/riak_kv_wm_index.erl index 0af983969d..5b22eca4cf 100644 --- a/src/riak_kv_wm_index.erl +++ b/src/riak_kv_wm_index.erl @@ -76,7 +76,7 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. %% @spec malformed_request(reqdata(), context()) -> %% {boolean(), reqdata(), context()} diff --git a/src/riak_kv_wm_keylist.erl b/src/riak_kv_wm_keylist.erl index 3ec48e69d6..7894951f60 100644 --- a/src/riak_kv_wm_keylist.erl +++ b/src/riak_kv_wm_keylist.erl @@ -102,7 +102,7 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. %% @spec content_types_provided(reqdata(), context()) -> diff --git a/src/riak_kv_wm_link_walker.erl b/src/riak_kv_wm_link_walker.erl index 14efa777f7..7bac885f3a 100644 --- a/src/riak_kv_wm_link_walker.erl +++ b/src/riak_kv_wm_link_walker.erl @@ -252,7 +252,7 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. %% @spec allowed_methods(reqdata(), context()) -> %% {[method()], reqdata(), context()} diff --git a/src/riak_kv_wm_mapred.erl b/src/riak_kv_wm_mapred.erl index 198142c53d..fc0bec4b7a 100644 --- a/src/riak_kv_wm_mapred.erl +++ b/src/riak_kv_wm_mapred.erl @@ -51,7 +51,7 @@ service_available(RD, State) -> end. forbidden(RD, State) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, State}. + {riak_kv_wm_utils:is_forbidden(RD), RD, State}. allowed_methods(RD, State) -> {['GET','HEAD','POST'], RD, State}. diff --git a/src/riak_kv_wm_object.erl b/src/riak_kv_wm_object.erl index b5bf9a1448..3f1173b7ef 100644 --- a/src/riak_kv_wm_object.erl +++ b/src/riak_kv_wm_object.erl @@ -191,7 +191,7 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. %% @spec allowed_methods(reqdata(), context()) -> %% {[method()], reqdata(), context()} diff --git a/src/riak_kv_wm_props.erl b/src/riak_kv_wm_props.erl index 76e8426e81..0d5ecd8605 100644 --- a/src/riak_kv_wm_props.erl +++ b/src/riak_kv_wm_props.erl @@ -110,7 +110,7 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. %% @spec allowed_methods(reqdata(), context()) -> %% {[method()], reqdata(), context()} diff --git a/src/riak_kv_wm_stats.erl b/src/riak_kv_wm_stats.erl index 1b47c5fbd1..a91dcb75a8 100644 --- a/src/riak_kv_wm_stats.erl +++ b/src/riak_kv_wm_stats.erl @@ -77,7 +77,7 @@ service_available(ReqData, Ctx) -> end. forbidden(RD, Ctx) -> - {not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}. + {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. produce_body(ReqData, Ctx) -> Body = mochijson2:encode({struct, get_stats()}), diff --git a/src/riak_kv_wm_utils.erl b/src/riak_kv_wm_utils.erl index 2f05b782fb..83af041462 100644 --- a/src/riak_kv_wm_utils.erl +++ b/src/riak_kv_wm_utils.erl @@ -36,7 +36,7 @@ accept_value/2, any_to_list/1, any_to_bool/1, - is_valid_referer/1 + is_forbidden/1 ]). -include_lib("webmachine/include/webmachine.hrl"). @@ -234,7 +234,18 @@ any_to_bool(V) when is_integer(V) -> any_to_bool(V) when is_boolean(V) -> V. +is_forbidden(RD) -> + is_null_origin(RD) or not is_valid_referer(RD). +%% @doc Check if the Origin header is "null". This is useful to look for attempts +%% at CSRF, but is not a complete answer to the problem. +is_null_origin(RD) -> + case wrq:get_req_header("Origin", RD) of + "null" -> + true; + _ -> + false + end. %% @doc Validate that the Referer matches up with scheme, host and port of the %% machine that received the request. From 3b0ddfed9185a7d2e95f866f7df35bbdff2e7fc6 Mon Sep 17 00:00:00 2001 From: Jared Morrow Date: Fri, 13 Jul 2012 08:10:23 -0600 Subject: [PATCH 13/61] Roll version 1.2.0 --- src/riak_kv.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/riak_kv.app.src b/src/riak_kv.app.src index 2198756311..ebef13fc79 100644 --- a/src/riak_kv.app.src +++ b/src/riak_kv.app.src @@ -3,7 +3,7 @@ {application, riak_kv, [ {description, "Riak Key/Value Store"}, - {vsn, "1.1.2"}, + {vsn, "1.2.0"}, {applications, [ kernel, stdlib, From e8eaa91e8aa361f2a956e0b0d869d1f470006609 Mon Sep 17 00:00:00 2001 From: Jared Morrow Date: Fri, 13 Jul 2012 15:20:23 -0600 Subject: [PATCH 14/61] Fix revisions to tags for release --- rebar.config | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/rebar.config b/rebar.config index 67455688de..235a6dad64 100644 --- a/rebar.config +++ b/rebar.config @@ -8,18 +8,18 @@ ]}. {deps, [ - {riak_core, ".*", {git, "git://github.com/basho/riak_core", "master"}}, - {luke, ".*", {git, "git://github.com/basho/luke", "master"}}, - {erlang_js, ".*", {git, "git://github.com/basho/erlang_js", "master"}}, - {bitcask, ".*", {git, "git://github.com/basho/bitcask", "master"}}, - {merge_index, ".*", {git, "git://github.com/basho/merge_index", - "master"}}, - {ebloom, ".*", {git, "git://github.com/basho/ebloom", "master"}}, - {eper, ".*", {git, "git://github.com/basho/eper.git", "master"}}, - {eleveldb, ".*", {git, "git://github.com/basho/eleveldb.git", - "master"}}, - {sext, ".*", {git, "git://github.com/esl/sext", "master"}}, - {riak_pipe, ".*", {git, "git://github.com/basho/riak_pipe.git", - "master"}}, - {riak_api, ".*", {git, "git://github.com/basho/riak_api.git", "master"}} + {riak_core, "1.2.0", {git, "git://github.com/basho/riak_core", {branch, "1.2"}}}, + {luke, "0.2.5", {git, "git://github.com/basho/luke", {tag, "0.2.5"}}}, + {erlang_js, "1.2.0", {git, "git://github.com/basho/erlang_js", {tag, "1.2.0"}}}, + {bitcask, "1.5.1", {git, "git://github.com/basho/bitcask", {tag, "1.5.1"}}}, + {merge_index, "1.2.0", {git, "git://github.com/basho/merge_index", + {branch, "1.2"}}}, + {ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}}, + {eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "3280b736"}}}, + {eleveldb, "1.2.0", {git, "git://github.com/basho/eleveldb.git", + {tag, "1.2.0"}}}, + {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, + {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", + {branch, "1.2"}}}, + {riak_api, "1.2.0", {git, "git://github.com/basho/riak_api.git", {branch, "1.2"}}} ]}. From 448c765580b5f3871776f925aad36a0f362ae74c Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 23 Feb 2012 16:12:12 -0600 Subject: [PATCH 15/61] Add the riak_kv_yessir_backend.erl storage manager for simulation purposes. %% @doc riak_kv_yessir_backend is a backend for benchmarking Riak without %% any disk I/O or RAM constraints. %% %% Riak: "Store this key/value pair." %% Backend: "Yes, sir!" %% Riak: "Get me that key/value pair." %% Backend: "Yes, sir!" %% %% This backend uses zero disk resources and uses constant memory. %% %% * All put requests are immediately acknowledged 'ok'. No %% data about the put request is stored. %% * All get requests are fulfilled by creating a constant binary for %% the value. No attempt is made to correlate get keys with %% previously-put keys or to correlate get values with previously-put %% values. %% - Get operation keys that are formatted in with the convention %% <<"integer.anything">> will use integer as the returned binary's %% Size. %% %% This backend is the Riak storage manager equivalent of: %% %% * cat > /dev/null %% * cat < /dev/zero --- src/riak_kv_yessir_backend.erl | 224 +++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 src/riak_kv_yessir_backend.erl diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl new file mode 100644 index 0000000000..b894174774 --- /dev/null +++ b/src/riak_kv_yessir_backend.erl @@ -0,0 +1,224 @@ +%% ------------------------------------------------------------------- +%% +%% riak_fs_backend: storage engine based on basic filesystem access +%% +%% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved. +%% +%% This file is provided to you under the Apache License, +%% Version 2.0 (the "License"); you may not use this file +%% except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, +%% software distributed under the License is distributed on an +%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%% KIND, either express or implied. See the License for the +%% specific language governing permissions and limitations +%% under the License. +%% +%% ------------------------------------------------------------------- + +%% @doc riak_kv_yessir_backend is a backend for benchmarking Riak without +%% any disk I/O or RAM constraints. +%% +%% Riak: "Store this key/value pair." +%% Backend: "Yes, sir!" +%% Riak: "Get me that key/value pair." +%% Backend: "Yes, sir!" +%% +%% This backend uses zero disk resources and uses constant memory. +%% +%% * All put requests are immediately acknowledged 'ok'. No +%% data about the put request is stored. +%% * All get requests are fulfilled by creating a constant binary for +%% the value. No attempt is made to correlate get keys with +%% previously-put keys or to correlate get values with previously-put +%% values. +%% - Get operation keys that are formatted in with the convention +%% <<"integer.anything">> will use integer as the returned binary's +%% Size. +%% +%% This backend is the Riak storage manager equivalent of: +%% +%% * cat > /dev/null +%% * cat < /dev/zero +%% +%% TODO list: +%% +%% * Add configuration option for random percent of not_found replies for get +%% - Anything non-zero would trigger read-repair, which could be useful +%% for some simulations. +%% * Is there a need for simulations for get to return different vclocks? + +-module(riak_kv_yessir_backend). +-behavior(riak_kv_backend). + +%% KV Backend API +-export([api_version/0, + capabilities/1, + capabilities/2, + start/2, + stop/1, + get/3, + put/5, + delete/4, + drop/1, + fold_buckets/4, + fold_keys/4, + fold_objects/4, + is_empty/1, + status/1, + callback/3]). + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). +-endif. + +-define(API_VERSION, 1). +-define(CAPABILITIES, [async_fold]). + +-record(state, { + default_get = <<>>, + op_get = 0, + op_put = 0, + op_delete = 0 + }). +-type state() :: #state{}. +-type config() :: [{atom(), term()}]. + +%% =================================================================== +%% Public API +%% =================================================================== + +%% @doc Return the major version of the +%% current API. +-spec api_version() -> {ok, integer()}. +api_version() -> + {ok, ?API_VERSION}. + +%% @doc Return the capabilities of the backend. +-spec capabilities(state()) -> {ok, [atom()]}. +capabilities(_) -> + {ok, ?CAPABILITIES}. + +%% @doc Return the capabilities of the backend. +-spec capabilities(riak_object:bucket(), state()) -> {ok, [atom()]}. +capabilities(_, _) -> + {ok, ?CAPABILITIES}. + +%% @doc Start this backend, yes, sir! +-spec start(integer(), config()) -> {ok, state()} | {error, term()}. +start(_Partition, Config) -> + DefaultLen = case app_helper:get_prop_or_env( + default_size, Config, yessir_backend) of + undefined -> 1024; + N -> N + end, + {ok, #state{default_get = <<42:(DefaultLen*8)>>}}. + +%% @doc Stop this backend, yes, sir! +-spec stop(state()) -> ok. +stop(_State) -> + ok. + +%% @doc Get a fake object, yes, sir! +-spec get(riak_object:bucket(), riak_object:key(), state()) -> + {ok, any(), state()}. +get(Bucket, Key, #state{op_get = Gets} = S) -> + Bin = case get_binsize(Key) of + undefined -> S#state.default_get; + N -> <<42:(N*8)>> + end, + O = riak_object:increment_vclock(riak_object:new(Bucket, Key, Bin), + <<"yessir!">>, 1), + {ok, term_to_binary(O), S#state{op_get = Gets + 1}}. + +%% @doc Store an object, yes, sir! +-type index_spec() :: {add, Index, SecondaryKey} | {remove, Index, SecondaryKey}. +-spec put(riak_object:bucket(), riak_object:key(), [index_spec()], binary(), state()) -> + {ok, state()}. +put(_Bucket, _PKey, _IndexSpecs, _Val, #state{op_put = Puts} = S) -> + {ok, S#state{op_put = Puts + 1}}. + +%% @doc Delete an object, yes, sir! +-spec delete(riak_object:bucket(), riak_object:key(), [index_spec()], state()) -> + {ok, state()}. +delete(_Bucket, _Key, _IndexSpecs, #state{op_delete = Deletes} = S) -> + {ok, S#state{op_delete = Deletes + 1}}. + +%% @doc Fold over all the buckets, yes, sir! +-spec fold_buckets(riak_kv_backend:fold_buckets_fun(), + any(), + [], + state()) -> {ok, any()}. +fold_buckets(_FoldBucketsFun, Acc, _Opts, _S) -> + {ok, Acc}. + +%% @doc Fold over all the keys for one or all buckets, yes, sir! +-spec fold_keys(riak_kv_backend:fold_keys_fun(), + any(), + [{atom(), term()}], + state()) -> {ok, term()}. +fold_keys(_FoldKeysFun, Acc, _Opts, _S) -> + {ok, Acc}. + +%% @doc Fold over all the objects for one or all buckets, yes, sir! +-spec fold_objects(riak_kv_backend:fold_objects_fun(), + any(), + [{atom(), term()}], + state()) -> {ok, any()}. +fold_objects(_FoldObjectsFun, Acc, _Opts, _S) -> + {ok, Acc}. + +%% @doc Delete all objects from this backend, yes, sir! +-spec drop(state()) -> {ok, state()}. +drop(S) -> + {ok, S}. + +%% @doc Returns true if this bitcasks backend contains any +%% non-tombstone values; otherwise returns false. +-spec is_empty(state()) -> false. +is_empty(_S) -> + false. + +-spec status(state()) -> [{atom(), term()}]. +status(#state{op_put = Puts, op_get = Gets, op_delete = Deletes}) -> + [{puts, Puts}, {gets, Gets}, {deletes, Deletes}]. + +%% @doc Register an asynchronous callback +-spec callback(reference(), any(), state()) -> {ok, state()}. +callback(_Ref, _Whatever, S) -> + {ok, S}. + + +%% =================================================================== +%% Internal functions +%% =================================================================== + +get_binsize(<> = Bin) when $0 =< X, X =< $9-> + get_binsize(Bin, 0); +get_binsize(_) -> + undefined. + +get_binsize(<>, Val) when $0 =< X, X =< $9-> + get_binsize(Rest, (Val * 10) + (X - $0)); +get_binsize(_, Val) -> + Val. + +%% +%% Test +%% +-ifdef(TEST). +simple_test() -> + Config = [], + riak_kv_backend:standard_test(?MODULE, Config). + +-ifdef(EQC). +eqc_test() -> + Cleanup = fun(_State,_Olds) -> ok end, + Config = [], + ?assertEqual(true, backend_eqc:test(?MODULE, false, Config, Cleanup)). +-endif. % EQC +-endif. % TEST From 93daaa6c434f3c6f49c8dbd02f50f7e98ad690d8 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 23 Feb 2012 16:59:14 -0600 Subject: [PATCH 16/61] Fix cut-and-paste-o, comment out broken tests --- src/riak_kv_yessir_backend.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index b894174774..47b4b94c69 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -1,6 +1,6 @@ %% ------------------------------------------------------------------- %% -%% riak_fs_backend: storage engine based on basic filesystem access +%% riak_kv_yessir_backend: simulation backend for Riak %% %% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved. %% @@ -210,6 +210,7 @@ get_binsize(_, Val) -> %% %% Test %% +-ifdef(USE_BROKEN_TESTS). -ifdef(TEST). simple_test() -> Config = [], @@ -222,3 +223,4 @@ eqc_test() -> ?assertEqual(true, backend_eqc:test(?MODULE, false, Config, Cleanup)). -endif. % EQC -endif. % TEST +-endif. % USE_BROKEN_TESTS From 06f77397ab9deacdef09b3254379a17c79039736 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 23 Feb 2012 17:03:27 -0600 Subject: [PATCH 17/61] Add variable latency todo --- src/riak_kv_yessir_backend.erl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index 47b4b94c69..e684c00545 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -51,6 +51,10 @@ %% - Anything non-zero would trigger read-repair, which could be useful %% for some simulations. %% * Is there a need for simulations for get to return different vclocks? +%% * Add variable latency before responding. This callback API is +%% synchronous, but adding constant- & uniform- & pareto-distributed +%% delays would simulate disk I/O latencies because all other backend +%% APIs are also synchronous. -module(riak_kv_yessir_backend). -behavior(riak_kv_backend). From a808f095b594ee24c190f504cc141f78be286d8f Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Fri, 15 Jun 2012 14:41:14 -0500 Subject: [PATCH 18/61] Add 'yessir.' prefix to get_binsize/1 check --- src/riak_kv_yessir_backend.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index e684c00545..0563430760 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -37,8 +37,8 @@ %% previously-put keys or to correlate get values with previously-put %% values. %% - Get operation keys that are formatted in with the convention -%% <<"integer.anything">> will use integer as the returned binary's -%% Size. +%% <<"yessir.{integer}.anything">> will use integer (interpreted in +%% base 10) as the returned binary's Size. %% %% This backend is the Riak storage manager equivalent of: %% @@ -201,8 +201,8 @@ callback(_Ref, _Whatever, S) -> %% Internal functions %% =================================================================== -get_binsize(<> = Bin) when $0 =< X, X =< $9-> - get_binsize(Bin, 0); +get_binsize(<<"yessir.", Rest/binary>>) -> + get_binsize(Rest, 0); get_binsize(_) -> undefined. From 808680e55630fc4a38998a084672cd4b2f8ce625 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Mon, 16 Jul 2012 15:47:08 -0400 Subject: [PATCH 19/61] Make sure yessir objects have a last-modified metadata entry --- src/riak_kv_yessir_backend.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index 0563430760..b6a62a03fd 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -135,7 +135,10 @@ get(Bucket, Key, #state{op_get = Gets} = S) -> undefined -> S#state.default_get; N -> <<42:(N*8)>> end, - O = riak_object:increment_vclock(riak_object:new(Bucket, Key, Bin), + O = riak_object:increment_vclock(riak_object:new(Bucket, Key, Bin, + dict:store(<<"X-Riak-Last-Modified">>, + erlang:now(), + dict:new())), <<"yessir!">>, 1), {ok, term_to_binary(O), S#state{op_get = Gets + 1}}. From 0dbc67da8d5f2354aa22f5cfe8f0236d77603c7b Mon Sep 17 00:00:00 2001 From: Chris Tilt Date: Tue, 17 Jul 2012 16:12:00 -0700 Subject: [PATCH 20/61] Clean up configuration documentation. --- src/riak_kv_yessir_backend.erl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index 9889ae10ba..9be55d795a 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -54,9 +54,16 @@ %% * cat > /dev/null %% * cat < /dev/zero %% -%% Configuration file parameters: -%% default_size - The number of bytes of generated data for the value -%% key_count - The number of keys that will be folded over, e.g. list_keys() +%% === Configuration Options === +%% +%% The following configuration options are available for the yessir backend. +%% The options should be specified in the `yessir_backend' section of your +%% app.config file. +%% +%%
    +%%
  • `default_size' - The number of bytes of generated data for the value.
  • +%%
  • `key_count' - The number of keys that will be folded over, e.g. list_keys().
  • +%%
%% %% TODO list: %% From 2346cc45e0e1e1b375c67308b1ea2f5e9b9fcfd3 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Tue, 17 Jul 2012 18:34:09 -0500 Subject: [PATCH 21/61] Change config key names to 'yessir_' prefix, edit EDoc accordingly --- src/riak_kv_yessir_backend.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index 9be55d795a..b10302df4a 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -57,12 +57,12 @@ %% === Configuration Options === %% %% The following configuration options are available for the yessir backend. -%% The options should be specified in the `yessir_backend' section of your +%% The options should be specified in the `riak_kv' section of your %% app.config file. %% %%
    -%%
  • `default_size' - The number of bytes of generated data for the value.
  • -%%
  • `key_count' - The number of keys that will be folded over, e.g. list_keys().
  • +%%
  • `yessir_default_size' - The number of bytes of generated data for the value.
  • +%%
  • `yessir_key_count' - The number of keys that will be folded over, e.g. list_keys().
  • %%
%% %% TODO list: @@ -138,12 +138,12 @@ capabilities(_, _) -> -spec start(integer(), config()) -> {ok, state()} | {error, term()}. start(_Partition, Config) -> DefaultLen = case app_helper:get_prop_or_env( - default_size, Config, yessir_backend) of + yessir_default_size, Config, yessir_backend) of undefined -> 1024; Len -> Len end, KeyCount = case app_helper:get_prop_or_env( - key_count, Config, yessir_backend) of + yessir_key_count, Config, yessir_backend) of undefined -> 1024; Count -> Count end, From 4c43c68ce69860cc92722063e09fc0e338946dcf Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Tue, 17 Jul 2012 21:54:28 -0600 Subject: [PATCH 22/61] Call eleveldb:close as added in https://github.com/basho/eleveldb/pull/33 Should fix the MANIFEST missing race, and may help with occational memory free coredumps we've been seeing. --- src/riak_kv_eleveldb_backend.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/riak_kv_eleveldb_backend.erl b/src/riak_kv_eleveldb_backend.erl index cc13456039..7ea698f872 100644 --- a/src/riak_kv_eleveldb_backend.erl +++ b/src/riak_kv_eleveldb_backend.erl @@ -277,6 +277,7 @@ fold_objects(FoldObjectsFun, Acc, Opts, #state{fold_opts=FoldOpts, %% and return a fresh reference. -spec drop(state()) -> {ok, state()} | {error, term(), state()}. drop(State0) -> + eleveldb:close(State0#state.ref), case eleveldb:destroy(State0#state.data_root, []) of ok -> case open_db(State0) of From b4f488105ce5f5d3e3422a24eeb43177998e4111 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Wed, 18 Jul 2012 19:17:51 -0600 Subject: [PATCH 23/61] Updated eleveldb dependency to get eleveldb:close --- rebar.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index 235a6dad64..de2cbabf42 100644 --- a/rebar.config +++ b/rebar.config @@ -16,8 +16,8 @@ {branch, "1.2"}}}, {ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}}, {eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "3280b736"}}}, - {eleveldb, "1.2.0", {git, "git://github.com/basho/eleveldb.git", - {tag, "1.2.0"}}}, + {eleveldb, "1.2.1", {git, "git://github.com/basho/eleveldb.git", + {tag, "1.2.1"}}}, {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", {branch, "1.2"}}}, From 62fed8c3ae5375289e8676644e8ac5d46737e574 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 19 Jul 2012 15:44:17 +0100 Subject: [PATCH 24/61] Register the kv stats mod with riak_core on app start-up Also fix riak_kv_vnode test --- src/riak_kv_app.erl | 6 ++---- src/riak_kv_vnode.erl | 8 ++++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/riak_kv_app.erl b/src/riak_kv_app.erl index ae774d6ee3..1e641013d7 100644 --- a/src/riak_kv_app.erl +++ b/src/riak_kv_app.erl @@ -118,15 +118,13 @@ start(_Type, _StartArgs) -> mapred_2i_pipe, [{true, true}, {false, false}]}), - %% register stats - riak_kv_stat:register_stats(), - %% Go ahead and mark the riak_kv service as up in the node watcher. %% The riak_core_ring_handler blocks until all vnodes have been started %% synchronously. riak_core:register(riak_kv, [ {vnode_module, riak_kv_vnode}, - {bucket_validator, riak_kv_bucket} + {bucket_validator, riak_kv_bucket}, + {stat_mod, riak_kv_stat} ]), ok = riak_api_pb_service:register([{riak_kv_pb_object, 3, 6}, %% ClientID stuff diff --git a/src/riak_kv_vnode.erl b/src/riak_kv_vnode.erl index 968ab96c6b..c4ebb32ba7 100644 --- a/src/riak_kv_vnode.erl +++ b/src/riak_kv_vnode.erl @@ -1379,11 +1379,15 @@ list_buckets_test_() -> {foreach, fun() -> application:start(sasl), - application:get_all_env(riak_kv), application:start(folsom), - riak_kv_stat:register_stats() + riak_core_stat_cache:start_link(), + riak_kv_stat:register_stats(), + application:get_all_env(riak_kv) + end, fun(Env) -> + riak_core_stat_cache:stop(), + application:stop(folsom), application:stop(sasl), [application:unset_env(riak_kv, K) || {K, _V} <- application:get_all_env(riak_kv)], From 3408ad55d80000f6f37090096cbf41c946ffd38b Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 19 Jul 2012 21:30:46 +0100 Subject: [PATCH 25/61] Delete registered folsom metrics before registering In case of crash and restart, attempt to put folsom in a clean consistent state --- src/riak_kv_stat.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/riak_kv_stat.erl b/src/riak_kv_stat.erl index d23bc24f7e..b9f25cca47 100644 --- a/src/riak_kv_stat.erl +++ b/src/riak_kv_stat.erl @@ -192,6 +192,7 @@ start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). register_stats() -> + [(catch folsom_metrics:delete_metric({?APP, Name})) || {Name, _Type} <- stats()], [register_stat({?APP, Name}, Type) || {Name, Type} <- stats()], riak_core_stat_cache:register_app(?APP, {?MODULE, produce_stats, []}). From 6af4c10bf82d30f50b4de38fa69f93208ed54652 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Tue, 24 Jul 2012 11:46:33 -0600 Subject: [PATCH 26/61] Changed semantics of backend:drop - backend must close all handles. Resolves issues around eleveldb locking and handoff. --- src/riak_kv_bitcask_backend.erl | 45 ++++++++++++-------------------- src/riak_kv_eleveldb_backend.erl | 16 ++++++------ test/backend_eqc.erl | 20 +++++++------- 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/src/riak_kv_bitcask_backend.erl b/src/riak_kv_bitcask_backend.erl index ee7ffc95c4..1713e2a5ac 100644 --- a/src/riak_kv_bitcask_backend.erl +++ b/src/riak_kv_bitcask_backend.erl @@ -124,7 +124,12 @@ start(Partition, Config) -> %% @doc Stop the bitcask backend -spec stop(state()) -> ok. stop(#state{ref=Ref}) -> - bitcask:close(Ref). + case Ref of + undefined -> + ok; + _ -> + bitcask:close(Ref) + end. %% @doc Retrieve an object from the bitcask backend -spec get(riak_object:bucket(), riak_object:key(), state()) -> @@ -304,8 +309,7 @@ fold_objects(FoldObjectsFun, Acc, Opts, #state{opts=BitcaskOpts, -spec drop(state()) -> {ok, state()} | {error, term(), state()}. drop(#state{ref=Ref, partition=Partition, - root=DataRoot, - opts=BitcaskOpts}=State) -> + root=DataRoot}=State) -> %% Close the bitcask reference bitcask:close(Ref), @@ -321,32 +325,17 @@ drop(#state{ref=Ref, CleanupDir = check_for_cleanup_dir(DataRoot, auto), move_unused_dirs(CleanupDir, PartitionDirs), + %% Spawn a process to cleanup the old data files. + %% The use of spawn is intentional. We do not + %% care if this process dies since any lingering + %% files will be cleaned up on the next drop. + %% The worst case is that the files hang + %% around and take up some disk space. + spawn(drop_data_cleanup(PartitionStr, CleanupDir)), + %% Make sure the data directory is now empty data_directory_cleanup(PartitionDir), - - case make_data_dir(filename:join([DataRoot, - PartitionStr])) of - {ok, DataDir} -> - %% Spawn a process to cleanup the old data files. - %% The use of spawn is intentional. We do not - %% care if this process dies since any lingering - %% files will be cleaned up on the next drop. - %% The worst case is that the files hang - %% around and take up some disk space. - spawn(drop_data_cleanup(PartitionStr, CleanupDir)), - - %% Now open the bitcask and return an updated state - %% so this backend can continue processing. - case bitcask:open(filename:join(DataRoot, DataDir), BitcaskOpts) of - Ref1 when is_reference(Ref1) -> - {ok, State#state{data_dir=DataDir, - ref=Ref1}}; - {error, Reason} -> - {error, Reason, State#state{data_dir=DataDir}} - end; - {error, Reason1} -> - {error, Reason1, State} - end. + {ok, State#state{ref = undefined}}. %% @doc Returns true if this bitcasks backend contains any %% non-tombstone values; otherwise returns false. @@ -737,7 +726,7 @@ drop_test() -> %% Stop the backend ok = stop(State1), os:cmd("rm -rf test/bitcask-backend/*"), - ?assertEqual(["42", "auto_cleanup"], lists:sort(DataDirs)), + ?assertEqual(["auto_cleanup"], lists:sort(DataDirs)), %% The drop cleanup happens in a separate process so %% there is no guarantee it has happened yet when %% this test runs. diff --git a/src/riak_kv_eleveldb_backend.erl b/src/riak_kv_eleveldb_backend.erl index 7ea698f872..5ad59c0ace 100644 --- a/src/riak_kv_eleveldb_backend.erl +++ b/src/riak_kv_eleveldb_backend.erl @@ -106,8 +106,13 @@ start(Partition, Config) -> %% @doc Stop the eleveldb backend -spec stop(state()) -> ok. -stop(_State) -> - %% No-op; GC handles cleanup +stop(State) -> + case State#state.ref of + undefined -> + ok; + _ -> + eleveldb:close(State#state.ref) + end, ok. %% @doc Retrieve an object from the eleveldb backend @@ -280,12 +285,7 @@ drop(State0) -> eleveldb:close(State0#state.ref), case eleveldb:destroy(State0#state.data_root, []) of ok -> - case open_db(State0) of - {ok, State} -> - {ok, State}; - {error, Reason} -> - {error, Reason, State0} - end; + {ok, State0#state{ref = undefined}}; {error, Reason} -> {error, Reason, State0} end. diff --git a/test/backend_eqc.erl b/test/backend_eqc.erl index 022aa1746f..e85db88a44 100644 --- a/test/backend_eqc.erl +++ b/test/backend_eqc.erl @@ -249,12 +249,13 @@ init_backend(Backend, _Volatile, Config) -> S. drop(Backend, State) -> - case Backend:drop(State) of - {ok, NewState} -> - NewState; - {error, _, NewState} -> - NewState - end. + State1 = case Backend:drop(State) of + {ok, NewState} -> + NewState; + {error, _, NewState} -> + NewState + end, + Backend:stop(State1). delete(Bucket, Key, Backend, BackendState, Indexes) -> IndexSpecs = [{remove, Idx, SKey} || {B,Idx,SKey,K} <- Indexes, @@ -349,9 +350,10 @@ next_state_data(_From, _To, S, _R, {call, _M, put, [Bucket, Key, IndexSpecs, Val next_state_data(_From, _To, S, _R, {call, _M, delete, [Bucket, Key|_]}) -> S#qcst{d = orddict:erase({Bucket, Key}, S#qcst.d), i = remove_indexes(Bucket, Key, S#qcst.i)}; -next_state_data(_From, _To, S, R, {call, ?MODULE, drop, _}) -> +next_state_data(_From, _To, S, _R, {call, ?MODULE, drop, _}) -> + S#qcst{d=orddict:new(), - s=R, + s=undefined, i=ordsets:new()}; next_state_data(_From, _To, S, _R, _C) -> S. @@ -373,7 +375,7 @@ running(#qcst{backend=Backend, {history, {call, Backend, fold_keys, [fold_keys_fun(), get_fold_buffer(), fold_keys_opts(), State]}}, {history, {call, Backend, fold_objects, [fold_objects_fun(), get_fold_buffer(), g_opts(), State]}}, {history, {call, Backend, is_empty, [State]}}, - {history, {call, ?MODULE, drop, [Backend, State]}}, + {stopped, {call, ?MODULE, drop, [Backend, State]}}, {stopped, {call, Backend, stop, [State]}} ]. From c408cb08d7e31b1c096ef25521ad879c29b146d9 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 25 Jul 2012 13:32:18 +0100 Subject: [PATCH 27/61] Put riak_kv_stat under supervision of riak_core riak_core now supervisior folsom as an included app, stat modules need to be part of the same supervision tree for consistency. --- src/riak_kv_stat.erl | 1 + src/riak_kv_sup.erl | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/riak_kv_stat.erl b/src/riak_kv_stat.erl index b9f25cca47..6cd5240391 100644 --- a/src/riak_kv_stat.erl +++ b/src/riak_kv_stat.erl @@ -211,6 +211,7 @@ update(Arg) -> %% gen_server init([]) -> + register_stats(), {ok, ok}. handle_call(_Req, _From, State) -> diff --git a/src/riak_kv_sup.erl b/src/riak_kv_sup.erl index 78db14b990..9529b0b0b1 100644 --- a/src/riak_kv_sup.erl +++ b/src/riak_kv_sup.erl @@ -47,9 +47,6 @@ init([]) -> {riak_core_vnode_master, start_link, [riak_kv_vnode, riak_kv_legacy_vnode, riak_kv]}, permanent, 5000, worker, [riak_core_vnode_master]}, - RiakStat = {riak_kv_stat, - {riak_kv_stat, start_link, []}, - permanent, 5000, worker, [riak_kv_stat]}, MapJSPool = {?JSPOOL_MAP, {riak_kv_js_manager, start_link, [?JSPOOL_MAP, read_js_pool_size(map_js_vm_count, "map")]}, @@ -114,7 +111,6 @@ init([]) -> % Build the process list... Processes = lists:flatten([ ?IF(HasStorageBackend, VMaster, []), - RiakStat, GetFsmSup, PutFsmSup, DeleteSup, From 9c2908ae2f91d157e0189f84d6406e7ade8cfb94 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 25 Jul 2012 14:41:05 +0100 Subject: [PATCH 28/61] Remove check of app_env for stats, stats is always on now --- src/riak_kv_wm_stats.erl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/riak_kv_wm_stats.erl b/src/riak_kv_wm_stats.erl index a91dcb75a8..11540e054e 100644 --- a/src/riak_kv_wm_stats.erl +++ b/src/riak_kv_wm_stats.erl @@ -68,13 +68,7 @@ content_types_provided(ReqData, Context) -> service_available(ReqData, Ctx) -> - case app_helper:get_env(riak_kv, riak_kv_stat, false) of - false -> - {false, wrq:append_to_response_body("riak_kv_stat is disabled on this node.\n", ReqData), - Ctx}; - true -> - {true, ReqData, Ctx} - end. + {true, ReqData, Ctx}. forbidden(RD, Ctx) -> {riak_kv_wm_utils:is_forbidden(RD), RD, Ctx}. @@ -93,5 +87,3 @@ pretty_print(RD1, C1=#ctx{}) -> get_stats() -> proplists:delete(disk, riak_kv_stat:get_stats()) ++ riak_core_stat:get_stats(). - - From b2c31a6dfb28de2b82d6b8825c6233549a8784f7 Mon Sep 17 00:00:00 2001 From: glickbot Date: Sun, 22 Jul 2012 22:42:20 -0700 Subject: [PATCH 29/61] Corrected the order of the host tokens to enable referer validation. --- src/riak_kv_wm_utils.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/riak_kv_wm_utils.erl b/src/riak_kv_wm_utils.erl index 83af041462..aacc2be6c3 100644 --- a/src/riak_kv_wm_utils.erl +++ b/src/riak_kv_wm_utils.erl @@ -250,7 +250,7 @@ is_null_origin(RD) -> %% @doc Validate that the Referer matches up with scheme, host and port of the %% machine that received the request. is_valid_referer(RD) -> - OriginTuple = {wrq:scheme(RD), string:join(wrq:host_tokens(RD), "."), wrq:port(RD)}, + OriginTuple = {wrq:scheme(RD), string:join(lists:reverse(wrq:host_tokens(RD)), "."), wrq:port(RD)}, case referer_tuple(RD) of undefined -> true; From ad192ee775b2f5a68430d230c0999a2caabd1155 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Mon, 30 Jul 2012 15:45:23 -0600 Subject: [PATCH 30/61] Added warning if eleveldb block_size is set. --- src/riak_kv_eleveldb_backend.erl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/riak_kv_eleveldb_backend.erl b/src/riak_kv_eleveldb_backend.erl index 5ad59c0ace..3e6e98ef92 100644 --- a/src/riak_kv_eleveldb_backend.erl +++ b/src/riak_kv_eleveldb_backend.erl @@ -342,6 +342,21 @@ init_state(DataRoot, Config) -> %% Use read options for folding, but FORCE fill_cache to false FoldOpts = lists:keystore(fill_cache, 1, ReadOpts, {fill_cache, false}), + %% Warn if block_size is set + SSTBS = proplists:get_value(sst_block_size, OpenOpts, false), + BS = proplists:get_value(block_size, OpenOpts, false), + case BS /= false andalso SSTBS == false of + true -> + lager:warning("eleveldb block_size has been renamed sst_block_size " + "and the current setting of ~p is being ignored. " + "Changing sst_block_size is strongly cautioned " + "against unless you know what you are doing. Remove " + "block_size from app.config to get rid of this " + "message.\n", [BS]); + _ -> + ok + end, + %% Generate a debug message with the options we'll use for each operation lager:debug("Datadir ~s options for LevelDB: ~p\n", [DataRoot, [{open, OpenOpts}, {read, ReadOpts}, {write, WriteOpts}, {fold, FoldOpts}]]), From dab2748ff66bba80f19bf07a126158ef8038c645 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Mon, 30 Jul 2012 18:11:10 -0600 Subject: [PATCH 31/61] Bumped eleveldb to 1.2.2 for LRU cache + block_size fixes. --- rebar.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index de2cbabf42..d052cc8079 100644 --- a/rebar.config +++ b/rebar.config @@ -16,8 +16,8 @@ {branch, "1.2"}}}, {ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}}, {eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "3280b736"}}}, - {eleveldb, "1.2.1", {git, "git://github.com/basho/eleveldb.git", - {tag, "1.2.1"}}}, + {eleveldb, "1.2.2", {git, "git://github.com/basho/eleveldb.git", + {tag, "1.2.2"}}}, {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", {branch, "1.2"}}}, From f1e938a8d3efca0545309ddaa20d9d6308b09f43 Mon Sep 17 00:00:00 2001 From: Bryan Fink Date: Tue, 31 Jul 2012 12:19:22 -0400 Subject: [PATCH 32/61] catch noproc in index and listkeys coverage pipe link (basho/riak_pipe#48) It is possible that the coverage fsm handling the index query at the head of a pipe will finish (or otherwise exit) before we try to link to it. This patch wraps the link in a try-catch to prevent a 'noproc' exit (if the coverage fsm did finish successfully faster than expected, we want to pick up the 'done' message from our inbox). The listkeys pipe coverage fitting had the same potential problem. --- src/riak_kv_pipe_index.erl | 22 +++++++++++++++++++--- src/riak_kv_pipe_listkeys.erl | 22 +++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/riak_kv_pipe_index.erl b/src/riak_kv_pipe_index.erl index b144d88263..b7790f69e8 100644 --- a/src/riak_kv_pipe_index.erl +++ b/src/riak_kv_pipe_index.erl @@ -147,7 +147,23 @@ queue_existing_pipe(Pipe, Bucket, Query, Timeout) -> [LKP, {Bucket, Query}, NVal]]), %% wait for cover to hit everything - erlang:link(Sender), + {RealTO, TOReason} = + try erlang:link(Sender) of + true -> + %% Sender was alive - wait as expected + {Timeout, timeout} + catch error:noproc -> + %% Sender finished early; it's always spawned locally, + %% so we'll get a noproc exit, instead of an exit signal + + %% messages had better already be in our mailbox, + %% don't wait any extra time for them + {0, + %% we'll have no idea what its failure was, unless it + %% sent us an error message + index_coverage_failure} + end, + receive {ReqId, done} -> %% this eoi will flow into the other pipe @@ -157,8 +173,8 @@ queue_existing_pipe(Pipe, Bucket, Query, Timeout) -> %% this destroy should not harm the other pipe riak_pipe:destroy(LKP), Error - after Timeout -> + after RealTO -> %% this destroy should not harm the other pipe riak_pipe:destroy(LKP), - {error, timeout} + {error, TOReason} end. diff --git a/src/riak_kv_pipe_listkeys.erl b/src/riak_kv_pipe_listkeys.erl index a137d4ef61..0e29c5701b 100644 --- a/src/riak_kv_pipe_listkeys.erl +++ b/src/riak_kv_pipe_listkeys.erl @@ -156,7 +156,23 @@ queue_existing_pipe(Pipe, Bucket, Timeout) -> [LKP, Bucket, NVal]]), %% wait for cover to hit everything - erlang:link(Sender), + {RealTO, TOReason} = + try erlang:link(Sender) of + true -> + %% Sender was alive - wait as expected + {Timeout, timeout} + catch error:noproc -> + %% Sender finished early; it's always spawned locally, + %% so we'll get a noproc exit, instead of an exit signal + + %% messages had better already be in our mailbox, + %% don't wait any extra time for them + {0, + %% we'll have no idea what its failure was, unless it + %% sent us an error message + listkeys_coverage_failure} + end, + receive {ReqId, done} -> %% this eoi will flow into the other pipe @@ -166,8 +182,8 @@ queue_existing_pipe(Pipe, Bucket, Timeout) -> %% this destroy should not harm the other pipe riak_pipe:destroy(LKP), Error - after Timeout -> + after RealTO -> %% this destroy should not harm the other pipe riak_pipe:destroy(LKP), - {error, timeout} + {error, TOReason} end. From 87ab2c020d8220cc56c71c5080a8084f4527745b Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Tue, 31 Jul 2012 14:55:01 -0400 Subject: [PATCH 33/61] Fix object folding to return a to_binaried riak_object --- src/riak_kv_yessir_backend.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/riak_kv_yessir_backend.erl b/src/riak_kv_yessir_backend.erl index b10302df4a..0b5ea4e7df 100644 --- a/src/riak_kv_yessir_backend.erl +++ b/src/riak_kv_yessir_backend.erl @@ -305,8 +305,13 @@ fold_keys_fun(FoldKeysFun, Bucket) -> %% Return a function to fold over keys on this backend fold_objects_fun(FoldObjectsFun, Bucket, Size) -> fun(Key, VR, Acc) when Key /= undefined -> - Value = value_for_random(VR, Size), - FoldObjectsFun(Bucket, Key, Value, Acc); + Bin = value_for_random(VR, Size), + Meta = dict:new(), + Meta1 = dict:store(<<"X-Riak-Last-Modified">>, erlang:now(), Meta), + Meta2 = dict:store(<<"X-Riak-VTag">>, make_vtag(erlang:now()), Meta1), + O = riak_object:increment_vclock(riak_object:new(Bucket, Key, Bin, Meta2), + <<"yessir!">>, 1), + FoldObjectsFun(Bucket, Key, term_to_binary(O), Acc); (_, _, Acc) -> Acc end. From d7701259b1c6cee7ccb3211e4a766bb5cced987b Mon Sep 17 00:00:00 2001 From: Kelly McLaughlin Date: Thu, 2 Aug 2012 09:49:53 -0600 Subject: [PATCH 34/61] Remove the async_folds option passed into the backend at startup. The original design for async folding support had the backend make the decision to use async folding at start time, but we changed to having the decision be made per fold call. This change removes some leftover cruft from that original path that is now obsolete. --- src/riak_kv_eleveldb_backend.erl | 3 +-- src/riak_kv_vnode.erl | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/riak_kv_eleveldb_backend.erl b/src/riak_kv_eleveldb_backend.erl index 5ad59c0ace..873e1c5c70 100644 --- a/src/riak_kv_eleveldb_backend.erl +++ b/src/riak_kv_eleveldb_backend.erl @@ -543,8 +543,7 @@ eqc_test_() -> [?_assertEqual(true, backend_eqc:test(?MODULE, false, [{data_root, - "test/eleveldb-backend"}, - {async_folds, false}]))]}, + "test/eleveldb-backend"}]))]}, {timeout, 60000, [?_assertEqual(true, backend_eqc:test(?MODULE, false, diff --git a/src/riak_kv_vnode.erl b/src/riak_kv_vnode.erl index c4ebb32ba7..effa0fc2cf 100644 --- a/src/riak_kv_vnode.erl +++ b/src/riak_kv_vnode.erl @@ -240,7 +240,7 @@ init([Index]) -> {ok, VId} = get_vnodeid(Index), DeleteMode = app_helper:get_env(riak_kv, delete_mode, 3000), AsyncFolding = app_helper:get_env(riak_kv, async_folds, true) == true, - case catch Mod:start(Index, [{async_folds, AsyncFolding}|Configuration]) of + case catch Mod:start(Index, Configuration) of {ok, ModState} -> %% Get the backend capabilities State = #state{idx=Index, From 33121c5b7e9a561f646aabc2a523563c01bcac85 Mon Sep 17 00:00:00 2001 From: Jared Morrow Date: Mon, 6 Aug 2012 13:19:35 -0600 Subject: [PATCH 35/61] Fix dependency revisions for 1.2.0 release --- rebar.config | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rebar.config b/rebar.config index d052cc8079..a0f099725a 100644 --- a/rebar.config +++ b/rebar.config @@ -8,18 +8,18 @@ ]}. {deps, [ - {riak_core, "1.2.0", {git, "git://github.com/basho/riak_core", {branch, "1.2"}}}, + {riak_core, "1.2.0", {git, "git://github.com/basho/riak_core", {tag, "1.2.0"}}}, {luke, "0.2.5", {git, "git://github.com/basho/luke", {tag, "0.2.5"}}}, {erlang_js, "1.2.0", {git, "git://github.com/basho/erlang_js", {tag, "1.2.0"}}}, {bitcask, "1.5.1", {git, "git://github.com/basho/bitcask", {tag, "1.5.1"}}}, {merge_index, "1.2.0", {git, "git://github.com/basho/merge_index", - {branch, "1.2"}}}, + {tag, "1.2.0"}}}, {ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}}, {eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "3280b736"}}}, {eleveldb, "1.2.2", {git, "git://github.com/basho/eleveldb.git", {tag, "1.2.2"}}}, {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", - {branch, "1.2"}}}, - {riak_api, "1.2.0", {git, "git://github.com/basho/riak_api.git", {branch, "1.2"}}} + {tag, "1.2.0"}}}, + {riak_api, "1.2.0", {git, "git://github.com/basho/riak_api.git", {tag, "1.2.0"}}} ]}. From da66187d481b2a730911f8048cbfbdc9e21e7f54 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Mon, 2 Jul 2012 16:04:14 -0400 Subject: [PATCH 36/61] Start stat cache in FSM qc tests. --- test/fsm_eqc_util.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/fsm_eqc_util.erl b/test/fsm_eqc_util.erl index 1da7bf051c..509e09f064 100644 --- a/test/fsm_eqc_util.erl +++ b/test/fsm_eqc_util.erl @@ -183,6 +183,7 @@ start_mock_servers() -> application:load(riak_core), application:start(crypto), application:start(folsom), + riak_core_stat_cache:start_link(), riak_kv_stat:register_stats(), riak_core_ring_events:start_link(), riak_core_node_watcher_events:start_link(), From 40a67ae2552554dbadc50bc3e8d68c9b71d649d1 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Mon, 2 Jul 2012 17:52:37 -0400 Subject: [PATCH 37/61] Fix some setup and teardown in riak_kv_vnode tests. --- src/riak_kv_vnode.erl | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/riak_kv_vnode.erl b/src/riak_kv_vnode.erl index c4ebb32ba7..1b942c10f5 100644 --- a/src/riak_kv_vnode.erl +++ b/src/riak_kv_vnode.erl @@ -1371,19 +1371,15 @@ backend_with_known_key(BackendMod) -> S1), {S2, B, K}. -must_be_first_setup_stuff_test() -> - application:start(sasl), - erlang:put({?MODULE, kv}, application:get_all_env(riak_kv)). - list_buckets_test_() -> {foreach, fun() -> application:start(sasl), + Env = application:get_all_env(riak_kv), application:start(folsom), riak_core_stat_cache:start_link(), riak_kv_stat:register_stats(), - application:get_all_env(riak_kv) - + Env end, fun(Env) -> riak_core_stat_cache:stop(), @@ -1457,11 +1453,6 @@ filter_keys_test() -> flush_msgs(). -must_be_last_cleanup_stuff_test() -> - [application:unset_env(riak_kv, K) || - {K, _V} <- application:get_all_env(riak_kv)], - [application:set_env(riak_kv, K, V) || {K, V} <- erlang:get({?MODULE, kv})]. - new_result_listener(Type) -> case Type of buckets -> From 2fec010f7c9e97fc9541916da60371b47e99a771 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 10:44:23 -0400 Subject: [PATCH 38/61] Fix keys_fsm_eqc test. * New keys_fsm requires ack_keys when backpressure is turned on. * Correct the startup order of applications based on reltool's computed list. * Use the memory backend and its reset() function instead of deleting keys. * Isolate the state directory of the test to .eunit/keys_fsm_eqc. * Cleanup ring files in the state directory before the test instead of rejiggering the ring. * Use a consistent node name and use longnames so that the put_fsm doesn't get confused. * Wait for KV application and service to start rather than using an arbitrary sleep. --- test/keys_fsm_eqc.erl | 196 ++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 102 deletions(-) diff --git a/test/keys_fsm_eqc.erl b/test/keys_fsm_eqc.erl index 161f966d85..7662b693e1 100644 --- a/test/keys_fsm_eqc.erl +++ b/test/keys_fsm_eqc.erl @@ -53,40 +53,37 @@ eqc_test_() -> }. setup() -> - %% Shut logging up - too noisy. - application:load(sasl), - application:set_env(sasl, sasl_error_logger, {file, "keys_fsm_eqc_sasl.log"}), - error_logger:tty(false), - error_logger:logfile({open, "keys_fsm_eqc.log"}), - %% Cleanup in case a previous test did not cleanup(setup), - %% Pause the make sure everything is cleaned up - timer:sleep(2000), + + %% Load application environments + do_dep_apps(load, dep_apps()), %% Start erlang node - TestNode = list_to_atom("testnode" ++ integer_to_list(element(3, now()))), - net_kernel:start([TestNode, shortnames]), + {ok, Hostname} = inet:gethostname(), + TestNode = list_to_atom("keys_fsm_eqc@" ++ Hostname), + net_kernel:start([TestNode, longnames]), + + %% Start dependent applications do_dep_apps(start, dep_apps()), - %% Create a fresh ring for the test - riak_core_ring_manager:ring_trans( - fun(R0, _Args) -> - R1 = riak_core_ring:add_member(node(), R0, node()), - R2 = lists:foldl(fun({I, _OldNode}, RAcc) -> - riak_core_ring:transfer_node(I, node(), RAcc) - end, R1, riak_core_ring:all_owners(R0)), - {new_ring, R2} - end, undefined), + %% Wait for KV to be ready + riak_core:wait_for_application(riak_kv), + riak_core:wait_for_service(riak_kv), ok. +cleanup(setup) -> + os:cmd("rm -rf keys_fsm_eqc/ring"), + cleanup(ok); cleanup(_) -> do_dep_apps(stop, lists:reverse(dep_apps())), catch exit(whereis(riak_kv_vnode_master), kill), %% Leaks occasionally catch exit(whereis(riak_sysmon_filter), kill), %% Leaks occasionally + catch riak_core_stat_cache:stop(), net_kernel:stop(), %% Reset the riak_core vnode_modules application:set_env(riak_core, vnode_modules, []), + do_dep_apps(unload, lists:reverse(dep_apps())), ok. %% Call unused callback functions to clear them in the coverage @@ -101,60 +98,51 @@ coverage_test() -> prop_basic_listkeys() -> ?FORALL({ReqId, Bucket, KeyFilter, NVal, ObjectCount, Timeout, ClientType}, {g_reqid(), g_bucket(), g_key_filter(), g_n_val(), g_object_count(), g_timeout(), g_client_type()}, - ?TRAPEXIT( - begin - {ok, Client} = riak:local_client(), - {ok, Buckets} = Client:list_buckets(), - case lists:member(Bucket, Buckets) of - true -> % bucket has already been used - %% Delete the existing keys in the bucket - {ok, OldKeys} = Client:list_keys(Bucket), - [Client:delete(Bucket, OldKey) || OldKey <- OldKeys]; - false -> - ok - end, - %% Set bucket properties - BucketProps = riak_core_bucket:get_bucket(Bucket), - NewBucketProps = orddict:store(n_val, NVal, BucketProps), - riak_core_bucket:set_bucket(Bucket, NewBucketProps), - %% Create objects in bucket - GeneratedKeys = [list_to_binary(integer_to_list(X)) || X <- lists:seq(1, ObjectCount)], - [ok = Client:put(riak_object:new(Bucket, Key, <<"val">>)) || Key <- GeneratedKeys], - - %% Set the expected output based on if a - %% key filter is being used or not. - case KeyFilter of - none -> - ExpectedKeys = GeneratedKeys; - _ -> - ExpectedKeyFilter = - fun(K, Acc) -> - case KeyFilter(K) of - true -> - [K | Acc]; - false -> - Acc - end - end, - ExpectedKeys = lists:foldl(ExpectedKeyFilter, [], GeneratedKeys) - end, - %% Call start_link - Keys = start_link(ReqId, Bucket, KeyFilter, Timeout, ClientType), - ?WHENFAIL( - begin - io:format("Bucket: ~p n_val: ~p ObjectCount: ~p KeyFilter: ~p~n", [Bucket, NVal, ObjectCount, KeyFilter]), - io:format("Expected Key Count: ~p Actual Key Count: ~p~n", - [length(ExpectedKeys), length(Keys)]), - io:format("Expected Keys: ~p~nActual Keys: ~p~n", - [ExpectedKeys, lists:sort(Keys)]) - end, - conjunction( - [ - {results, equals(lists:sort(Keys), lists:sort(ExpectedKeys))} - ])) - - end - )). + ?TRAPEXIT( + begin + riak_kv_memory_backend:reset(), + {ok, Client} = riak:local_client(), + BucketProps = riak_core_bucket:get_bucket(Bucket), + NewBucketProps = orddict:store(n_val, NVal, BucketProps), + riak_core_bucket:set_bucket(Bucket, NewBucketProps), + %% Create objects in bucket + GeneratedKeys = [list_to_binary(integer_to_list(X)) || X <- lists:seq(1, ObjectCount)], + [ok = Client:put(riak_object:new(Bucket, Key, <<"val">>)) || Key <- GeneratedKeys], + + %% Set the expected output based on if a + %% key filter is being used or not. + case KeyFilter of + none -> + ExpectedKeys = GeneratedKeys; + _ -> + ExpectedKeyFilter = + fun(K, Acc) -> + case KeyFilter(K) of + true -> + [K | Acc]; + false -> + Acc + end + end, + ExpectedKeys = lists:foldl(ExpectedKeyFilter, [], GeneratedKeys) + end, + %% Call start_link + Keys = start_link(ReqId, Bucket, KeyFilter, Timeout, ClientType), + ?WHENFAIL( + begin + io:format("Bucket: ~p n_val: ~p ObjectCount: ~p KeyFilter: ~p~n", [Bucket, NVal, ObjectCount, KeyFilter]), + io:format("Expected Key Count: ~p Actual Key Count: ~p~n", + [length(ExpectedKeys), length(Keys)]), + io:format("Expected Keys: ~p~nActual Keys: ~p~n", + [ExpectedKeys, lists:sort(Keys)]) + end, + conjunction( + [ + {results, equals(lists:sort(Keys), lists:sort(ExpectedKeys))} + ])) + + end + )). %%==================================================================== %% Wrappers @@ -205,17 +193,6 @@ g_timeout() -> %% Helpers %%==================================================================== -prepare() -> - application:load(sasl), - error_logger:delete_report_handler(sasl_report_tty_h), - error_logger:delete_report_handler(error_logger_tty_h), - - TestNode = list_to_atom("testnode" ++ integer_to_list(element(3, now())) ++ - "@localhost"), - {ok, _} = net_kernel:start([TestNode, longnames]), - do_dep_apps(start, dep_apps()), - ok. - test() -> test(100). @@ -226,25 +203,37 @@ check() -> check(prop_basic_listkeys(), current_counterexample()). dep_apps() -> + Silencer = fun(load) -> + %% Silence logging junk + application:set_env(kernel, error_logger, silent), + filelib:ensure_dir("keys_fsm_eqc/log/sasl.log"), + application:set_env(sasl, sasl_error_logger, {file, "keys_fsm_eqc/log/sasl.log"}), + error_logger:tty(false); + (_) -> ok + end, + SetupFun = - fun(start) -> - %% Set some missing env vars that are normally - %% part of release packaging. - application:set_env(riak_core, ring_creation_size, 64), - application:set_env(riak_kv, storage_backend, riak_kv_memory_backend), - application:set_env(riak_kv, vnode_vclocks, true), - application:set_env(riak_kv, delete_mode, immediate), - application:set_env(riak_kv, legacy_keylisting, false), - - %% Start riak_kv - timer:sleep(500); - (stop) -> - ok + fun(load) -> + %% Set some missing env vars that are normally + %% part of release packaging. + application:set_env(riak_core, ring_creation_size, 64), + application:set_env(riak_core, ring_state_dir, "keys_fsm_eqc/ring"), + application:set_env(riak_core, platform_data_dir, "keys_fsm_eqc/data"), + application:set_env(riak_kv, storage_backend, riak_kv_memory_backend), + application:set_env(riak_kv, test, true), + application:set_env(riak_kv, vnode_vclocks, true), + application:set_env(riak_kv, delete_mode, immediate), + application:set_env(riak_kv, legacy_keylisting, false), + application:set_env(lager, handlers, [{lager_file_backend, [{"keys_fsm_eqc/log/debug.log", debug, 10485760, "$D0", 5}]}]), + application:set_env(lager, crash_log, "keys_fsm_eqc/log/crash.log"); + (_) -> ok end, - XX = fun(_) -> error_logger:info_msg("Registered: ~w\n", [lists:sort(registered())]) end, - [sasl, crypto, riak_sysmon, webmachine, XX, os_mon, - compiler, syntax_tools, lager, riak_core, XX, luke, erlang_js, - inets, mochiweb, riak_pipe, SetupFun, riak_kv, SetupFun]. + + [sasl, Silencer, crypto, public_key, ssl, riak_sysmon, os_mon, + runtime_tools, erlang_js, inets, mochiweb, webmachine, luke, + basho_stats, bitcask, compiler, syntax_tools, lager, folsom, + riak_core, riak_pipe, riak_kv, SetupFun]. + do_dep_apps(StartStop, Apps) -> lists:map(fun(A) when is_atom(A) -> application:StartStop(A); @@ -253,6 +242,9 @@ do_dep_apps(StartStop, Apps) -> data_sink(ReqId, KeyList, Done) -> receive + {ReqId, From={_Pid,_Ref}, {keys, Keys}} -> + riak_kv_keys_fsm:ack_keys(From), + data_sink(ReqId, KeyList++Keys, false); {ReqId, {keys, Keys}} -> data_sink(ReqId, KeyList++Keys, false); {ReqId, done} -> @@ -289,5 +281,5 @@ wait_for_replies(Sink, ReqId) -> ?debugFmt("Received keys for older run: ~p~n", [ORef]) end. - -endif. % EQC +-endif. % EQC From 20d9663c3219b0b078bc6aaee35cb1d28cbab77b Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 11:30:07 -0400 Subject: [PATCH 39/61] Factor out the common setup/cleanup stuff into riak_kv_test_util so we can use it elsewhere. --- src/riak_kv_test_util.erl | 122 ++++++++++++++++++++++++++++++++++++-- test/keys_fsm_eqc.erl | 85 ++++---------------------- 2 files changed, 128 insertions(+), 79 deletions(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index e94cc30fbb..262c4fdec7 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -29,21 +29,50 @@ -export([call_unused_fsm_funs/1, stop_process/1, wait_for_pid/1, - wait_for_children/1]). + wait_for_children/1, + common_setup/1, + common_setup/2, + common_cleanup/1, + common_cleanup/2]). + -include_lib("eunit/include/eunit.hrl"). +-define(SETUPTHUNK, fun(_) -> ok end). + +%% Creates a setup function for tests that need Riak KV stood +%% up in an isolated fashion. +common_setup(T) when is_atom(T) -> + common_setup(atom_to_list(T)); +common_setup(TestName) -> + common_setup(TestName, ?SETUPTHUNK). + +common_setup(T, S) when is_atom(T) -> + common_setup(atom_to_list(T), S); +common_setup(TestName, Setup) -> + fun() -> setup(TestName, Setup) end. +%% Creates a cleanup function for tests that need Riak KV stood up in +%% an isolated fashion. +common_cleanup(T) when is_atom(T) -> + common_cleanup(atom_to_list(T)); +common_cleanup(TestName) -> + common_cleanup(TestName, ?SETUPTHUNK). + +common_cleanup(T, C) when is_atom(T) -> + common_cleanup(atom_to_list(T), C); +common_cleanup(TestName, Cleanup) -> + fun(X) -> cleanup(TestName, Cleanup, X) end. + +%% Calls gen_fsm functions that might not have been touched by a test call_unused_fsm_funs(Mod) -> Mod:handle_event(event, statename, state), Mod:handle_sync_event(event, from, stateneame, state), Mod:handle_info(info, statename, statedata), Mod:terminate(reason, statename, state), Mod:code_change(oldvsn, statename, state, extra). - - - + %% Stop a running pid - unlink and exit(kill) the process -%% +%% stop_process(undefined) -> ok; stop_process(RegName) when is_atom(RegName) -> @@ -96,4 +125,87 @@ wait_for_children(PPid) -> ok end. +%% Performs setup for a test +setup(TestName, SetupFun) -> + %% Cleanup in case a previous test did not + cleanup(TestName, SetupFun, setup), + + %% Load application environments + Deps = dep_apps(TestName, SetupFun), + do_dep_apps(load, Deps), + + %% Start erlang node + {ok, Hostname} = inet:gethostname(), + TestNode = list_to_atom(TestName ++ "@" ++ Hostname), + net_kernel:start([TestNode, longnames]), + + %% Start dependent applications + do_dep_apps(start, Deps), + + %% Wait for KV to be ready + riak_core:wait_for_application(riak_kv), + riak_core:wait_for_service(riak_kv), + ok. + +cleanup(Test, CleanupFun, setup) -> + %% Remove existing ring files so we have a fresh ring + os:cmd("rm -rf " ++ Test ++ "/ring"), + cleanup(Test, CleanupFun, ok); +cleanup(Test, CleanupFun, _) -> + Deps = lists:reverse(dep_apps(Test, CleanupFun)), + + %% Stop the applications in reverse order + do_dep_apps(stop, Deps), + + %% Cleanup potentially runaway processes + catch exit(whereis(riak_kv_vnode_master), kill), + catch exit(whereis(riak_sysmon_filter), kill), + catch riak_core_stat_cache:stop(), + + %% Stop distributed Erlang + net_kernel:stop(), + + %% Reset the riak_core vnode_modules + application:set_env(riak_core, vnode_modules, []), + + %% Unload the dependent applications + do_dep_apps(unload, Deps), + ok. + +dep_apps(Test, Extra) -> + Silencer = fun(load) -> + %% Silence logging junk + application:set_env(kernel, error_logger, silent), + filelib:ensure_dir(Test ++ "/log/sasl.log"), + application:set_env(sasl, sasl_error_logger, {file, Test++"/log/sasl.log"}), + error_logger:tty(false); + (_) -> ok + end, + + DefaultSetupFun = + fun(load) -> + %% Set some missing env vars that are normally part of + %% release packaging. These can be overridden by the + %% Extra fun. + application:set_env(riak_core, ring_creation_size, 64), + application:set_env(riak_core, ring_state_dir, Test ++ "/ring"), + application:set_env(riak_core, platform_data_dir, Test ++ "/data"), + application:set_env(lager, handlers, [{lager_file_backend, + [ + {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), + application:set_env(lager, crash_log, Test ++ "/log/crash.log"); + (_) -> ok + end, + + [sasl, Silencer, crypto, public_key, ssl, riak_sysmon, os_mon, + runtime_tools, erlang_js, inets, mochiweb, webmachine, luke, + basho_stats, bitcask, compiler, syntax_tools, lager, folsom, + riak_core, riak_pipe, riak_kv, DefaultSetupFun, Extra]. + + +do_dep_apps(StartStop, Apps) -> + lists:map(fun(A) when is_atom(A) -> application:StartStop(A); + (F) -> F(StartStop) + end, Apps). + -endif. % TEST diff --git a/test/keys_fsm_eqc.erl b/test/keys_fsm_eqc.erl index 7662b693e1..e078c93d45 100644 --- a/test/keys_fsm_eqc.erl +++ b/test/keys_fsm_eqc.erl @@ -42,8 +42,8 @@ eqc_test_() -> {spawn, [{setup, - fun setup/0, - fun cleanup/1, + riak_kv_test_util:common_setup(?MODULE, fun configure/1), + riak_kv_test_util:common_cleanup(?MODULE, fun configure/1), [%% Run the quickcheck tests {timeout, 60000, % timeout is in msec ?_assertEqual(true, quickcheck(numtests(?TEST_ITERATIONS, ?QC_OUT(prop_basic_listkeys()))))} @@ -52,40 +52,6 @@ eqc_test_() -> ] }. -setup() -> - %% Cleanup in case a previous test did not - cleanup(setup), - - %% Load application environments - do_dep_apps(load, dep_apps()), - - %% Start erlang node - {ok, Hostname} = inet:gethostname(), - TestNode = list_to_atom("keys_fsm_eqc@" ++ Hostname), - net_kernel:start([TestNode, longnames]), - - %% Start dependent applications - do_dep_apps(start, dep_apps()), - - %% Wait for KV to be ready - riak_core:wait_for_application(riak_kv), - riak_core:wait_for_service(riak_kv), - ok. - -cleanup(setup) -> - os:cmd("rm -rf keys_fsm_eqc/ring"), - cleanup(ok); -cleanup(_) -> - do_dep_apps(stop, lists:reverse(dep_apps())), - catch exit(whereis(riak_kv_vnode_master), kill), %% Leaks occasionally - catch exit(whereis(riak_sysmon_filter), kill), %% Leaks occasionally - catch riak_core_stat_cache:stop(), - net_kernel:stop(), - %% Reset the riak_core vnode_modules - application:set_env(riak_core, vnode_modules, []), - do_dep_apps(unload, lists:reverse(dep_apps())), - ok. - %% Call unused callback functions to clear them in the coverage %% checker so the real code stands out. coverage_test() -> @@ -193,6 +159,15 @@ g_timeout() -> %% Helpers %%==================================================================== +configure(load) -> + application:set_env(riak_kv, storage_backend, riak_kv_memory_backend), + application:set_env(riak_kv, test, true), + application:set_env(riak_kv, vnode_vclocks, true), + application:set_env(riak_kv, delete_mode, immediate), + application:set_env(riak_kv, legacy_keylisting, false); +configure(_) -> + ok. + test() -> test(100). @@ -202,44 +177,6 @@ test(N) -> check() -> check(prop_basic_listkeys(), current_counterexample()). -dep_apps() -> - Silencer = fun(load) -> - %% Silence logging junk - application:set_env(kernel, error_logger, silent), - filelib:ensure_dir("keys_fsm_eqc/log/sasl.log"), - application:set_env(sasl, sasl_error_logger, {file, "keys_fsm_eqc/log/sasl.log"}), - error_logger:tty(false); - (_) -> ok - end, - - SetupFun = - fun(load) -> - %% Set some missing env vars that are normally - %% part of release packaging. - application:set_env(riak_core, ring_creation_size, 64), - application:set_env(riak_core, ring_state_dir, "keys_fsm_eqc/ring"), - application:set_env(riak_core, platform_data_dir, "keys_fsm_eqc/data"), - application:set_env(riak_kv, storage_backend, riak_kv_memory_backend), - application:set_env(riak_kv, test, true), - application:set_env(riak_kv, vnode_vclocks, true), - application:set_env(riak_kv, delete_mode, immediate), - application:set_env(riak_kv, legacy_keylisting, false), - application:set_env(lager, handlers, [{lager_file_backend, [{"keys_fsm_eqc/log/debug.log", debug, 10485760, "$D0", 5}]}]), - application:set_env(lager, crash_log, "keys_fsm_eqc/log/crash.log"); - (_) -> ok - end, - - [sasl, Silencer, crypto, public_key, ssl, riak_sysmon, os_mon, - runtime_tools, erlang_js, inets, mochiweb, webmachine, luke, - basho_stats, bitcask, compiler, syntax_tools, lager, folsom, - riak_core, riak_pipe, riak_kv, SetupFun]. - - -do_dep_apps(StartStop, Apps) -> - lists:map(fun(A) when is_atom(A) -> application:StartStop(A); - (F) -> F(StartStop) - end, Apps). - data_sink(ReqId, KeyList, Done) -> receive {ReqId, From={_Pid,_Ref}, {keys, Keys}} -> From f6abfe672921355beb78b01fd81eb3b0ff5de5ec Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 12:17:56 -0400 Subject: [PATCH 40/61] Fix mapred_test, extracting common setup/teardown stuff. --- test/mapred_test.erl | 180 ++++++++----------------------------------- 1 file changed, 30 insertions(+), 150 deletions(-) diff --git a/test/mapred_test.erl b/test/mapred_test.erl index faa0f25274..5f79365a41 100644 --- a/test/mapred_test.erl +++ b/test/mapred_test.erl @@ -21,130 +21,34 @@ -module(mapred_test). -include_lib("eunit/include/eunit.hrl"). - -compile(export_all). -dep_apps() -> - DelMe = "./EUnit-SASL.log", - DataDir = "./EUnit-datadir", - os:cmd("rm -rf " ++ DataDir), - os:cmd("mkdir " ++ DataDir), - KillDamnFilterProc = fun() -> - catch exit(whereis(riak_sysmon_filter), kill), - wait_until_dead(whereis(riak_sysmon_filter)) - end, - Core_Settings = [{handoff_ip, "0.0.0.0"}, - {handoff_port, 9183}, - {ring_creation_size, 16}, - {ring_state_dir, DataDir}], - KV_Settings = [{storage_backend, riak_kv_memory_backend}, - {vnode_vclocks, true}, - {pb_ip, "0.0.0.0"}, - {pb_port, 48087}, % arbitrary # - {map_js_vm_count, 4}, - {reduce_js_vm_count, 3}], - [ - fun(start) -> - net_kernel:start([mapred_test@localhost, shortnames]), - timer:sleep(50), - _ = application:stop(sasl), - _ = application:load(sasl), - put(old_sasl_l, app_helper:get_env(sasl, sasl_error_logger)), - ok = application:set_env(sasl, sasl_error_logger, {file, DelMe}), - ok = application:start(sasl), - %%error_logger:tty(false); - error_logger:tty(true); - (stop) -> - ok = application:stop(sasl), - ok = application:set_env(sasl, sasl_error_logger, erase(old_sasl_l)); - (fullstop) -> - _ = application:stop(sasl) - end, - %% public_key and ssl are not needed here but started by others so - %% stop them when we're done. - crypto, public_key, ssl, - fun(start) -> - ok = application:start(riak_sysmon); - (stop) -> - ok = application:stop(riak_sysmon), - KillDamnFilterProc(); - (fullstop) -> - _ = application:stop(riak_sysmon), - KillDamnFilterProc() - end, - webmachine, - os_mon, - compiler, - syntax_tools, - lager, - fun(start) -> - _ = application:load(riak_core), - %% riak_core_handoff_listener uses {reusaddr, true}, but - %% sometimes we just restart too quickly and hit an - %% eaddrinuse when restarting riak_core? - timer:sleep(1000), - %% io:format(user, "DEBUGG: ~s\n", [os:cmd("netstat -na | egrep -vi 'stream|dgram'")]), - [begin - put({?MODULE,AppKey}, app_helper:get_env(riak_core, AppKey)), - ok = application:set_env(riak_core, AppKey, Val) - end || {AppKey, Val} <- Core_Settings], - ok = application:start(riak_core); - (stop) -> - ok = application:stop(riak_core), - [ok = application:set_env(riak_core, AppKey, get({?MODULE, AppKey})) - || {AppKey, _Val} <- Core_Settings]; - (fullstop) -> - _ = application:stop(riak_core) - end, - riak_pipe, - luke, - erlang_js, - inets, - mochiweb, - fun(start) -> - _ = application:load(riak_kv), - [begin - put({?MODULE,AppKey}, app_helper:get_env(riak_kv, AppKey)), - ok = application:set_env(riak_kv, AppKey, Val) - end || {AppKey, Val} <- KV_Settings], - ok = application:start(riak_kv); - (stop) -> - ok = application:stop(riak_kv), - net_kernel:stop(), - [ok = application:set_env(riak_kv, AppKey, get({?MODULE, AppKey})) - || {AppKey, _Val} <- KV_Settings]; - (fullstop) -> - _ = application:stop(riak_kv) - end]. - -do_dep_apps(fullstop) -> - lists:map(fun(A) when is_atom(A) -> _ = application:stop(A); - (F) -> F(fullstop) - end, lists:reverse(dep_apps())); -do_dep_apps(StartStop) -> - Apps = if StartStop == start -> dep_apps(); - StartStop == stop -> lists:reverse(dep_apps()) - end, - lists:map(fun(A) when is_atom(A) -> ok = application:StartStop(A); - (F) -> F(StartStop) - end, Apps). +setup() -> + riak_kv_test_util:common_setup(?MODULE, fun configure/1). -prepare_runtime() -> - fun() -> - do_dep_apps(fullstop), - timer:sleep(50), - do_dep_apps(start), - timer:sleep(50), - riak_core:wait_for_service(riak_kv), - riak_core:wait_for_service(riak_pipe), - [foo1, foo2] - end. +cleanup() -> + riak_kv_test_util:common_cleanup(?MODULE, fun configure/1). -teardown_runtime() -> - fun(_PrepareThingie) -> - do_dep_apps(stop), - timer:sleep(50) - end. +configure(load) -> + KVSettings = [{storage_backend, riak_kv_memory_backend}, + {test, true}, + {vnode_vclocks, true}, + {pb_ip, "0.0.0.0"}, + {pb_port, 48087}, % arbitrary # + {map_js_vm_count, 4}, + {reduce_js_vm_count, 3}], + CoreSettings = [{handoff_ip, "0.0.0.0"}, + {handoff_port, 9183}, + {ring_creation_size, 16}], + [ application:set_env(riak_core, K, V) || {K,V} <- CoreSettings ], + [ application:set_env(riak_kv, K, V) || {K,V} <- KVSettings ], + ok; +configure(unload) -> + application:set_env(riak_api, services, dict:new()); +configure(start) -> + riak_core:wait_for_service(riak_pipe); +configure(_) -> + ok. inputs_gen_seq(Pipe, Max, _Timeout) -> [riak_pipe:queue_work(Pipe, X) || X <- lists:seq(1, Max)], @@ -158,30 +62,6 @@ inputs_gen_bkeys_1(Pipe, {Bucket, Start, End}, _Timeout) -> riak_pipe:eoi(Pipe), ok. -setup_demo_test_() -> - {foreach, - prepare_runtime(), - teardown_runtime(), - [ - fun(_) -> - {"Setup demo test", - fun() -> - Num = 5, - {ok, C} = riak:local_client(), - [ok = C:put(riak_object:new( - <<"foonum">>, - list_to_binary("bar"++integer_to_list(X)), - X)) - || X <- lists:seq(1, Num)], - [{ok, _} = C:get(<<"foonum">>, - list_to_binary("bar"++integer_to_list(X))) - || X <- lists:seq(1, Num)], - ok - end} - end - ] - }. - compat_basic1_test_() -> IntsBucket = <<"foonum">>, ReduceSumFun = fun(Inputs, _) -> [lists:sum(Inputs)] end, @@ -189,8 +69,8 @@ compat_basic1_test_() -> LinkKey = <<"yo">>, {setup, - prepare_runtime(), - teardown_runtime(), + setup(), + cleanup(), fun(_) -> [ ?_test( @@ -381,8 +261,8 @@ compat_buffer_and_prereduce_test_() -> ReduceSumFun = fun(Inputs, _) -> [lists:sum(Inputs)] end, {setup, - prepare_runtime(), - teardown_runtime(), + setup(), + cleanup(), fun(_) -> [ ?_test( @@ -461,8 +341,8 @@ compat_javascript_test_() -> NotFoundBkey = {<<"does not">>, <<"exit">>}, {setup, - prepare_runtime(), - teardown_runtime(), + setup(), + cleanup(), fun(_) -> [ ?_test( From d2221393fe822b4ad335c11ed606439d8037a7c8 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 12:51:12 -0400 Subject: [PATCH 41/61] Fix riak_kv_delete and remove registered services at unload time. --- src/riak_kv_delete.erl | 84 ++++++--------------------------------- src/riak_kv_test_util.erl | 8 ++++ 2 files changed, 21 insertions(+), 71 deletions(-) diff --git a/src/riak_kv_delete.erl b/src/riak_kv_delete.erl index 64b4d6945a..8d9a4cc96d 100644 --- a/src/riak_kv_delete.erl +++ b/src/riak_kv_delete.erl @@ -185,11 +185,10 @@ get_w_options(Bucket, Options) -> -ifdef(TEST). delete_test_() -> - cleanup(ignored_arg), %% Execute the test cases - { foreach, - fun setup/0, - fun cleanup/1, + {foreach, + setup(), + cleanup(), [ fun invalid_r_delete/0, fun invalid_rw_delete/0, @@ -286,75 +285,18 @@ invalid_pw_delete() -> ?assert(false) end. -setup() -> - %% Shut logging up - too noisy. - application:load(sasl), - application:set_env(sasl, sasl_error_logger, {file, "riak_kv_delete_test_sasl.log"}), - error_logger:tty(false), - error_logger:logfile({open, "riak_kv_delete_test.log"}), - %% Start erlang node - TestNode = list_to_atom("testnode" ++ integer_to_list(element(3, now())) ++ - integer_to_list(element(2, now()))), - case net_kernel:start([TestNode, shortnames]) of - {ok, _} -> - ok; - {error, {already_started, _}} -> - ok - end, - do_dep_apps(start, dep_apps()), - application:set_env(riak_core, default_bucket_props, [{r, quorum}, - {w, quorum}, {pr, 0}, {pw, 0}, {rw, quorum}, {n_val, 3}]), - %% There's some weird interaction with the quickcheck tests in put_fsm_eqc - %% that somehow makes the riak_kv_delete sup not be running if those tests - %% run before these. I'm sick of trying to figure out what is not being - %% cleaned up right, thus the following workaround. - case whereis(riak_kv_delete_sup) of - undefined -> - {ok, _} = riak_kv_delete_sup:start_link(); - _ -> - ok - end, - riak_kv_get_fsm_sup:start_link(), - timer:sleep(500). - -cleanup(_Pid) -> - do_dep_apps(stop, lists:reverse(dep_apps())), - catch exit(whereis(riak_kv_vnode_master), kill), %% Leaks occasionally - catch exit(whereis(riak_sysmon_filter), kill), %% Leaks occasionally - catch unlink(whereis(riak_kv_get_fsm_sup)), - catch unlink(whereis(riak_kv_delete_sup)), - catch exit(whereis(riak_kv_get_fsm_sup), kill), %% Leaks occasionally - catch exit(whereis(riak_kv_delete_sup), kill), %% Leaks occasionally - net_kernel:stop(), - %% Reset the riak_core vnode_modules - application:unset_env(riak_core, default_bucket_props), - application:unset_env(sasl, sasl_error_logger), - error_logger:tty(true), - application:set_env(riak_core, vnode_modules, []). +configure(load) -> + application:set_env(riak_core, default_bucket_props, + [{r, quorum}, {w, quorum}, {pr, 0}, {pw, 0}, + {rw, quorum}, {n_val, 3}]), + application:set_env(riak_kv, storage_backend, riak_kv_memory_backend); +configure(_) -> ok. -dep_apps() -> - SetupFun = - fun(start) -> - %% Set some missing env vars that are normally - %% part of release packaging. - application:set_env(riak_core, ring_creation_size, 64), - application:set_env(riak_kv, storage_backend, riak_kv_memory_backend), - %% Create a fresh ring for the test - Ring = riak_core_ring:fresh(), - riak_core_ring_manager:set_ring_global(Ring), +setup() -> + riak_kv_test_util:common_setup(?MODULE, fun configure/1). - %% Start riak_kv - timer:sleep(500); - (stop) -> - ok - end, - XX = fun(_) -> error_logger:info_msg("Registered: ~w\n", [lists:sort(registered())]) end, - [sasl, crypto, riak_sysmon, webmachine, XX, riak_core, XX, luke, erlang_js, - inets, mochiweb, os_mon, SetupFun, riak_kv]. +cleanup() -> + riak_kv_test_util:common_cleanup(?MODULE, fun configure/1). -do_dep_apps(StartStop, Apps) -> - lists:map(fun(A) when is_atom(A) -> application:StartStop(A); - (F) -> F(StartStop) - end, Apps). -endif. diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index 262c4fdec7..6ecfe156bf 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -194,6 +194,14 @@ dep_apps(Test, Extra) -> [ {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), application:set_env(lager, crash_log, Test ++ "/log/crash.log"); + (unload) -> + %% TODO: Remove this when the deregistration PR gets merged + Services = riak_api_pb_service:dispatch_table(), + NewServices = lists:foldl( + fun dict:erase/2, + Services, + lists:flatten([lists:seq(3,6), lists:seq(9,26)])), + application:set_env(riak_api, services, NewServices); (_) -> ok end, From 82854cdb63a78b69084123f1e6800b6b75cb110e Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 13:22:08 -0400 Subject: [PATCH 42/61] Fix vnode_status_test_. --- src/riak_kv_vnode.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/riak_kv_vnode.erl b/src/riak_kv_vnode.erl index 1b942c10f5..38b703467f 100644 --- a/src/riak_kv_vnode.erl +++ b/src/riak_kv_vnode.erl @@ -1287,8 +1287,9 @@ assign_vnodeid_restart_earlier_ts_test() -> vnode_status_test_() -> {setup, fun() -> - os:cmd("chmod u+rwx kv_vnode_status_test"), - os:cmd("rm -rf kv_vnode_status_test"), + filelib:ensure_dir("kv_vnode_status_test/.test"), + ?cmd("chmod u+rwx kv_vnode_status_test"), + ?cmd("rm -rf kv_vnode_status_test"), application:set_env(riak_kv, vnode_status, "kv_vnode_status_test"), ok end, From 492481258d2ecd182a216fc8c9c4734402b1f90d Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 13:22:33 -0400 Subject: [PATCH 43/61] Update to a more recent rebar and run the eunits in verbose mode. --- rebar | Bin 108239 -> 121349 bytes rebar.config | 1 + 2 files changed, 1 insertion(+) diff --git a/rebar b/rebar index 8645775d99f1dc0ca77093ad46ae7369342ff15e..7721baed490f271a90001047412c71e34d954eba 100755 GIT binary patch delta 113420 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%0ARcS>ohPLSSpnORhWra69vd3#;+ON8 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

74@lYI$FB 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�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�eGmbJ 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 delta 100132 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

YTy~Sg417~UhyIz`5>lMzH{{W5?D7rUYS<5E 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¥$P)p{c>4r6M3Vx_(XZ|VdB7fPok#vMO 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 R%|IxC-!nq-U<-%%{{SpFuNeRU diff --git a/rebar.config b/rebar.config index a0f099725a..ec5833b07c 100644 --- a/rebar.config +++ b/rebar.config @@ -1,6 +1,7 @@ {cover_enabled, true}. {edoc_opts, [{preprocess, true}]}. {erl_opts, [warnings_as_errors, {parse_transform, lager_transform}]}. +{eunit_opts, [verbose]}. {erl_first_files, [ "src/riak_kv_backend.erl", From ad0d5707c56097d2149d597ac27ba1bf5beb96db Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 14:19:24 -0400 Subject: [PATCH 44/61] On Travis, log to the console rather than the disk. We need to see what's going on. --- src/riak_kv_test_util.erl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index 6ecfe156bf..56537a1745 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -190,10 +190,15 @@ dep_apps(Test, Extra) -> application:set_env(riak_core, ring_creation_size, 64), application:set_env(riak_core, ring_state_dir, Test ++ "/ring"), application:set_env(riak_core, platform_data_dir, Test ++ "/data"), - application:set_env(lager, handlers, [{lager_file_backend, - [ - {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), - application:set_env(lager, crash_log, Test ++ "/log/crash.log"); + case os:getenv("TRAVIS") of + false -> + application:set_env(lager, handlers, [{lager_file_backend, + [ + {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), + application:set_env(lager, crash_log, Test ++ "/log/crash.log"); + _ -> + application:set_env(lager, handlers [{lager_console_backend, info}]) + end; (unload) -> %% TODO: Remove this when the deregistration PR gets merged Services = riak_api_pb_service:dispatch_table(), From a1f21e3e82504aa5ba512748cca09ff48c492d0e Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 14:34:02 -0400 Subject: [PATCH 45/61] Temporarily disable other OTPs in the matrix. --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6dc62f0c58..69e4c1a569 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,6 @@ before_script: - "ulimit -n 4096" otp_release: - R15B01 - - R15B - - R14B04 - - R14B03 + # - R15B + # - R14B04 + # - R14B03 From 285ead07c0bb47dd41b3e6efb2c5271e704753a8 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 14:38:49 -0400 Subject: [PATCH 46/61] Fix syntax error. --- src/riak_kv_test_util.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index 56537a1745..9b561c21e7 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -197,7 +197,7 @@ dep_apps(Test, Extra) -> {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), application:set_env(lager, crash_log, Test ++ "/log/crash.log"); _ -> - application:set_env(lager, handlers [{lager_console_backend, info}]) + application:set_env(lager, handlers, [{lager_console_backend, info}]) end; (unload) -> %% TODO: Remove this when the deregistration PR gets merged From 2572d183edb78c4be910b20f9d0a7ae0bb9d1dec Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 15:59:49 -0400 Subject: [PATCH 47/61] Use a random handoff and pb_port in configuration, hopefully avoiding eaddrinuse errors. --- src/riak_kv_test_util.erl | 3 ++- test/mapred_test.erl | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index 9b561c21e7..a19d6446ba 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -190,6 +190,7 @@ dep_apps(Test, Extra) -> application:set_env(riak_core, ring_creation_size, 64), application:set_env(riak_core, ring_state_dir, Test ++ "/ring"), application:set_env(riak_core, platform_data_dir, Test ++ "/data"), + application:set_env(riak_core, handoff_port, 0), %% pick a random handoff port case os:getenv("TRAVIS") of false -> application:set_env(lager, handlers, [{lager_file_backend, @@ -197,7 +198,7 @@ dep_apps(Test, Extra) -> {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), application:set_env(lager, crash_log, Test ++ "/log/crash.log"); _ -> - application:set_env(lager, handlers, [{lager_console_backend, info}]) + application:set_env(lager, handlers, [{lager_console_backend, debug}]) end; (unload) -> %% TODO: Remove this when the deregistration PR gets merged diff --git a/test/mapred_test.erl b/test/mapred_test.erl index 5f79365a41..e30941cc3f 100644 --- a/test/mapred_test.erl +++ b/test/mapred_test.erl @@ -34,17 +34,16 @@ configure(load) -> {test, true}, {vnode_vclocks, true}, {pb_ip, "0.0.0.0"}, - {pb_port, 48087}, % arbitrary # + {pb_port, 0}, % arbitrary # {map_js_vm_count, 4}, {reduce_js_vm_count, 3}], CoreSettings = [{handoff_ip, "0.0.0.0"}, - {handoff_port, 9183}, + {handoff_port, 0}, {ring_creation_size, 16}], [ application:set_env(riak_core, K, V) || {K,V} <- CoreSettings ], [ application:set_env(riak_kv, K, V) || {K,V} <- KVSettings ], ok; -configure(unload) -> - application:set_env(riak_api, services, dict:new()); + configure(start) -> riak_core:wait_for_service(riak_pipe); configure(_) -> From 0f53f8e33b5517761ab8b8d33cdfc7ff0dfefcf9 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 16:18:25 -0400 Subject: [PATCH 48/61] Fix riak_kv_multi_backend:bad_config_test/0. --- src/riak_kv_multi_backend.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/riak_kv_multi_backend.erl b/src/riak_kv_multi_backend.erl index 0967a82cb2..5d2e51e1be 100644 --- a/src/riak_kv_multi_backend.erl +++ b/src/riak_kv_multi_backend.erl @@ -603,6 +603,7 @@ extra_callback_test() -> application:stop(bitcask). bad_config_test() -> + application:unset_env(riak_kv, multi_backend), ErrorReason = multi_backend_config_unset, ?assertEqual({error, ErrorReason}, start(0, [])). From a478a302fc17060d4e3e712e5aeaa8133e3db492 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 3 Jul 2012 16:34:09 -0400 Subject: [PATCH 49/61] Re-enable other OTPs in the matrix. [ci skip] --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 69e4c1a569..6dc62f0c58 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,6 @@ before_script: - "ulimit -n 4096" otp_release: - R15B01 - # - R15B - # - R14B04 - # - R14B03 + - R15B + - R14B04 + - R14B03 From b3c072abd32da213f96a308810e22ba488fe7e95 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Wed, 8 Aug 2012 17:00:31 -0400 Subject: [PATCH 50/61] Address review comments and fix startup problems. * Don't call application:unload/1. * Don't start folsom since it is an included application of riak_core. * Improve the documentation on new riak_kv_test_util functions. --- src/riak_kv_test_util.erl | 92 +++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index a19d6446ba..0cdd67d373 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -39,31 +39,39 @@ -define(SETUPTHUNK, fun(_) -> ok end). -%% Creates a setup function for tests that need Riak KV stood +%% @doc Creates a setup function for tests that need Riak KV stood %% up in an isolated fashion. +%% @see setup/3 +-spec common_setup(TestName::atom() | string()) -> fun(). common_setup(T) when is_atom(T) -> common_setup(atom_to_list(T)); common_setup(TestName) -> common_setup(TestName, ?SETUPTHUNK). +-spec common_setup(atom() | string(), SetupFun::fun((load|start|stop) -> any()) -> fun(). common_setup(T, S) when is_atom(T) -> common_setup(atom_to_list(T), S); common_setup(TestName, Setup) -> fun() -> setup(TestName, Setup) end. -%% Creates a cleanup function for tests that need Riak KV stood up in +%% @doc Creates a cleanup function for tests that need Riak KV stood up in %% an isolated fashion. +%% @see cleanup/3 +-spec common_cleanup(TestName::atom() | string()) -> fun(). common_cleanup(T) when is_atom(T) -> common_cleanup(atom_to_list(T)); common_cleanup(TestName) -> common_cleanup(TestName, ?SETUPTHUNK). +-spec common_cleanup(TestName::atom() | string(), CleanupFun::fun((stop) -> any())) -> fun(). common_cleanup(T, C) when is_atom(T) -> common_cleanup(atom_to_list(T), C); common_cleanup(TestName, Cleanup) -> fun(X) -> cleanup(TestName, Cleanup, X) end. -%% Calls gen_fsm functions that might not have been touched by a test +%% @doc Calls gen_fsm functions that might not have been touched by a +%% test +-spec call_unused_fsm_funs(module()) -> any(). call_unused_fsm_funs(Mod) -> Mod:handle_event(event, statename, state), Mod:handle_sync_event(event, from, stateneame, state), @@ -71,8 +79,7 @@ call_unused_fsm_funs(Mod) -> Mod:terminate(reason, statename, state), Mod:code_change(oldvsn, statename, state, extra). -%% Stop a running pid - unlink and exit(kill) the process -%% +%% @doc Stop a running pid - unlink and exit(kill) the process stop_process(undefined) -> ok; stop_process(RegName) when is_atom(RegName) -> @@ -82,7 +89,7 @@ stop_process(Pid) when is_pid(Pid) -> exit(Pid, shutdown), ok = wait_for_pid(Pid). -%% Wait for a pid to exit +%% @doc Wait for a pid to exit wait_for_pid(Pid) -> Mref = erlang:monitor(process, Pid), receive @@ -125,7 +132,22 @@ wait_for_children(PPid) -> ok end. -%% Performs setup for a test +%% @doc Performs generic, riak_kv-specific and test-specific setup +%% when used within a test fixture. This includes cleaning up any +%% leaky state from previous tests (internally calling `cleanup/3'), +%% loading dependent applications, starting distributed Erlang, +%% starting dependent applications, and waiting for riak_kv to become +%% available. +%% +%% The given `SetupFun' will be called first with the argument `stop' +%% before other applications are stopped (to cleanup leaky test +%% state), `load' after all other applications are loaded, and then +%% `start' after all other applications are started. It is generally +%% good practice to use the same function in the `SetupFun' as the +%% `CleanupFun' given to `cleanup/3'. +%% +%% @see common_setup/2, dep_apps/2, do_dep_apps/2 +-spec setup(TestName::string(), fun((load|start|stop) -> any()) -> ok. setup(TestName, SetupFun) -> %% Cleanup in case a previous test did not cleanup(TestName, SetupFun, setup), @@ -147,6 +169,14 @@ setup(TestName, SetupFun) -> riak_core:wait_for_service(riak_kv), ok. +%% @doc Performs generic, riak_kv-specific and test-specific cleanup +%% when used within a test fixture. This includes stopping dependent +%% applications, stopping distributed Erlang, and killing pernicious +%% processes. The given `CleanupFun' will be called with the argument +%% `stop' before other components are stopped. +%% +%% @see common_cleanup/2, dep_apps/2, do_dep_apps/2 +-spec cleanup(Test::string(), CleanupFun::fun((stop) -> any()), SetupResult::setup | atom()) -> ok. cleanup(Test, CleanupFun, setup) -> %% Remove existing ring files so we have a fresh ring os:cmd("rm -rf " ++ Test ++ "/ring"), @@ -167,11 +197,26 @@ cleanup(Test, CleanupFun, _) -> %% Reset the riak_core vnode_modules application:set_env(riak_core, vnode_modules, []), - - %% Unload the dependent applications - do_dep_apps(unload, Deps), ok. +%% @doc Calculates a list of dependent applications and functions that +%% can be passed to do_deps_apps/2 to perform the lifecycle phase on +%% them all at once. This ensures that applications start and stop in +%% the correct order and the test also has a chance to inject its own +%% setup and teardown code. Included in the sequence are two default +%% setup functions, one that silences SASL logging and redirects it to +%% a file, and one that configures some settings for riak_core and +%% lager. +%% +%% By passing the `Test' argument, the test's data and logging state +%% is also isolated to its own directory so as not to clobber other +%% tests. +%% +%% The `Extra' function takes an atom which represents the phase of +%% application lifecycle, one of `load', `start' or `stop'. +%% +%% @see common_setup/2, common_cleanup/2 +-spec dep_apps(Test::string(), Extra:fun((load | start | stop) -> any())) -> [ atom() | fun() ]. dep_apps(Test, Extra) -> Silencer = fun(load) -> %% Silence logging junk @@ -200,8 +245,12 @@ dep_apps(Test, Extra) -> _ -> application:set_env(lager, handlers, [{lager_console_backend, debug}]) end; - (unload) -> - %% TODO: Remove this when the deregistration PR gets merged + (stop) -> + %% TODO: Remove this when the deregistration PR gets + %% merged. The list of codes being erased from the + %% dispatch table are the ones registered by calling + %% riak_api_pb_service:register/1 in + %% riak_kv_app:start/2. Services = riak_api_pb_service:dispatch_table(), NewServices = lists:foldl( fun dict:erase/2, @@ -217,9 +266,26 @@ dep_apps(Test, Extra) -> riak_core, riak_pipe, riak_kv, DefaultSetupFun, Extra]. +%% @doc Runs the application-lifecycle phase across all of the given +%% applications and functions. +%% @see dep_apps/2 +-spec do_dep_apps(load | start | stop, [ atom() | fun() ]) -> [ any() ]. do_dep_apps(StartStop, Apps) -> - lists:map(fun(A) when is_atom(A) -> application:StartStop(A); + lists:map(fun(A) when is_atom(A) -> + case include_app_phase(StartStop, A) of + true -> application:StartStop(A); + _ -> ok + end; (F) -> F(StartStop) end, Apps). +%% @doc Determines whether a given application should be modified in +%% the given phase. If this returns false, the application will not be +%% loaded, started, or stopped by `do_dep_apps/2'. +-spec include_app_phase(Phase::load | start | stop, Application::atom()) -> true | false. +include_app_phase(stop, crypto) -> false; +include_app_phase(start, folsom) -> false; +include_app_phase(_Phase, _App) -> true. + + -endif. % TEST From 1be5f243e802dc31b12fbc97e3a4fead4b00c50f Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Fri, 10 Aug 2012 11:04:48 -0400 Subject: [PATCH 51/61] Fix -spec typos, thanks @rzezeski. --- src/riak_kv_test_util.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index 0cdd67d373..5f3dba8d2c 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -48,7 +48,7 @@ common_setup(T) when is_atom(T) -> common_setup(TestName) -> common_setup(TestName, ?SETUPTHUNK). --spec common_setup(atom() | string(), SetupFun::fun((load|start|stop) -> any()) -> fun(). +-spec common_setup(atom() | string(), SetupFun::fun((load|start|stop) -> any())) -> fun(). common_setup(T, S) when is_atom(T) -> common_setup(atom_to_list(T), S); common_setup(TestName, Setup) -> @@ -147,7 +147,7 @@ wait_for_children(PPid) -> %% `CleanupFun' given to `cleanup/3'. %% %% @see common_setup/2, dep_apps/2, do_dep_apps/2 --spec setup(TestName::string(), fun((load|start|stop) -> any()) -> ok. +-spec setup(TestName::string(), fun((load|start|stop) -> any())) -> ok. setup(TestName, SetupFun) -> %% Cleanup in case a previous test did not cleanup(TestName, SetupFun, setup), @@ -216,7 +216,7 @@ cleanup(Test, CleanupFun, _) -> %% application lifecycle, one of `load', `start' or `stop'. %% %% @see common_setup/2, common_cleanup/2 --spec dep_apps(Test::string(), Extra:fun((load | start | stop) -> any())) -> [ atom() | fun() ]. +-spec dep_apps(Test::string(), Extra::fun((load | start | stop) -> any())) -> [ atom() | fun() ]. dep_apps(Test, Extra) -> Silencer = fun(load) -> %% Silence logging junk From c3960511ab57abf60ea323053fee58e59fe2bbe0 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Fri, 10 Aug 2012 12:01:17 -0400 Subject: [PATCH 52/61] Use regular logging on Travis for now so we can actually read the output. --- src/riak_kv_test_util.erl | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/riak_kv_test_util.erl b/src/riak_kv_test_util.erl index 5f3dba8d2c..37a3fe33f8 100644 --- a/src/riak_kv_test_util.erl +++ b/src/riak_kv_test_util.erl @@ -236,15 +236,10 @@ dep_apps(Test, Extra) -> application:set_env(riak_core, ring_state_dir, Test ++ "/ring"), application:set_env(riak_core, platform_data_dir, Test ++ "/data"), application:set_env(riak_core, handoff_port, 0), %% pick a random handoff port - case os:getenv("TRAVIS") of - false -> - application:set_env(lager, handlers, [{lager_file_backend, - [ - {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), - application:set_env(lager, crash_log, Test ++ "/log/crash.log"); - _ -> - application:set_env(lager, handlers, [{lager_console_backend, debug}]) - end; + application:set_env(lager, handlers, [{lager_file_backend, + [ + {Test ++ "/log/debug.log", debug, 10485760, "$D0", 5}]}]), + application:set_env(lager, crash_log, Test ++ "/log/crash.log"); (stop) -> %% TODO: Remove this when the deregistration PR gets %% merged. The list of codes being erased from the From e5db760de78c9e2fbc43bae25cfe73b2d2d26cce Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Fri, 10 Aug 2012 16:46:47 -0600 Subject: [PATCH 53/61] Moved eleveldb back to master after 1.2.0 release ready for next point. --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index ec5833b07c..1457de5695 100644 --- a/rebar.config +++ b/rebar.config @@ -18,7 +18,7 @@ {ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}}, {eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "3280b736"}}}, {eleveldb, "1.2.2", {git, "git://github.com/basho/eleveldb.git", - {tag, "1.2.2"}}}, + {branch, "master"}}}, {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", {tag, "1.2.0"}}}, From 197b4fda15516bd369939753cadd4be2a5f12fa4 Mon Sep 17 00:00:00 2001 From: Jared Morrow Date: Fri, 10 Aug 2012 22:11:55 -0600 Subject: [PATCH 54/61] Make eleveldb dependency a wildcard on the version --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 1457de5695..af8acd8748 100644 --- a/rebar.config +++ b/rebar.config @@ -17,7 +17,7 @@ {tag, "1.2.0"}}}, {ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}}, {eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "3280b736"}}}, - {eleveldb, "1.2.2", {git, "git://github.com/basho/eleveldb.git", + {eleveldb, "1.2.*", {git, "git://github.com/basho/eleveldb.git", {branch, "master"}}}, {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", From 7419c0ce73c4c709f0ccb80de27640a3cac04b55 Mon Sep 17 00:00:00 2001 From: Jared Morrow Date: Fri, 10 Aug 2012 22:31:49 -0600 Subject: [PATCH 55/61] Change riak_pipe dependency to point at branch to bring in point release changes --- rebar.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index af8acd8748..a1f9a9213d 100644 --- a/rebar.config +++ b/rebar.config @@ -20,7 +20,7 @@ {eleveldb, "1.2.*", {git, "git://github.com/basho/eleveldb.git", {branch, "master"}}}, {sext, "0.4.*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}}, - {riak_pipe, "1.2.0", {git, "git://github.com/basho/riak_pipe.git", - {tag, "1.2.0"}}}, + {riak_pipe, "1.2.*", {git, "git://github.com/basho/riak_pipe.git", + {branch, "1.2"}}}, {riak_api, "1.2.0", {git, "git://github.com/basho/riak_api.git", {tag, "1.2.0"}}} ]}. From 59a257b6f5a14c5dfa518e8de111ea9204146bd5 Mon Sep 17 00:00:00 2001 From: Jon Meredith Date: Thu, 16 Aug 2012 13:36:19 -0600 Subject: [PATCH 56/61] Unpin riak_core back to 1.2 branch --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index a1f9a9213d..2130e28cdd 100644 --- a/rebar.config +++ b/rebar.config @@ -9,7 +9,7 @@ ]}. {deps, [ - {riak_core, "1.2.0", {git, "git://github.com/basho/riak_core", {tag, "1.2.0"}}}, + {riak_core, "1.2.*", {git, "git://github.com/basho/riak_core", {branch, "1.2"}}}, {luke, "0.2.5", {git, "git://github.com/basho/luke", {tag, "0.2.5"}}}, {erlang_js, "1.2.0", {git, "git://github.com/basho/erlang_js", {tag, "1.2.0"}}}, {bitcask, "1.5.1", {git, "git://github.com/basho/bitcask", {tag, "1.5.1"}}}, From 4c825aa3f9ee6445615fc28f26fffa3f6e790ee3 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Mon, 20 Aug 2012 10:06:17 -0400 Subject: [PATCH 57/61] Require riak_api to be started first. --- src/riak_kv.app.src | 1 + 1 file changed, 1 insertion(+) diff --git a/src/riak_kv.app.src b/src/riak_kv.app.src index 2198756311..937af4dddd 100644 --- a/src/riak_kv.app.src +++ b/src/riak_kv.app.src @@ -9,6 +9,7 @@ stdlib, sasl, crypto, + riak_api, riak_core, luke, erlang_js, From c599803e78596f24b05b5f8cd110d847b7b15377 Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Mon, 20 Aug 2012 13:35:50 -0400 Subject: [PATCH 58/61] Echo log files to the console when the suite fails. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6dc62f0c58..b636a6c288 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: erlang +script: (rebar compile && rebar eunit skip_deps=true) || (find . -name "*.log" -print -exec cat \{\} \; && sh -c "exit 1") notifications: webhooks: http://basho-engbot.herokuapp.com/travis?key=ad9a6e51d706903e1fd0963c7b8e064b93e85b56 email: eng@basho.com From 1c6a60d679e5889b41ca0adf5076baccc8b6f637 Mon Sep 17 00:00:00 2001 From: Bryan Fink Date: Wed, 22 Aug 2012 11:53:43 -0400 Subject: [PATCH 59/61] correct for proper host token ordering fix in webmachine --- src/riak_kv_wm_utils.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/riak_kv_wm_utils.erl b/src/riak_kv_wm_utils.erl index aacc2be6c3..83af041462 100644 --- a/src/riak_kv_wm_utils.erl +++ b/src/riak_kv_wm_utils.erl @@ -250,7 +250,7 @@ is_null_origin(RD) -> %% @doc Validate that the Referer matches up with scheme, host and port of the %% machine that received the request. is_valid_referer(RD) -> - OriginTuple = {wrq:scheme(RD), string:join(lists:reverse(wrq:host_tokens(RD)), "."), wrq:port(RD)}, + OriginTuple = {wrq:scheme(RD), string:join(wrq:host_tokens(RD), "."), wrq:port(RD)}, case referer_tuple(RD) of undefined -> true; From 81559340b08171d3a95528e3c777dcf2f5025bcb Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Sun, 5 Aug 2012 21:05:56 -0400 Subject: [PATCH 60/61] Don't return partial results in the error tuple from a timed out 2I query. --- src/riak_client.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/riak_client.erl b/src/riak_client.erl index 798c5bb3e1..b85263215d 100644 --- a/src/riak_client.erl +++ b/src/riak_client.erl @@ -791,7 +791,7 @@ wait_for_query_results(ReqId, Timeout, Acc) -> {ReqId,{results, Res}} -> wait_for_query_results(ReqId, Timeout, [Res | Acc]); {ReqId, Error} -> {error, Error} after Timeout -> - {error, timeout, Acc} + {error, timeout} end. add_inputs(_FlowPid, []) -> From db17f879b8da6130274799410e43e026b912383f Mon Sep 17 00:00:00 2001 From: Ryan Zezeski Date: Fri, 24 Aug 2012 16:53:43 -0400 Subject: [PATCH 61/61] Rename gen_server2 to riak_core_gen_server --- src/riak_kv_map_master.erl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/riak_kv_map_master.erl b/src/riak_kv_map_master.erl index dd9f2c1a8c..ebc1489330 100644 --- a/src/riak_kv_map_master.erl +++ b/src/riak_kv_map_master.erl @@ -23,7 +23,7 @@ -module(riak_kv_map_master). -include_lib("riak_kv_js_pools.hrl"). --behaviour(gen_server2). +-behaviour(riak_core_gen_server). %% API -export([start_link/0, @@ -47,17 +47,18 @@ next}). new_mapper({_, Node}=VNode, QTerm, MapInputs, PhasePid) -> - gen_server2:pcall({?SERVER, Node}, 5, {new_mapper, VNode, - QTerm, MapInputs, PhasePid}, infinity). + riak_core_gen_server:pcall({?SERVER, Node}, 5, + {new_mapper, VNode, QTerm, MapInputs, PhasePid}, + infinity). queue_depth() -> Nodes = [node()|nodes()], - [{Node, gen_server2:pcall({?SERVER, Node}, 0, queue_depth, - infinity)} || Node <- Nodes]. + [{Node, riak_core_gen_server:pcall({?SERVER, Node}, 0, queue_depth, + infinity)} || Node <- Nodes]. start_link() -> - gen_server2:start_link({local, ?SERVER}, ?MODULE, [], []). + riak_core_gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). init([]) -> process_flag(trap_exit, true),