Packages
erlcloud
0.9.2-rc.1
3.8.3
3.8.2
3.8.1
3.7.6
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.8
3.6.7
3.6.5
3.6.4
3.6.3
3.6.2
3.6.1
3.6.0
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.10
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.4.5
3.4.3
3.4.1
3.4.0
3.3.9
3.3.8
3.3.7
3.3.6
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.18
3.2.17
3.2.16
3.2.15
3.2.14
3.2.13
3.2.12
3.2.11
3.2.10
3.2.7
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.17
3.1.16
3.1.14
3.1.13
3.1.12
3.1.11
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
2.2.16
2.2.15
2.2.14
2.2.13
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.2
2.2.1
2.2.0
2.1.0
2.0.5
2.0.4
2.0.3
2.0.0
0.13.10
0.13.9
0.13.8
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.0
0.12.0
0.11.0
0.9.2
0.9.2-rc.1
0.9.1
0.9.0
AWS APIs library for Erlang
Current section
Files
Jump to
Current section
Files
src/erlcloud_sdb.erl
-module(erlcloud_sdb).
-type sdb_attribute() :: {string(), string() | {replace, string()}}.
-type sdb_attributes() :: [sdb_attribute()].
-type sdb_conditional() :: {string(), string() | exists | not_exists}.
-type sdb_conditionals() :: [sdb_conditional()].
-type sdb_delete_attribute() :: {string(), string()} | string().
-type sdb_delete_attributes() :: [sdb_delete_attribute()].
%% Library initialization.
-export([configure/2, configure/3, new/2, new/3]).
%% SDB API Functions
-export([
%% Domains
create_domain/1, create_domain/2,
delete_domain/1, delete_domain/2,
domain_metadata/1, domain_metadata/2,
list_domains/0, list_domains/1, list_domains/2, list_domains/3,
%% Items
batch_put_attributes/2, batch_put_attributes/3,
delete_attributes/2, delete_attributes/3,
delete_attributes/4, delete_attributes/5,
get_attributes/2, get_attributes/3, get_attributes/4, get_attributes/5,
put_attributes/3, put_attributes/4, put_attributes/5,
select/1, select/2, select/3, select/4,
select_all/1, select_all/2, select_all/3
]).
%% Export all functions for unit tests
-ifdef(TEST).
-compile(export_all).
-endif.
-include_lib("erlcloud/include/erlcloud.hrl").
-include_lib("erlcloud/include/erlcloud_aws.hrl").
-define(API_VERSION, "2009-04-15").
-define(SDB_TIMEOUT, 10000).
-spec(new/2 :: (string(), string()) -> aws_config()).
new(AccessKeyID, SecretAccessKey) ->
#aws_config{access_key_id=AccessKeyID,
secret_access_key=SecretAccessKey}.
-spec(new/3 :: (string(), string(), string()) -> aws_config()).
new(AccessKeyID, SecretAccessKey, Host) ->
#aws_config{access_key_id=AccessKeyID,
secret_access_key=SecretAccessKey,
sdb_host=Host}.
-spec(configure/2 :: (string(), string()) -> ok).
configure(AccessKeyID, SecretAccessKey) ->
put(aws_config, new(AccessKeyID, SecretAccessKey)),
ok.
-spec(configure/3 :: (string(), string(), string()) -> ok).
configure(AccessKeyID, SecretAccessKey, Host) ->
put(aws_config, new(AccessKeyID, SecretAccessKey, Host)),
ok.
default_config() -> erlcloud_aws:default_config().
-spec create_domain/1 :: (string()) -> proplist().
create_domain(Name) ->
create_domain(Name, default_config()).
-spec create_domain/2 :: (string(), aws_config()) -> proplist().
create_domain(Name, Config)
when is_list(Name) ->
sdb_simple_request(Config, "CreateDomain", [{"DomainName", Name}]).
-spec delete_domain/1 :: (string()) -> proplist().
delete_domain(Name) ->
delete_domain(Name, default_config()).
-spec delete_domain/2 :: (string(), aws_config()) -> proplist().
delete_domain(Name, Config)
when is_list(Name) ->
sdb_simple_request(Config, "DeleteDomain", [{"DomainName", Name}]).
-spec domain_metadata/1 :: (string()) -> proplist().
domain_metadata(Name) ->
domain_metadata(Name, default_config()).
-spec domain_metadata/2 :: (string(), aws_config()) -> proplist().
domain_metadata(Name, Config)
when is_list(Name) ->
{Doc, Result} = sdb_request(Config, "DomainMetadata", [{"DomainName", Name}]),
MR = hd(xmerl_xpath:string("/DomainMetadataResponse/DomainMetadataResult", Doc)),
Metadata = erlcloud_xml:decode([
{item_count, "ItemCount", integer},
{item_names_size_bytes, "ItemNamesSizeBytes", integer},
{attribute_name_count, "AttributeNameCount", integer},
{attribute_names_size_bytes, "AttributeNamesSizeBytes", integer},
{attribute_value_count, "AttributeValueCount", integer},
{attribute_values_size_bytes, "AttributeValuesSizeBytes", integer},
{timestamp, "Timestamp", integer}
], MR),
[{domain_metadata, Metadata}|Result].
-spec batch_put_attributes/2 :: (string(), [{string(), sdb_attributes()}]) -> proplist().
batch_put_attributes(DomainName, Items) ->
batch_put_attributes(DomainName, Items, default_config()).
-spec batch_put_attributes/3 :: (string(), [{string(), sdb_attributes()}], aws_config()) -> proplist().
batch_put_attributes(DomainName, Items, Config)
when is_list(DomainName), is_list(Items) ->
ItemParams = [[{"ItemName", Name}|attributes_list(Attrs)] || {Name, Attrs} <- Items],
sdb_simple_request(Config, "BatchPutAttributes",
[{"DomainName", DomainName}|erlcloud_aws:param_list(ItemParams, "Item")]).
-spec delete_attributes/2 :: (string(), string()) -> proplist().
delete_attributes(DomainName, ItemName) ->
delete_attributes(DomainName, ItemName, []).
-spec delete_attributes/3 :: (string(), string(), sdb_delete_attributes() | aws_config()) -> proplist().
delete_attributes(DomainName, ItemName, Config)
when is_record(Config, aws_config) ->
delete_attributes(DomainName, ItemName, [], Config);
delete_attributes(DomainName, ItemName, Attributes) ->
delete_attributes(DomainName, ItemName, Attributes, []).
-spec delete_attributes/4 :: (string(), string(), sdb_delete_attributes(), sdb_conditionals() | aws_config()) -> proplist().
delete_attributes(DomainName, ItemName, Attributes, Config)
when is_record(Config, aws_config) ->
delete_attributes(DomainName, ItemName, Attributes, [], Config);
delete_attributes(DomainName, ItemName, Attributes, Conditionals) ->
delete_attributes(DomainName, ItemName, Attributes, Conditionals, default_config()).
-spec delete_attributes/5 :: (string(), string(), sdb_delete_attributes(), sdb_conditionals(), aws_config()) -> proplist().
delete_attributes(DomainName, ItemName, Attributes, Conditionals, Config)
when is_list(DomainName), is_list(ItemName), is_list(Attributes),
is_list(Conditionals) ->
Params = [{"DomainName", DomainName}, {"ItemName", ItemName}|
delete_attributes_list(Attributes)] ++ conditionals_list(Conditionals),
sdb_simple_request(Config, "DeleteAttributes", Params).
-spec get_attributes/2 :: (string(), string()) -> proplist().
get_attributes(DomainName, ItemName) ->
get_attributes(DomainName, ItemName, []).
-spec get_attributes/3 :: (string(), string(), [string()] | boolean() | aws_config()) -> proplist().
get_attributes(DomainName, ItemName, Config)
when is_record(Config, aws_config) ->
get_attributes(DomainName, ItemName, [], Config);
get_attributes(DomainName, ItemName, ConsistentRead)
when is_boolean(ConsistentRead) ->
get_attributes(DomainName, ItemName, [], ConsistentRead);
get_attributes(DomainName, ItemName, AttributeNames) ->
get_attributes(DomainName, ItemName, AttributeNames, false).
-spec get_attributes/4 :: (string(), string(), [string()], boolean() | aws_config()) -> proplist().
get_attributes(DomainName, ItemName, AttributeNames, Config)
when is_record(Config, aws_config) ->
get_attributes(DomainName, ItemName, AttributeNames, false, Config);
get_attributes(DomainName, ItemName, AttributeNames, ConsistentRead) ->
get_attributes(DomainName, ItemName, AttributeNames, ConsistentRead,
default_config()).
-spec get_attributes/5 :: (string(), string(), [string()], boolean(), aws_config()) -> proplist().
get_attributes(DomainName, ItemName, AttributeNames, ConsistentRead, Config) ->
{Doc, Result} = sdb_request(Config, "GetAttributes",
[{"DomainName", DomainName}, {"ItemName", ItemName},
{"ConsistentRead", ConsistentRead}|
erlcloud_aws:param_list(AttributeNames, "AttributeName")]),
[{attributes,
extract_attributes(xmerl_xpath:string("/GetAttributesResponse/GetAttributesResult/Attribute", Doc))}|
Result].
extract_attributes(Attributes) ->
[extract_attribute(Attr) || Attr <- Attributes].
extract_attribute(Node) ->
{erlcloud_xml:get_text("Name", Node), erlcloud_xml:get_text("Value", Node)}.
-spec list_domains/0 :: () -> proplist().
list_domains() ->
list_domains(default_config()).
-spec list_domains/1 :: (string() | 1..100 | none | aws_config()) -> proplist().
list_domains(Config) when is_record(Config, aws_config) ->
list_domains("", Config);
list_domains(MaxDomains) when is_integer(MaxDomains); MaxDomains =:= none ->
list_domains("", MaxDomains);
list_domains(FirstToken) ->
list_domains(FirstToken, none).
-spec list_domains/2 :: (string(), 1..100 | none | aws_config()) -> proplist().
list_domains(FirstToken, Config) when is_record(Config, aws_config) ->
list_domains(FirstToken, none, Config);
list_domains(FirstToken, MaxDomains) ->
list_domains(FirstToken, MaxDomains, default_config()).
maybe_add_maxdomains(none, Params) ->
Params;
maybe_add_maxdomains(MaxDomains, Params) ->
[{"MaxNumberOfDomains", MaxDomains} | Params].
maybe_add_nexttoken([], Params) ->
Params;
maybe_add_nexttoken(Token, Params) ->
[{"NextToken", Token} | Params].
-spec list_domains/3 :: (string(), 1..100 | none, aws_config()) -> proplist().
list_domains(FirstToken, MaxDomains, Config)
when is_list(FirstToken),
is_integer(MaxDomains) orelse MaxDomains =:= none ->
Params =
maybe_add_nexttoken(FirstToken,
maybe_add_maxdomains(MaxDomains, [])),
{Doc, Result} = sdb_request(Config, "ListDomains", Params),
[{domains, erlcloud_xml:get_list("/ListDomainsResponse/ListDomainsResult/DomainName", Doc)},
{next_token, erlcloud_xml:get_text("/ListDomainsResponse/ListDomainsResult/NextToken", Doc)}|Result].
-spec put_attributes/3 :: (string(), string(), sdb_attributes()) -> proplist().
put_attributes(DomainName, ItemName, Attributes) ->
put_attributes(DomainName, ItemName, Attributes, []).
-spec put_attributes/4 :: (string(), string(), sdb_attributes(), sdb_conditionals() | aws_config()) -> proplist().
put_attributes(DomainName, ItemName, Attributes, Config)
when is_record(Config, aws_config) ->
put_attributes(DomainName, ItemName, Attributes, [], Config);
put_attributes(DomainName, ItemName, Attributes, Conditionals) ->
put_attributes(DomainName, ItemName, Attributes, Conditionals, default_config()).
-spec put_attributes/5 :: (string(), string(), sdb_attributes(), sdb_conditionals(), aws_config()) -> proplist().
put_attributes(DomainName, ItemName, Attributes, Conditionals, Config)
when is_list(DomainName), is_list(ItemName), is_list(Attributes),
is_list(Conditionals) ->
Params = [{"DomainName", DomainName}, {"ItemName", ItemName}|
attributes_list(Attributes)] ++ conditionals_list(Conditionals),
sdb_simple_request(Config, "PutAttributes", Params).
%% These functions will return the first page of results along with
%% a token to retrieve the next page, if any.
-spec select/1 :: (string()) -> proplist().
select(SelectExpression) -> select(SelectExpression, none).
-spec select/2 :: (string(), string() | none | boolean() | aws_config()) -> proplist().
select(SelectExpression, Config)
when is_record(Config, aws_config) ->
select(SelectExpression, none, Config);
select(SelectExpression, ConsistentRead)
when is_boolean(ConsistentRead) ->
select(SelectExpression, none, ConsistentRead);
select(SelectExpression, NextToken) ->
select(SelectExpression, NextToken, false).
-spec select/3 :: (string(), string() | none, boolean() | aws_config()) -> proplist().
select(SelectExpression, NextToken, Config)
when is_record(Config, aws_config) ->
select(SelectExpression, NextToken, false, Config);
select(SelectExpression, NextToken, ConsistentRead) ->
select(SelectExpression, NextToken, ConsistentRead, default_config()).
-spec select/4 :: (string(), string() | none, boolean(), aws_config()) -> proplist().
select(SelectExpression, NextToken, ConsistentRead, Config)
when is_list(SelectExpression),
is_list(NextToken) orelse NextToken =:= none,
is_boolean(ConsistentRead) ->
{Items, NewNextToken, Metadata} = sdb_select_request(SelectExpression,
NextToken,
ConsistentRead,
Config),
Metadata2 = case NewNextToken of
done -> Metadata;
Token -> [{next_token, Token}|Metadata]
end,
[{items, Items}|Metadata2].
%% These functions will make multiple requests until all
%% pages of results have been consumed.
-spec select_all/1 :: (string()) -> proplist().
select_all(SelectExpression) ->
select_all(SelectExpression, false).
-spec select_all/2 :: (string(), boolean()) -> proplist().
select_all(SelectExpression, ConsistentRead)
when is_boolean(ConsistentRead) ->
select_all(SelectExpression, ConsistentRead, default_config());
select_all(SelectExpression, Config) ->
select_all(SelectExpression, false, Config).
-spec select_all/3 :: (string(), boolean(), aws_config()) -> proplist().
select_all(SelectExpression, ConsistentRead, Config)
when is_list(SelectExpression),
is_boolean(ConsistentRead) ->
select_all(SelectExpression, none, ConsistentRead, Config, [], []).
-spec select_all/6 :: (string(), string() | none | done, boolean(),
aws_config(), proplist(), proplist()) -> proplist().
select_all(_, done, _, _, Items, Metadata) ->
[{items, Items}|Metadata];
select_all(SelectExpression, NextToken, ConsistentRead, Config, Items, Metadata) ->
{NewItems, NewNextToken, NewMetadata} = sdb_select_request(SelectExpression,
NextToken,
ConsistentRead,
Config),
select_all(SelectExpression, NewNextToken, ConsistentRead,
Config, Items ++ NewItems, Metadata ++ NewMetadata).
sdb_select_request(SelectExpression, NextToken, ConsistentRead, Config) ->
{Doc, Metadata} = sdb_request(Config, "Select",
[{"SelectExpression", SelectExpression},
{"NextToken", NextToken},
{"ConsistentRead", ConsistentRead}]),
NewNextToken = extract_token(Doc),
Items = extract_items(xmerl_xpath:string("/SelectResponse/SelectResult/Item", Doc)),
{Items, NewNextToken, Metadata}.
extract_token(Doc) ->
case xmerl_xpath:string("/SelectResponse/SelectResult/NextToken", Doc) of
[] ->
done;
[Token] ->
erlcloud_xml:get_text(Token)
end.
extract_items(Items) ->
[extract_item(Item) || Item <- Items].
extract_item(Item) ->
[
{name, erlcloud_xml:get_text("Name", Item)},
{attributes, extract_attributes(xmerl_xpath:string("Attribute", Item))}
].
sdb_request(Config, Action, Params) ->
case sdb_request_with_retry(Config, Action, Params, 1, ?SDB_TIMEOUT, erlang:now()) of
{ok, {Doc, Metadata}} ->
{Doc, Metadata};
{error, Error} ->
erlang:error({aws_error, Error})
end.
sdb_request_with_retry(Config, Action, Params, Try, Timeout, StartTime) ->
case sdb_request_safe(Config, Action, Params) of
{ok, Doc, Metadata} ->
{ok, {Doc, Metadata}};
{error, {http_error, 503, _StatusLine, _Body}} ->
%% Convert from microseconds to milliseconds
Waited = timer:now_diff(erlang:now(), StartTime) / 1000.0,
case Waited of
_TooLong when Waited > Timeout ->
{error, retry_timeout};
_ ->
Wait = math:pow(2, Try) * 200.0,
%% Not exactly random since we're relying on the
%% calling process to hold our PRNG state.
FuzzWait = random:uniform(round(Wait)),
timer:sleep(FuzzWait),
sdb_request_with_retry(Config, Action, Params,
Try + 1, Timeout, StartTime)
end;
{error, _} = Error ->
Error
end.
sdb_request_safe(Config, Action, Params) ->
QParams = [{"Action", Action}, {"Version", ?API_VERSION}|Params],
case erlcloud_aws:aws_request_xml2(post, Config#aws_config.sdb_host,
"/", QParams, Config) of
{ok, Doc} ->
{ok, Doc, [{box_usage, erlcloud_xml:get_float("/*/ResponseMetadata/BoxUsage", Doc)}]};
{error, Error} ->
{error, Error}
end.
sdb_simple_request(Config, Action, Params) ->
{_Doc, Result} = sdb_request(Config, Action, Params),
Result.
delete_attributes_list(Attrs) ->
erlcloud_aws:param_list(
[case Attr of
{Name, Value} -> [{"Name", Name}, {"Value", Value}];
Name when is_list(Name) -> [{"Name", Name}]
end || Attr <- Attrs],
"Attribute").
attributes_list(Attrs) ->
erlcloud_aws:param_list(
[[{"Name", Name}|
case Value of
{replace, V} -> [{"Value", V}, {"Replace", true}];
V -> [{"Value", V}]
end] ||
{Name, Value} <- Attrs],
"Attribute").
conditionals_list(Conditionals) ->
erlcloud_aws:param_list(
[[{"Name", Name},
case Value of
exists -> {"Exists", "true"};
not_exists -> {"Exists", "false"};
V -> {"Value", V}
end] ||
{Name, Value} <- Conditionals],
"Expected").