diff options
author | Simon MacMullen <simon@rabbitmq.com> | 2012-04-02 15:22:40 +0100 |
---|---|---|
committer | Simon MacMullen <simon@rabbitmq.com> | 2012-04-02 15:22:40 +0100 |
commit | 2c6b877bdb35b5928c512196762de4ef15a1e8a5 (patch) | |
tree | b1e36e56769ac383721b071f5881260cf714ca11 /src | |
parent | b46957894bcdcebab47f45ed4ddc8d6faa08f948 (diff) | |
parent | c167d35820b2b74c3f587b7b215f016e69919891 (diff) | |
download | rabbitmq-server-2c6b877bdb35b5928c512196762de4ef15a1e8a5.tar.gz |
Merge in default
Diffstat (limited to 'src')
-rw-r--r-- | src/rabbit_control.erl | 18 | ||||
-rw-r--r-- | src/rabbit_misc.erl | 5 | ||||
-rw-r--r-- | src/rabbit_mnesia.erl | 5 | ||||
-rw-r--r-- | src/rabbit_registry.erl | 5 | ||||
-rw-r--r-- | src/rabbit_runtime_parameter.erl | 28 | ||||
-rw-r--r-- | src/rabbit_runtime_parameters.erl | 153 | ||||
-rw-r--r-- | src/rabbit_upgrade_functions.erl | 8 |
7 files changed, 219 insertions, 3 deletions
diff --git a/src/rabbit_control.erl b/src/rabbit_control.erl index 51f88c8f..6cf35dd3 100644 --- a/src/rabbit_control.erl +++ b/src/rabbit_control.erl @@ -267,6 +267,24 @@ action(list_user_permissions, Node, Args = [_Username], _Opts, Inform) -> list_user_permissions, Args}), rabbit_auth_backend_internal:user_perms_info_keys()); +action(set_parameter, Node, [AppName, Key, Value], _Opts, Inform) -> + Inform("Setting runtime parameter ~p for app ~p to ~p", + [Key, AppName, Value]), + rpc_call(Node, rabbit_runtime_parameters, set, + [list_to_binary(AppName), list_to_binary(Key), + rabbit_runtime_parameters:parse(Value)]); + +action(clear_parameter, Node, [AppName, Key], _Opts, Inform) -> + Inform("Clearing runtime parameter ~p for app ~p", [Key, AppName]), + rpc_call(Node, rabbit_runtime_parameters, clear, [list_to_binary(AppName), + list_to_binary(Key)]); + +action(list_parameters, Node, Args = [], _Opts, Inform) -> + Inform("Listing runtime parameters", []), + display_info_list( + rpc_call(Node, rabbit_runtime_parameters, list_formatted, Args), + rabbit_runtime_parameters:info_keys()); + action(list_queues, Node, Args, Opts, Inform) -> Inform("Listing queues", []), VHostArg = list_to_binary(proplists:get_value(?VHOST_OPT, Opts)), diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index c1be7613..3b7e0b41 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -54,7 +54,7 @@ -export([const_ok/0, const/1]). -export([ntoa/1, ntoab/1]). -export([is_process_alive/1]). --export([pget/2, pget/3, pget_or_die/2]). +-export([pget/2, pget/3, pget_or_die/2, pset/3]). -export([format_message_queue/2]). -export([append_rpc_all_nodes/4]). -export([multi_call/2]). @@ -198,6 +198,7 @@ -spec(pget/2 :: (term(), [term()]) -> term()). -spec(pget/3 :: (term(), [term()], term()) -> term()). -spec(pget_or_die/2 :: (term(), [term()]) -> term() | no_return()). +-spec(pset/3 :: (term(), term(), [term()]) -> term()). -spec(format_message_queue/2 :: (any(), priority_queue:q()) -> term()). -spec(append_rpc_all_nodes/4 :: ([node()], atom(), atom(), [any()]) -> [any()]). -spec(multi_call/2 :: @@ -846,6 +847,8 @@ pget_or_die(K, P) -> V -> V end. +pset(Key, Value, List) -> [{Key, Value} | proplists:delete(Key, List)]. + format_message_queue(_Opt, MQ) -> Len = priority_queue:len(MQ), {Len, diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl index c714d3a7..7e9346f9 100644 --- a/src/rabbit_mnesia.erl +++ b/src/rabbit_mnesia.erl @@ -296,6 +296,11 @@ table_definitions() -> [{record_name, exchange_serial}, {attributes, record_info(fields, exchange_serial)}, {match, #exchange_serial{name = exchange_name_match(), _='_'}}]}, + {rabbit_runtime_parameters, + [{record_name, runtime_parameters}, + {attributes, record_info(fields, runtime_parameters)}, + {disc_copies, [node()]}, + {match, #runtime_parameters{_='_'}}]}, {rabbit_durable_queue, [{record_name, amqqueue}, {attributes, record_info(fields, amqqueue)}, diff --git a/src/rabbit_registry.erl b/src/rabbit_registry.erl index 8c0ebcbe..46c93503 100644 --- a/src/rabbit_registry.erl +++ b/src/rabbit_registry.erl @@ -95,8 +95,9 @@ sanity_check_module(ClassModule, Module) -> true -> ok end. -class_module(exchange) -> rabbit_exchange_type; -class_module(auth_mechanism) -> rabbit_auth_mechanism. +class_module(exchange) -> rabbit_exchange_type; +class_module(auth_mechanism) -> rabbit_auth_mechanism; +class_module(runtime_parameter) -> rabbit_runtime_parameter. %%--------------------------------------------------------------------------- diff --git a/src/rabbit_runtime_parameter.erl b/src/rabbit_runtime_parameter.erl new file mode 100644 index 00000000..51a00db7 --- /dev/null +++ b/src/rabbit_runtime_parameter.erl @@ -0,0 +1,28 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (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.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(rabbit_runtime_parameter). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + [ + {validate, 3}, + {notify, 3}, + {notify_clear, 2} + ]; +behaviour_info(_Other) -> + undefined. diff --git a/src/rabbit_runtime_parameters.erl b/src/rabbit_runtime_parameters.erl new file mode 100644 index 00000000..81c0cb64 --- /dev/null +++ b/src/rabbit_runtime_parameters.erl @@ -0,0 +1,153 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (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.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(rabbit_runtime_parameters). + +-include("rabbit.hrl"). + +-export([parse/1, set/3, clear/2, list/0, list/1, list_formatted/0, lookup/2, + value/2, value/3, info_keys/0]). + +-import(rabbit_misc, [pget/2, pset/3]). + +-define(TABLE, rabbit_runtime_parameters). + +%%--------------------------------------------------------------------------- + +set(AppName, Key, Term) -> + Module = lookup_app(AppName), + validate(Term), + Module:validate(AppName, Key, Term), + ok = rabbit_misc:execute_mnesia_transaction( + fun () -> + ok = mnesia:write(?TABLE, c(AppName, Key, Term), write) + end), + Module:notify(AppName, Key, Term), + ok. + +clear(AppName, Key) -> + Module = lookup_app(AppName), + ok = rabbit_misc:execute_mnesia_transaction( + fun () -> + ok = mnesia:delete(?TABLE, {AppName, Key}, write) + end), + Module:notify_clear(AppName, Key), + ok. + +list() -> + [p(P) || P <- rabbit_misc:dirty_read_all(?TABLE)]. + +list(Name) -> + [p(P) || P <- mnesia:dirty_match_object( + ?TABLE, #runtime_parameters{key = {Name, '_'}, _ = '_'})]. + +list_formatted() -> + [pset(value, format(pget(value, P)), P) || P <- list()]. + +lookup(AppName, Key) -> + case lookup0(AppName, Key, rabbit_misc:const(not_found)) of + not_found -> not_found; + Params -> p(Params) + end. + +value(AppName, Key) -> + case lookup0(AppName, Key, rabbit_misc:const(not_found)) of + not_found -> not_found; + Params -> Params#runtime_parameters.value + end. + +value(AppName, Key, Default) -> + Params = lookup0(AppName, Key, + fun () -> lookup_missing(AppName, Key, Default) end), + Params#runtime_parameters.value. + +lookup0(AppName, Key, DefaultFun) -> + case mnesia:dirty_read(?TABLE, {AppName, Key}) of + [] -> DefaultFun(); + [R] -> R + end. + +lookup_missing(AppName, Key, Default) -> + rabbit_misc:execute_mnesia_transaction( + fun () -> + case mnesia:read(?TABLE, {AppName, Key}) of + [] -> mnesia:write(?TABLE, c(AppName, Key, Default), write), + Default; + [R] -> R + end + end). + +c(AppName, Key, Default) -> #runtime_parameters{key = {AppName, Key}, + value = Default}. + +p(#runtime_parameters{key = {AppName, Key}, value = Value}) -> + [{app_name, AppName}, + {key, Key}, + {value, Value}]. + +info_keys() -> [app_name, key, value]. + +%%--------------------------------------------------------------------------- + +lookup_app(App) -> + case rabbit_registry:lookup_module( + runtime_parameter, list_to_atom(binary_to_list(App))) of + {error, not_found} -> exit({application_not_found, App}); + {ok, Module} -> Module + end. + +parse(Src0) -> + Src = case lists:reverse(Src0) of + [$. |_] -> Src0; + _ -> Src0 ++ "." + end, + case erl_scan:string(Src) of + {ok, Scanned, _} -> + case erl_parse:parse_term(Scanned) of + {ok, Parsed} -> + Parsed; + {error, E} -> + exit({could_not_parse_value, format_parse_error(E)}) + end; + {error, E, _} -> + exit({could_not_scan_value, 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(I) || I <- L]; +validate(T) when is_tuple(T) -> exit({tuple, T}); +validate(true) -> ok; +validate(false) -> ok; +validate(null) -> ok; +validate(A) when is_atom(A) -> exit({non_bool_atom, A}); +validate(N) when is_number(N) -> ok; +validate(B) when is_binary(B) -> ok. + +validate_proplist([]) -> ok; +validate_proplist([{K, V} | Rest]) when is_binary(K) -> validate(V), + validate_proplist(Rest); +validate_proplist([{K, _V} | _Rest]) -> exit({bad_key, K}); +validate_proplist([H | _Rest]) -> exit({not_two_tuple,H}). diff --git a/src/rabbit_upgrade_functions.erl b/src/rabbit_upgrade_functions.erl index 9f2535bd..485ccc5f 100644 --- a/src/rabbit_upgrade_functions.erl +++ b/src/rabbit_upgrade_functions.erl @@ -36,6 +36,7 @@ -rabbit_upgrade({exchange_scratch, mnesia, [trace_exchanges]}). -rabbit_upgrade({mirrored_supervisor, mnesia, []}). -rabbit_upgrade({topic_trie_node, mnesia, []}). +-rabbit_upgrade({runtime_parameters, mnesia, []}). %% ------------------------------------------------------------------- @@ -56,6 +57,7 @@ -spec(exchange_scratch/0 :: () -> 'ok'). -spec(mirrored_supervisor/0 :: () -> 'ok'). -spec(topic_trie_node/0 :: () -> 'ok'). +-spec(runtime_parameters/0 :: () -> 'ok'). -endif. @@ -185,6 +187,12 @@ topic_trie_node() -> {attributes, [trie_node, edge_count, binding_count]}, {type, ordered_set}]). +runtime_parameters() -> + create(rabbit_runtime_parameters, + [{record_name, runtime_parameters}, + {attributes, [key, value]}, + {disc_copies, [node()]}]). + %%-------------------------------------------------------------------- transform(TableName, Fun, FieldList) -> |