summaryrefslogtreecommitdiff
path: root/src/rabbit_runtime_parameters.erl
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2013-08-19 17:14:13 +0100
committerSimon MacMullen <simon@rabbitmq.com>2013-08-19 17:14:13 +0100
commit11049881a87eb51e9bf6efbb4d2ef1ee4be62bfe (patch)
tree2a3f21103e1d6050802ed32714d1e62763aeb0a5 /src/rabbit_runtime_parameters.erl
parentbd1305279e255adcf583afdd55a7cee18a9fcddb (diff)
parentaf4ef7640e817141615298c504e9129d14be1d9d (diff)
downloadrabbitmq-server-bug24969.tar.gz
Merge defaultbug24969
Diffstat (limited to 'src/rabbit_runtime_parameters.erl')
-rw-r--r--src/rabbit_runtime_parameters.erl258
1 files changed, 120 insertions, 138 deletions
diff --git a/src/rabbit_runtime_parameters.erl b/src/rabbit_runtime_parameters.erl
index 172cee92..c13c333e 100644
--- a/src/rabbit_runtime_parameters.erl
+++ b/src/rabbit_runtime_parameters.erl
@@ -10,16 +10,17 @@
%%
%% The Original Code is RabbitMQ.
%%
-%% The Initial Developer of the Original Code is VMware, Inc.
-%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved.
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved.
%%
-module(rabbit_runtime_parameters).
-include("rabbit.hrl").
--export([parse_set/3, set/3, clear/2, list/0, list/1, list_formatted/0,
- lookup/2, value/2, value/3, info_keys/0]).
+-export([parse_set/4, set/4, set_any/4, clear/3, clear_any/3, list/0, list/1,
+ list_component/1, list/2, list_formatted/1, lookup/3,
+ value/3, value/4, info_keys/0]).
%%----------------------------------------------------------------------------
@@ -27,15 +28,26 @@
-type(ok_or_error_string() :: 'ok' | {'error_string', string()}).
--spec(parse_set/3 :: (binary(), binary(), string()) -> ok_or_error_string()).
--spec(set/3 :: (binary(), binary(), term()) -> ok_or_error_string()).
--spec(clear/2 :: (binary(), binary()) -> ok_or_error_string()).
+-spec(parse_set/4 :: (rabbit_types:vhost(), binary(), binary(), string())
+ -> ok_or_error_string()).
+-spec(set/4 :: (rabbit_types:vhost(), binary(), binary(), term())
+ -> ok_or_error_string()).
+-spec(set_any/4 :: (rabbit_types:vhost(), binary(), binary(), term())
+ -> ok_or_error_string()).
+-spec(clear/3 :: (rabbit_types:vhost(), binary(), binary())
+ -> ok_or_error_string()).
+-spec(clear_any/3 :: (rabbit_types:vhost(), binary(), binary())
+ -> ok_or_error_string()).
-spec(list/0 :: () -> [rabbit_types:infos()]).
--spec(list/1 :: (binary()) -> [rabbit_types:infos()] | 'not_found').
--spec(list_formatted/0 :: () -> [rabbit_types:infos()]).
--spec(lookup/2 :: (binary(), binary()) -> rabbit_types:infos()).
--spec(value/2 :: (binary(), binary()) -> term()).
--spec(value/3 :: (binary(), binary(), term()) -> term()).
+-spec(list/1 :: (rabbit_types:vhost() | '_') -> [rabbit_types:infos()]).
+-spec(list_component/1 :: (binary()) -> [rabbit_types:infos()]).
+-spec(list/2 :: (rabbit_types:vhost() | '_', binary() | '_')
+ -> [rabbit_types:infos()]).
+-spec(list_formatted/1 :: (rabbit_types:vhost()) -> [rabbit_types:infos()]).
+-spec(lookup/3 :: (rabbit_types:vhost(), binary(), binary())
+ -> rabbit_types:infos() | 'not_found').
+-spec(value/3 :: (rabbit_types:vhost(), binary(), binary()) -> term()).
+-spec(value/4 :: (rabbit_types:vhost(), binary(), binary(), term()) -> term()).
-spec(info_keys/0 :: () -> rabbit_types:info_keys()).
-endif.
@@ -48,36 +60,39 @@
%%---------------------------------------------------------------------------
-parse_set(Component, Key, String) ->
- case parse(String) of
- {ok, Term} -> set(Component, Key, Term);
- {errors, L} -> format_error(L)
+parse_set(_, <<"policy">>, _, _) ->
+ {error_string, "policies may not be set using this method"};
+parse_set(VHost, Component, Name, String) ->
+ case rabbit_misc:json_decode(String) of
+ {ok, JSON} -> set(VHost, Component, Name,
+ rabbit_misc:json_to_term(JSON));
+ error -> {error_string, "JSON decoding error"}
end.
-set(Component, Key, Term) ->
- case set0(Component, Key, Term) of
- ok -> ok;
- {errors, L} -> format_error(L)
- end.
+set(_, <<"policy">>, _, _) ->
+ {error_string, "policies may not be set using this method"};
+set(VHost, Component, Name, Term) ->
+ set_any(VHost, Component, Name, Term).
format_error(L) ->
{error_string, rabbit_misc:format_many([{"Validation failed~n", []} | L])}.
-set0(Component, Key, Term) ->
+set_any(VHost, Component, Name, Term) ->
+ case set_any0(VHost, Component, Name, Term) of
+ ok -> ok;
+ {errors, L} -> format_error(L)
+ end.
+
+set_any0(VHost, Component, Name, Term) ->
case lookup_component(Component) of
{ok, Mod} ->
- case flatten_errors(validate(Term)) of
+ case flatten_errors(Mod:validate(VHost, Component, Name, Term)) of
ok ->
- case flatten_errors(Mod:validate(Component, Key, Term)) of
- ok ->
- case mnesia_update(Component, Key, Term) of
- {old, Term} -> ok;
- _ -> Mod:notify(Component, Key, Term)
- end,
- ok;
- E ->
- E
- end;
+ case mnesia_update(VHost, Component, Name, Term) of
+ {old, Term} -> ok;
+ _ -> Mod:notify(VHost, Component, Name, Term)
+ end,
+ ok;
E ->
E
end;
@@ -85,96 +100,105 @@ set0(Component, Key, Term) ->
E
end.
-mnesia_update(Component, Key, Term) ->
- rabbit_misc:execute_mnesia_transaction(
- fun () ->
- Res = case mnesia:read(?TABLE, {Component, Key}, read) of
- [] -> new;
- [Params] -> {old, Params#runtime_parameters.value}
- end,
- ok = mnesia:write(?TABLE, c(Component, Key, Term), write),
- Res
- end).
-
-clear(Component, Key) ->
- case clear0(Component, Key) of
- ok -> ok;
- {errors, L} -> format_error(L)
+mnesia_update(VHost, Comp, Name, Term) ->
+ F = fun () ->
+ Res = case mnesia:read(?TABLE, {VHost, Comp, Name}, read) of
+ [] -> new;
+ [Params] -> {old, Params#runtime_parameters.value}
+ end,
+ ok = mnesia:write(?TABLE, c(VHost, Comp, Name, Term), write),
+ Res
+ end,
+ rabbit_misc:execute_mnesia_transaction(rabbit_vhost:with(VHost, F)).
+
+clear(_, <<"policy">> , _) ->
+ {error_string, "policies may not be cleared using this method"};
+clear(VHost, Component, Name) ->
+ clear_any(VHost, Component, Name).
+
+clear_any(VHost, Component, Name) ->
+ case lookup(VHost, Component, Name) of
+ not_found -> {error_string, "Parameter does not exist"};
+ _ -> mnesia_clear(VHost, Component, Name),
+ case lookup_component(Component) of
+ {ok, Mod} -> Mod:notify_clear(VHost, Component, Name);
+ _ -> ok
+ end
end.
-clear0(Component, Key) ->
- case lookup_component(Component) of
- {ok, Mod} -> case flatten_errors(Mod:validate_clear(Component, Key)) of
- ok -> mnesia_clear(Component, Key),
- Mod:notify_clear(Component, Key),
- ok;
- E -> E
- end;
- E -> E
- end.
-
-mnesia_clear(Component, Key) ->
- ok = rabbit_misc:execute_mnesia_transaction(
- fun () ->
- ok = mnesia:delete(?TABLE, {Component, Key}, write)
- end).
+mnesia_clear(VHost, Component, Name) ->
+ F = fun () ->
+ ok = mnesia:delete(?TABLE, {VHost, Component, Name}, write)
+ end,
+ ok = rabbit_misc:execute_mnesia_transaction(rabbit_vhost:with(VHost, F)).
list() ->
- [p(P) || P <- rabbit_misc:dirty_read_all(?TABLE)].
-
-list(Component) ->
- case lookup_component(Component) of
- {ok, _} -> Match = #runtime_parameters{key = {Component, '_'}, _ = '_'},
- [p(P) || P <- mnesia:dirty_match_object(?TABLE, Match)];
- _ -> not_found
- end.
-
-list_formatted() ->
- [pset(value, format(pget(value, P)), P) || P <- list()].
-
-lookup(Component, Key) ->
- case lookup0(Component, Key, rabbit_misc:const(not_found)) of
+ [p(P) || #runtime_parameters{ key = {_VHost, Comp, _Name}} = P <-
+ rabbit_misc:dirty_read_all(?TABLE), Comp /= <<"policy">>].
+
+list(VHost) -> list(VHost, '_').
+list_component(Component) -> list('_', Component).
+
+list(VHost, Component) ->
+ case VHost of
+ '_' -> ok;
+ _ -> rabbit_vhost:assert(VHost)
+ end,
+ Match = #runtime_parameters{key = {VHost, Component, '_'}, _ = '_'},
+ [p(P) || #runtime_parameters{key = {_VHost, Comp, _Name}} = P <-
+ mnesia:dirty_match_object(?TABLE, Match),
+ Comp =/= <<"policy">> orelse Component =:= <<"policy">>].
+
+list_formatted(VHost) ->
+ [pset(value, format(pget(value, P)), P) || P <- list(VHost)].
+
+lookup(VHost, Component, Name) ->
+ case lookup0(VHost, Component, Name, rabbit_misc:const(not_found)) of
not_found -> not_found;
Params -> p(Params)
end.
-value(Component, Key) ->
- case lookup0(Component, Key, rabbit_misc:const(not_found)) of
+value(VHost, Component, Name) ->
+ case lookup0(VHost, Component, Name, rabbit_misc:const(not_found)) of
not_found -> not_found;
Params -> Params#runtime_parameters.value
end.
-value(Component, Key, Default) ->
- Params = lookup0(Component, Key,
- fun () -> lookup_missing(Component, Key, Default) end),
+value(VHost, Component, Name, Default) ->
+ Params = lookup0(VHost, Component, Name,
+ fun () ->
+ lookup_missing(VHost, Component, Name, Default)
+ end),
Params#runtime_parameters.value.
-lookup0(Component, Key, DefaultFun) ->
- case mnesia:dirty_read(?TABLE, {Component, Key}) of
+lookup0(VHost, Component, Name, DefaultFun) ->
+ case mnesia:dirty_read(?TABLE, {VHost, Component, Name}) of
[] -> DefaultFun();
[R] -> R
end.
-lookup_missing(Component, Key, Default) ->
+lookup_missing(VHost, Component, Name, Default) ->
rabbit_misc:execute_mnesia_transaction(
fun () ->
- case mnesia:read(?TABLE, {Component, Key}, read) of
- [] -> Record = c(Component, Key, Default),
+ case mnesia:read(?TABLE, {VHost, Component, Name}, read) of
+ [] -> Record = c(VHost, Component, Name, Default),
mnesia:write(?TABLE, Record, write),
Record;
[R] -> R
end
end).
-c(Component, Key, Default) -> #runtime_parameters{key = {Component, Key},
- value = Default}.
+c(VHost, Component, Name, Default) ->
+ #runtime_parameters{key = {VHost, Component, Name},
+ value = Default}.
-p(#runtime_parameters{key = {Component, Key}, value = Value}) ->
- [{component, Component},
- {key, Key},
+p(#runtime_parameters{key = {VHost, Component, Name}, value = Value}) ->
+ [{vhost, VHost},
+ {component, Component},
+ {name, Name},
{value, Value}].
-info_keys() -> [component, key, value].
+info_keys() -> [component, name, value].
%%---------------------------------------------------------------------------
@@ -186,51 +210,9 @@ lookup_component(Component) ->
{ok, Module} -> {ok, Module}
end.
-parse(Src0) ->
- Src1 = string:strip(Src0),
- Src = case lists:reverse(Src1) of
- [$. |_] -> Src1;
- _ -> Src1 ++ "."
- end,
- case erl_scan:string(Src) of
- {ok, Scanned, _} ->
- case erl_parse:parse_term(Scanned) of
- {ok, Parsed} ->
- {ok, Parsed};
- {error, E} ->
- {errors,
- [{"Could not parse value: ~s", [format_parse_error(E)]}]}
- end;
- {error, E, _} ->
- {errors, [{"Could not scan value: ~s", [format_parse_error(E)]}]}
- end.
-
-format_parse_error({_Line, Mod, Err}) ->
- lists:flatten(Mod:format_error(Err)).
-
format(Term) ->
- list_to_binary(rabbit_misc:format("~p", [Term])).
-
-%%---------------------------------------------------------------------------
-
-%% We will want to be able to biject these to JSON. So we have some
-%% generic restrictions on what we consider acceptable.
-validate(Proplist = [T | _]) when is_tuple(T) -> validate_proplist(Proplist);
-validate(L) when is_list(L) -> validate_list(L);
-validate(T) when is_tuple(T) -> {error, "tuple: ~p", [T]};
-validate(B) when is_boolean(B) -> ok;
-validate(null) -> ok;
-validate(A) when is_atom(A) -> {error, "atom: ~p", [A]};
-validate(N) when is_number(N) -> ok;
-validate(B) when is_binary(B) -> ok;
-validate(B) when is_bitstring(B) -> {error, "bitstring: ~p", [B]}.
-
-validate_list(L) -> [validate(I) || I <- L].
-validate_proplist(L) -> [vp(I) || I <- L].
-
-vp({K, V}) when is_binary(K) -> validate(V);
-vp({K, _V}) -> {error, "bad key: ~p", [K]};
-vp(H) -> {error, "not two tuple: ~p", [H]}.
+ {ok, JSON} = rabbit_misc:json_encode(rabbit_misc:term_to_json(Term)),
+ list_to_binary(JSON).
flatten_errors(L) ->
case [{F, A} || I <- lists:flatten([L]), {error, F, A} <- [I]] of