summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/rabbitmqctl.1.pod8
-rw-r--r--ebin/rabbit_app.in2
-rw-r--r--include/rabbit.hrl7
-rw-r--r--packaging/RPMS/Fedora/Makefile3
-rw-r--r--packaging/RPMS/Fedora/init.d14
-rw-r--r--packaging/RPMS/Fedora/rabbitmq-server.spec10
-rw-r--r--packaging/RPMS/Fedora/rabbitmqctl_wrapper19
-rw-r--r--packaging/common/rabbitmq-script-wrapper (renamed from packaging/debs/Debian/debian/rabbitmqctl_wrapper)8
-rw-r--r--packaging/debs/Debian/Makefile2
-rw-r--r--packaging/debs/Debian/debian/init.d13
-rw-r--r--packaging/debs/Debian/debian/rules5
-rwxr-xr-xscripts/rabbitmq-multi5
-rwxr-xr-xscripts/rabbitmq-server5
-rw-r--r--src/rabbit.erl11
-rw-r--r--src/rabbit_access_control.erl36
-rw-r--r--src/rabbit_channel.erl67
-rw-r--r--src/rabbit_control.erl6
-rw-r--r--src/rabbit_guid.erl126
-rw-r--r--src/rabbit_misc.erl40
-rw-r--r--src/rabbit_mnesia.erl3
-rw-r--r--src/rabbit_persister.erl2
-rw-r--r--src/rabbit_reader.erl22
-rw-r--r--src/rabbit_router.erl6
-rw-r--r--src/rabbit_tests.erl12
24 files changed, 273 insertions, 159 deletions
diff --git a/docs/rabbitmqctl.1.pod b/docs/rabbitmqctl.1.pod
index e9b9514ef6..d86aa2717d 100644
--- a/docs/rabbitmqctl.1.pod
+++ b/docs/rabbitmqctl.1.pod
@@ -114,11 +114,11 @@ delete_vhost I<vhostpath>
list_vhosts
list all virtual hosts.
-set_permissions [-p I<vhostpath>] I<username> I<regexp> I<regexp>
+set_permissions [-p I<vhostpath>] I<username> I<regexp> I<regexp> I<regexp>
set the permissions for the user named I<username> in the virtual
- host I<vhostpath>, granting them configuration access to resources
- with names matching the first I<regexp> and messaging access to
- resources with names matching the second I<regexp>.
+ host I<vhostpath>, granting 'configure', 'write' and 'read' access
+ to resources with names matching the first, second and third
+ I<regexp>, respectively.
clear_permissions [-p I<vhostpath>] I<username>
remove the permissions for the user named I<username> in the
diff --git a/ebin/rabbit_app.in b/ebin/rabbit_app.in
index e6d17f122e..8eb611ab17 100644
--- a/ebin/rabbit_app.in
+++ b/ebin/rabbit_app.in
@@ -19,5 +19,5 @@
{default_user, <<"guest">>},
{default_pass, <<"guest">>},
{default_vhost, <<"/">>},
- {default_permissions, [<<".*">>, <<".*">>]},
+ {default_permissions, [<<".*">>, <<".*">>, <<".*">>]},
{memory_alarms, auto}]}]}.
diff --git a/include/rabbit.hrl b/include/rabbit.hrl
index c42df1eab3..4608bf97a6 100644
--- a/include/rabbit.hrl
+++ b/include/rabbit.hrl
@@ -30,7 +30,7 @@
%%
-record(user, {username, password}).
--record(permission, {configuration, messaging}).
+-record(permission, {configure, write, read}).
-record(user_vhost, {username, virtual_host}).
-record(user_permission, {user_vhost, permission}).
@@ -95,8 +95,9 @@
#user{username :: username(),
password :: password()}).
-type(permission() ::
- #permission{configuration :: regexp(),
- messaging :: regexp()}).
+ #permission{configure :: regexp(),
+ write :: regexp(),
+ read :: regexp()}).
-type(amqqueue() ::
#amqqueue{name :: queue_name(),
durable :: bool(),
diff --git a/packaging/RPMS/Fedora/Makefile b/packaging/RPMS/Fedora/Makefile
index cf3a93dfa1..973608ccba 100644
--- a/packaging/RPMS/Fedora/Makefile
+++ b/packaging/RPMS/Fedora/Makefile
@@ -1,5 +1,6 @@
VERSION=0.0.0
SOURCE_TARBALL_DIR=../../../dist
+COMMON_DIR=../../common
TARBALL=$(SOURCE_TARBALL_DIR)/rabbitmq-server-$(VERSION).tar.gz
TOP_DIR=$(shell pwd)
#Under debian we do not want to check build dependencies, since that
@@ -30,7 +31,7 @@ prepare:
SPECS/rabbitmq-server.spec
cp init.d SOURCES/rabbitmq-server.init
- cp rabbitmqctl_wrapper SOURCES/rabbitmq-server.wrapper
+ cp ${COMMON_DIR}/* SOURCES/
cp rabbitmq-server.logrotate SOURCES/rabbitmq-server.logrotate
server: prepare
diff --git a/packaging/RPMS/Fedora/init.d b/packaging/RPMS/Fedora/init.d
index a006a5a7a2..9f4dbb43b8 100644
--- a/packaging/RPMS/Fedora/init.d
+++ b/packaging/RPMS/Fedora/init.d
@@ -16,8 +16,8 @@
# Short-Description: Enable AMQP service provided by RabbitMQ broker
### END INIT INFO
-DAEMON_NAME=rabbitmq-multi
-DAEMON=/usr/lib/rabbitmq/bin/$DAEMON_NAME
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DAEMON=/usr/sbin/rabbitmq-multi
NAME=rabbitmq-server
DESC=rabbitmq-server
USER=rabbitmq
@@ -39,7 +39,7 @@ cd /
start_rabbitmq () {
set +e
- su $USER -s /bin/sh -c "$DAEMON start_all ${NODE_COUNT}" > /var/log/rabbitmq/startup_log 2> /var/log/rabbitmq/startup_err
+ $DAEMON start_all ${NODE_COUNT} > /var/log/rabbitmq/startup_log 2> /var/log/rabbitmq/startup_err
case "$?" in
0)
echo SUCCESS && touch $LOCK_FILE
@@ -61,7 +61,7 @@ stop_rabbitmq () {
set +e
status_rabbitmq quiet
if [ $RETVAL = 0 ] ; then
- su $USER -s /bin/sh -c "$DAEMON stop_all" > /var/log/rabbitmq/shutdown_log 2> /var/log/rabbitmq/shutdown_err
+ $DAEMON stop_all > /var/log/rabbitmq/shutdown_log 2> /var/log/rabbitmq/shutdown_err
RETVAL=$?
if [ $RETVAL != 0 ] ; then
echo FAILED - check /var/log/rabbitmq/shutdown_log, _err
@@ -78,9 +78,9 @@ stop_rabbitmq () {
status_rabbitmq() {
set +e
if [ "$1" != "quiet" ] ; then
- su $USER -s /bin/sh -c "$DAEMON status" 2>&1
+ $DAEMON status 2>&1
else
- su $USER -s /bin/sh -c "$DAEMON status" > /dev/null 2>&1
+ $DAEMON status > /dev/null 2>&1
fi
if [ $? != 0 ] ; then
RETVAL=1
@@ -90,7 +90,7 @@ status_rabbitmq() {
rotate_logs_rabbitmq() {
set +e
- su $USER -s /bin/sh -c "$DAEMON rotate_logs ${ROTATE_SUFFIX}" 2>&1
+ $DAEMON rotate_logs ${ROTATE_SUFFIX} 2>&1
set -e
}
diff --git a/packaging/RPMS/Fedora/rabbitmq-server.spec b/packaging/RPMS/Fedora/rabbitmq-server.spec
index fc109bdbcc..bedf8d816c 100644
--- a/packaging/RPMS/Fedora/rabbitmq-server.spec
+++ b/packaging/RPMS/Fedora/rabbitmq-server.spec
@@ -5,7 +5,7 @@ License: MPLv1.1
Group: Development/Libraries
Source: http://www.rabbitmq.com/releases/rabbitmq-server/v%{version}/%{name}-%{version}.tar.gz
Source1: rabbitmq-server.init
-Source2: rabbitmq-server.wrapper
+Source2: rabbitmq-script-wrapper
Source3: rabbitmq-server.logrotate
URL: http://www.rabbitmq.com/
Vendor: LShift Ltd., Cohesive Financial Technologies LLC., Rabbit Technlogies Ltd.
@@ -39,6 +39,7 @@ fi
%prep
%setup -n %{name}-%{version}
+sed -i 's|/usr/lib/|%{_libdir}/|' %SOURCE2
%build
make
@@ -59,9 +60,10 @@ install -m 0755 %SOURCE1 %{buildroot}%{_initrddir}/rabbitmq-server
chmod 0755 %{buildroot}%{_initrddir}/rabbitmq-server
sed -i 's|/usr/lib/|%{_libdir}/|' %{buildroot}%{_initrddir}/rabbitmq-server
-mkdir -p %{buildroot}%{_sbindir}
-install -m 0755 %SOURCE2 %{buildroot}%{_sbindir}/rabbitmqctl
-sed -i 's|/usr/lib/|%{_libdir}/|' %{buildroot}%{_sbindir}/rabbitmqctl
+
+install -p -D -m 0755 %SOURCE2 %{buildroot}%{_sbindir}/rabbitmqctl
+install -p -D -m 0755 %SOURCE2 %{buildroot}%{_sbindir}/rabbitmq-server
+install -p -D -m 0755 %SOURCE2 %{buildroot}%{_sbindir}/rabbitmq-multi
mkdir -p %{buildroot}/etc/logrotate.d
install -m 0644 %SOURCE3 %{buildroot}/etc/logrotate.d/rabbitmq-server
diff --git a/packaging/RPMS/Fedora/rabbitmqctl_wrapper b/packaging/RPMS/Fedora/rabbitmqctl_wrapper
deleted file mode 100644
index 6b387d2997..0000000000
--- a/packaging/RPMS/Fedora/rabbitmqctl_wrapper
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-# Escape spaces and quotes, because shell is revolting.
-for arg in "$@" ; do
- # Escape quotes in parameters, so that they're passed through cleanly.
- arg=$(sed -e 's/"/\\"/' <<-END
- $arg
- END
- )
- CMDLINE="${CMDLINE} \"${arg}\""
-done
-
-cd /
-if [ `id -u` = 0 ] ; then
- su rabbitmq -s /bin/sh -c "/usr/lib/rabbitmq/bin/rabbitmqctl ${CMDLINE}"
-else
- /usr/lib/rabbitmq/bin/rabbitmqctl
- echo -e "\nOnly root should run rabbitmqctl\n"
- exit 1
-fi
diff --git a/packaging/debs/Debian/debian/rabbitmqctl_wrapper b/packaging/common/rabbitmq-script-wrapper
index d53a6ca9c6..217d1658b5 100644
--- a/packaging/debs/Debian/debian/rabbitmqctl_wrapper
+++ b/packaging/common/rabbitmq-script-wrapper
@@ -11,11 +11,13 @@ done
cd /
+SCRIPT=`basename $0`
+
if [ `id -u` = 0 ] ; then
- su rabbitmq -s /bin/sh -c "/usr/lib/rabbitmq/bin/rabbitmqctl ${CMDLINE}"
+ su rabbitmq -s /bin/sh -c "/usr/lib/rabbitmq/bin/${SCRIPT} ${CMDLINE}"
else
- /usr/lib/rabbitmq/bin/rabbitmqctl
- echo -e "\nOnly root should run rabbitmqctl\n"
+ /usr/lib/rabbitmq/bin/${SCRIPT}
+ echo -e "\nOnly root should run ${SCRIPT}\n"
exit 1
fi
diff --git a/packaging/debs/Debian/Makefile b/packaging/debs/Debian/Makefile
index 9479feb001..67fabae0aa 100644
--- a/packaging/debs/Debian/Makefile
+++ b/packaging/debs/Debian/Makefile
@@ -1,5 +1,6 @@
TARBALL_DIR=../../../dist
TARBALL=$(shell (cd $(TARBALL_DIR); echo rabbitmq-server-[0-9]*.tar.gz))
+COMMON_DIR=../../common
DEBIAN_ORIG_TARBALL=$(shell echo $(TARBALL) | sed -e 's:\(.*\)-\(.*\)\(\.tar\.gz\):\1_\2\.orig\3:g')
VERSION=$(shell echo $(TARBALL) | sed -e 's:rabbitmq-server-\(.*\)\.tar\.gz:\1:g')
UNPACKED_DIR=rabbitmq-server-$(VERSION)
@@ -19,6 +20,7 @@ package: clean
cp $(TARBALL_DIR)/$(TARBALL) $(DEBIAN_ORIG_TARBALL)
tar -zxvf $(DEBIAN_ORIG_TARBALL)
cp -r debian $(UNPACKED_DIR)
+ cp $(COMMON_DIR)/* $(UNPACKED_DIR)/debian/
chmod a+x $(UNPACKED_DIR)/debian/rules
UNOFFICIAL_RELEASE=$(UNOFFICIAL_RELEASE) VERSION=$(VERSION) ./check-changelog.sh rabbitmq-server $(UNPACKED_DIR)
cd $(UNPACKED_DIR); GNUPGHOME=$(GNUPG_PATH)/.gnupg dpkg-buildpackage -rfakeroot $(SIGNING)
diff --git a/packaging/debs/Debian/debian/init.d b/packaging/debs/Debian/debian/init.d
index 70dd0adf5f..aff0ce4da9 100644
--- a/packaging/debs/Debian/debian/init.d
+++ b/packaging/debs/Debian/debian/init.d
@@ -9,7 +9,8 @@
# Short-Description: Enable AMQP service provided by RabbitMQ broker
### END INIT INFO
-DAEMON=/usr/lib/rabbitmq/bin/rabbitmq-multi
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DAEMON=/usr/sbin/rabbitmq-multi
NAME=rabbitmq-server
DESC=rabbitmq-server
USER=rabbitmq
@@ -29,7 +30,7 @@ cd /
start_rabbitmq () {
set +e
- su $USER -s /bin/sh -c "$DAEMON start_all ${NODE_COUNT}" > /var/log/rabbitmq/startup_log 2> /var/log/rabbitmq/startup_err
+ $DAEMON start_all ${NODE_COUNT} > /var/log/rabbitmq/startup_log 2> /var/log/rabbitmq/startup_err
case "$?" in
0)
echo SUCCESS
@@ -51,7 +52,7 @@ stop_rabbitmq () {
set +e
status_rabbitmq quiet
if [ $RETVAL = 0 ] ; then
- su $USER -s /bin/sh -c "$DAEMON stop_all" > /var/log/rabbitmq/shutdown_log 2> /var/log/rabbitmq/shutdown_err
+ $DAEMON stop_all > /var/log/rabbitmq/shutdown_log 2> /var/log/rabbitmq/shutdown_err
RETVAL=$?
if [ $RETVAL != 0 ] ; then
echo FAILED - check /var/log/rabbitmq/shutdown_log, _err
@@ -66,9 +67,9 @@ stop_rabbitmq () {
status_rabbitmq() {
set +e
if [ "$1" != "quiet" ] ; then
- su $USER -s /bin/sh -c "$DAEMON status" 2>&1
+ $DAEMON status 2>&1
else
- su $USER -s /bin/sh -c "$DAEMON status" > /dev/null 2>&1
+ $DAEMON status > /dev/null 2>&1
fi
if [ $? != 0 ] ; then
RETVAL=1
@@ -78,7 +79,7 @@ status_rabbitmq() {
rotate_logs_rabbitmq() {
set +e
- su $USER -s /bin/sh -c "$DAEMON rotate_logs ${ROTATE_SUFFIX}" 2>&1
+ $DAEMON rotate_logs ${ROTATE_SUFFIX} 2>&1
set -e
}
diff --git a/packaging/debs/Debian/debian/rules b/packaging/debs/Debian/debian/rules
index 908ec4817f..31904851a9 100644
--- a/packaging/debs/Debian/debian/rules
+++ b/packaging/debs/Debian/debian/rules
@@ -14,5 +14,6 @@ DOCDIR=$(DEB_DESTDIR)usr/share/doc/rabbitmq-server/
install/rabbitmq-server::
mkdir -p $(DOCDIR)
rm $(RABBIT_LIB)LICENSE*
- cp debian/rabbitmqctl_wrapper $(DEB_DESTDIR)usr/sbin/rabbitmqctl
- chmod a+x $(DEB_DESTDIR)usr/sbin/rabbitmqctl
+ for script in rabbitmqctl rabbitmq-server rabbitmq-multi; do \
+ install -p -D -m 0755 debian/rabbitmq-script-wrapper $(DEB_DESTDIR)usr/sbin/$$script; \
+ done
diff --git a/scripts/rabbitmq-multi b/scripts/rabbitmq-multi
index 84985e900f..164c5e187c 100755
--- a/scripts/rabbitmq-multi
+++ b/scripts/rabbitmq-multi
@@ -54,6 +54,11 @@ export \
RABBITMQ_SCRIPT_HOME \
RABBITMQ_PIDS_FILE
+# we need to turn off path expansion because some of the vars, notably
+# RABBITMQ_MULTI_ERL_ARGS, may contain terms that look like globs and
+# there is no other way of preventing their expansion.
+set -f
+
exec erl \
-pa "`dirname $0`/../ebin" \
-noinput \
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server
index 572262c97e..9a35c47721 100755
--- a/scripts/rabbitmq-server
+++ b/scripts/rabbitmq-server
@@ -73,6 +73,11 @@ fi
RABBITMQ_START_RABBIT=
[ "x" = "x$RABBITMQ_NODE_ONLY" ] && RABBITMQ_START_RABBIT='-noinput -s rabbit'
+# we need to turn off path expansion because some of the vars, notably
+# RABBITMQ_SERVER_ERL_ARGS, contain terms that look like globs and
+# there is no other way of preventing their expansion.
+set -f
+
exec erl \
-pa "`dirname $0`/../ebin" \
${RABBITMQ_START_RABBIT} \
diff --git a/src/rabbit.erl b/src/rabbit.erl
index a1c9441ace..0d1ce689ea 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -155,6 +155,10 @@ start(normal, []) ->
fun () ->
ok = start_child(rabbit_persister)
end},
+ {"guid generator",
+ fun () ->
+ ok = start_child(rabbit_guid)
+ end},
{"builtin applications",
fun () ->
{ok, DefaultVHost} = application:get_env(default_vhost),
@@ -280,13 +284,14 @@ insert_default_data() ->
{ok, DefaultUser} = application:get_env(default_user),
{ok, DefaultPass} = application:get_env(default_pass),
{ok, DefaultVHost} = application:get_env(default_vhost),
- {ok, [DefaultConfigurationPerm, DefaultMessagingPerm]} =
+ {ok, [DefaultConfigurePerm, DefaultWritePerm, DefaultReadPerm]} =
application:get_env(default_permissions),
ok = rabbit_access_control:add_vhost(DefaultVHost),
ok = rabbit_access_control:add_user(DefaultUser, DefaultPass),
ok = rabbit_access_control:set_permissions(DefaultUser, DefaultVHost,
- DefaultConfigurationPerm,
- DefaultMessagingPerm),
+ DefaultConfigurePerm,
+ DefaultWritePerm,
+ DefaultReadPerm),
ok.
start_builtin_amq_applications() ->
diff --git a/src/rabbit_access_control.erl b/src/rabbit_access_control.erl
index 394eb2b124..da0ab9cf7a 100644
--- a/src/rabbit_access_control.erl
+++ b/src/rabbit_access_control.erl
@@ -38,7 +38,7 @@
-export([add_user/2, delete_user/1, change_password/2, list_users/0,
lookup_user/1]).
-export([add_vhost/1, delete_vhost/1, list_vhosts/0]).
--export([set_permissions/4, clear_permissions/2,
+-export([set_permissions/5, clear_permissions/2,
list_vhost_permissions/1, list_user_permissions/1]).
%%----------------------------------------------------------------------------
@@ -58,12 +58,13 @@
-spec(add_vhost/1 :: (vhost()) -> 'ok').
-spec(delete_vhost/1 :: (vhost()) -> 'ok').
-spec(list_vhosts/0 :: () -> [vhost()]).
--spec(set_permissions/4 :: (username(), vhost(), regexp(), regexp()) -> 'ok').
+-spec(set_permissions/5 ::
+ (username(), vhost(), regexp(), regexp(), regexp()) -> 'ok').
-spec(clear_permissions/2 :: (username(), vhost()) -> 'ok').
-spec(list_vhost_permissions/1 ::
- (vhost()) -> [{username(), regexp(), regexp()}]).
+ (vhost()) -> [{username(), regexp(), regexp(), regexp()}]).
-spec(list_user_permissions/1 ::
- (username()) -> [{vhost(), regexp(), regexp()}]).
+ (username()) -> [{vhost(), regexp(), regexp(), regexp()}]).
-endif.
@@ -272,7 +273,7 @@ internal_delete_vhost(VHostPath) ->
ok = rabbit_exchange:delete(Name, false)
end,
rabbit_exchange:list(VHostPath)),
- lists:foreach(fun ({Username, _, _}) ->
+ lists:foreach(fun ({Username, _, _, _}) ->
ok = clear_permissions(Username, VHostPath)
end,
list_vhost_permissions(VHostPath)),
@@ -289,9 +290,8 @@ validate_regexp(RegexpBin) ->
{error, Reason} -> throw({error, {invalid_regexp, Regexp, Reason}})
end.
-set_permissions(Username, VHostPath, ConfigurationPerm, MessagingPerm) ->
- validate_regexp(ConfigurationPerm),
- validate_regexp(MessagingPerm),
+set_permissions(Username, VHostPath, ConfigurePerm, WritePerm, ReadPerm) ->
+ lists:map(fun validate_regexp/1, [ConfigurePerm, WritePerm, ReadPerm]),
rabbit_misc:execute_mnesia_transaction(
rabbit_misc:with_user_and_vhost(
Username, VHostPath,
@@ -301,8 +301,9 @@ set_permissions(Username, VHostPath, ConfigurationPerm, MessagingPerm) ->
username = Username,
virtual_host = VHostPath},
permission = #permission{
- configuration = ConfigurationPerm,
- messaging = MessagingPerm}},
+ configure = ConfigurePerm,
+ write = WritePerm,
+ read = ReadPerm}},
write)
end)).
@@ -317,24 +318,25 @@ clear_permissions(Username, VHostPath) ->
end)).
list_vhost_permissions(VHostPath) ->
- [{Username, ConfigurationPerm, MessagingPerm} ||
- {Username, _, ConfigurationPerm, MessagingPerm} <-
+ [{Username, ConfigurePerm, WritePerm, ReadPerm} ||
+ {Username, _, ConfigurePerm, WritePerm, ReadPerm} <-
list_permissions(rabbit_misc:with_vhost(
VHostPath, match_user_vhost('_', VHostPath)))].
list_user_permissions(Username) ->
- [{VHostPath, ConfigurationPerm, MessagingPerm} ||
- {_, VHostPath, ConfigurationPerm, MessagingPerm} <-
+ [{VHostPath, ConfigurePerm, WritePerm, ReadPerm} ||
+ {_, VHostPath, ConfigurePerm, WritePerm, ReadPerm} <-
list_permissions(rabbit_misc:with_user(
Username, match_user_vhost(Username, '_')))].
list_permissions(QueryThunk) ->
- [{Username, VHostPath, ConfigurationPerm, MessagingPerm} ||
+ [{Username, VHostPath, ConfigurePerm, WritePerm, ReadPerm} ||
#user_permission{user_vhost = #user_vhost{username = Username,
virtual_host = VHostPath},
permission = #permission{
- configuration = ConfigurationPerm,
- messaging = MessagingPerm}} <-
+ configure = ConfigurePerm,
+ write = WritePerm,
+ read = ReadPerm}} <-
%% TODO: use dirty ops instead
rabbit_misc:execute_mnesia_transaction(QueryThunk)].
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index 5a1c095266..7574cd673a 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -35,12 +35,12 @@
-behaviour(gen_server2).
--export([start_link/4, do/2, do/3, shutdown/1]).
+-export([start_link/5, do/2, do/3, shutdown/1]).
-export([send_command/2, deliver/4, conserve_memory/2]).
-export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]).
--record(ch, {state, reader_pid, writer_pid, limiter_pid,
+-record(ch, {state, channel, reader_pid, writer_pid, limiter_pid,
transaction_id, tx_participants, next_tag,
uncommitted_ack_q, unacked_message_q,
username, virtual_host,
@@ -54,7 +54,8 @@
-ifdef(use_specs).
--spec(start_link/4 :: (pid(), pid(), username(), vhost()) -> pid()).
+-spec(start_link/5 ::
+ (channel_number(), pid(), pid(), username(), vhost()) -> pid()).
-spec(do/2 :: (pid(), amqp_method()) -> 'ok').
-spec(do/3 :: (pid(), amqp_method(), maybe(content())) -> 'ok').
-spec(shutdown/1 :: (pid()) -> 'ok').
@@ -66,9 +67,10 @@
%%----------------------------------------------------------------------------
-start_link(ReaderPid, WriterPid, Username, VHost) ->
+start_link(Channel, ReaderPid, WriterPid, Username, VHost) ->
{ok, Pid} = gen_server2:start_link(
- ?MODULE, [ReaderPid, WriterPid, Username, VHost], []),
+ ?MODULE, [Channel, ReaderPid, WriterPid,
+ Username, VHost], []),
Pid.
do(Pid, Method) ->
@@ -91,11 +93,12 @@ conserve_memory(Pid, Conserve) ->
%%---------------------------------------------------------------------------
-init([ReaderPid, WriterPid, Username, VHost]) ->
+init([Channel, ReaderPid, WriterPid, Username, VHost]) ->
process_flag(trap_exit, true),
link(WriterPid),
rabbit_alarm:register(self(), {?MODULE, conserve_memory, []}),
{ok, #ch{state = starting,
+ channel = Channel,
reader_pid = ReaderPid,
writer_pid = WriterPid,
limiter_pid = undefined,
@@ -123,8 +126,11 @@ handle_cast({method, Method, Content}, State) ->
{stop, normal, State#ch{state = terminating}}
catch
exit:{amqp, Error, Explanation, none} ->
- {stop, {amqp, Error, Explanation,
- rabbit_misc:method_record_type(Method)}, State};
+ ok = notify_queues(internal_rollback(State)),
+ Reason = {amqp, Error, Explanation,
+ rabbit_misc:method_record_type(Method)},
+ State#ch.reader_pid ! {channel_exit, State#ch.channel, Reason},
+ {stop, normal, State#ch{state = terminating}};
exit:normal ->
{stop, normal, State};
_:Reason ->
@@ -224,11 +230,14 @@ clear_permission_cache() ->
erase(permission_cache),
ok.
-check_configuration_permitted(Resource, #ch{ username = Username}) ->
- check_resource_access(Username, Resource, #permission.configuration).
+check_configure_permitted(Resource, #ch{ username = Username}) ->
+ check_resource_access(Username, Resource, #permission.configure).
-check_messaging_permitted(Resource, #ch{ username = Username}) ->
- check_resource_access(Username, Resource, #permission.messaging).
+check_write_permitted(Resource, #ch{ username = Username}) ->
+ check_resource_access(Username, Resource, #permission.write).
+
+check_read_permitted(Resource, #ch{ username = Username}) ->
+ check_resource_access(Username, Resource, #permission.read).
expand_queue_name_shortcut(<<>>, #ch{ most_recently_declared_queue = <<>> }) ->
rabbit_misc:protocol_error(
@@ -299,13 +308,13 @@ handle_method(#'basic.publish'{exchange = ExchangeNameBin,
immediate = Immediate},
Content, State = #ch{ virtual_host = VHostPath}) ->
ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin),
- check_messaging_permitted(ExchangeName, State),
+ check_write_permitted(ExchangeName, State),
Exchange = rabbit_exchange:lookup_or_die(ExchangeName),
%% We decode the content's properties here because we're almost
%% certain to want to look at delivery-mode and priority.
DecodedContent = rabbit_binary_parser:ensure_content_decoded(Content),
PersistentKey = case is_message_persistent(DecodedContent) of
- true -> rabbit_misc:guid();
+ true -> rabbit_guid:guid();
false -> none
end,
{noreply, publish(Mandatory, Immediate,
@@ -343,7 +352,7 @@ handle_method(#'basic.get'{queue = QueueNameBin,
_, State = #ch{ writer_pid = WriterPid,
next_tag = DeliveryTag }) ->
QueueName = expand_queue_name_shortcut(QueueNameBin, State),
- check_messaging_permitted(QueueName, State),
+ check_read_permitted(QueueName, State),
case rabbit_amqqueue:with_or_die(
QueueName,
fun (Q) -> rabbit_amqqueue:basic_get(Q, self(), NoAck) end) of
@@ -378,10 +387,10 @@ handle_method(#'basic.consume'{queue = QueueNameBin,
case dict:find(ConsumerTag, ConsumerMapping) of
error ->
QueueName = expand_queue_name_shortcut(QueueNameBin, State),
- check_messaging_permitted(QueueName, State),
+ check_read_permitted(QueueName, State),
ActualConsumerTag =
case ConsumerTag of
- <<>> -> rabbit_misc:binstring_guid("amq.ctag");
+ <<>> -> rabbit_guid:binstring_guid("amq.ctag");
Other -> Other
end,
@@ -537,7 +546,7 @@ handle_method(#'exchange.declare'{exchange = ExchangeNameBin,
_, State = #ch{ virtual_host = VHostPath }) ->
CheckedType = rabbit_exchange:check_type(TypeNameBin),
ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin),
- check_configuration_permitted(ExchangeName, State),
+ check_configure_permitted(ExchangeName, State),
X = case rabbit_exchange:lookup(ExchangeName) of
{ok, FoundX} -> FoundX;
{error, not_found} ->
@@ -557,7 +566,7 @@ handle_method(#'exchange.declare'{exchange = ExchangeNameBin,
nowait = NoWait},
_, State = #ch{ virtual_host = VHostPath }) ->
ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin),
- check_configuration_permitted(ExchangeName, State),
+ check_configure_permitted(ExchangeName, State),
X = rabbit_exchange:lookup_or_die(ExchangeName),
ok = rabbit_exchange:assert_type(X, rabbit_exchange:check_type(TypeNameBin)),
return_ok(State, NoWait, #'exchange.declare_ok'{});
@@ -567,7 +576,7 @@ handle_method(#'exchange.delete'{exchange = ExchangeNameBin,
nowait = NoWait},
_, State = #ch { virtual_host = VHostPath }) ->
ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin),
- check_configuration_permitted(ExchangeName, State),
+ check_configure_permitted(ExchangeName, State),
case rabbit_exchange:delete(ExchangeName, IfUnused) of
{error, not_found} ->
rabbit_misc:protocol_error(
@@ -614,15 +623,15 @@ handle_method(#'queue.declare'{queue = QueueNameBin,
{error, not_found} ->
ActualNameBin =
case QueueNameBin of
- <<>> -> rabbit_misc:binstring_guid("amq.gen");
+ <<>> -> rabbit_guid:binstring_guid("amq.gen");
Other -> check_name('queue', Other)
end,
QueueName = rabbit_misc:r(VHostPath, queue, ActualNameBin),
- check_configuration_permitted(QueueName, State),
+ check_configure_permitted(QueueName, State),
Finish(rabbit_amqqueue:declare(QueueName,
Durable, AutoDelete, Args));
Other = #amqqueue{name = QueueName} ->
- check_configuration_permitted(QueueName, State),
+ check_configure_permitted(QueueName, State),
Other
end,
return_queue_declare_ok(State, NoWait, Q);
@@ -632,7 +641,7 @@ handle_method(#'queue.declare'{queue = QueueNameBin,
nowait = NoWait},
_, State = #ch{ virtual_host = VHostPath }) ->
QueueName = rabbit_misc:r(VHostPath, queue, QueueNameBin),
- check_configuration_permitted(QueueName, State),
+ check_configure_permitted(QueueName, State),
Q = rabbit_amqqueue:with_or_die(QueueName, fun (Q) -> Q end),
return_queue_declare_ok(State, NoWait, Q);
@@ -643,7 +652,7 @@ handle_method(#'queue.delete'{queue = QueueNameBin,
},
_, State) ->
QueueName = expand_queue_name_shortcut(QueueNameBin, State),
- check_configuration_permitted(QueueName, State),
+ check_configure_permitted(QueueName, State),
case rabbit_amqqueue:with_or_die(
QueueName,
fun (Q) -> rabbit_amqqueue:delete(Q, IfUnused, IfEmpty) end) of
@@ -680,7 +689,7 @@ handle_method(#'queue.purge'{queue = QueueNameBin,
nowait = NoWait},
_, State) ->
QueueName = expand_queue_name_shortcut(QueueNameBin, State),
- check_messaging_permitted(QueueName, State),
+ check_read_permitted(QueueName, State),
{ok, PurgedMessageCount} = rabbit_amqqueue:with_or_die(
QueueName,
fun (Q) -> rabbit_amqqueue:purge(Q) end),
@@ -730,11 +739,11 @@ binding_action(Fun, ExchangeNameBin, QueueNameBin, RoutingKey, Arguments,
%% FIXME: don't allow binding to internal exchanges -
%% including the one named "" !
QueueName = expand_queue_name_shortcut(QueueNameBin, State),
- check_configuration_permitted(QueueName, State),
+ check_write_permitted(QueueName, State),
ActualRoutingKey = expand_routing_key_shortcut(QueueNameBin, RoutingKey,
State),
ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin),
- check_configuration_permitted(ExchangeName, State),
+ check_read_permitted(ExchangeName, State),
case Fun(ExchangeName, QueueName, ActualRoutingKey, Arguments) of
{error, queue_not_found} ->
rabbit_misc:protocol_error(
@@ -823,7 +832,7 @@ ack(TxnKey, UAQ) ->
[QPid | L]
end, [], UAQ).
-make_tx_id() -> rabbit_misc:guid().
+make_tx_id() -> rabbit_guid:guid().
new_tx(State) ->
State#ch{transaction_id = make_tx_id(),
diff --git a/src/rabbit_control.erl b/src/rabbit_control.erl
index 293cd79751..e6717d689f 100644
--- a/src/rabbit_control.erl
+++ b/src/rabbit_control.erl
@@ -114,7 +114,7 @@ Available commands:
delete_vhost <VHostPath>
list_vhosts
- set_permissions [-p <VHostPath>] <UserName> <Regexp> <Regexp>
+ set_permissions [-p <VHostPath>] <UserName> <Regexp> <Regexp> <Regexp>
clear_permissions [-p <VHostPath>] <UserName>
list_permissions [-p <VHostPath>]
list_user_permissions <UserName>
@@ -267,10 +267,10 @@ action(Command, Node, Args, Inform) ->
{VHost, RemainingArgs} = parse_vhost_flag(Args),
action(Command, Node, VHost, RemainingArgs, Inform).
-action(set_permissions, Node, VHost, [Username, CPerm, MPerm], Inform) ->
+action(set_permissions, Node, VHost, [Username, CPerm, WPerm, RPerm], Inform) ->
Inform("Setting permissions for user ~p in vhost ~p", [Username, VHost]),
call(Node, {rabbit_access_control, set_permissions,
- [Username, VHost, CPerm, MPerm]});
+ [Username, VHost, CPerm, WPerm, RPerm]});
action(clear_permissions, Node, VHost, [Username], Inform) ->
Inform("Clearing permissions for user ~p in vhost ~p", [Username, VHost]),
diff --git a/src/rabbit_guid.erl b/src/rabbit_guid.erl
new file mode 100644
index 0000000000..51c1665bbb
--- /dev/null
+++ b/src/rabbit_guid.erl
@@ -0,0 +1,126 @@
+%% 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 Developers of the Original Code are LShift Ltd,
+%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
+%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
+%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
+%% Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
+%% Ltd. Portions created by Cohesive Financial Technologies LLC are
+%% Copyright (C) 2007-2009 Cohesive Financial Technologies
+%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
+%% (C) 2007-2009 Rabbit Technologies Ltd.
+%%
+%% All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.
+%%
+
+-module(rabbit_guid).
+
+-include("rabbit.hrl").
+
+-behaviour(gen_server).
+
+-export([start_link/0]).
+-export([guid/0, string_guid/1, binstring_guid/1]).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {serial}).
+
+%%----------------------------------------------------------------------------
+
+-ifdef(use_specs).
+
+-spec(start_link/0 :: () -> {'ok', pid()} | 'ignore' | {'error', any()}).
+-spec(guid/0 :: () -> guid()).
+-spec(string_guid/1 :: (any()) -> string()).
+-spec(binstring_guid/1 :: (any()) -> binary()).
+
+-endif.
+
+%%----------------------------------------------------------------------------
+
+start_link() ->
+ %% The persister can get heavily loaded, and we don't want that to
+ %% impact guid generation. We therefore keep the serial in a
+ %% separate process rather than calling rabbit_persister:serial/0
+ %% directly in the functions below.
+ gen_server:start_link({local, ?SERVER}, ?MODULE,
+ [rabbit_persister:serial()], []).
+
+%% generate a guid that is monotonically increasing per process.
+%%
+%% The id is only unique within a single cluster and as long as the
+%% persistent message store hasn't been deleted.
+guid() ->
+ %% We don't use erlang:now() here because a) it may return
+ %% duplicates when the system clock has been rewound prior to a
+ %% restart, or ids were generated at a high rate (which causes
+ %% now() to move ahead of the system time), and b) it is really
+ %% slow since it takes a global lock and makes a system call.
+ %%
+ %% rabbit_persister:serial/0, in combination with self/0 (which
+ %% includes the node name) uniquely identifies a process in space
+ %% and time. We combine that with a process-local counter to give
+ %% us a GUID that is monotonically increasing per process.
+ G = case get(guid) of
+ undefined -> {{gen_server:call(?SERVER, serial), self()}, 0};
+ {S, I} -> {S, I+1}
+ end,
+ put(guid, G),
+ G.
+
+%% generate a readable string representation of a guid. Note that any
+%% monotonicity of the guid is not preserved in the encoding.
+string_guid(Prefix) ->
+ %% we use the (undocumented) ssl_base64 module here because it is
+ %% present throughout OTP R11 and R12 whereas base64 only becomes
+ %% available in R11B-4.
+ %%
+ %% TODO: once debian stable and EPEL have moved from R11B-2 to
+ %% R11B-4 or later we should change this to use base64.
+ Prefix ++ "-" ++ ssl_base64:encode(erlang:md5(term_to_binary(guid()))).
+
+binstring_guid(Prefix) ->
+ list_to_binary(string_guid(Prefix)).
+
+%%----------------------------------------------------------------------------
+
+init([Serial]) ->
+ {ok, #state{serial = Serial}}.
+
+handle_call(serial, _From, State = #state{serial = Serial}) ->
+ {reply, Serial, State};
+
+handle_call(_Request, _From, State) ->
+ {noreply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl
index 214c952834..5d176f8fac 100644
--- a/src/rabbit_misc.erl
+++ b/src/rabbit_misc.erl
@@ -46,7 +46,6 @@
-export([ensure_ok/2]).
-export([localnode/1, tcp_name/3]).
-export([intersperse/2, upmap/2, map_in_order/2]).
--export([guid/0, string_guid/1, binstring_guid/1]).
-export([dirty_read_all/1, dirty_foreach_key/2, dirty_dump_log/1]).
-export([append_file/2, ensure_parent_dirs_exist/1]).
-export([format_stderr/2]).
@@ -99,9 +98,6 @@
-spec(intersperse/2 :: (A, [A]) -> [A]).
-spec(upmap/2 :: (fun ((A) -> B), [A]) -> [B]).
-spec(map_in_order/2 :: (fun ((A) -> B), [A]) -> [B]).
--spec(guid/0 :: () -> guid()).
--spec(string_guid/1 :: (any()) -> string()).
--spec(binstring_guid/1 :: (any()) -> binary()).
-spec(dirty_read_all/1 :: (atom()) -> [any()]).
-spec(dirty_foreach_key/2 :: (fun ((any()) -> any()), atom()) ->
'ok' | 'aborted').
@@ -302,42 +298,6 @@ map_in_order(F, L) ->
lists:reverse(
lists:foldl(fun (E, Acc) -> [F(E) | Acc] end, [], L)).
-%% generate a guid that is monotonically increasing per process.
-%%
-%% The id is only unique within a single cluster and as the persistent
-%% message store hasn't been deleted.
-guid() ->
- %% We don't use erlang:now() here because a) it may return
- %% duplicates when the system clock has been rewound prior to a
- %% restart, or ids were generated at a high rate (which causes
- %% now() to move ahead of the system time), and b) it is really
- %% slow since it takes a global lock and makes a system call.
- %%
- %% rabbit_persister:serial/0, in combination with self/0 (which
- %% includes the node name) uniquely identifies a process in space
- %% and time. We combine that with a process-local counter to give
- %% us a GUID that is monotonically increasing per process.
- G = case get(guid) of
- undefined -> {{rabbit_persister:serial(), self()}, 0};
- {S, I} -> {S, I+1}
- end,
- put(guid, G),
- G.
-
-%% generate a readable string representation of a guid. Note that any
-%% monotonicity of the guid is not preserved in the encoding.
-string_guid(Prefix) ->
- %% we use the (undocumented) ssl_base64 module here because it is
- %% present throughout OTP R11 and R12 whereas base64 only becomes
- %% available in R11B-4.
- %%
- %% TODO: once debian stable and EPEL have moved from R11B-2 to
- %% R11B-4 or later we should change this to use base64.
- Prefix ++ "-" ++ ssl_base64:encode(erlang:md5(term_to_binary(guid()))).
-
-binstring_guid(Prefix) ->
- list_to_binary(string_guid(Prefix)).
-
dirty_read_all(TableName) ->
mnesia:dirty_select(TableName, [{'$1',[],['$1']}]).
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index c0bf3d254e..15213861bd 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -143,8 +143,7 @@ table_definitions() ->
{disc_copies, [node()]}]},
{rabbit_queue,
[{record_name, amqqueue},
- {attributes, record_info(fields, amqqueue)},
- {index, [pid]}]}].
+ {attributes, record_info(fields, amqqueue)}]}].
table_names() ->
[Tab || {Tab, _} <- table_definitions()].
diff --git a/src/rabbit_persister.erl b/src/rabbit_persister.erl
index c34ad85100..94033a4f3d 100644
--- a/src/rabbit_persister.erl
+++ b/src/rabbit_persister.erl
@@ -92,7 +92,7 @@ start_link() ->
transaction(MessageList) ->
?LOGDEBUG("transaction ~p~n", [MessageList]),
- TxnKey = rabbit_misc:guid(),
+ TxnKey = rabbit_guid:guid(),
gen_server:call(?SERVER, {transaction, TxnKey, MessageList}).
extend_transaction(TxnKey, MessageList) ->
diff --git a/src/rabbit_reader.erl b/src/rabbit_reader.erl
index a6094ebc58..dbb9358314 100644
--- a/src/rabbit_reader.erl
+++ b/src/rabbit_reader.erl
@@ -231,8 +231,12 @@ start_connection(Parent, Deb, ClientSock) ->
connection_state = pre_init},
handshake, 8))
catch
- Ex -> rabbit_log:error("error on TCP connection ~p from ~s:~p~n~p~n",
- [self(), PeerAddressS, PeerPort, Ex])
+ Ex -> (if Ex == connection_closed_abruptly ->
+ fun rabbit_log:warning/2;
+ true ->
+ fun rabbit_log:error/2
+ end)("exception on TCP connection ~p from ~s:~p~n~p~n",
+ [self(), PeerAddressS, PeerPort, Ex])
after
rabbit_log:info("closing TCP connection ~p from ~s:~p~n",
[self(), PeerAddressS, PeerPort]),
@@ -284,6 +288,8 @@ mainloop(Parent, Deb, State = #v1{sock= Sock, recv_ref = Ref}) ->
exit(Reason);
{'EXIT', _Pid, E = {writer, send_failed, _Error}} ->
throw(E);
+ {channel_exit, Channel, Reason} ->
+ mainloop(Parent, Deb, handle_channel_exit(Channel, Reason, State));
{'EXIT', Pid, Reason} ->
mainloop(Parent, Deb, handle_dependent_exit(Pid, Reason, State));
{terminate_channel, Channel, Ref1} ->
@@ -351,6 +357,14 @@ terminate_channel(Channel, Ref, State) ->
end,
State.
+handle_channel_exit(Channel, Reason, State) ->
+ %% We remove the channel from the inbound map only. That allows
+ %% the channel to be re-opened, but also means the remaining
+ %% cleanup, including possibly closing the connection, is deferred
+ %% until we get the (normal) exit signal.
+ erase({channel, Channel}),
+ handle_exception(State, Channel, Reason).
+
handle_dependent_exit(Pid, normal, State) ->
channel_cleanup(Pid),
maybe_close(State);
@@ -711,8 +725,8 @@ send_to_new_channel(Channel, AnalyzedFrame, State) ->
vhost = VHost}} = State,
WriterPid = rabbit_writer:start(Sock, Channel, FrameMax),
ChPid = rabbit_framing_channel:start_link(
- fun rabbit_channel:start_link/4,
- [self(), WriterPid, Username, VHost]),
+ fun rabbit_channel:start_link/5,
+ [Channel, self(), WriterPid, Username, VHost]),
put({channel, Channel}, {chpid, ChPid}),
put({chpid, ChPid}, {channel, Channel}),
ok = rabbit_framing_channel:process(ChPid, AnalyzedFrame);
diff --git a/src/rabbit_router.erl b/src/rabbit_router.erl
index 26d857bef0..ff42ea0460 100644
--- a/src/rabbit_router.erl
+++ b/src/rabbit_router.erl
@@ -32,7 +32,7 @@
-module(rabbit_router).
-include("rabbit.hrl").
--behaviour(gen_server).
+-behaviour(gen_server2).
-export([start_link/0,
deliver/5]).
@@ -58,7 +58,7 @@
%%----------------------------------------------------------------------------
start_link() ->
- gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+ gen_server2:start_link({local, ?SERVER}, ?MODULE, [], []).
-ifdef(BUG19758).
@@ -143,7 +143,7 @@ handle_call({deliver, QPids, Mandatory, Immediate, Txn, Message},
spawn(
fun () ->
R = run_bindings(QPids, Mandatory, Immediate, Txn, Message),
- gen_server:reply(From, R)
+ gen_server2:reply(From, R)
end),
{noreply, State}.
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index ef390e4de6..6312e8e364 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -444,7 +444,7 @@ test_user_management() ->
{error, {no_such_vhost, _}} =
control_action(delete_vhost, ["/testhost"]),
{error, {no_such_user, _}} =
- control_action(set_permissions, ["foo", ".*", ".*"]),
+ control_action(set_permissions, ["foo", ".*", ".*", ".*"]),
{error, {no_such_user, _}} =
control_action(clear_permissions, ["foo"]),
{error, {no_such_user, _}} =
@@ -452,9 +452,7 @@ test_user_management() ->
{error, {no_such_vhost, _}} =
control_action(list_permissions, ["-p", "/testhost"]),
{error, {invalid_regexp, _, _}} =
- control_action(set_permissions, ["guest", "+foo", ".*"]),
- {error, {invalid_regexp, _, _}} =
- control_action(set_permissions, ["guest", ".*", "+foo"]),
+ control_action(set_permissions, ["guest", "+foo", ".*", ".*"]),
%% user creation
ok = control_action(add_user, ["foo", "bar"]),
@@ -471,9 +469,9 @@ test_user_management() ->
%% user/vhost mapping
ok = control_action(set_permissions, ["-p", "/testhost",
- "foo", ".*", ".*"]),
+ "foo", ".*", ".*", ".*"]),
ok = control_action(set_permissions, ["-p", "/testhost",
- "foo", ".*", ".*"]),
+ "foo", ".*", ".*", ".*"]),
ok = control_action(list_permissions, ["-p", "/testhost"]),
ok = control_action(list_user_permissions, ["foo"]),
@@ -489,7 +487,7 @@ test_user_management() ->
%% deleting a populated vhost
ok = control_action(add_vhost, ["/testhost"]),
ok = control_action(set_permissions, ["-p", "/testhost",
- "foo", ".*", ".*"]),
+ "foo", ".*", ".*", ".*"]),
ok = control_action(delete_vhost, ["/testhost"]),
%% user deletion