%% -------------------------------------------------------------------
%%
%% riakc_pb_socket: protocol buffer client
%%
%% Copyright (c) 2007-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
%% 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 Manages a connection to Riak via the Protocol Buffers
%% transport and executes the commands that can be performed over that
%% connection.
%% @end
-module(riakc_pb_socket).
-include_lib("kernel/include/inet.hrl").
-include("riak_dt_pb.hrl").
-include("riak_kv_pb.hrl").
-include("riak_pb.hrl").
-include("riak_pb_kv_codec.hrl").
-include("riak_search_pb.hrl").
-include("riak_ts_pb.hrl").
-include("riak_ts_ttb.hrl").
-include("riak_yokozuna_pb.hrl").
-include("riakc.hrl").
-behaviour(gen_server).
-export([start_link/2, start_link/3,
start/2, start/3,
stop/1,
set_options/2, set_options/3,
is_connected/1, is_connected/2,
ping/1, ping/2,
get_client_id/1, get_client_id/2,
set_client_id/2, set_client_id/3,
get_server_info/1, get_server_info/2,
get/3, get/4, get/5,
put/2, put/3, put/4,
delete/3, delete/4, delete/5,
delete_vclock/4, delete_vclock/5, delete_vclock/6,
delete_obj/2, delete_obj/3, delete_obj/4,
list_buckets/1, list_buckets/2, list_buckets/3,
stream_list_buckets/1, stream_list_buckets/2, stream_list_buckets/3,
legacy_list_buckets/2,
list_keys/2, list_keys/3,
stream_list_keys/2, stream_list_keys/3,
get_bucket/2, get_bucket/3, get_bucket/4,
get_bucket_type/2, get_bucket_type/3,
set_bucket/3, set_bucket/4, set_bucket/5,
set_bucket_type/3, set_bucket_type/4,
reset_bucket/2, reset_bucket/3, reset_bucket/4,
mapred/3, mapred/4, mapred/5,
mapred_stream/4, mapred_stream/5, mapred_stream/6,
mapred_bucket/3, mapred_bucket/4, mapred_bucket/5,
mapred_bucket_stream/5, mapred_bucket_stream/6,
search/3, search/4, search/5, search/6,
get_index/4, get_index/5, get_index/6, get_index/7, %% @deprecated
get_index_eq/4, get_index_range/5, get_index_eq/5, get_index_range/6,
cs_bucket_fold/3,
default_timeout/1,
tunnel/4,
get_preflist/3, get_preflist/4,
get_coverage/2, get_coverage/3,
replace_coverage/3, replace_coverage/4]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
%% Yokozuna admin commands
-export([list_search_indexes/1, list_search_indexes/2,
create_search_index/2, create_search_index/3, create_search_index/4,
get_search_index/2, get_search_index/3,
delete_search_index/2, delete_search_index/3,
set_search_index/3,
get_search_schema/2, get_search_schema/3,
create_search_schema/3, create_search_schema/4]).
%% Pre-Riak 2.0 Counter API - NOT for CRDT counters
-export([counter_incr/4, counter_val/3]).
-export([counter_incr/5, counter_val/4]).
%% Datatypes API
-export([fetch_type/3, fetch_type/4,
update_type/4, update_type/5,
modify_type/5]).
%% supporting functions used in riakc_ts
-export([mk_reqid/0]).
-deprecated({get_index,'_', eventually}).
-type ctx() :: any().
-type rpb_req() :: {tunneled, msg_id(), binary()} | atom() | tuple().
-type rpb_resp() :: atom() | tuple().
-type msg_id() :: non_neg_integer(). %% Request identifier for tunneled message types
-type search_admin_opt() :: {timeout, timeout()} |
{call_timeout, timeout()}.
-type search_admin_opts() :: [search_admin_opt()].
-type index_opt() :: {timeout, timeout()} |
{call_timeout, timeout()} |
{stream, boolean()} |
{continuation, binary()} |
{pagination_sort, boolean()} |
{max_results, non_neg_integer() | all}.
-type index_opts() :: [index_opt()].
-type range_index_opt() :: {return_terms, boolean()} |
{term_regex, binary()}.
-type range_index_opts() :: [index_opt() | range_index_opt()].
-type cs_opt() :: {timeout, timeout()} |
{continuation, binary()} |
{max_results, non_neg_integer() | all} |
{start_key, binary()} |
{start_incl, boolean()} |
{end_key, binary()} |
{end_incl, boolean()}.
-type cs_opts() :: [cs_opt()].
%% Which client operation the default timeout is being requested
%% for. `timeout' is the global default timeout. Any of these defaults
%% can be overridden by setting the application environment variable
%% of the same name on the `riakc' application, for example:
%% `application:set_env(riakc, ping_timeout, 5000).'
-record(request, {ref :: reference(),
msg :: rpb_req(),
from, ctx :: ctx(),
timeout :: timeout(),
tref :: reference() | undefined,
opts :: proplists:proplist()
}).
-type request_queue_t() :: queue:queue(#request{}).
-ifdef(deprecated_now).
-define(NOW, erlang:system_time(micro_seconds)).
-else.
-define(NOW, erlang:now()).
-endif.
-type portnum() :: non_neg_integer(). %% The TCP port number of the Riak node's Protocol Buffers interface
-type address() :: string() | atom() | inet:ip_address(). %% The TCP/IP host name or address of the Riak node
-record(state, {address :: address(), % address to connect to
port :: portnum(), % port to connect to
auto_reconnect = false :: boolean(), % if true, automatically reconnects to server
% if false, exits on connection failure/request timeout
queue_if_disconnected = false :: boolean(), % if true, add requests to queue if disconnected
sock :: port() | ssl:sslsocket() | undefined, % gen_tcp socket
keepalive = false :: boolean(), % if true, enabled TCP keepalive for the socket
transport = gen_tcp :: 'gen_tcp' | 'ssl',
active :: #request{} | undefined, % active request
queue :: request_queue_t() | undefined, % queue of pending requests
connects=0 :: non_neg_integer(), % number of successful connects
failed=[] :: [connection_failure()], % breakdown of failed connects
connect_timeout=infinity :: timeout(), % timeout of TCP connection
credentials :: undefined | {string(), string()}, % username/password
cacertfile, % Path to CA certificate file
certfile, % Path to client certificate file, when using
% certificate authentication
keyfile, % Path to certificate keyfile, when using
% certificate authentication
ssl_opts = [], % Arbitrary SSL options, see the erlang SSL
% documentation.
reconnect_interval=?FIRST_RECONNECT_INTERVAL :: non_neg_integer()}).
-export_type([address/0, portnum/0]).
%% @private Like `gen_server:call/3', but with the timeout hardcoded
%% to `infinity'.
call_infinity(Pid, Msg) ->
gen_server:call(Pid, Msg, infinity).
%% @doc Create a linked process to talk with the riak server on Address:Port
%% Client id will be assigned by the server.
-spec start_link(address(), portnum()) -> {ok, pid()} | {error, term()}.
start_link(Address, Port) ->
start_link(Address, Port, []).
%% @doc Create a linked process to talk with the riak server on Address:Port with Options.
%% Client id will be assigned by the server.
-spec start_link(address(), portnum(), client_options()) -> {ok, pid()} | {error, term()}.
start_link(Address, Port, Options) when is_list(Options) ->
gen_server:start_link(?MODULE, [Address, Port, Options], []).
%% @doc Create a process to talk with the riak server on Address:Port.
%% Client id will be assigned by the server.
-spec start(address(), portnum()) -> {ok, pid()} | {error, term()}.
start(Address, Port) ->
start(Address, Port, []).
%% @doc Create a process to talk with the riak server on Address:Port with Options.
-spec start(address(), portnum(), client_options()) -> {ok, pid()} | {error, term()}.
start(Address, Port, Options) when is_list(Options) ->
gen_server:start(?MODULE, [Address, Port, Options], []).
%% @doc Disconnect the socket and stop the process.
-spec stop(pid()) -> ok.
stop(Pid) ->
call_infinity(Pid, stop).
%% @doc Change the options for this socket. Allows you to connect with one
%% set of options then run with another (e.g. connect with no options to
%% make sure the server is there, then enable queue_if_disconnected).
%% @equiv set_options(Pid, Options, infinity)
%% @see start_link/3
-spec set_options(pid(), client_options()) -> ok.
set_options(Pid, Options) ->
call_infinity(Pid, {set_options, Options}).
%% @doc Like set_options/2, but with a gen_server timeout.
%% @see start_link/3
%% @deprecated
-spec set_options(pid(), client_options(), timeout()) -> ok.
set_options(Pid, Options, Timeout) ->
gen_server:call(Pid, {set_options, Options}, Timeout).
%% @doc Determines whether the client is connected. Returns true if
%% connected, or false and a list of connection failures and frequencies if
%% disconnected.
%% @equiv is_connected(Pid, infinity)
-spec is_connected(pid()) -> true | {false, [connection_failure()]}.
is_connected(Pid) ->
call_infinity(Pid, is_connected).
%% @doc Determines whether the client is connected, with the specified
%% timeout to the client process. Returns true if connected, or false
%% and a list of connection failures and frequencies if disconnected.
%% @see is_connected/1
%% @deprecated
-spec is_connected(pid(), timeout()) -> true | {false, [connection_failure()]}.
is_connected(Pid, Timeout) ->
gen_server:call(Pid, is_connected, Timeout).
%% @doc Ping the server
%% @equiv ping(Pid, default_timeout(ping_timeout))
-spec ping(pid()) -> pong.
ping(Pid) ->
call_infinity(Pid, {req, rpbpingreq, default_timeout(ping_timeout)}).
%% @doc Ping the server specifying timeout
-spec ping(pid(), timeout()) -> pong.
ping(Pid, Timeout) ->
call_infinity(Pid, {req, rpbpingreq, Timeout}).
%% @doc Get the client id for this connection
%% @equiv get_client_id(Pid, default_timeout(get_client_id_timeout))
-spec get_client_id(pid()) -> {ok, client_id()} | {error, term()}.
get_client_id(Pid) ->
get_client_id(Pid, default_timeout(get_client_id_timeout)).
%% @doc Get the client id for this connection specifying timeout
-spec get_client_id(pid(), timeout()) -> {ok, client_id()} | {error, term()}.
get_client_id(Pid, Timeout) ->
call_infinity(Pid, {req, rpbgetclientidreq, Timeout}).
%% @doc Set the client id for this connection
%% @equiv set_client_id(Pid, ClientId, default_timeout(set_client_id_timeout))
-spec set_client_id(pid(), client_id()) -> {ok, client_id()} | {error, term()}.
set_client_id(Pid, ClientId) ->
set_client_id(Pid, ClientId, default_timeout(set_client_id_timeout)).
%% @doc Set the client id for this connection specifying timeout
-spec set_client_id(pid(), client_id(), timeout()) -> {ok, client_id()} | {error, term()}.
set_client_id(Pid, ClientId, Timeout) ->
call_infinity(Pid,
{req, #rpbsetclientidreq{client_id = ClientId},
Timeout}).
%% @doc Get the server information for this connection
%% @equiv get_server_info(Pid, default_timeout(get_server_info_timeout))
-spec get_server_info(pid()) -> {ok, server_info()} | {error, term()}.
get_server_info(Pid) ->
get_server_info(Pid, default_timeout(get_server_info_timeout)).
%% @doc Get the server information for this connection specifying timeout
-spec get_server_info(pid(), timeout()) -> {ok, server_info()} | {error, term()}.
get_server_info(Pid, Timeout) ->
call_infinity(Pid, {req, rpbgetserverinforeq, Timeout}).
%% @doc Get bucket/key from the server.
%% Will return {error, notfound} if the key is not on the server.
%% @equiv get(Pid, Bucket, Key, [], default_timeout(get_timeout))
-spec get(pid(), bucket() | bucket_and_type(), key()) -> {ok, riakc_obj()} | {error, term()}.
get(Pid, Bucket, Key) ->
get(Pid, Bucket, Key, [], default_timeout(get_timeout)).
%% @doc Get bucket/key from the server specifying timeout.
%% Will return {error, notfound} if the key is not on the server.
%% @equiv get(Pid, Bucket, Key, Options, Timeout)
-spec get(pid(), bucket() | bucket_and_type(), key(), TimeoutOrOptions::timeout() | get_options()) ->
{ok, riakc_obj()} | {error, term()} | unchanged.
get(Pid, Bucket, Key, Timeout) when is_integer(Timeout); Timeout =:= infinity ->
get(Pid, Bucket, Key, [], Timeout);
get(Pid, Bucket, Key, Options) ->
get(Pid, Bucket, Key, Options, default_timeout(get_timeout)).
%% @doc Get bucket/key from the server supplying options and timeout.
%% unchanged will be returned when the
%% {if_modified, Vclock} option is specified and the
%% object is unchanged.
-spec get(pid(), bucket() | bucket_and_type(), key(), get_options(), timeout()) ->
{ok, riakc_obj()} | {error, term()} | unchanged.
get(Pid, Bucket, Key, Options, Timeout) ->
{T, B} = maybe_bucket_type(Bucket),
Req = get_options(Options, #rpbgetreq{type =T, bucket = B, key = Key}),
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Put the metadata/value in the object under bucket/key
%% @equiv put(Pid, Obj, [])
%% @see put/4
-spec put(pid(), riakc_obj()) ->
ok | {ok, riakc_obj()} | {ok, key()} | {error, term()}.
put(Pid, Obj) ->
put(Pid, Obj, []).
%% @doc Put the metadata/value in the object under bucket/key with options or timeout.
%% @equiv put(Pid, Obj, Options, Timeout)
%% @see put/4
-spec put(pid(), riakc_obj(), TimeoutOrOptions::timeout() | put_options()) ->
ok | {ok, riakc_obj()} | riakc_obj() | {ok, key()} | {error, term()}.
put(Pid, Obj, Timeout) when is_integer(Timeout); Timeout =:= infinity ->
put(Pid, Obj, [], Timeout);
put(Pid, Obj, Options) ->
put(Pid, Obj, Options, default_timeout(put_timeout)).
%% @doc Put the metadata/value in the object under bucket/key with
%% options and timeout. Put throws `siblings' if the
%% riakc_obj contains siblings that have not been resolved by
%% calling {@link riakc_obj:select_sibling/2.} or {@link
%% riakc_obj:update_value/2} and {@link
%% riakc_obj:update_metadata/2}. If the object has no key and
%% the Riak node supports it, `{ok, Key::key()}' will be returned
%% when the object is created, or `{ok, Obj::riakc_obj()}' if
%% `return_body' was specified.
%% @throws siblings
%% @end
-spec put(pid(), riakc_obj(), put_options(), timeout()) ->
ok | {ok, riakc_obj()} | riakc_obj() | {ok, key()} | {error, term()}.
put(Pid, Obj, Options, Timeout) ->
Content = riak_pb_kv_codec:encode_content({riakc_obj:get_update_metadata(Obj),
riakc_obj:get_update_value(Obj)}),
Req = put_options(Options,
#rpbputreq{bucket = riakc_obj:only_bucket(Obj),
type = riakc_obj:bucket_type(Obj),
key = riakc_obj:key(Obj),
vclock = riakc_obj:vclock(Obj),
content = Content}),
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Delete the key/value
%% @equiv delete(Pid, Bucket, Key, [])
-spec delete(pid(), bucket() | bucket_and_type(), key()) -> ok | {error, term()}.
delete(Pid, Bucket, Key) ->
delete(Pid, Bucket, Key, []).
%% @doc Delete the key/value specifying timeout or options. Note that the rw quorum is deprecated, use r and w.
%% @equiv delete(Pid, Bucket, Key, Options, Timeout)
-spec delete(pid(), bucket() | bucket_and_type(), key(), TimeoutOrOptions::timeout() | delete_options()) ->
ok | {error, term()}.
delete(Pid, Bucket, Key, Timeout) when is_integer(Timeout); Timeout =:= infinity ->
delete(Pid, Bucket, Key, [], Timeout);
delete(Pid, Bucket, Key, Options) ->
delete(Pid, Bucket, Key, Options, default_timeout(delete_timeout)).
%% @doc Delete the key/value with options and timeout. Note that the rw quorum is deprecated, use r and w.
-spec delete(pid(), bucket() | bucket_and_type(), key(), delete_options(), timeout()) -> ok | {error, term()}.
delete(Pid, Bucket, Key, Options, Timeout) ->
{T, B} = maybe_bucket_type(Bucket),
Req = delete_options(Options, #rpbdelreq{type = T, bucket = B, key = Key}),
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Delete the object at Bucket/Key, giving the vector clock.
%% @equiv delete_vclock(Pid, Bucket, Key, VClock, [])
-spec delete_vclock(pid(), bucket() | bucket_and_type(), key(), riakc_obj:vclock()) -> ok | {error, term()}.
delete_vclock(Pid, Bucket, Key, VClock) ->
delete_vclock(Pid, Bucket, Key, VClock, []).
%% @doc Delete the object at Bucket/Key, specifying timeout or options and giving the vector clock.
%% @equiv delete_vclock(Pid, Bucket, Key, VClock, Options, Timeout)
-spec delete_vclock(pid(), bucket() | bucket_and_type(), key(), riakc_obj:vclock(), TimeoutOrOptions::timeout() | delete_options()) ->
ok | {error, term()}.
delete_vclock(Pid, Bucket, Key, VClock, Timeout) when is_integer(Timeout); Timeout =:= infinity ->
delete_vclock(Pid, Bucket, Key, VClock, [], Timeout);
delete_vclock(Pid, Bucket, Key, VClock, Options) ->
delete_vclock(Pid, Bucket, Key, VClock, Options, default_timeout(delete_timeout)).
%% @doc Delete the key/value with options and timeout and giving the
%% vector clock. This form of delete ensures that subsequent get and
%% put requests will be correctly ordered with the delete.
%% @see delete_obj/4
-spec delete_vclock(pid(), bucket() | bucket_and_type(), key(), riakc_obj:vclock(), delete_options(), timeout()) ->
ok | {error, term()}.
delete_vclock(Pid, Bucket, Key, VClock, Options, Timeout) ->
{T, B} = maybe_bucket_type(Bucket),
Req = delete_options(Options, #rpbdelreq{type = T, bucket = B, key = Key,
vclock=VClock}),
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Delete the riak object.
%% @equiv delete_vclock(Pid, riakc_obj:bucket(Obj), riakc_obj:key(Obj), riakc_obj:vclock(Obj))
%% @see delete_vclock/6
-spec delete_obj(pid(), riakc_obj()) -> ok | {error, term()}.
delete_obj(Pid, Obj) ->
delete_vclock(Pid, riakc_obj:bucket(Obj), riakc_obj:key(Obj),
riakc_obj:vclock(Obj), [], default_timeout(delete_timeout)).
%% @doc Delete the riak object with options.
%% @equiv delete_vclock(Pid, riakc_obj:bucket(Obj), riakc_obj:key(Obj), riakc_obj:vclock(Obj), Options)
%% @see delete_vclock/6
-spec delete_obj(pid(), riakc_obj(), delete_options()) -> ok | {error, term()}.
delete_obj(Pid, Obj, Options) ->
delete_vclock(Pid, riakc_obj:bucket(Obj), riakc_obj:key(Obj),
riakc_obj:vclock(Obj), Options, default_timeout(delete_timeout)).
%% @doc Delete the riak object with options and timeout.
%% @equiv delete_vclock(Pid, riakc_obj:bucket(Obj), riakc_obj:key(Obj), riakc_obj:vclock(Obj), Options, Timeout)
%% @see delete_vclock/6
-spec delete_obj(pid(), riakc_obj(), delete_options(), timeout()) -> ok | {error, term()}.
delete_obj(Pid, Obj, Options, Timeout) ->
delete_vclock(Pid, riakc_obj:bucket(Obj), riakc_obj:key(Obj),
riakc_obj:vclock(Obj), Options, Timeout).
%% @doc List all buckets on the server in the "default" bucket type.
%% This is a potentially expensive operation and should not be used in production.
%% @equiv list_buckets(Pid, default_timeout(list_buckets_timeout))
-spec list_buckets(pid()) -> {ok, [bucket()]} | {error, term()}.
list_buckets(Pid) ->
list_buckets(Pid, <<"default">>, []).
%% @doc List all buckets in a bucket type, specifying server-side timeout.
%% This is a potentially expensive operation and should not be used in production.
-spec list_buckets(pid(), timeout()|list()|binary()) -> {ok, [bucket()]} |
{error, term()}.
list_buckets(Pid, Type) when is_binary(Type) ->
list_buckets(Pid, Type, []);
list_buckets(Pid, Timeout) when is_integer(Timeout) ->
list_buckets(Pid, <<"default">>, [{timeout, Timeout}]);
list_buckets(Pid, Options) ->
list_buckets(Pid, <<"default">>, Options).
list_buckets(Pid, Type, Options) when is_binary(Type), is_list(Options) ->
case stream_list_buckets(Pid, Type, Options) of
{ok, ReqId} ->
riakc_utils:wait_for_list(ReqId);
Error ->
Error
end.
stream_list_buckets(Pid) ->
stream_list_buckets(Pid, <<"default">>, []).
stream_list_buckets(Pid, Type) when is_binary(Type) ->
stream_list_buckets(Pid, Type, []);
stream_list_buckets(Pid, Timeout) when is_integer(Timeout) ->
stream_list_buckets(Pid, <<"default">>,[{timeout, Timeout}]);
stream_list_buckets(Pid, Options) ->
stream_list_buckets(Pid, <<"default">>, Options).
stream_list_buckets(Pid, Type, Options) ->
AllowListing = riakc_utils:get_allow_listing(Options),
do_stream_list_buckets(AllowListing, Pid, Type, Options).
do_stream_list_buckets(false, _Pid, _Type, _Options) ->
{error, <<"Bucket and key list operations are expensive "
"and should not be used in production.">>};
do_stream_list_buckets(true, Pid, Type, Options) ->
ST = case proplists:get_value(timeout, Options) of
undefined -> ?DEFAULT_PB_TIMEOUT;
T -> T
end,
ReqId = mk_reqid(),
CT = ST + ?DEFAULT_ADDITIONAL_CLIENT_TIMEOUT,
Req = #rpblistbucketsreq{timeout=ST, type=Type, stream=true},
call_infinity(Pid, {req, Req, CT, {ReqId, self()}}).
legacy_list_buckets(Pid, Options) when is_pid(Pid), is_list(Options) ->
AllowListing = riakc_utils:get_allow_listing(Options),
do_legacy_list_buckets(AllowListing, Pid, Options).
do_legacy_list_buckets(false, _Pid, _Options) ->
{error, <<"Bucket and key list operations are expensive "
"and should not be used in production.">>};
do_legacy_list_buckets(true, Pid, Options) ->
ST = case proplists:get_value(timeout, Options) of
undefined -> ?DEFAULT_PB_TIMEOUT;
T -> T
end,
CT = ST + ?DEFAULT_ADDITIONAL_CLIENT_TIMEOUT,
Req = #rpblistbucketsreq{timeout=ST},
call_infinity(Pid, {req, Req, CT}).
%% @doc List all keys in a bucket
%% This is a potentially expensive operation and should not be used in production.
%% @equiv list_keys(Pid, Bucket, default_timeout(list_keys_timeout))
-spec list_keys(pid(), bucket() | bucket_and_type()) -> {ok, [key()]} | {error, term()}.
list_keys(Pid, Bucket) ->
list_keys(Pid, Bucket, []).
%% @doc List all keys in a bucket specifying timeout. This is
%% implemented using {@link stream_list_keys/3} and then waiting for
%% the results to complete streaming.
%% This is a potentially expensive operation and should not be used in production.
-spec list_keys(pid(), bucket() | bucket_and_type(), list()|timeout()) -> {ok, [key()]} |
{error, term()}.
list_keys(Pid, Bucket, infinity) ->
list_keys(Pid, Bucket, [{timeout, undefined}]);
list_keys(Pid, Bucket, Timeout) when is_integer(Timeout) ->
list_keys(Pid, Bucket, [{timeout, Timeout}]);
list_keys(Pid, Bucket, Options) ->
case stream_list_keys(Pid, Bucket, Options) of
{ok, ReqId} ->
riakc_utils:wait_for_list(ReqId);
Error ->
Error
end.
%% @doc Stream list of keys in the bucket to the calling process. The
%% process receives these messages.
%% ``` {ReqId::req_id(), {keys, [key()]}}
%% {ReqId::req_id(), done}'''
%% This is a potentially expensive operation and should not be used in production.
%% @equiv stream_list_keys(Pid, Bucket, default_timeout(stream_list_keys_timeout))
-spec stream_list_keys(pid(), bucket()) -> {ok, req_id()} | {error, term()}.
stream_list_keys(Pid, Bucket) ->
stream_list_keys(Pid, Bucket, []).
%% @doc Stream list of keys in the bucket to the calling process specifying server side
%% timeout.
%% The process receives these messages.
%% ``` {ReqId::req_id(), {keys, [key()]}}
%% {ReqId::req_id(), done}'''
%% This is a potentially expensive operation and should not be used in production.
%% @equiv stream_list_keys(Pid, Bucket, Timeout, default_timeout(stream_list_keys_call_timeout))
-spec stream_list_keys(pid(), bucket() | bucket_and_type(), integer()|list()) ->
{ok, req_id()} |
{error, term()}.
stream_list_keys(Pid, Bucket, infinity) ->
stream_list_keys(Pid, Bucket, [{timeout, undefined}]);
stream_list_keys(Pid, Bucket, Timeout) when is_integer(Timeout) ->
stream_list_keys(Pid, Bucket, [{timeout, Timeout}]);
stream_list_keys(Pid, Bucket, Options) ->
AllowListing = riakc_utils:get_allow_listing(Options),
do_stream_list_keys(AllowListing, Pid, Bucket, Options).
do_stream_list_keys(false, _Pid, _Bucket, _Options) ->
{error, <<"Bucket and key list operations are expensive "
"and should not be used in production.">>};
do_stream_list_keys(true, Pid, Bucket, Options) ->
ST = case proplists:get_value(timeout, Options) of
undefined -> ?DEFAULT_PB_TIMEOUT;
T -> T
end,
{BT, B} = maybe_bucket_type(Bucket),
CT = ST + ?DEFAULT_ADDITIONAL_CLIENT_TIMEOUT,
Req = #rpblistkeysreq{type=BT, bucket=B, timeout=ST},
ReqId = mk_reqid(),
call_infinity(Pid, {req, Req, CT, {ReqId, self()}}).
%% @doc Get bucket properties.
%% @equiv get_bucket(Pid, Bucket, default_timeout(get_bucket_timeout))
-spec get_bucket(pid(), bucket() | bucket_and_type()) -> {ok, bucket_props()} | {error, term()}.
get_bucket(Pid, Bucket) ->
get_bucket(Pid, Bucket, default_timeout(get_bucket_timeout)).
%% @doc Get bucket properties specifying a server side timeout.
%% @equiv get_bucket(Pid, Bucket, Timeout, default_timeout(get_bucket_call_timeout))
-spec get_bucket(pid(), bucket() | bucket_and_type(), timeout()) -> {ok, bucket_props()} | {error, term()}.
get_bucket(Pid, Bucket, Timeout) ->
get_bucket(Pid, Bucket, Timeout, default_timeout(get_bucket_call_timeout)).
%% @doc Get bucket properties specifying a server side and local call timeout.
%% @deprecated because `CallTimeout' is ignored
-spec get_bucket(pid(), bucket() | bucket_and_type(), timeout(), timeout()) -> {ok, bucket_props()} |
{error, term()}.
get_bucket(Pid, Bucket, Timeout, _CallTimeout) ->
{T, B} = maybe_bucket_type(Bucket),
Req = #rpbgetbucketreq{type = T, bucket = B},
call_infinity(Pid, {req, Req, Timeout}).
get_bucket_type(Pid, BucketType) ->
get_bucket_type(Pid, BucketType, default_timeout(get_bucket_timeout)).
get_bucket_type(Pid, BucketType, Timeout) ->
Req = #rpbgetbuckettypereq{type = BucketType},
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Set bucket properties.
%% @equiv set_bucket(Pid, Bucket, BucketProps, default_timeout(set_bucket_timeout))
-spec set_bucket(pid(), bucket() | bucket_and_type(), bucket_props()) -> ok | {error, term()}.
set_bucket(Pid, Bucket, BucketProps) ->
set_bucket(Pid, Bucket, BucketProps, default_timeout(set_bucket_timeout)).
%% @doc Set bucket properties specifying a server side timeout.
%% @equiv set_bucket(Pid, Bucket, BucketProps, Timeout, default_timeout(set_bucket_call_timeout))
-spec set_bucket(pid(), bucket() | bucket_and_type(), bucket_props(), timeout()) -> ok | {error, term()}.
set_bucket(Pid, Bucket, BucketProps, Timeout) ->
set_bucket(Pid, Bucket, BucketProps, Timeout,
default_timeout(set_bucket_call_timeout)).
%% @doc Set bucket properties specifying a server side and local call timeout.
%% @deprecated because `CallTimeout' is ignored
-spec set_bucket(pid(), bucket() | bucket_and_type(), bucket_props(), timeout(), timeout()) -> ok | {error, term()}.
set_bucket(Pid, Bucket, BucketProps, Timeout, _CallTimeout) ->
PbProps = riak_pb_codec:encode_bucket_props(BucketProps),
{T, B} = maybe_bucket_type(Bucket),
Req = #rpbsetbucketreq{type = T, bucket = B, props = PbProps},
call_infinity(Pid, {req, Req, Timeout}).
set_bucket_type(Pid, BucketType, BucketProps) ->
set_bucket_type(Pid, BucketType, BucketProps, default_timeout(set_bucket_timeout)).
set_bucket_type(Pid, BucketType, BucketProps, Timeout) ->
PbProps = riak_pb_codec:encode_bucket_props(BucketProps),
Req = #rpbsetbuckettypereq{type = BucketType, props = PbProps},
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Reset bucket properties back to the defaults.
%% @equiv reset_bucket(Pid, Bucket, default_timeout(reset_bucket_timeout), default_timeout(reset_bucket_call_timeout))
-spec reset_bucket(pid(), bucket() | bucket_and_type()) -> ok | {error, term()}.
reset_bucket(Pid, Bucket) ->
reset_bucket(Pid, Bucket, default_timeout(reset_bucket_timeout), default_timeout(reset_bucket_call_timeout)).
%% @doc Reset bucket properties back to the defaults.
%% @equiv reset_bucket(Pid, Bucket, Timeout, default_timeout(reset_bucket_call_timeout))
-spec reset_bucket(pid(), bucket() | bucket_and_type(), timeout()) -> ok | {error, term()}.
reset_bucket(Pid, Bucket, Timeout) ->
reset_bucket(Pid, Bucket, Timeout, default_timeout(reset_bucket_call_timeout)).
%% @doc Reset bucket properties back to the defaults.
%% @deprecated because `CallTimeout' is ignored
-spec reset_bucket(pid(), bucket() | bucket_and_type(), timeout(), timeout()) -> ok | {error, term()}.
reset_bucket(Pid, Bucket, Timeout, _CallTimeout) ->
{T, B} = maybe_bucket_type(Bucket),
Req = #rpbresetbucketreq{type = T, bucket = B},
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Perform a MapReduce job across the cluster.
%% See the MapReduce documentation for explanation of behavior.
%% @equiv mapred(Inputs, Query, default_timeout(mapred))
-spec mapred(pid(), mapred_inputs(), [mapred_queryterm()]) ->
{ok, mapred_result()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, term()}.
mapred(Pid, Inputs, Query) ->
mapred(Pid, Inputs, Query, default_timeout(mapred_timeout)).
%% @doc Perform a MapReduce job across the cluster with a job timeout.
%% See the MapReduce documentation for explanation of behavior.
%% @equiv mapred(Pid, Inputs, Query, Timeout, default_timeout(mapred_call_timeout))
-spec mapred(pid(), mapred_inputs(), [mapred_queryterm()], timeout()) ->
{ok, mapred_result()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, term()}.
mapred(Pid, Inputs, Query, Timeout) ->
mapred(Pid, Inputs, Query, Timeout, default_timeout(mapred_call_timeout)).
%% @doc Perform a MapReduce job across the cluster with a job and
%% local call timeout. See the MapReduce documentation for
%% explanation of behavior. This is implemented by using
%% mapred_stream/6 and then waiting for all results.
%% @see mapred_stream/6
-spec mapred(pid(), mapred_inputs(), [mapred_queryterm()], timeout(), timeout()) ->
{ok, mapred_result()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, term()}.
mapred(Pid, Inputs, Query, Timeout, CallTimeout) ->
case mapred_stream(Pid, Inputs, Query, self(), Timeout, CallTimeout) of
{ok, ReqId} ->
wait_for_mapred(ReqId, Timeout);
Error ->
Error
end.
%% @doc Perform a streaming MapReduce job across the cluster sending results
%% to ClientPid.
%% See the MapReduce documentation for explanation of behavior.
%% The ClientPid will receive messages in this format:
%% ``` {ReqId::req_id(), {mapred, Phase::non_neg_integer(), mapred_result()}}
%% {ReqId::req_id(), done}'''
%% @equiv mapred_stream(ConnectionPid, Inputs, Query, ClientPid, default_timeout(mapred_stream_timeout))
-spec mapred_stream(ConnectionPid::pid(),Inputs::mapred_inputs(),Query::[mapred_queryterm()], ClientPid::pid()) ->
{ok, req_id()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, Err :: term()}.
mapred_stream(Pid, Inputs, Query, ClientPid) ->
mapred_stream(Pid, Inputs, Query, ClientPid, default_timeout(mapred_stream_timeout)).
%% @doc Perform a streaming MapReduce job with a timeout across the cluster.
%% sending results to ClientPid.
%% See the MapReduce documentation for explanation of behavior.
%% The ClientPid will receive messages in this format:
%% ``` {ReqId::req_id(), {mapred, Phase::non_neg_integer(), mapred_result()}}
%% {ReqId::req_id(), done}'''
%% @equiv mapred_stream(ConnectionPid, Inputs, Query, ClientPid, Timeout, default_timeout(mapred_stream_call_timeout))
-spec mapred_stream(ConnectionPid::pid(),Inputs::mapred_inputs(),Query::[mapred_queryterm()], ClientPid::pid(), Timeout::timeout()) ->
{ok, req_id()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, Err :: term()}.
mapred_stream(Pid, Inputs, Query, ClientPid, Timeout) ->
mapred_stream(Pid, Inputs, Query, ClientPid, Timeout,
default_timeout(mapred_stream_call_timeout)).
%% @doc Perform a streaming MapReduce job with a map/red timeout across the cluster,
%% a local call timeout and sending results to ClientPid.
%% See the MapReduce documentation for explanation of behavior.
%% The ClientPid will receive messages in this format:
%% ``` {ReqId::req_id(), {mapred, Phase::non_neg_integer(), mapred_result()}}
%% {ReqId::req_id(), done}'''
%% @deprecated because `CallTimeout' is ignored
-spec mapred_stream(ConnectionPid::pid(),Inputs::mapred_inputs(),
Query::[mapred_queryterm()], ClientPid::pid(),
Timeout::timeout(), CallTimeout::timeout()) ->
{ok, req_id()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, Err :: term()}.
mapred_stream(Pid, {index,Bucket,Name,Key}, Query, ClientPid, Timeout, CallTimeout) when is_tuple(Name) ->
Index = riakc_obj:index_id_to_bin(Name),
mapred_stream(Pid, {index,Bucket,Index,Key}, Query, ClientPid, Timeout, CallTimeout);
mapred_stream(Pid, {index,Bucket,Name,StartKey,EndKey}, Query, ClientPid, Timeout, CallTimeout) when is_tuple(Name) ->
Index = riakc_obj:index_id_to_bin(Name),
mapred_stream(Pid, {index,Bucket,Index,StartKey,EndKey}, Query, ClientPid, Timeout, CallTimeout);
mapred_stream(Pid, {index,Bucket,Name,Key}, Query, ClientPid, Timeout, CallTimeout) when is_binary(Name) andalso is_integer(Key) ->
BinKey = list_to_binary(integer_to_list(Key)),
mapred_stream(Pid, {index,Bucket,Name,BinKey}, Query, ClientPid, Timeout, CallTimeout);
mapred_stream(Pid, {index,Bucket,Name,StartKey,EndKey}, Query, ClientPid, Timeout, CallTimeout) when is_binary(Name) andalso is_integer(StartKey) ->
BinStartKey = list_to_binary(integer_to_list(StartKey)),
mapred_stream(Pid, {index,Bucket,Name,BinStartKey,EndKey}, Query, ClientPid, Timeout, CallTimeout);
mapred_stream(Pid, {index,Bucket,Name,StartKey,EndKey}, Query, ClientPid, Timeout, CallTimeout) when is_binary(Name) andalso is_integer(EndKey) ->
BinEndKey = list_to_binary(integer_to_list(EndKey)),
mapred_stream(Pid, {index,Bucket,Name,StartKey,BinEndKey}, Query, ClientPid, Timeout, CallTimeout);
mapred_stream(Pid, Inputs, Query, ClientPid, Timeout, _CallTimeout) ->
AllowListing = riakc_utils:get_allow_listing(),
do_mapred_stream(AllowListing, Pid, Inputs, Query, ClientPid, Timeout).
do_mapred_stream(false, _Pid, Bucket, _Query, _ClientPid, _Timeout) when is_binary(Bucket) ->
{error, <<"Bucket list operations are expensive "
"and should not be used in production.">>};
do_mapred_stream(false, _Pid, {Type, Bucket}, _Query, _ClientPid, _Timeout)
when is_binary(Type), is_binary(Bucket) ->
{error, <<"Bucket list operations are expensive "
"and should not be used in production.">>};
do_mapred_stream(_AllowListing, Pid, Inputs, Query, ClientPid, Timeout) ->
MapRed = [{'inputs', Inputs},
{'query', Query},
{'timeout', Timeout}],
send_mapred_req(Pid, MapRed, ClientPid).
%% @doc Perform a MapReduce job against a bucket across the cluster.
%% See the MapReduce documentation for explanation of behavior.
%% This uses list_keys under the hood and so is potentially an expensive operation that should not be used in production.
%% @equiv mapred_bucket(Pid, Bucket, Query, default_timeout(mapred_bucket_timeout))
-spec mapred_bucket(Pid::pid(), Bucket::bucket(), Query::[mapred_queryterm()]) ->
{ok, mapred_result()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, Err :: term()}.
mapred_bucket(Pid, Bucket, Query) ->
mapred_bucket(Pid, Bucket, Query, default_timeout(mapred_bucket_timeout)).
%% @doc Perform a MapReduce job against a bucket with a timeout
%% across the cluster.
%% See the MapReduce documentation for explanation of behavior.
%% This uses list_keys under the hood and so is potentially an expensive operation that should not be used in production.
%% @equiv mapred_bucket(Pid, Bucket, Query, Timeout, default_timeout(mapred_bucket_call_timeout))
-spec mapred_bucket(Pid::pid(), Bucket::bucket(), Query::[mapred_queryterm()], Timeout::timeout()) ->
{ok, mapred_result()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, Err :: term()}.
mapred_bucket(Pid, Bucket, Query, Timeout) ->
mapred_bucket(Pid, Bucket, Query, Timeout, default_timeout(mapred_bucket_call_timeout)).
%% @doc Perform a MapReduce job against a bucket with a timeout
%% across the cluster and local call timeout.
%% See the MapReduce documentation for explanation of behavior.
%% This uses list_keys under the hood and so is potentially an expensive operation that should not be used in production.
-spec mapred_bucket(Pid::pid(), Bucket::bucket(), Query::[mapred_queryterm()],
Timeout::timeout(), CallTimeout::timeout()) ->
{ok, mapred_result()} |
{error, {badqterm, mapred_queryterm()}} |
{error, timeout} |
{error, Err :: term()}.
mapred_bucket(Pid, Bucket, Query, Timeout, CallTimeout) ->
case mapred_bucket_stream(Pid, Bucket, Query, self(), Timeout, CallTimeout) of
{ok, ReqId} ->
wait_for_mapred(ReqId, Timeout);
Error ->
Error
end.
%% @doc Perform a streaming MapReduce job against a bucket with a timeout
%% across the cluster.
%% See the MapReduce documentation for explanation of behavior.
%% This uses list_keys under the hood and so is potentially an expensive operation that should not be used in production.
%% The ClientPid will receive messages in this format:
%% ``` {ReqId::req_id(), {mapred, Phase::non_neg_integer(), mapred_result()}}
%% {ReqId::req_id(), done}'''
%% @equiv mapred_bucket_stream(Pid, Bucket, Query, ClientPid, Timeout, default_timeout(mapred_bucket_stream_call_timeout))
-spec mapred_bucket_stream(ConnectionPid::pid(), bucket(), [mapred_queryterm()], ClientPid::pid(), timeout()) ->
{ok, req_id()} |
{error, term()}.
mapred_bucket_stream(Pid, Bucket, Query, ClientPid, Timeout) ->
mapred_bucket_stream(Pid, Bucket, Query, ClientPid, Timeout,
default_timeout(mapred_bucket_stream_call_timeout)).
%% @doc Perform a streaming MapReduce job against a bucket with a server timeout
%% across the cluster and a call timeout.
%% See the MapReduce documentation for explanation of behavior.
%% This uses list_keys under the hood and so is potentially an expensive operation that should not be used in production.
%% The ClientPid will receive messages in this format:
%% ``` {ReqId::req_id(), {mapred, Phase::non_neg_integer(), mapred_result()}}
%% {ReqId::req_id(), done}'''
%% @deprecated because `CallTimeout' is ignored
-spec mapred_bucket_stream(ConnectionPid::pid(), bucket(), [mapred_queryterm()], ClientPid::pid(), timeout(), timeout()) ->
{ok, req_id()} | {error, term()}.
mapred_bucket_stream(Pid, Bucket, Query, ClientPid, Timeout, _CallTimeout) ->
MapRed = [{'inputs', Bucket},
{'query', Query},
{'timeout', Timeout}],
send_mapred_req(Pid, MapRed, ClientPid).
%% @doc Execute a search query. This command will return an error
%% unless executed against a Riak Search cluster.
-spec search(pid(), binary(), binary()) ->
{ok, search_result()} | {error, term()}.
search(Pid, Index, SearchQuery) ->
search(Pid, Index, SearchQuery, []).
%% @doc Execute a search query. This command will return an error
%% unless executed against a Riak Search cluster.
-spec search(pid(), binary(), binary(), search_options()) ->
{ok, search_result()} | {error, term()}.
search(Pid, Index, SearchQuery, Options) ->
Timeout = default_timeout(search_timeout),
search(Pid, Index, SearchQuery, Options, Timeout).
%% @doc Execute a search query. This command will return an error
%% unless executed against a Riak Search cluster.
-spec search(pid(), binary(), binary(), search_options(), timeout()) ->
{ok, search_result()} | {error, term()}.
search(Pid, Index, SearchQuery, Options, Timeout) ->
CallTimeout = default_timeout(search_call_timeout),
search(Pid, Index, SearchQuery, Options, Timeout, CallTimeout).
%% @doc Execute a search query. This command will return an error
%% unless executed against a Riak Search cluster.
%% @deprecated because `CallTimeout' is ignored
-spec search(pid(), binary(), binary(), search_options(), timeout(), timeout()) ->
{ok, search_result()} | {error, term()}.
search(Pid, Index, SearchQuery, Options, Timeout, _CallTimeout) ->
Req = search_options(Options, #rpbsearchqueryreq{q = SearchQuery, index = Index}),
call_infinity(Pid, {req, Req, Timeout}).
-spec get_search_schema(pid(), binary(), search_admin_opts()) ->
{ok, search_schema()} | {error, term()}.
get_search_schema(Pid, SchemaName, Opts) ->
Timeout = proplists:get_value(timeout, Opts, default_timeout(search_timeout)),
Req = #rpbyokozunaschemagetreq{ name = SchemaName },
call_infinity(Pid, {req, Req, Timeout}).
-spec get_search_schema(pid(), binary()) ->
{ok, search_schema()} | {error, term()}.
get_search_schema(Pid, SchemaName) ->
get_search_schema(Pid, SchemaName, []).
-spec get_search_index(pid(), binary(), search_admin_opts()) ->
{ok, search_index()} | {error, term()}.
get_search_index(Pid, Index, Opts) ->
Timeout = proplists:get_value(timeout, Opts, default_timeout(search_timeout)),
Req = #rpbyokozunaindexgetreq{ name = Index },
Results = call_infinity(Pid, {req, Req, Timeout}),
case Results of
{ok, [Result]} ->
{ok, Result};
{ok, []} ->
{error, notfound};
X -> X
end.
-spec get_search_index(pid(), binary()) ->
{ok, search_index()} | {error, term()}.
get_search_index(Pid, Index) ->
get_search_index(Pid, Index, []).
-spec list_search_indexes(pid(), search_admin_opts()) ->
{ok, [search_index()]} | {error, term()}.
list_search_indexes(Pid, Opts) ->
Timeout = proplists:get_value(timeout, Opts, default_timeout(search_timeout)),
call_infinity(Pid, {req, #rpbyokozunaindexgetreq{}, Timeout}).
-spec list_search_indexes(pid()) ->
{ok, [search_index()]} | {error, term()}.
list_search_indexes(Pid) ->
list_search_indexes(Pid, []).
%% @doc Create a schema, which is a required component of an index.
-spec create_search_schema(pid(), binary(), binary()) ->
ok | {error, term()}.
create_search_schema(Pid, SchemaName, Content) ->
create_search_schema(Pid, SchemaName, Content, []).
%% @doc Create a schema, which is a required component of an index.
-spec create_search_schema(pid(), binary(), binary(), search_admin_opts()) ->
ok | {error, term()}.
create_search_schema(Pid, SchemaName, Content, Opts) ->
Timeout = proplists:get_value(timeout, Opts, default_timeout(search_timeout)),
Req = #rpbyokozunaschemaputreq{
schema = #rpbyokozunaschema{name = SchemaName, content = Content}
},
call_infinity(Pid, {req, Req, Timeout}).
%% @doc Create a search index.
-spec create_search_index(pid(), binary()) ->
ok | {error, term()}.
create_search_index(Pid, Index) ->
create_search_index(Pid, Index, <<>>, []).
-spec create_search_index(pid(), binary(), timeout() | search_admin_opts()) ->
ok | {error, term()}.
create_search_index(Pid, Index, Timeout)
when is_integer(Timeout); Timeout =:= infinity ->
create_search_index(Pid, Index, <<>>, [{timeout, Timeout}]);
create_search_index(Pid, Index, Opts) ->
create_search_index(Pid, Index, <<>>, Opts).
-spec create_search_index(pid(), binary(), binary(),
timeout()|search_admin_opts()) ->
ok | {error, term()}.
create_search_index(Pid, Index, SchemaName, Timeout)
when is_integer(Timeout); Timeout =:= infinity ->
create_search_index(Pid, Index, SchemaName, [{timeout, Timeout}]);
create_search_index(Pid, Index, SchemaName, Opts) ->
ST = proplists:get_value(timeout, Opts, default_timeout(search_timeout)),
NVal = proplists:get_value(n_val, Opts),
Req = set_index_create_req_nval(NVal, Index, SchemaName),
Req1 = case proplists:is_defined(timeout, Opts) of
true ->
set_index_create_req_timeout(ST, Req);
_ ->
Req
end,
CT = if
is_integer(ST) ->
%% Add an extra 500ms to the create_search_index timeout
%% and use that for the client-side timeout.
%% This should give the creation process time to throw
%% back a proper response.
ST + ?DEFAULT_ADDITIONAL_CLIENT_TIMEOUT;
true ->
ST
end,
call_infinity(Pid, {req, Req1, CT}).
%% @doc Delete a search index.
-spec delete_search_index(pid(), binary()) ->
ok | {error, term()}.
delete_search_index(Pid, Index) ->
delete_search_index(Pid, Index, []).
%% @doc Delete a search index.
-spec delete_search_index(pid(), binary(), search_admin_opts()) ->
ok | {error, term()}.
delete_search_index(Pid, Index, Opts) ->
Timeout = proplists:get_value(timeout, Opts, default_timeout(search_timeout)),
Req = #rpbyokozunaindexdeletereq{name = Index},
call_infinity(Pid, {req, Req, Timeout}).
-spec set_search_index(pid(), bucket() | bucket_and_type(), binary()) ->
ok | {error, term()}.
set_search_index(Pid, Bucket, Index) ->
set_bucket(Pid, Bucket, [{search_index, Index}]).
%% Deprecated, argument explosion functions for indexes
%% @doc Execute a secondary index equality query.
%%
%% @deprecated use {@link get_index_eq/4}
%% @see get_index_eq/4
-spec get_index(pid(), bucket() | bucket_and_type(), binary() | secondary_index_id(), key() | integer()) ->
{ok, index_results()} | {error, term()}.
get_index(Pid, Bucket, Index, Key) ->
get_index_eq(Pid, Bucket, Index, Key).
%% @doc Execute a secondary index equality query with specified
%% timeouts.
%%
%% @deprecated use {@link get_index_eq/5}
%% @see get_index_eq/5
-spec get_index(pid(), bucket() | bucket_and_type(), binary() | secondary_index_id(), key() | integer(), timeout(), timeout()) ->
{ok, index_results()} | {error, term()}.
get_index(Pid, Bucket, Index, Key, Timeout, _CallTimeout) ->
get_index_eq(Pid, Bucket, Index, Key, [{timeout, Timeout}]).
%% @doc Execute a secondary index range query.
%%
%% @deprecated use {@link get_index_range/5}
%% @see get_index_range/5
-spec get_index(pid(), bucket(), binary() | secondary_index_id(), key() | integer(), key() | integer()) ->
{ok, index_results()} | {error, term()}.
get_index(Pid, Bucket, Index, StartKey, EndKey) ->
get_index_range(Pid, Bucket, Index, StartKey, EndKey).
%% @doc Execute a secondary index range query with specified
%% timeouts.
%%
%% @deprecated use {@link get_index_range/6}
%% @see get_index_range/6
-spec get_index(pid(), bucket() | bucket_and_type(), binary() | secondary_index_id(), key() | integer() | list(),
key() | integer() | list(), timeout(), timeout()) ->
{ok, index_results()} | {error, term()}.
get_index(Pid, Bucket, Index, StartKey, EndKey, Timeout, _CallTimeout) ->
get_index_range(Pid, Bucket, Index, StartKey, EndKey, [{timeout, Timeout}]).
%% @doc Execute a secondary index equality query.
%% equivalent to all defaults for the options.
%% @see get_index_eq/5. for options and their effect
-spec get_index_eq(pid(), bucket() | bucket_and_type(), binary() | secondary_index_id(), key() | integer()) ->
{ok, index_results()} | {error, term()}.
get_index_eq(Pid, Bucket, Index, Key) ->
get_index_eq(Pid, Bucket, Index, Key, []).
%% @doc Execute a secondary index equality query with specified options
%%
continuation in the response if this option is used.