diff options
author | Simon MacMullen <simon@rabbitmq.com> | 2013-08-19 17:14:13 +0100 |
---|---|---|
committer | Simon MacMullen <simon@rabbitmq.com> | 2013-08-19 17:14:13 +0100 |
commit | 11049881a87eb51e9bf6efbb4d2ef1ee4be62bfe (patch) | |
tree | 2a3f21103e1d6050802ed32714d1e62763aeb0a5 /src/rabbit_runtime_parameters.erl | |
parent | bd1305279e255adcf583afdd55a7cee18a9fcddb (diff) | |
parent | af4ef7640e817141615298c504e9129d14be1d9d (diff) | |
download | rabbitmq-server-bug24969.tar.gz |
Merge defaultbug24969
Diffstat (limited to 'src/rabbit_runtime_parameters.erl')
-rw-r--r-- | src/rabbit_runtime_parameters.erl | 258 |
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 |