summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2012-04-02 15:22:40 +0100
committerSimon MacMullen <simon@rabbitmq.com>2012-04-02 15:22:40 +0100
commit2c6b877bdb35b5928c512196762de4ef15a1e8a5 (patch)
treeb1e36e56769ac383721b071f5881260cf714ca11 /src
parentb46957894bcdcebab47f45ed4ddc8d6faa08f948 (diff)
parentc167d35820b2b74c3f587b7b215f016e69919891 (diff)
downloadrabbitmq-server-2c6b877bdb35b5928c512196762de4ef15a1e8a5.tar.gz
Merge in default
Diffstat (limited to 'src')
-rw-r--r--src/rabbit_control.erl18
-rw-r--r--src/rabbit_misc.erl5
-rw-r--r--src/rabbit_mnesia.erl5
-rw-r--r--src/rabbit_registry.erl5
-rw-r--r--src/rabbit_runtime_parameter.erl28
-rw-r--r--src/rabbit_runtime_parameters.erl153
-rw-r--r--src/rabbit_upgrade_functions.erl8
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) ->