diff options
author | Emile Joubert <emile@rabbitmq.com> | 2010-06-11 12:42:28 +0100 |
---|---|---|
committer | Emile Joubert <emile@rabbitmq.com> | 2010-06-11 12:42:28 +0100 |
commit | 10843dcf5a3c0506e89b916b5c29812d66ed923d (patch) | |
tree | f33367e462e094e8a5511451b315bdbb67904fd5 | |
parent | 4babcc4ee3f168071f6ad1ff3024a01e3ff9eba6 (diff) | |
parent | bd2423da0244f0be90bdd0bce5464edd138ad12c (diff) | |
download | rabbitmq-server-10843dcf5a3c0506e89b916b5c29812d66ed923d.tar.gz |
Merged bug21846 into default
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | include/rabbit_exchange_type_spec.hrl | 1 | ||||
-rwxr-xr-x | packaging/common/rabbitmq-server.ocf | 172 | ||||
-rwxr-xr-x | scripts/rabbitmq-multi | 3 | ||||
-rw-r--r-- | scripts/rabbitmq-multi.bat | 6 | ||||
-rwxr-xr-x | scripts/rabbitmq-server | 3 | ||||
-rw-r--r-- | scripts/rabbitmq-server.bat | 6 | ||||
-rw-r--r-- | scripts/rabbitmq-service.bat | 6 | ||||
-rwxr-xr-x | scripts/rabbitmqctl | 3 | ||||
-rw-r--r-- | scripts/rabbitmqctl.bat | 6 | ||||
-rw-r--r-- | src/rabbit_channel.erl | 28 | ||||
-rw-r--r-- | src/rabbit_exchange.erl | 43 | ||||
-rw-r--r-- | src/rabbit_exchange_type.erl | 6 | ||||
-rw-r--r-- | src/rabbit_exchange_type_direct.erl | 4 | ||||
-rw-r--r-- | src/rabbit_exchange_type_fanout.erl | 4 | ||||
-rw-r--r-- | src/rabbit_exchange_type_headers.erl | 4 | ||||
-rw-r--r-- | src/rabbit_exchange_type_topic.erl | 4 |
17 files changed, 204 insertions, 115 deletions
@@ -70,6 +70,12 @@ define usage_dep $(call usage_xml_to_erl, $(1)): $(1) $(DOCS_DIR)/usage.xsl endef +ifneq "$(SBIN_DIR)" "" +ifneq "$(TARGET_DIR)" "" +SCRIPTS_REL_PATH=$(shell ./calculate-relative $(TARGET_DIR)/sbin $(SBIN_DIR)) +endif +endif + all: $(TARGETS) $(DEPS_FILE): $(SOURCES) $(INCLUDES) @@ -234,13 +240,7 @@ $(SOURCE_DIR)/%_usage.erl: docs_all: $(MANPAGES) $(WEB_MANPAGES) -install: SCRIPTS_REL_PATH=$(shell ./calculate-relative $(TARGET_DIR)/sbin $(SBIN_DIR)) install: all docs_all install_dirs - @[ -n "$(TARGET_DIR)" ] || (echo "Please set TARGET_DIR."; false) - @[ -n "$(SBIN_DIR)" ] || (echo "Please set SBIN_DIR."; false) - @[ -n "$(MAN_DIR)" ] || (echo "Please set MAN_DIR."; false) - - mkdir -p $(TARGET_DIR) cp -r ebin include LICENSE LICENSE-MPL-RabbitMQ INSTALL $(TARGET_DIR) chmod 0755 scripts/* @@ -256,8 +256,14 @@ install: all docs_all install_dirs done install_dirs: - mkdir -p $(SBIN_DIR) + @ OK=true && \ + { [ -n "$(TARGET_DIR)" ] || { echo "Please set TARGET_DIR."; OK=false; }; } && \ + { [ -n "$(SBIN_DIR)" ] || { echo "Please set SBIN_DIR."; OK=false; }; } && \ + { [ -n "$(MAN_DIR)" ] || { echo "Please set MAN_DIR."; OK=false; }; } && $$OK + mkdir -p $(TARGET_DIR)/sbin + mkdir -p $(SBIN_DIR) + mkdir -p $(MAN_DIR) $(foreach XML, $(USAGES_XML), $(eval $(call usage_dep, $(XML)))) diff --git a/include/rabbit_exchange_type_spec.hrl b/include/rabbit_exchange_type_spec.hrl index 38057beb..cb564365 100644 --- a/include/rabbit_exchange_type_spec.hrl +++ b/include/rabbit_exchange_type_spec.hrl @@ -38,5 +38,6 @@ -spec(delete/2 :: (exchange(), list(binding())) -> 'ok'). -spec(add_binding/2 :: (exchange(), binding()) -> 'ok'). -spec(remove_bindings/2 :: (exchange(), list(binding())) -> 'ok'). +-spec(assert_args_equivalence/2 :: (exchange(), amqp_table()) -> 'ok'). -endif. diff --git a/packaging/common/rabbitmq-server.ocf b/packaging/common/rabbitmq-server.ocf index 97c58ea2..db0ed70b 100755 --- a/packaging/common/rabbitmq-server.ocf +++ b/packaging/common/rabbitmq-server.ocf @@ -35,21 +35,22 @@ ## ## OCF instance parameters -## OCF_RESKEY_multi -## OCF_RESKEY_ctl -## OCF_RESKEY_nodename -## OCF_RESKEY_ip -## OCF_RESKEY_port -## OCF_RESKEY_cluster_config_file -## OCF_RESKEY_config_file -## OCF_RESKEY_log_base -## OCF_RESKEY_mnesia_base -## OCF_RESKEY_server_start_args +## OCF_RESKEY_multi +## OCF_RESKEY_ctl +## OCF_RESKEY_nodename +## OCF_RESKEY_ip +## OCF_RESKEY_port +## OCF_RESKEY_cluster_config_file +## OCF_RESKEY_config_file +## OCF_RESKEY_log_base +## OCF_RESKEY_mnesia_base +## OCF_RESKEY_server_start_args ####################################################################### # Initialization: -. ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat} +. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs ####################################################################### @@ -63,7 +64,7 @@ OCF_RESKEY_log_base_default="/var/log/rabbitmq" : ${OCF_RESKEY_log_base=${OCF_RESKEY_log_base_default}} meta_data() { - cat <<END + cat <<END <?xml version="1.0"?> <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> <resource-agent name="rabbitmq-server"> @@ -113,7 +114,7 @@ The IP address for rabbitmq-server to listen on The IP Port for rabbitmq-server to listen on </longdesc> <shortdesc lang="en">IP Port</shortdesc> -<content type="string" default="" /> +<content type="integer" default="" /> </parameter> <parameter name="cluster_config_file" unique="0" required="0"> @@ -161,7 +162,8 @@ Additional arguments provided to the server on startup <actions> <action name="start" timeout="600" /> <action name="stop" timeout="120" /> -<action name="monitor" timeout="20" interval="10" depth="0" start-delay="0" /> +<action name="status" timeout="20" interval="10" /> +<action name="monitor" timeout="20" interval="10" /> <action name="validate-all" timeout="30" /> <action name="meta-data" timeout="5" /> </actions> @@ -170,8 +172,8 @@ END } rabbit_usage() { - cat <<END -usage: $0 {start|stop|monitor|validate-all|meta-data} + cat <<END +usage: $0 {start|stop|status|monitor|validate-all|meta-data} Expects to have a fully populated OCF RA-compliant environment set. END @@ -202,35 +204,35 @@ export_vars() { rabbit_validate_partial() { if [ ! -x $RABBITMQ_MULTI ]; then - ocf_log err "rabbitmq-server multi $RABBITMQ_MULTI does not exist or is not executable"; - return $OCF_ERR_ARGS; + ocf_log err "rabbitmq-server multi $RABBITMQ_MULTI does not exist or is not executable"; + exit $OCF_ERR_INSTALLED; fi if [ ! -x $RABBITMQ_CTL ]; then - ocf_log err "rabbitmq-server ctl $RABBITMQ_CTL does not exist or is not executable"; - return $OCF_ERR_ARGS; + ocf_log err "rabbitmq-server ctl $RABBITMQ_CTL does not exist or is not executable"; + exit $OCF_ERR_INSTALLED; fi } rabbit_validate_full() { if [ ! -z $RABBITMQ_CLUSTER_CONFIG_FILE ] && [ ! -e $RABBITMQ_CLUSTER_CONFIG_FILE ]; then - ocf_log err "rabbitmq-server cluster_config_file $RABBITMQ_CLUSTER_CONFIG_FILE does not exist or is not a file"; - return $OCF_ERR_ARGS; + ocf_log err "rabbitmq-server cluster_config_file $RABBITMQ_CLUSTER_CONFIG_FILE does not exist or is not a file"; + exit $OCF_ERR_INSTALLED; fi if [ ! -z $RABBITMQ_CONFIG_FILE ] && [ ! -e $RABBITMQ_CONFIG_FILE ]; then - ocf_log err "rabbitmq-server config_file $RABBITMQ_CONFIG_FILE does not exist or is not a file"; - return $OCF_ERR_ARGS; + ocf_log err "rabbitmq-server config_file $RABBITMQ_CONFIG_FILE does not exist or is not a file"; + exit $OCF_ERR_INSTALLED; fi if [ ! -z $RABBITMQ_LOG_BASE ] && [ ! -d $RABBITMQ_LOG_BASE ]; then - ocf_log err "rabbitmq-server log_base $RABBITMQ_LOG_BASE does not exist or is not a directory"; - return $OCF_ERR_ARGS; + ocf_log err "rabbitmq-server log_base $RABBITMQ_LOG_BASE does not exist or is not a directory"; + exit $OCF_ERR_INSTALLED; fi if [ ! -z $RABBITMQ_MNESIA_BASE ] && [ ! -d $RABBITMQ_MNESIA_BASE ]; then - ocf_log err "rabbitmq-server mnesia_base $RABBITMQ_MNESIA_BASE does not exist or is not a directory"; - return $OCF_ERR_ARGS; + ocf_log err "rabbitmq-server mnesia_base $RABBITMQ_MNESIA_BASE does not exist or is not a directory"; + exit $OCF_ERR_INSTALLED; fi rabbit_validate_partial @@ -243,25 +245,26 @@ rabbit_status() { $RABBITMQ_CTL $NODENAME_ARG status > /dev/null 2> /dev/null rc=$? case "$rc" in - 0) - return $OCF_SUCCESS - ;; - 2) - return $OCF_NOT_RUNNING - ;; - *) - ocf_log err "Unexpected return from rabbitmqctl $NODENAME_ARG status: $rc" - return $OCF_ERR_GENERIC + 0) + ocf_log debug "RabbitMQ server is running normally" + return $OCF_SUCCESS + ;; + 2) + ocf_log debug "RabbitMQ server is not running" + return $OCF_NOT_RUNNING + ;; + *) + ocf_log err "Unexpected return from rabbitmqctl $NODENAME_ARG status: $rc" + exit $OCF_ERR_GENERIC esac } rabbit_start() { local rc - rabbit_validate_full - rc=$? - if [ "$rc" != $OCF_SUCCESS ]; then - return $rc + if rabbit_status; then + ocf_log info "Resource already running." + return $OCF_SUCCESS fi export_vars @@ -270,24 +273,23 @@ rabbit_start() { rc=$? if [ "$rc" != 0 ]; then - ocf_log err "rabbitmq-server start command failed: $RABBITMQ_MULTI start_all 1, $rc" - return $rc + ocf_log err "rabbitmq-server start command failed: $RABBITMQ_MULTI start_all 1, $rc" + return $rc fi # Spin waiting for the server to come up. # Let the CRM/LRM time us out if required start_wait=1 while [ $start_wait = 1 ]; do - rabbit_status - rc=$? - if [ "$rc" = $OCF_SUCCESS ]; then - start_wait=0 - - elif [ "$rc" != $OCF_NOT_RUNNING ]; then - ocf_log info "rabbitmq-server start failed: $rc" - return $OCF_ERR_GENERIC - fi - sleep 2 + rabbit_status + rc=$? + if [ "$rc" = $OCF_SUCCESS ]; then + start_wait=0 + elif [ "$rc" != $OCF_NOT_RUNNING ]; then + ocf_log info "rabbitmq-server start failed: $rc" + exit $OCF_ERR_GENERIC + fi + sleep 1 done return $OCF_SUCCESS @@ -295,28 +297,34 @@ rabbit_start() { rabbit_stop() { local rc + + if ! rabbit_status; then + ocf_log info "Resource not running." + return $OCF_SUCCESS + fi + $RABBITMQ_MULTI stop_all & rc=$? if [ "$rc" != 0 ]; then - ocf_log err "rabbitmq-server stop command failed: $RABBITMQ_MULTI stop_all, $rc" - return $rc + ocf_log err "rabbitmq-server stop command failed: $RABBITMQ_MULTI stop_all, $rc" + return $rc fi # Spin waiting for the server to shut down. # Let the CRM/LRM time us out if required stop_wait=1 while [ $stop_wait = 1 ]; do - rabbit_status - rc=$? - if [ "$rc" = $OCF_NOT_RUNNING ]; then - stop_wait=0 + rabbit_status + rc=$? + if [ "$rc" = $OCF_NOT_RUNNING ]; then + stop_wait=0 break - elif [ "$rc" != $OCF_SUCCESS ]; then - ocf_log info "rabbitmq-server stop failed: $rc" - return $OCF_ERR_GENERIC - fi - sleep 2 + elif [ "$rc" != $OCF_SUCCESS ]; then + ocf_log info "rabbitmq-server stop failed: $rc" + exit $OCF_ERR_GENERIC + fi + sleep 1 done return $OCF_SUCCESS @@ -329,34 +337,38 @@ rabbit_monitor() { case $__OCF_ACTION in meta-data) - meta_data - exit $OCF_SUCCESS - ;; + meta_data + exit $OCF_SUCCESS + ;; usage|help) - rabbit_usage - exit $OCF_SUCCESS - ;; + rabbit_usage + exit $OCF_SUCCESS + ;; esac -rabbit_validate_partial || exit +if ocf_is_probe; then + rabbit_validate_partial +else + rabbit_validate_full +fi case $__OCF_ACTION in start) - rabbit_start + rabbit_start ;; stop) - rabbit_stop + rabbit_stop ;; - monitor) - rabbit_monitor + status|monitor) + rabbit_monitor ;; validate-all) exit $OCF_SUCCESS - ;; + ;; *) - rabbit_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; + rabbit_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac -exit $?
\ No newline at end of file +exit $? diff --git a/scripts/rabbitmq-multi b/scripts/rabbitmq-multi index 8341d35c..59050692 100755 --- a/scripts/rabbitmq-multi +++ b/scripts/rabbitmq-multi @@ -29,7 +29,8 @@ ## ## Contributor(s): ______________________________________. ## -NODENAME=rabbit +[ "x" = "x$HOSTNAME" ] && HOSTNAME=`env hostname -s` +NODENAME=rabbit@${HOSTNAME%%.*} SCRIPT_HOME=$(dirname $0) PIDS_FILE=/var/lib/rabbitmq/pids MULTI_ERL_ARGS= diff --git a/scripts/rabbitmq-multi.bat b/scripts/rabbitmq-multi.bat index a4b7f2e9..a4f8c8b4 100644 --- a/scripts/rabbitmq-multi.bat +++ b/scripts/rabbitmq-multi.bat @@ -42,8 +42,12 @@ if "!RABBITMQ_BASE!"=="" ( set RABBITMQ_BASE=!APPDATA!\RabbitMQ
)
+if "!COMPUTERNAME!"=="" (
+ set COMPUTERNAME=localhost
+)
+
if "!RABBITMQ_NODENAME!"=="" (
- set RABBITMQ_NODENAME=rabbit
+ set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME!
)
if "!RABBITMQ_NODE_IP_ADDRESS!"=="" (
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server index ccdfc401..2261b56e 100755 --- a/scripts/rabbitmq-server +++ b/scripts/rabbitmq-server @@ -30,7 +30,8 @@ ## Contributor(s): ______________________________________. ## -NODENAME=rabbit +[ "x" = "x$HOSTNAME" ] && HOSTNAME=`env hostname -s` +NODENAME=rabbit@${HOSTNAME%%.*} SERVER_ERL_ARGS="+K true +A30 +P 1048576 \ -kernel inet_default_listen_options [{nodelay,true}] \ -kernel inet_default_connect_options [{nodelay,true}]" diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat index 57fe1328..a290f935 100644 --- a/scripts/rabbitmq-server.bat +++ b/scripts/rabbitmq-server.bat @@ -42,8 +42,12 @@ if "!RABBITMQ_BASE!"=="" ( set RABBITMQ_BASE=!APPDATA!\RabbitMQ
)
+if "!COMPUTERNAME!"=="" (
+ set COMPUTERNAME=localhost
+)
+
if "!RABBITMQ_NODENAME!"=="" (
- set RABBITMQ_NODENAME=rabbit
+ set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME!
)
if "!RABBITMQ_NODE_IP_ADDRESS!"=="" (
diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat index a4021fd6..bd117b83 100644 --- a/scripts/rabbitmq-service.bat +++ b/scripts/rabbitmq-service.bat @@ -48,8 +48,12 @@ if "!RABBITMQ_BASE!"=="" ( set RABBITMQ_BASE=!APPDATA!\!RABBITMQ_SERVICENAME!
)
+if "!COMPUTERNAME!"=="" (
+ set COMPUTERNAME=localhost
+)
+
if "!RABBITMQ_NODENAME!"=="" (
- set RABBITMQ_NODENAME=rabbit
+ set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME!
)
if "!RABBITMQ_NODE_IP_ADDRESS!"=="" (
diff --git a/scripts/rabbitmqctl b/scripts/rabbitmqctl index cfb775eb..92e5312b 100755 --- a/scripts/rabbitmqctl +++ b/scripts/rabbitmqctl @@ -30,7 +30,8 @@ ## Contributor(s): ______________________________________. ## -NODENAME=rabbit +[ "x" = "x$HOSTNAME" ] && HOSTNAME=`env hostname -s` +NODENAME=rabbit@${HOSTNAME%%.*} . `dirname $0`/rabbitmq-env diff --git a/scripts/rabbitmqctl.bat b/scripts/rabbitmqctl.bat index 55572451..563b9e58 100644 --- a/scripts/rabbitmqctl.bat +++ b/scripts/rabbitmqctl.bat @@ -38,8 +38,12 @@ set TDP0=%~dp0 set STAR=%*
setlocal enabledelayedexpansion
+if "!COMPUTERNAME!"=="" (
+ set COMPUTERNAME=localhost
+)
+
if "!RABBITMQ_NODENAME!"=="" (
- set RABBITMQ_NODENAME=rabbit
+ set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME!
)
if not exist "!ERLANG_HOME!\bin\erl.exe" (
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl index d6544b96..2ebb8f88 100644 --- a/src/rabbit_channel.erl +++ b/src/rabbit_channel.erl @@ -681,18 +681,17 @@ handle_method(#'exchange.declare'{exchange = ExchangeNameBin, AutoDelete, Args) end, - ok = rabbit_exchange:assert_type(X, CheckedType), + ok = rabbit_exchange:assert_equivalence(X, CheckedType, Durable, + AutoDelete, Args), return_ok(State, NoWait, #'exchange.declare_ok'{}); handle_method(#'exchange.declare'{exchange = ExchangeNameBin, - type = TypeNameBin, passive = true, nowait = NoWait}, _, State = #ch{ virtual_host = VHostPath }) -> ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), check_configure_permitted(ExchangeName, State), - X = rabbit_exchange:lookup_or_die(ExchangeName), - ok = rabbit_exchange:assert_type(X, rabbit_exchange:check_type(TypeNameBin)), + _ = rabbit_exchange:lookup_or_die(ExchangeName), return_ok(State, NoWait, #'exchange.declare_ok'{}); handle_method(#'exchange.delete'{exchange = ExchangeNameBin, @@ -727,14 +726,27 @@ handle_method(#'queue.declare'{queue = QueueNameBin, end, %% We use this in both branches, because queue_declare may yet return an %% existing queue. - Finish = fun (#amqqueue{name = QueueName} = Q) -> + Finish = fun (#amqqueue{name = QueueName, + durable = Durable1, + auto_delete = AutoDelete1} = Q) + when Durable =:= Durable1, AutoDelete =:= AutoDelete1 -> check_exclusive_access(Q, Owner, strict), check_configure_permitted(QueueName, State), + %% We need to notify the reader within the channel + %% process so that we can be sure there are no + %% outstanding exclusive queues being declared as the + %% connection shuts down. case Owner of none -> ok; _ -> ok = rabbit_reader_queue_collector:register_exclusive_queue(CollectorPid, Q) end, - Q + Q; + %% non-equivalence trumps exclusivity arbitrarily + (#amqqueue{name = QueueName}) -> + rabbit_misc:protocol_error( + precondition_failed, + "parameters for ~s not equivalent", + [rabbit_misc:rs(QueueName)]) end, Q = case rabbit_amqqueue:with( rabbit_misc:r(VHostPath, queue, QueueNameBin), @@ -820,14 +832,14 @@ handle_method(#'tx.select'{}, _, State) -> handle_method(#'tx.commit'{}, _, #ch{transaction_id = none}) -> rabbit_misc:protocol_error( - not_allowed, "channel is not transactional", []); + precondition_failed, "channel is not transactional", []); handle_method(#'tx.commit'{}, _, State) -> {reply, #'tx.commit_ok'{}, internal_commit(State)}; handle_method(#'tx.rollback'{}, _, #ch{transaction_id = none}) -> rabbit_misc:protocol_error( - not_allowed, "channel is not transactional", []); + precondition_failed, "channel is not transactional", []); handle_method(#'tx.rollback'{}, _, State) -> {reply, #'tx.rollback_ok'{}, internal_rollback(State)}; diff --git a/src/rabbit_exchange.erl b/src/rabbit_exchange.erl index 99799f7a..c5149b08 100644 --- a/src/rabbit_exchange.erl +++ b/src/rabbit_exchange.erl @@ -39,7 +39,9 @@ -export([add_binding/5, delete_binding/5, list_bindings/1]). -export([delete/2]). -export([delete_queue_bindings/1, delete_transient_queue_bindings/1]). --export([check_type/1, assert_type/2]). +-export([assert_equivalence/5]). +-export([assert_args_equivalence/2]). +-export([check_type/1]). %% EXTENDED API -export([list_exchange_bindings/1]). @@ -64,7 +66,9 @@ -spec(declare/5 :: (exchange_name(), exchange_type(), boolean(), boolean(), amqp_table()) -> exchange()). -spec(check_type/1 :: (binary()) -> atom()). --spec(assert_type/2 :: (exchange(), atom()) -> 'ok'). +-spec(assert_equivalence/5 :: (exchange(), atom(), boolean(), boolean(), + amqp_table()) -> 'ok'). +-spec(assert_args_equivalence/2 :: (exchange(), amqp_table()) -> 'ok'). -spec(lookup/1 :: (exchange_name()) -> {'ok', exchange()} | not_found()). -spec(lookup_or_die/1 :: (exchange_name()) -> exchange()). -spec(list/1 :: (vhost()) -> [exchange()]). @@ -185,13 +189,36 @@ check_type(TypeBin) -> T end. -assert_type(#exchange{ type = ActualType }, RequiredType) - when ActualType == RequiredType -> - ok; -assert_type(#exchange{ name = Name, type = ActualType }, RequiredType) -> +assert_equivalence(X = #exchange{ durable = Durable, + auto_delete = AutoDelete, + type = Type}, + Type, Durable, AutoDelete, + RequiredArgs) -> + ok = (type_to_module(Type)):assert_args_equivalence(X, RequiredArgs); +assert_equivalence(#exchange{ name = Name }, _Type, _Durable, _AutoDelete, + _Args) -> rabbit_misc:protocol_error( - not_allowed, "cannot redeclare ~s of type '~s' with type '~s'", - [rabbit_misc:rs(Name), ActualType, RequiredType]). + precondition_failed, + "cannot redeclare ~s with different type, durable or autodelete value", + [rabbit_misc:rs(Name)]). + +alternate_exchange_value(Args) -> + lists:keysearch(<<"alternate-exchange">>, 1, Args). + +assert_args_equivalence(#exchange{ name = Name, + arguments = Args }, + RequiredArgs) -> + %% The spec says "Arguments are compared for semantic + %% equivalence". The only arg we care about is + %% "alternate-exchange". + Ae1 = alternate_exchange_value(RequiredArgs), + Ae2 = alternate_exchange_value(Args), + if Ae1==Ae2 -> ok; + true -> rabbit_misc:protocol_error( + precondition_failed, + "cannot redeclare ~s with inequivalent args", + [rabbit_misc:rs(Name)]) + end. lookup(Name) -> rabbit_misc:dirty_read({rabbit_exchange, Name}). diff --git a/src/rabbit_exchange_type.erl b/src/rabbit_exchange_type.erl index 699250f7..85760edc 100644 --- a/src/rabbit_exchange_type.erl +++ b/src/rabbit_exchange_type.erl @@ -54,7 +54,11 @@ behaviour_info(callbacks) -> {add_binding, 2}, %% called after bindings have been deleted. - {remove_bindings, 2} + {remove_bindings, 2}, + + %% called when comparing exchanges for equivalence - should return ok or + %% exit with #amqp_error{} + {assert_args_equivalence, 2} ]; behaviour_info(_Other) -> diff --git a/src/rabbit_exchange_type_direct.erl b/src/rabbit_exchange_type_direct.erl index c3fb2588..4f6eb851 100644 --- a/src/rabbit_exchange_type_direct.erl +++ b/src/rabbit_exchange_type_direct.erl @@ -36,7 +36,7 @@ -export([description/0, publish/2]). -export([validate/1, create/1, recover/2, delete/2, - add_binding/2, remove_bindings/2]). + add_binding/2, remove_bindings/2, assert_args_equivalence/2]). -include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, @@ -61,3 +61,5 @@ recover(_X, _Bs) -> ok. delete(_X, _Bs) -> ok. add_binding(_X, _B) -> ok. remove_bindings(_X, _Bs) -> ok. +assert_args_equivalence(X, Args) -> + rabbit_exchange:assert_args_equivalence(X, Args). diff --git a/src/rabbit_exchange_type_fanout.erl b/src/rabbit_exchange_type_fanout.erl index 62c862a5..4f9712b1 100644 --- a/src/rabbit_exchange_type_fanout.erl +++ b/src/rabbit_exchange_type_fanout.erl @@ -36,7 +36,7 @@ -export([description/0, publish/2]). -export([validate/1, create/1, recover/2, delete/2, - add_binding/2, remove_bindings/2]). + add_binding/2, remove_bindings/2, assert_args_equivalence/2]). -include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, @@ -59,3 +59,5 @@ recover(_X, _Bs) -> ok. delete(_X, _Bs) -> ok. add_binding(_X, _B) -> ok. remove_bindings(_X, _Bs) -> ok. +assert_args_equivalence(X, Args) -> + rabbit_exchange:assert_args_equivalence(X, Args). diff --git a/src/rabbit_exchange_type_headers.erl b/src/rabbit_exchange_type_headers.erl index 0991bf0d..315e8000 100644 --- a/src/rabbit_exchange_type_headers.erl +++ b/src/rabbit_exchange_type_headers.erl @@ -37,7 +37,7 @@ -export([description/0, publish/2]). -export([validate/1, create/1, recover/2, delete/2, - add_binding/2, remove_bindings/2]). + add_binding/2, remove_bindings/2, assert_args_equivalence/2]). -include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, @@ -135,3 +135,5 @@ recover(_X, _Bs) -> ok. delete(_X, _Bs) -> ok. add_binding(_X, _B) -> ok. remove_bindings(_X, _Bs) -> ok. +assert_args_equivalence(X, Args) -> + rabbit_exchange:assert_args_equivalence(X, Args). diff --git a/src/rabbit_exchange_type_topic.erl b/src/rabbit_exchange_type_topic.erl index e42c4518..0e22d545 100644 --- a/src/rabbit_exchange_type_topic.erl +++ b/src/rabbit_exchange_type_topic.erl @@ -36,7 +36,7 @@ -export([description/0, publish/2]). -export([validate/1, create/1, recover/2, delete/2, - add_binding/2, remove_bindings/2]). + add_binding/2, remove_bindings/2, assert_args_equivalence/2]). -include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, @@ -99,3 +99,5 @@ recover(_X, _Bs) -> ok. delete(_X, _Bs) -> ok. add_binding(_X, _B) -> ok. remove_bindings(_X, _Bs) -> ok. +assert_args_equivalence(X, Args) -> + rabbit_exchange:assert_args_equivalence(X, Args). |