From 78cb23553ff9fb7b28a6c2b552ad77b5fadb69f8 Mon Sep 17 00:00:00 2001 From: Bryan Hunt Date: Wed, 27 Jul 2016 16:01:57 +0100 Subject: [PATCH 01/42] try out lukes requests --- src/riakc_datatype.erl | 3 +- src/riakc_gset.erl | 141 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/riakc_gset.erl diff --git a/src/riakc_datatype.erl b/src/riakc_datatype.erl index 6561d76d..19bc7bbd 100644 --- a/src/riakc_datatype.erl +++ b/src/riakc_datatype.erl @@ -34,7 +34,7 @@ -endif. --define(MODULES, [riakc_set, riakc_counter, riakc_flag, riakc_register, riakc_map]). +-define(MODULES, [riakc_set, riakc_gset, riakc_counter, riakc_flag, riakc_register, riakc_map]). -export([module_for_type/1, module_for_term/1]). @@ -82,6 +82,7 @@ %% type. -spec module_for_type(Type::atom()) -> module(). module_for_type(set) -> riakc_set; +module_for_type(gset) -> riakc_gset; module_for_type(counter) -> riakc_counter; module_for_type(flag) -> riakc_flag; module_for_type(register) -> riakc_register; diff --git a/src/riakc_gset.erl b/src/riakc_gset.erl new file mode 100644 index 00000000..8682cf8a --- /dev/null +++ b/src/riakc_gset.erl @@ -0,0 +1,141 @@ +%% ------------------------------------------------------------------- +%% +%% riakc_gset: Eventually-consistent set type +%% +%% Copyright (c) 2013 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

Encapsulates a gset data-type. Riak's gsets differ from Erlang +%% gset types in several ways:

+%% +%% @end +-module(riakc_gset). +-behaviour(riakc_datatype). + +-ifdef(EQC). +-include_lib("eqc/include/eqc.hrl"). +-compile(export_all). +-endif. + +%% Callbacks +-export([new/0, new/1, new/2, + value/1, + to_op/1, + is_type/1, + type/0]). + +%% Operations +-export([add_element/2]). + +%% Query functions +-export([size/1, + is_element/2, + fold/3]). + +-record(gset, {value = ordsets:new() :: ordsets:ordset(binary()), + adds = ordsets:new() :: ordsets:ordset(binary()), + context = undefined :: riakc_datatype:context() }). + +-export_type([riakc_gset/0, gset_op/0]). +-opaque riakc_gset() :: #gset{}. + +-type simple_gset_op() :: {add_all, [binary()]}. +-type gset_op() :: simple_gset_op() | {update, [simple_gset_op()]}. + +%% @doc Creates a new, empty set container type. +-spec new() -> riakc_gset(). +new() -> + #gset{}. + +%% @doc Creates a new sset container with the opaque context. +-spec new(riakc_datatype:context()) -> riakc_gset(). +new(Context) -> + #gset{context=Context}. + +%% @doc Creates a new gset container with the given members and opaque +%% context. +-spec new([binary()], riakc_datatype:context()) -> riakc_gset(). +new(Value, Context) when is_list(Value) -> + #gset{value=ordsets:from_list(Value), + context=Context}. + +%% @doc Returns the original value of the set as an ordset. +-spec value(riakc_gset()) -> ordsets:ordset(binary()). +value(#gset{value=V}) -> V. + +%% @doc Extracts an operation from the gset that can be encoded into an +%% update request. +-spec to_op(riakc_gset()) -> riakc_datatype:update(gset_op()). +to_op(#gset{adds=[]}) -> + undefined; +to_op(#gset{adds=[A|AT], context=C}) -> + {type(), {add_all, [A|AT]}, C}; +to_op(#gset{adds=A, context=C}) -> + {type(), {update, [{add_all, [A]}]}, C}. + +%% @doc Determines whether the passed term is a gset container. +-spec is_type(term()) -> boolean(). +is_type(T) -> + is_record(T, gset). + +%% @doc Returns the symbolic name of this container. +-spec type() -> atom(). +type() -> gset. + +%% @doc Adds an element to the set. +-spec add_element(binary(), riakc_gset()) -> riakc_gset(). +add_element(Bin, #gset{adds=A0}=Set) when is_binary(Bin) -> + Set#gset{adds=ordsets:add_element(Bin, A0)}. + +%% @doc Returns the cardinality (size) of the set. Note: this only +%% operates on the original value as retrieved from Riak. +-spec size(riakc_gset()) -> pos_integer(). +size(#gset{value=V}) -> + ordsets:size(V). + +%% @doc Test whether an element is a member of the set. Note: this +%% only operates on the original value as retrieved from Riak. +-spec is_element(binary(), riakc_gset()) -> boolean(). +is_element(Bin, #gset{value=V}) when is_binary(Bin) -> + ordsets:is_element(Bin, V). + +%% @doc Folds over the members of the set. Note: this only +%% operates on the original value as retrieved from Riak. +-spec fold(fun((binary(), term()) -> term()), term(), riakc_gset()) -> term(). +fold(Fun, Acc0, #gset{value=V}) -> + ordsets:fold(Fun, Acc0, V). + +-ifdef(EQC). +gen_type() -> + ?LET({Elems, Ctx}, {list(binary()), binary()}, new(Elems, Ctx)). + +gen_op() -> + {elements([add_element]), + [binary()]}. +-endif. From 37379f1c4427632feba38a53ee451696f108874f Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Mon, 31 Oct 2016 10:47:00 +0000 Subject: [PATCH 02/42] Bring bet365 gset code up to date with refactor --- test/riakc_pb_socket_tests.erl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/riakc_pb_socket_tests.erl b/test/riakc_pb_socket_tests.erl index 88e95d09..32192177 100644 --- a/test/riakc_pb_socket_tests.erl +++ b/test/riakc_pb_socket_tests.erl @@ -1378,6 +1378,23 @@ integration_tests() -> Rsp -> ?debugFmt("hlls bucket is not present, skipping (~p)", [Rsp]) end + end)}, + {"add item to gset, twice", + ?_test(begin + riakc_test_utils:reset_riak(), + {ok, Pid} = riakc_test_utils:start_link(test_ip(), test_port()), + ok = riakc_pb_socket:update_type(Pid, + {<<"gset_bucket">>, <<"bucket">>}, <<"key">>, + riakc_gset:to_op(riakc_gset:add_element(<<"X">>, riakc_gset:new()))), + {ok, S0} = riakc_pb_socket:fetch_type(Pid, {<<"gset_bucket">>, <<"bucket">>}, <<"key">>), + ?assert(riakc_gset:is_element(<<"X">>, S0)), + ?assertEqual(riakc_gset:size(S0), 1), + ok = riakc_pb_socket:update_type(Pid, + {<<"set_bucket">>, <<"bucket">>}, <<"key">>, + riakc_gset:to_op(riakc_gset:add_element(<<"X">>, S0))), + {ok, S1} = riakc_pb_socket:fetch_type(Pid, {<<"gset_bucket">>, <<"bucket">>}, <<"key">>), + ?assert(riakc_gset:is_element(<<"X">>, S1)), + ?assertEqual(riakc_gset:size(S1), 1) end)} ]. From 2bb67a0bcd9eeefdeb71fcc03b1bf85c83720701 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 1 Nov 2016 14:33:38 +0000 Subject: [PATCH 03/42] Small changes for gset integration tests Typo in bucket name, copywrite etc etc --- src/riakc_gset.erl | 6 +++--- test/riakc_pb_socket_tests.erl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/riakc_gset.erl b/src/riakc_gset.erl index 8682cf8a..b8379961 100644 --- a/src/riakc_gset.erl +++ b/src/riakc_gset.erl @@ -2,7 +2,7 @@ %% %% riakc_gset: Eventually-consistent set type %% -%% Copyright (c) 2013 Basho Technologies, Inc. All Rights Reserved. +%% Copyright (c) 2016 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 @@ -21,7 +21,7 @@ %% ------------------------------------------------------------------- %% @doc

Encapsulates a gset data-type. Riak's gsets differ from Erlang -%% gset types in several ways:

+%% set types in several ways:

%%