diff --git a/README.md b/README.md index e3d7daa43c..bf04218909 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # RabbitMQ Server -[RabbitMQ](http://rabbitmq.com) is a [feature rich](http://www.rabbitmq.com/features.html), multi-protocol messaging broker. It supports: +[RabbitMQ](https://rabbitmq.com) is a [feature rich](https://rabbitmq.com/documentation.html), multi-protocol messaging broker. It supports: * AMQP 0-9-1 * STOMP 1.0 through 1.2 @@ -10,27 +10,27 @@ ## Installation - * [Installation guides](http://www.rabbitmq.com/download.html) for various platforms + * [Installation guides](https://rabbitmq.com/download.html) for various platforms ## Tutorials & Documentation - * [RabbitMQ tutorials](http://www.rabbitmq.com/getstarted.html) - * [Documentation guides](http://www.rabbitmq.com/documentation.html) + * [RabbitMQ tutorials](https://rabbitmq.com/getstarted.html) + * [Documentation guides](https://rabbitmq.com/documentation.html) * [Documentation Source Code](https://github.com/rabbitmq/rabbitmq-website/) - * [Client libraries and tools](http://www.rabbitmq.com/devtools.html) + * [Client libraries and tools](https://rabbitmq.com/devtools.html) * [Tutorials Source Code](https://github.com/rabbitmq/rabbitmq-tutorials/) ## Getting Help * [RabbitMQ mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users) * `#rabbitmq` on Freenode - * [Commercial RabbitMQ support](http://www.rabbitmq.com/services.html) from [Pivotal](http://pivotal.io) + * [Commercial RabbitMQ support](https://rabbitmq.com/services.html) from [Pivotal](http://pivotal.io) ## Contributing -See [CONTRIBUTING.md](./CONTRIBUTING.md) and our [development process overview](http://www.rabbitmq.com/github.html). +See [CONTRIBUTING.md](./CONTRIBUTING.md) and our [development process overview](https://rabbitmq.com/github.html). ## License @@ -40,8 +40,8 @@ RabbitMQ server is [licensed under the MPL](LICENSE-MPL-RabbitMQ). ## Building From Source and Packaging - * [Building RabbitMQ Server From Source](http://www.rabbitmq.com/build-server.html) - * [Building RabbitMQ Server Packages](http://www.rabbitmq.com/build-server.html) + * [Building RabbitMQ Server From Source](https://rabbitmq.com/build-server.html) + * [Building RabbitMQ Server Packages](https://rabbitmq.com/build-server.html) ## Copyright diff --git a/docs/rabbitmq-service.8 b/docs/rabbitmq-service.8 index 1e0f3760bb..12b7f28a33 100644 --- a/docs/rabbitmq-service.8 +++ b/docs/rabbitmq-service.8 @@ -89,8 +89,8 @@ using the service control panel. .It Ev RABBITMQ_SERVICENAME Defaults to RabbitMQ. .It Ev RABBITMQ_BASE -Defaults to the application data directory of the current user. -This is the location of log and database directories. +Note: Windows only. Defaults to the application data directory of the +current user. This is the location of log and database directories. .It Ev RABBITMQ_NODENAME Defaults to .Qq rabbit . diff --git a/docs/rabbitmq.conf.example b/docs/rabbitmq.conf.example index 6d30af1ecb..c0ef61fac1 100644 --- a/docs/rabbitmq.conf.example +++ b/docs/rabbitmq.conf.example @@ -1,5 +1,5 @@ # ====================================== -# RabbbitMQ broker section +# RabbitMQ broker section # ====================================== ## Related doc guide: http://rabbitmq.com/configure.html. See @@ -240,6 +240,13 @@ # tcp_listen_options.backlog = 128 # tcp_listen_options.nodelay = true # tcp_listen_options.exit_on_close = false +# +# tcp_listen_options.keepalive = true +# tcp_listen_options.send_timeout = 15000 +# +# tcp_listen_options.buffer = 196608 +# tcp_listen_options.sndbuf = 196608 +# tcp_listen_options.recbuf = 196608 ## ## Resource Limits & Flow Control @@ -345,23 +352,23 @@ ## Relevant doc guide: http://rabbitmq.com//cluster-formation.html ## -# autocluster.peer_discovery_backend = rabbit_peer_discovery_classic_config +# cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config # -# autocluster.classic_config.nodes.node1 = rabbit1@hostname -# autocluster.classic_config.nodes.node2 = rabbit2@hostname -# autocluster.classic_config.nodes.node3 = rabbit3@hostname -# autocluster.classic_config.nodes.node4 = rabbit4@hostname +# cluster_formation.classic_config.nodes.1 = rabbit1@hostname +# cluster_formation.classic_config.nodes.2 = rabbit2@hostname +# cluster_formation.classic_config.nodes.3 = rabbit3@hostname +# cluster_formation.classic_config.nodes.4 = rabbit4@hostname ## DNS-based peer discovery. This backend will list A records ## of the configured hostname and perform reverse lookups for ## the addresses returned. -# autocluster.peer_discovery_backend = rabbit_peer_discovery_dns -# autocluster.dns.hostname = rabbitmq.discovery.mycompany.local +# cluster_formation.peer_discovery_backend = rabbit_peer_discovery_dns +# cluster_formation.dns.hostname = discovery.eng.example.local ## This node's type can be configured. If you are not sure ## what node type to use, always use 'disc'. -# autocluster.node_type = disc +# cluster_formation.node_type = disc ## Interval (in milliseconds) at which we send keepalive messages ## to other cluster members. Note that this is not the same thing @@ -452,7 +459,7 @@ # Kernel section # ====================================== -# kernel.net_ticktime = 60 +# net_ticktime = 60 ## ---------------------------------------------------------------------------- ## RabbitMQ Management Plugin @@ -684,7 +691,7 @@ ## # log.file.level = info -## File rotation config. No rotation by defualt. +## File rotation config. No rotation by default. ## DO NOT SET rotation date to ''. Leave the value unset if "" is the desired value # log.file.rotation.date = $D0 # log.file.rotation.size = 0 diff --git a/erlang.mk b/erlang.mk index 1a45ad1bbe..d0c5b398db 100644 --- a/erlang.mk +++ b/erlang.mk @@ -17,7 +17,7 @@ ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) export ERLANG_MK_FILENAME -ERLANG_MK_VERSION = 2.0.0-pre.2-278-gd9a9158 +ERLANG_MK_VERSION = 2.0.0-pre.2-304-g5a961bd ERLANG_MK_WITHOUT = # Make 3.81 and 3.82 are deprecated. @@ -199,6 +199,87 @@ endif # The erlang.mk package index is bundled in the default erlang.mk build. # Search for the string "copyright" to skip to the rest of the code. +# Copyright (c) 2015-2017, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: distclean-kerl + +KERL_INSTALL_DIR ?= $(HOME)/erlang + +ifeq ($(strip $(KERL)),) +KERL := $(ERLANG_MK_TMP)/kerl/kerl +endif + +export KERL + +KERL_GIT ?= https://github.com/kerl/kerl +KERL_COMMIT ?= master + +KERL_MAKEFLAGS ?= + +OTP_GIT ?= https://github.com/erlang/otp + +define kerl_otp_target +ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(1)),) +$(KERL_INSTALL_DIR)/$(1): $(KERL) + MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $(1) $(1) + $(KERL) install $(1) $(KERL_INSTALL_DIR)/$(1) +endif +endef + +define kerl_hipe_target +ifeq ($(wildcard $(KERL_INSTALL_DIR)/$1-native),) +$(KERL_INSTALL_DIR)/$1-native: $(KERL) + KERL_CONFIGURE_OPTIONS=--enable-native-libs \ + MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $1 $1-native + $(KERL) install $1-native $(KERL_INSTALL_DIR)/$1-native +endif +endef + +$(KERL): + $(verbose) mkdir -p $(ERLANG_MK_TMP) + $(gen_verbose) git clone --depth 1 $(KERL_GIT) $(ERLANG_MK_TMP)/kerl + $(verbose) cd $(ERLANG_MK_TMP)/kerl && git checkout $(KERL_COMMIT) + $(verbose) chmod +x $(KERL) + +distclean:: distclean-kerl + +distclean-kerl: + $(gen_verbose) rm -rf $(KERL) + +# Allow users to select which version of Erlang/OTP to use for a project. + +ERLANG_OTP ?= +ERLANG_HIPE ?= + +# Use kerl to enforce a specific Erlang/OTP version for a project. +ifneq ($(strip $(ERLANG_OTP)),) +export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_OTP)/bin:$(PATH) +SHELL := env PATH=$(PATH) $(SHELL) +$(eval $(call kerl_otp_target,$(ERLANG_OTP))) + +# Build Erlang/OTP only if it doesn't already exist. +ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_OTP))$(BUILD_ERLANG_OTP),) +$(info Building Erlang/OTP $(ERLANG_OTP)... Please wait...) +$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_OTP) ERLANG_OTP=$(ERLANG_OTP) BUILD_ERLANG_OTP=1 >&2) +endif + +else +# Same for a HiPE enabled VM. +ifneq ($(strip $(ERLANG_HIPE)),) +export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_HIPE)-native/bin:$(PATH) +SHELL := env PATH=$(PATH) $(SHELL) +$(eval $(call kerl_hipe_target,$(ERLANG_HIPE))) + +# Build Erlang/OTP only if it doesn't already exist. +ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_HIPE))$(BUILD_ERLANG_OTP),) +$(info Building HiPE-enabled Erlang/OTP $(ERLANG_OTP)... Please wait...) +$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_HIPE) ERLANG_HIPE=$(ERLANG_HIPE) BUILD_ERLANG_OTP=1 >&2) +endif + +endif +endif + PACKAGES += aberth pkg_aberth_name = aberth pkg_aberth_description = Generic BERT-RPC server in Erlang @@ -535,14 +616,6 @@ pkg_cl_fetch = git pkg_cl_repo = https://github.com/tonyrog/cl pkg_cl_commit = master -PACKAGES += classifier -pkg_classifier_name = classifier -pkg_classifier_description = An Erlang Bayesian Filter and Text Classifier -pkg_classifier_homepage = https://github.com/inaka/classifier -pkg_classifier_fetch = git -pkg_classifier_repo = https://github.com/inaka/classifier -pkg_classifier_commit = master - PACKAGES += clique pkg_clique_name = clique pkg_clique_description = CLI Framework for Erlang @@ -943,14 +1016,6 @@ pkg_dnssd_fetch = git pkg_dnssd_repo = https://github.com/benoitc/dnssd_erlang pkg_dnssd_commit = master -PACKAGES += dtl -pkg_dtl_name = dtl -pkg_dtl_description = Django Template Language: A full-featured port of the Django template engine to Erlang. -pkg_dtl_homepage = https://github.com/oinksoft/dtl -pkg_dtl_fetch = git -pkg_dtl_repo = https://github.com/oinksoft/dtl -pkg_dtl_commit = master - PACKAGES += dynamic_compile pkg_dynamic_compile_name = dynamic_compile pkg_dynamic_compile_description = compile and load erlang modules from string input @@ -1519,6 +1584,14 @@ pkg_erwa_fetch = git pkg_erwa_repo = https://github.com/bwegh/erwa pkg_erwa_commit = master +PACKAGES += escalus +pkg_escalus_name = escalus +pkg_escalus_description = An XMPP client library in Erlang for conveniently testing XMPP servers +pkg_escalus_homepage = https://github.com/esl/escalus +pkg_escalus_fetch = git +pkg_escalus_repo = https://github.com/esl/escalus +pkg_escalus_commit = master + PACKAGES += espec pkg_espec_name = espec pkg_espec_description = ESpec: Behaviour driven development framework for Erlang @@ -1911,14 +1984,6 @@ pkg_gold_fever_fetch = git pkg_gold_fever_repo = https://github.com/inaka/gold_fever pkg_gold_fever_commit = master -PACKAGES += gossiperl -pkg_gossiperl_name = gossiperl -pkg_gossiperl_description = Gossip middleware in Erlang -pkg_gossiperl_homepage = http://gossiperl.com/ -pkg_gossiperl_fetch = git -pkg_gossiperl_repo = https://github.com/gossiperl/gossiperl -pkg_gossiperl_commit = master - PACKAGES += gpb pkg_gpb_name = gpb pkg_gpb_description = A Google Protobuf implementation for Erlang @@ -1943,6 +2008,22 @@ pkg_grapherl_fetch = git pkg_grapherl_repo = https://github.com/eproxus/grapherl pkg_grapherl_commit = master +PACKAGES += grpc +pkg_grpc_name = grpc +pkg_grpc_description = gRPC server in Erlang +pkg_grpc_homepage = https://github.com/Bluehouse-Technology/grpc +pkg_grpc_fetch = git +pkg_grpc_repo = https://github.com/Bluehouse-Technology/grpc +pkg_grpc_commit = master + +PACKAGES += grpc_client +pkg_grpc_client_name = grpc_client +pkg_grpc_client_description = gRPC client in Erlang +pkg_grpc_client_homepage = https://github.com/Bluehouse-Technology/grpc_client +pkg_grpc_client_fetch = git +pkg_grpc_client_repo = https://github.com/Bluehouse-Technology/grpc_client +pkg_grpc_client_commit = master + PACKAGES += gun pkg_gun_name = gun pkg_gun_description = Asynchronous SPDY, HTTP and Websocket client written in Erlang. @@ -3615,6 +3696,14 @@ pkg_stripe_fetch = git pkg_stripe_repo = https://github.com/mattsta/stripe-erlang pkg_stripe_commit = v1 +PACKAGES += subproc +pkg_subproc_name = subproc +pkg_subproc_description = unix subprocess manager with {active,once|false} modes +pkg_subproc_homepage = http://dozzie.jarowit.net/trac/wiki/subproc +pkg_subproc_fetch = git +pkg_subproc_repo = https://github.com/dozzie/subproc +pkg_subproc_commit = v0.1.0 + PACKAGES += supervisor3 pkg_supervisor3_name = supervisor3 pkg_supervisor3_description = OTP supervisor with additional strategies @@ -4357,6 +4446,10 @@ define dep_autopatch_rebar.erl Write("C_SRC_TYPE = rebar\n"), Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"), Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]), + ToList = fun + (V) when is_atom(V) -> atom_to_list(V); + (V) when is_list(V) -> "'\\"" ++ V ++ "\\"'" + end, fun() -> Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"), case lists:keyfind(erl_opts, 1, Conf) of @@ -4364,18 +4457,18 @@ define dep_autopatch_rebar.erl {_, ErlOpts} -> lists:foreach(fun ({d, D}) -> - Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); + Write("ERLC_OPTS += -D" ++ ToList(D) ++ "=1\n"); ({d, DKey, DVal}) -> - Write("ERLC_OPTS += -D" ++ atom_to_list(DKey) ++ "=" ++ atom_to_list(DVal) ++ "\n"); + Write("ERLC_OPTS += -D" ++ ToList(DKey) ++ "=" ++ ToList(DVal) ++ "\n"); ({i, I}) -> Write(["ERLC_OPTS += -I ", I, "\n"]); ({platform_define, Regex, D}) -> case rebar_utils:is_arch(Regex) of - true -> Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); + true -> Write("ERLC_OPTS += -D" ++ ToList(D) ++ "=1\n"); false -> ok end; ({parse_transform, PT}) -> - Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n"); + Write("ERLC_OPTS += +'{parse_transform, " ++ ToList(PT) ++ "}'\n"); (_) -> ok end, ErlOpts) end, @@ -4588,8 +4681,14 @@ endef define dep_autopatch_appsrc_script.erl AppSrc = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)", AppSrcScript = AppSrc ++ ".script", - Bindings = erl_eval:new_bindings(), - {ok, [Conf]} = file:script(AppSrcScript, Bindings), + {ok, Conf0} = file:consult(AppSrc), + Bindings0 = erl_eval:new_bindings(), + Bindings1 = erl_eval:add_binding('CONFIG', Conf0, Bindings0), + Bindings = erl_eval:add_binding('SCRIPT', AppSrcScript, Bindings1), + Conf = case file:script(AppSrcScript, Bindings) of + {ok, [C]} -> C; + {ok, C} -> C + end, ok = file:write_file(AppSrc, io_lib:format("~p.~n", [Conf])), halt() endef @@ -4602,7 +4701,11 @@ define dep_autopatch_appsrc.erl true -> {ok, [{application, $(1), L0}]} = file:consult(AppSrcIn), L1 = lists:keystore(modules, 1, L0, {modules, []}), - L2 = case lists:keyfind(vsn, 1, L1) of {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); _ -> L1 end, + L2 = case lists:keyfind(vsn, 1, L1) of + {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); + {_, {cmd, _}} -> lists:keyreplace(vsn, 1, L1, {vsn, "cmd"}); + _ -> L1 + end, L3 = case lists:keyfind(registered, 1, L2) of false -> [{registered, []}|L2]; _ -> L2 end, ok = file:write_file(AppSrcOut, io_lib:format("~p.~n", [{application, $(1), L3}])), case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end @@ -4640,7 +4743,7 @@ endef define dep_fetch_hex mkdir -p $(ERLANG_MK_TMP)/hex $(DEPS_DIR)/$1; \ $(call core_http_get,$(ERLANG_MK_TMP)/hex/$1.tar,\ - https://s3.amazonaws.com/s3.hex.pm/tarballs/$1-$(strip $(word 2,$(dep_$1))).tar); \ + https://repo.hex.pm/tarballs/$1-$(strip $(word 2,$(dep_$1))).tar); \ tar -xOf $(ERLANG_MK_TMP)/hex/$1.tar contents.tar.gz | tar -C $(DEPS_DIR)/$1 -xzf -; endef @@ -4741,87 +4844,6 @@ ERLANG_MK_RECURSIVE_REL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-rel-deps-list.log ERLANG_MK_RECURSIVE_TEST_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-test-deps-list.log ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-shell-deps-list.log -# Copyright (c) 2015-2017, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-kerl - -KERL_INSTALL_DIR ?= $(HOME)/erlang - -ifeq ($(strip $(KERL)),) -KERL := $(ERLANG_MK_TMP)/kerl/kerl -endif - -export KERL - -KERL_GIT ?= https://github.com/kerl/kerl -KERL_COMMIT ?= master - -KERL_MAKEFLAGS ?= - -OTP_GIT ?= https://github.com/erlang/otp - -define kerl_otp_target -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(1)),) -$(KERL_INSTALL_DIR)/$(1): $(KERL) - MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $(1) $(1) - $(KERL) install $(1) $(KERL_INSTALL_DIR)/$(1) -endif -endef - -define kerl_hipe_target -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$1-native),) -$(KERL_INSTALL_DIR)/$1-native: $(KERL) - KERL_CONFIGURE_OPTIONS=--enable-native-libs \ - MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $1 $1-native - $(KERL) install $1-native $(KERL_INSTALL_DIR)/$1-native -endif -endef - -$(KERL): - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(gen_verbose) git clone --depth 1 $(KERL_GIT) $(ERLANG_MK_TMP)/kerl - $(verbose) cd $(ERLANG_MK_TMP)/kerl && git checkout $(KERL_COMMIT) - $(verbose) chmod +x $(KERL) - -distclean:: distclean-kerl - -distclean-kerl: - $(gen_verbose) rm -rf $(KERL) - -# Allow users to select which version of Erlang/OTP to use for a project. - -ERLANG_OTP ?= -ERLANG_HIPE ?= - -# Use kerl to enforce a specific Erlang/OTP version for a project. -ifneq ($(strip $(ERLANG_OTP)),) -export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_OTP)/bin:$(PATH) -SHELL := env PATH=$(PATH) $(SHELL) -$(eval $(call kerl_otp_target,$(ERLANG_OTP))) - -# Build Erlang/OTP only if it doesn't already exist. -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_OTP))$(BUILD_ERLANG_OTP),) -$(info Building Erlang/OTP $(ERLANG_OTP)... Please wait...) -$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_OTP) ERLANG_OTP=$(ERLANG_OTP) BUILD_ERLANG_OTP=1 >&2) -endif - -else -# Same for a HiPE enabled VM. -ifneq ($(strip $(ERLANG_HIPE)),) -export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_HIPE)-native/bin:$(PATH) -SHELL := env PATH=$(PATH) $(SHELL) -$(eval $(call kerl_hipe_target,$(ERLANG_HIPE))) - -# Build Erlang/OTP only if it doesn't already exist. -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_HIPE))$(BUILD_ERLANG_OTP),) -$(info Building HiPE-enabled Erlang/OTP $(ERLANG_OTP)... Please wait...) -$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_HIPE) ERLANG_HIPE=$(ERLANG_HIPE) BUILD_ERLANG_OTP=1 >&2) -endif - -endif -endif - # Copyright (c) 2015-2016, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -4924,7 +4946,7 @@ define app_file {id$(comma)$(space)"$(1)"}$(comma)) {modules, [$(call comma_list,$(2))]}, {registered, []}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]}, + {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(foreach dep,$(DEPS),$(call dep_name,$(dep))))]}, {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),) ]}. endef @@ -4936,7 +4958,7 @@ define app_file {id$(comma)$(space)"$(1)"}$(comma)) {modules, [$(call comma_list,$(2))]}, {registered, [$(call comma_list,$(PROJECT)_sup $(PROJECT_REGISTERED))]}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]}, + {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(foreach dep,$(DEPS),$(call dep_name,$(dep))))]}, {mod, {$(PROJECT_MOD), []}}, {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),) ]}. @@ -5357,7 +5379,7 @@ install-docs:: install-asciidoc install-asciidoc: asciidoc-manual $(foreach s,$(MAN_SECTIONS),\ mkdir -p $(MAN_INSTALL_PATH)/man$s/ && \ - install -g `id -u` -o `id -g` -m 0644 doc/man$s/*.gz $(MAN_INSTALL_PATH)/man$s/;) + install -g `id -g` -o `id -u` -m 0644 doc/man$s/*.gz $(MAN_INSTALL_PATH)/man$s/;) distclean-asciidoc-manual: $(gen_verbose) rm -rf $(addprefix doc/man,$(MAN_SECTIONS)) @@ -6272,12 +6294,13 @@ endif EDOC_OPTS ?= EDOC_SRC_DIRS ?= +EDOC_OUTPUT ?= doc define edoc.erl SrcPaths = lists:foldl(fun(P, Acc) -> filelib:wildcard(atom_to_list(P) ++ "/{src,c_src}") ++ Acc end, [], [$(call comma_list,$(patsubst %,'%',$(EDOC_SRC_DIRS)))]), - DefaultOpts = [{source_path, SrcPaths}, {subpackages, false}], + DefaultOpts = [{dir, "$(EDOC_OUTPUT)"}, {source_path, SrcPaths}, {subpackages, false}], edoc:application($(1), ".", [$(2)] ++ DefaultOpts), halt(0). endef @@ -6296,7 +6319,7 @@ edoc: distclean-edoc doc-deps $(gen_verbose) $(call erlang,$(call edoc.erl,$(PROJECT),$(EDOC_OPTS))) distclean-edoc: - $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info + $(gen_verbose) rm -f $(EDOC_OUTPUT)/*.css $(EDOC_OUTPUT)/*.html $(EDOC_OUTPUT)/*.png $(EDOC_OUTPUT)/edoc-info # Copyright (c) 2013-2016, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -6448,7 +6471,7 @@ define eunit.erl case "$(COVER)" of "" -> ok; _ -> - cover:export("eunit.coverdata") + cover:export("$(COVER_DATA_DIR)/eunit.coverdata") end, halt() endef @@ -6457,10 +6480,10 @@ EUNIT_ERL_OPTS += -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(CURDIR ifdef t ifeq (,$(findstring :,$(t))) -eunit: test-build +eunit: test-build cover-data-dir $(gen_verbose) $(call erlang,$(call eunit.erl,['$(t)']),$(EUNIT_ERL_OPTS)) else -eunit: test-build +eunit: test-build cover-data-dir $(gen_verbose) $(call erlang,$(call eunit.erl,fun $(t)/0),$(EUNIT_ERL_OPTS)) endif else @@ -6470,7 +6493,7 @@ EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.erl))) EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \ $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),'$(mod)') -eunit: test-build $(if $(IS_APP),,apps-eunit) +eunit: test-build $(if $(IS_APP),,apps-eunit) cover-data-dir $(gen_verbose) $(call erlang,$(call eunit.erl,[$(call comma_list,$(EUNIT_MODS))]),$(EUNIT_ERL_OPTS)) ifneq ($(ALL_APPS_DIRS),) @@ -6498,7 +6521,7 @@ define proper_check.erl case atom_to_list(F) of "prop_" ++ _ -> io:format("Testing ~p:~p/0~n", [M, F]), - proper:quickcheck(M:F()); + proper:quickcheck(M:F(), nocolors); _ -> true end @@ -6508,7 +6531,7 @@ define proper_check.erl case $(1) of all -> [true] =:= lists:usort([Module(M) || M <- [$(call comma_list,$(3))]]); module -> Module($(2)); - function -> proper:quickcheck($(2)) + function -> proper:quickcheck($(2), nocolors) end of true -> halt(0); @@ -6656,6 +6679,69 @@ build-shell-deps: $(ALL_SHELL_DEPS_DIRS) shell: build-shell-deps $(gen_verbose) $(SHELL_ERL) -pa $(SHELL_PATHS) $(SHELL_OPTS) +# Copyright 2017, Stanislaw Klekot +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: distclean-sphinx sphinx + +# Configuration. + +SPHINX_BUILD ?= sphinx-build +SPHINX_SOURCE ?= doc +SPHINX_CONFDIR ?= +SPHINX_FORMATS ?= html +SPHINX_DOCTREES ?= $(ERLANG_MK_TMP)/sphinx.doctrees +SPHINX_OPTS ?= + +#sphinx_html_opts = +#sphinx_html_output = html +#sphinx_man_opts = +#sphinx_man_output = man +#sphinx_latex_opts = +#sphinx_latex_output = latex + +# Helpers. + +sphinx_build_0 = @echo " SPHINX" $1; $(SPHINX_BUILD) -N -q +sphinx_build_1 = $(SPHINX_BUILD) -N +sphinx_build_2 = set -x; $(SPHINX_BUILD) +sphinx_build = $(sphinx_build_$(V)) + +define sphinx.build +$(call sphinx_build,$1) -b $1 -d $(SPHINX_DOCTREES) $(if $(SPHINX_CONFDIR),-c $(SPHINX_CONFDIR)) $(SPHINX_OPTS) $(sphinx_$1_opts) -- $(SPHINX_SOURCE) $(call sphinx.output,$1) + +endef + +define sphinx.output +$(if $(sphinx_$1_output),$(sphinx_$1_output),$1) +endef + +# Targets. + +ifneq ($(wildcard $(if $(SPHINX_CONFDIR),$(SPHINX_CONFDIR),$(SPHINX_SOURCE))/conf.py),) +docs:: sphinx +distclean:: distclean-sphinx +endif + +help:: + $(verbose) printf "%s\n" "" \ + "Sphinx targets:" \ + " sphinx Generate Sphinx documentation." \ + "" \ + "ReST sources and 'conf.py' file are expected in directory pointed by" \ + "SPHINX_SOURCE ('doc' by default). SPHINX_FORMATS lists formats to build (only" \ + "'html' format is generated by default); target directory can be specified by" \ + 'setting sphinx_$${format}_output, for example: sphinx_html_output = output/html' \ + "Additional Sphinx options can be set in SPHINX_OPTS." + +# Plugin-specific targets. + +sphinx: + $(foreach F,$(SPHINX_FORMATS),$(call sphinx.build,$F)) + +distclean-sphinx: + $(gen_verbose) rm -rf $(filter-out $(SPHINX_SOURCE),$(foreach F,$(SPHINX_FORMATS),$(call sphinx.output,$F))) + # Copyright (c) 2017, Jean-Sébastien Pédron # This file is contributed to erlang.mk and subject to the terms of the ISC License. @@ -6761,23 +6847,20 @@ distclean-xref: # Copyright (c) 2015, Viktor Söderqvist # This file is part of erlang.mk and subject to the terms of the ISC License. -COVER_REPORT_DIR = cover +COVER_REPORT_DIR ?= cover +COVER_DATA_DIR ?= $(CURDIR) # Hook in coverage to ct ifdef COVER ifdef CT_RUN ifneq ($(wildcard $(TEST_DIR)),) -# All modules in 'ebin' -COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam))) - test-build:: $(TEST_DIR)/ct.cover.spec -$(TEST_DIR)/ct.cover.spec: - $(verbose) echo Cover mods: $(COVER_MODS) +$(TEST_DIR)/ct.cover.spec: cover-data-dir $(gen_verbose) printf "%s\n" \ - '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ - '{export,"$(CURDIR)/ct.coverdata"}.' > $@ + "{incl_app, '$(PROJECT)', details}." \ + '{export,"$(abspath $(COVER_DATA_DIR))/ct.coverdata"}.' > $@ CT_RUN += -cover $(TEST_DIR)/ct.cover.spec endif @@ -6791,6 +6874,13 @@ ifneq ($(COVER_REPORT_DIR),) tests:: $(verbose) $(MAKE) --no-print-directory cover-report endif + +cover-data-dir: | $(COVER_DATA_DIR) + +$(COVER_DATA_DIR): + $(verbose) mkdir -p $(COVER_DATA_DIR) +else +cover-data-dir: endif clean:: coverdata-clean @@ -6813,19 +6903,19 @@ help:: # Plugin specific targets -COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) +COVERDATA = $(filter-out $(COVER_DATA_DIR)/all.coverdata,$(wildcard $(COVER_DATA_DIR)/*.coverdata)) .PHONY: coverdata-clean coverdata-clean: - $(gen_verbose) rm -f *.coverdata $(TEST_DIR)/ct.cover.spec + $(gen_verbose) rm -f $(COVER_DATA_DIR)/*.coverdata $(TEST_DIR)/ct.cover.spec # Merge all coverdata files into one. define cover_export.erl $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) - cover:export("$@"), halt(0). + cover:export("$(COVER_DATA_DIR)/$@"), halt(0). endef -all.coverdata: $(COVERDATA) +all.coverdata: $(COVERDATA) cover-data-dir $(gen_verbose) $(call erlang,$(cover_export.erl)) # These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to @@ -6836,6 +6926,7 @@ ifneq ($(COVER_REPORT_DIR),) cover-report-clean: $(gen_verbose) rm -rf $(COVER_REPORT_DIR) + $(if $(shell ls -A $(COVER_DATA_DIR)/),,$(verbose) rmdir $(COVER_DATA_DIR)) ifeq ($(COVERDATA),) cover-report: diff --git a/priv/schema/rabbit.schema b/priv/schema/rabbit.schema index 9bff18d75d..359abeb117 100644 --- a/priv/schema/rabbit.schema +++ b/priv/schema/rabbit.schema @@ -546,6 +546,7 @@ end}. end }. + %% Customising Socket Options. %% %% See (http://www.erlang.org/doc/man/inet.html#setopts-2) for @@ -801,6 +802,15 @@ fun(Conf) -> end end}. +%% Number of delegate processes to use for intra-cluster +%% communication. On a machine which has a very large number of cores +%% and is also part of a cluster, you may wish to increase this value. +%% + +{mapping, "delegate_count", "rabbit.delegate_count", [ + {datatype, integer}, {validators, ["non_negative_integer"]} +]}. + %% Mirror sync batch size, in messages. Increasing this will speed %% up syncing but total batch size in bytes must not exceed 2 GiB. %% Available in RabbitMQ 3.6.0 or later. @@ -859,12 +869,12 @@ end}. %% Cluster formation: Randomized startup delay -{mapping, "cluster_formation.randomized_startup_delay_range.min", "rabbit.cluster_formation.randomized_delay_range", +{mapping, "cluster_formation.randomized_startup_delay_range.min", "rabbit.cluster_formation.randomized_startup_delay_range", [{datatype, integer}]}. -{mapping, "cluster_formation.randomized_startup_delay_range.max", "rabbit.cluster_formation.randomized_delay_range", +{mapping, "cluster_formation.randomized_startup_delay_range.max", "rabbit.cluster_formation.randomized_startup_delay_range", [{datatype, integer}]}. -{translation, "rabbit.cluster_formation.randomized_delay_range", +{translation, "rabbit.cluster_formation.randomized_startup_delay_range", fun(Conf) -> Min = cuttlefish:conf_get("cluster_formation.randomized_startup_delay_range.min", Conf, undefined), Max = cuttlefish:conf_get("cluster_formation.randomized_startup_delay_range.max", Conf, undefined), @@ -1140,6 +1150,15 @@ end}. {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}} ]}. +% ========================== +% Kernel section +% ========================== + +{mapping, "net_ticktime", "kernel.net_ticktime",[ + {datatype, [integer]}, + {validators, ["non_zero_positive_integer"]} +]}. + % =============================== % Validators % =============================== @@ -1189,3 +1208,8 @@ end}. fun(Int) when is_integer(Int) -> Int >= 0 end}. + +{validator, "non_zero_positive_integer", "number should be greater or equal to one", +fun(Int) when is_integer(Int) -> + Int >= 1 +end}. diff --git a/rabbitmq-components.mk b/rabbitmq-components.mk index 2ed9bfb568..80b5e0dba9 100644 --- a/rabbitmq-components.mk +++ b/rabbitmq-components.mk @@ -40,6 +40,7 @@ endif dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master dep_amqp10_client = git_rmq rabbitmq-amqp1.0-client $(current_rmq_ref) $(base_rmq_ref) master dep_amqp10_common = git_rmq rabbitmq-amqp1.0-common $(current_rmq_ref) $(base_rmq_ref) master +dep_ra = git_rmq ra $(current_rmq_ref) $(base_rmq_ref) master dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master @@ -101,7 +102,6 @@ dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master -dep_ra = git_rmq ra $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master @@ -111,8 +111,8 @@ dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(curre # all projects use the same versions. It avoids conflicts and makes it # possible to work with rabbitmq-public-umbrella. -dep_cowboy = hex 2.0.0 -dep_cowlib = hex 2.0.0 +dep_cowboy = hex 2.2.2 +dep_cowlib = hex 2.1.0 dep_jsx = hex 2.8.2 dep_lager = hex 3.5.1 dep_ranch = hex 1.4.0 @@ -124,6 +124,7 @@ dep_sockjs = git https://github.com/rabbitmq/sockjs-erlang.git 405990ea62353d98d RABBITMQ_COMPONENTS = amqp_client \ amqp10_common \ amqp10_client \ + ra \ rabbit \ rabbit_common \ rabbitmq_amqp1_0 \ @@ -182,8 +183,7 @@ RABBITMQ_COMPONENTS = amqp_client \ rabbitmq_web_mqtt_examples \ rabbitmq_web_stomp \ rabbitmq_web_stomp_examples \ - rabbitmq_website \ - ra + rabbitmq_website # Several components have a custom erlang.mk/build.config, mainly # to disable eunit. Therefore, we can't use the top-level project's @@ -203,7 +203,7 @@ export current_rmq_ref ifeq ($(origin base_rmq_ref),undefined) ifneq ($(wildcard .git),) -possible_base_rmq_ref := v3.7.x +possible_base_rmq_ref := master ifeq ($(possible_base_rmq_ref),$(current_rmq_ref)) base_rmq_ref := $(current_rmq_ref) else @@ -303,7 +303,7 @@ prepare-dist:: @: # -------------------------------------------------------------------- -# rabbitmq-components.mk checks. +# Umbrella-specific settings. # -------------------------------------------------------------------- # If this project is under the Umbrella project, we override $(DEPS_DIR) @@ -325,28 +325,3 @@ ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),) SKIP_DEPS = 1 endif endif - -UPSTREAM_RMQ_COMPONENTS_MK = $(DEPS_DIR)/rabbit_common/mk/rabbitmq-components.mk - -ifeq ($(PROJECT),rabbit_common) -check-rabbitmq-components.mk: - @: -else -check-rabbitmq-components.mk: - $(verbose) cmp -s rabbitmq-components.mk \ - $(UPSTREAM_RMQ_COMPONENTS_MK) || \ - (echo "error: rabbitmq-components.mk must be updated!" 1>&2; \ - false) -endif - -ifeq ($(PROJECT),rabbit_common) -rabbitmq-components-mk: - @: -else -rabbitmq-components-mk: - $(gen_verbose) cp -a $(UPSTREAM_RMQ_COMPONENTS_MK) . -ifeq ($(DO_COMMIT),yes) - $(verbose) git diff --quiet rabbitmq-components.mk \ - || git commit -m 'Update rabbitmq-components.mk' rabbitmq-components.mk -endif -endif diff --git a/scripts/rabbitmq-diagnostics.bat b/scripts/rabbitmq-diagnostics.bat index 58b6c69e4f..311cfa3f5e 100644 --- a/scripts/rabbitmq-diagnostics.bat +++ b/scripts/rabbitmq-diagnostics.bat @@ -49,6 +49,8 @@ if not defined ERL_CRASH_DUMP_SECONDS ( -boot !CLEAN_BOOT_FILE! ^ -noinput -noshell -hidden -smp enable ^ !RABBITMQ_CTL_ERL_ARGS! ^ +-kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^ +-kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^ -sasl errlog_type error ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ -nodename !RABBITMQ_NODENAME! ^ diff --git a/scripts/rabbitmq-env b/scripts/rabbitmq-env index 67a3bddf48..7bc9587303 100755 --- a/scripts/rabbitmq-env +++ b/scripts/rabbitmq-env @@ -82,13 +82,23 @@ ESCRIPT_DIR="${RABBITMQ_HOME}/escript" [ -f ${RABBITMQ_CONF_ENV_FILE} ] && . ${RABBITMQ_CONF_ENV_FILE} || true DEFAULT_SCHEDULER_BIND_TYPE="db" -[ "x" = "x$RABBITMQ_SCHEDULER_BIND_TYPE" ] && RABBITMQ_SCHEDULER_BIND_TYPE=${DEFAULT_SCHEDULER_BIND_TYPE} +[ -n "$SCHEDULER_BIND_TYPE" ] || SCHEDULER_BIND_TYPE="$DEFAULT_SCHEDULER_BIND_TYPE" +[ -n "$RABBITMQ_SCHEDULER_BIND_TYPE" ] || RABBITMQ_SCHEDULER_BIND_TYPE="$SCHEDULER_BIND_TYPE" -DEFAULT_DISTRIBUTION_BUFFER_SIZE=128000 -[ "x" = "x$RABBITMQ_DISTRIBUTION_BUFFER_SIZE" ] && RABBITMQ_DISTRIBUTION_BUFFER_SIZE=${DEFAULT_DISTRIBUTION_BUFFER_SIZE} +DEFAULT_DISTRIBUTION_BUFFER_SIZE=1280000 +[ -n "$DISTRIBUTION_BUFFER_SIZE" ] || DISTRIBUTION_BUFFER_SIZE="$DEFAULT_DISTRIBUTION_BUFFER_SIZE" +[ -n "$RABBITMQ_DISTRIBUTION_BUFFER_SIZE" ] || RABBITMQ_DISTRIBUTION_BUFFER_SIZE="$DISTRIBUTION_BUFFER_SIZE" -## Common defaults -SERVER_ERL_ARGS="+P 1048576 +t 5000000 +stbt $RABBITMQ_SCHEDULER_BIND_TYPE +zdbbl $RABBITMQ_DISTRIBUTION_BUFFER_SIZE" +DEFAULT_MAX_NUMBER_OF_PROCESSES=10485760 +[ -n "$MAX_NUMBER_OF_PROCESSES" ] || MAX_NUMBER_OF_PROCESSES="$DEFAULT_MAX_NUMBER_OF_PROCESSES" +[ -n "$RABBITMQ_MAX_NUMBER_OF_PROCESSES" ] || RABBITMQ_MAX_NUMBER_OF_PROCESSES="$MAX_NUMBER_OF_PROCESSES" + +DEFAULT_MAX_NUMBER_OF_ATOMS=5000000 +[ -n "$MAX_NUMBER_OF_ATOMS" ] || MAX_NUMBER_OF_ATOMS="$DEFAULT_MAX_NUMBER_OF_ATOMS" +[ -n "$RABBITMQ_MAX_NUMBER_OF_ATOMS" ] || RABBITMQ_MAX_NUMBER_OF_ATOMS="$MAX_NUMBER_OF_ATOMS" + +## Common server defaults +SERVER_ERL_ARGS=" +P $RABBITMQ_MAX_NUMBER_OF_PROCESSES +t $RABBITMQ_MAX_NUMBER_OF_ATOMS +stbt $RABBITMQ_SCHEDULER_BIND_TYPE +zdbbl $RABBITMQ_DISTRIBUTION_BUFFER_SIZE " # We save the current value of $RABBITMQ_PID_FILE in case it was set by # an init script. If $CONF_ENV_FILE overrides it again, we must ignore @@ -180,6 +190,7 @@ rmq_check_if_shared_with_mnesia() { DEFAULT_NODE_IP_ADDRESS=auto DEFAULT_NODE_PORT=5672 + [ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS} [ "x" = "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_PORT=${NODE_PORT} @@ -190,6 +201,12 @@ DEFAULT_NODE_PORT=5672 [ "x" = "x$RABBITMQ_DIST_PORT" ] && [ "x" = "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_DIST_PORT=$((${DEFAULT_NODE_PORT} + 20000)) [ "x" = "x$RABBITMQ_DIST_PORT" ] && [ "x" != "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_DIST_PORT=$((${RABBITMQ_NODE_PORT} + 20000)) +[ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS=${CTL_ERL_ARGS} +[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MIN" ] && RABBITMQ_CTL_DIST_PORT_MIN=${CTL_DIST_PORT_MIN} +[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MAX" ] && RABBITMQ_CTL_DIST_PORT_MAX=${CTL_DIST_PORT_MAX} +[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MIN" ] && RABBITMQ_CTL_DIST_PORT_MIN=$((${RABBITMQ_DIST_PORT} + 10000)) +[ "x" = "x$RABBITMQ_CTL_DIST_PORT_MAX" ] && RABBITMQ_CTL_DIST_PORT_MAX=$((${RABBITMQ_DIST_PORT} + 10010)) + [ "x" = "x$RABBITMQ_NODENAME" ] && RABBITMQ_NODENAME=${NODENAME} [ "x" = "x$RABBITMQ_IO_THREAD_POOL_SIZE" ] && RABBITMQ_IO_THREAD_POOL_SIZE=${IO_THREAD_POOL_SIZE} [ "x" = "x$RABBITMQ_SERVER_ERL_ARGS" ] && RABBITMQ_SERVER_ERL_ARGS=${SERVER_ERL_ARGS} @@ -244,8 +261,6 @@ rmq_normalize_path_var RABBITMQ_LOGS rmq_normalize_path_var RABBITMQ_UPGRADE_LOG -[ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS=${CTL_ERL_ARGS} - # Check if files and directories non-related to Mnesia are configured # to be in $RABBITMQ_MNESIA_DIR. If this is the case, issue a warning # because it will prevent auto-clustering from working (the node will be @@ -349,7 +364,9 @@ run_escript() exec "${ERL_DIR}erl" +B \ -boot "${CLEAN_BOOT_FILE}" \ -noinput -noshell -hidden -smp enable \ - ${RABBITMQ_CTL_ERL_ARGS} \ + $RABBITMQ_CTL_ERL_ARGS \ + -kernel inet_dist_listen_min "$RABBITMQ_CTL_DIST_PORT_MIN" \ + -kernel inet_dist_listen_max "$RABBITMQ_CTL_DIST_PORT_MAX" \ -sasl errlog_type error \ -mnesia dir "\"${RABBITMQ_MNESIA_DIR}\"" \ -nodename "$RABBITMQ_NODENAME" \ diff --git a/scripts/rabbitmq-env.bat b/scripts/rabbitmq-env.bat index 4e23cdcd0e..6c68b29d37 100644 --- a/scripts/rabbitmq-env.bat +++ b/scripts/rabbitmq-env.bat @@ -27,37 +27,8 @@ if not defined ERLANG_HOME ( ) REM ## Set defaults -REM . ${SCRIPT_DIR}/rabbitmq-defaults call "%SCRIPT_DIR%\rabbitmq-defaults.bat" -set DEFAULT_SCHEDULER_BIND_TYPE=db - -REM [ "x" = "x$RABBITMQ_SCHEDULER_BIND_TYPE" ] && RABBITMQ_SCHEDULER_BIND_TYPE=${DEFAULT_SCHEDULER_BIND_TYPE} -REM set the default scheduling bind type -if "!RABBITMQ_SCHEDULER_BIND_TYPE!"=="" ( - set RABBITMQ_SCHEDULER_BIND_TYPE=!DEFAULT_SCHEDULER_BIND_TYPE! -) - -REM DEFAULT_DISTRIBUTION_BUFFER_SIZE=128000 -REM set the VM distribution buffer size -REM [ "x" = "x$RABBITMQ_DISTRIBUTION_BUFFER_SIZE" ] && RABBITMQ_DISTRIBUTION_BUFFER_SIZE=${DEFAULT_DISTRIBUTION_BUFFER_SIZE} -set DEFAULT_DISTRIBUTION_BUFFER_SIZE=128000 -if "!RABBITMQ_DISTRIBUTION_BUFFER_SIZE!"=="" ( - set RABBITMQ_DISTRIBUTION_BUFFER_SIZE=!DEFAULT_DISTRIBUTION_BUFFER_SIZE! -) - -REM # warn about old rabbitmq.conf file, if no new one -REM if [ -f /etc/rabbitmq/rabbitmq.conf ] && \ -REM [ ! -f ${CONF_ENV_FILE} ] ; then -REM echo -n "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- " -REM echo "location has moved to ${CONF_ENV_FILE}" -REM fi - -REM Common defaults -set SERVER_ERL_ARGS=+P 1048576 +t 5000000 +stbt !RABBITMQ_SCHEDULER_BIND_TYPE! +zdbbl !RABBITMQ_DISTRIBUTION_BUFFER_SIZE! - -REM ## Get configuration variables from the configure environment file -REM [ -f ${CONF_ENV_FILE} ] && . ${CONF_ENV_FILE} || true if "!RABBITMQ_CONF_ENV_FILE!"=="" ( set RABBITMQ_CONF_ENV_FILE=!CONF_ENV_FILE! ) @@ -66,6 +37,41 @@ if exist "!RABBITMQ_CONF_ENV_FILE!" ( call "!RABBITMQ_CONF_ENV_FILE!" ) +set DEFAULT_SCHEDULER_BIND_TYPE=db +if "!RABBITMQ_SCHEDULER_BIND_TYPE!"=="" ( + set RABBITMQ_SCHEDULER_BIND_TYPE=!SCHEDULER_BIND_TYPE! +) +if "!RABBITMQ_SCHEDULER_BIND_TYPE!"=="" ( + set RABBITMQ_SCHEDULER_BIND_TYPE=!DEFAULT_SCHEDULER_BIND_TYPE! +) + +set DEFAULT_DISTRIBUTION_BUFFER_SIZE=128000 +if "!RABBITMQ_DISTRIBUTION_BUFFER_SIZE!"=="" ( + set RABBITMQ_DISTRIBUTION_BUFFER_SIZE=!DISTRIBUTION_BUFFER_SIZE! +) +if "!RABBITMQ_DISTRIBUTION_BUFFER_SIZE!"=="" ( + set RABBITMQ_DISTRIBUTION_BUFFER_SIZE=!DEFAULT_DISTRIBUTION_BUFFER_SIZE! +) + +set DEFAULT_MAX_NUMBER_OF_PROCESSES=1048576 +if "!RABBITMQ_MAX_NUMBER_OF_PROCESSES!"=="" ( + set RABBITMQ_MAX_NUMBER_OF_PROCESSES=!MAX_NUMBER_OF_PROCESSES! +) +if "!RABBITMQ_MAX_NUMBER_OF_PROCESSES!"=="" ( + set RABBITMQ_MAX_NUMBER_OF_PROCESSES=!DEFAULT_MAX_NUMBER_OF_PROCESSES! +) + +set DEFAULT_MAX_NUMBER_OF_ATOMS=5000000 +if "!RABBITMQ_MAX_NUMBER_OF_ATOMS!"=="" ( + set RABBITMQ_MAX_NUMBER_OF_ATOMS=!MAX_NUMBER_OF_ATOMS! +) +if "!RABBITMQ_MAX_NUMBER_OF_ATOMS!"=="" ( + set RABBITMQ_MAX_NUMBER_OF_ATOMS=!DEFAULT_MAX_NUMBER_OF_ATOMS! +) + +REM Common defaults +set SERVER_ERL_ARGS=+P !RABBITMQ_MAX_NUMBER_OF_PROCESSES! +t !RABBITMQ_MAX_NUMBER_OF_ATOMS! +stbt !RABBITMQ_SCHEDULER_BIND_TYPE! +zdbbl !RABBITMQ_DISTRIBUTION_BUFFER_SIZE! + REM Make sure $RABBITMQ_BASE contains no non-ASCII characters. if not exist "!RABBITMQ_BASE!" ( mkdir "!RABBITMQ_BASE!" @@ -73,17 +79,18 @@ if not exist "!RABBITMQ_BASE!" ( for /f "delims=" %%F in ("!RABBITMQ_BASE!") do set RABBITMQ_BASE=%%~sF REM Check for the short names here too -if "!RABBITMQ_USE_LONGNAME!"=="" ( - if "!USE_LONGNAME!"=="" ( - set RABBITMQ_NAME_TYPE="-sname" - set NAMETYPE=shortnames - ) -) - if "!RABBITMQ_USE_LONGNAME!"=="true" ( + set RABBITMQ_NAME_TYPE=-name + set NAMETYPE=longnames +) else ( if "!USE_LONGNAME!"=="true" ( - set RABBITMQ_NAME_TYPE="-name" + set RABBITMQ_USE_LONGNAME=true + set RABBITMQ_NAME_TYPE=-name set NAMETYPE=longnames + ) else ( + set RABBITMQ_USE_LONGNAME=false + set RABBITMQ_NAME_TYPE=-sname + set NAMETYPE=shortnames ) ) @@ -333,11 +340,27 @@ if "!ERL_CRASH_DUMP!"=="" ( ) REM [ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS=${CTL_ERL_ARGS} -if "!$RABBITMQ_CTL_ERL_ARGS!"=="" ( +if "!RABBITMQ_CTL_ERL_ARGS!"=="" ( if not "!CTL_ERL_ARGS!"=="" ( set RABBITMQ_CTL_ERL_ARGS=!CTL_ERL_ARGS! ) ) +if "!RABBITMQ_CTL_DIST_PORT_MIN!"=="" ( + if not "!CTL_DIST_PORT_MIN!"=="" ( + set RABBITMQ_CTL_DIST_PORT_MIN=!CTL_DIST_PORT_MIN! + ) +) +if "!RABBITMQ_CTL_DIST_PORT_MAX!"=="" ( + if not "!CTL_DIST_PORT_MAX!"=="" ( + set RABBITMQ_CTL_DIST_PORT_MAX=!CTL_DIST_PORT_MAX! + ) +) +if "!RABBITMQ_CTL_DIST_PORT_MIN!"=="" ( + set /a RABBITMQ_CTL_DIST_PORT_MIN=10000+!RABBITMQ_DIST_PORT! +) +if "!RABBITMQ_CTL_DIST_PORT_MAX!"=="" ( + set /a RABBITMQ_CTL_DIST_PORT_MAX=10010+!RABBITMQ_DIST_PORT! +) REM ADDITIONAL WINDOWS ONLY CONFIG ITEMS REM rabbitmq-plugins.bat diff --git a/scripts/rabbitmq-plugins.bat b/scripts/rabbitmq-plugins.bat index 748a8ac20d..2c5087a043 100644 --- a/scripts/rabbitmq-plugins.bat +++ b/scripts/rabbitmq-plugins.bat @@ -49,6 +49,8 @@ if not defined ERL_CRASH_DUMP_SECONDS ( -boot !CLEAN_BOOT_FILE! ^ -noinput -noshell -hidden -smp enable ^ !RABBITMQ_CTL_ERL_ARGS! ^ +-kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^ +-kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^ -sasl errlog_type error ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ -nodename !RABBITMQ_NODENAME! ^ diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat index 8bb7dd07bf..26fc251251 100644 --- a/scripts/rabbitmq-server.bat +++ b/scripts/rabbitmq-server.bat @@ -55,12 +55,13 @@ if "!RABBITMQ_ADVANCED_CONFIG_FILE!" == "!RABBITMQ_ADVANCED_CONFIG_FILE_NOEX!.co "!ERLANG_HOME!\bin\erl.exe" ^ -pa "!RABBITMQ_EBIN_ROOT!" ^ + -boot !CLEAN_BOOT_FILE! ^ -noinput -hidden ^ -s rabbit_prelaunch ^ - !RABBITMQ_NAME_TYPE! rabbitmqprelaunch!RANDOM!!TIME:~9! ^ - -conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^ + !RABBITMQ_NAME_TYPE! rabbitmqprelaunch!RANDOM!!TIME:~9!@localhost ^ + -conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^ -rabbit enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" ^ - -rabbit plugins_dir "!$RABBITMQ_PLUGINS_DIR!" ^ + -rabbit plugins_dir "!RABBITMQ_PLUGINS_DIR!" ^ -extra "!RABBITMQ_NODENAME!" if ERRORLEVEL 2 ( diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat index 0b09392b1a..fb99b2babf 100644 --- a/scripts/rabbitmq-service.bat +++ b/scripts/rabbitmq-service.bat @@ -139,12 +139,14 @@ if "!RABBITMQ_ADVANCED_CONFIG_FILE!" == "!RABBITMQ_ADVANCED_CONFIG_FILE_NOEX!.co "!ERLANG_HOME!\bin\erl.exe" ^ -pa "!RABBITMQ_EBIN_ROOT!" ^ + -boot !CLEAN_BOOT_FILE! ^ -noinput -hidden ^ -s rabbit_prelaunch ^ + !RABBITMQ_NAME_TYPE! rabbitmqprelaunch!RANDOM!!TIME:~9!@localhost ^ -conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^ -rabbit enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" ^ - -rabbit plugins_dir "!$RABBITMQ_PLUGINS_DIR!" ^ - !RABBITMQ_NAME_TYPE! rabbitmqprelaunch!RANDOM!!TIME:~9! + -rabbit plugins_dir "!RABBITMQ_PLUGINS_DIR!" ^ + -extra "!RABBITMQ_NODENAME!" if ERRORLEVEL 3 ( rem ERRORLEVEL means (or greater) so we need to catch all other failure diff --git a/scripts/rabbitmqctl.bat b/scripts/rabbitmqctl.bat index 521a8f35d2..2cbb5d5dee 100644 --- a/scripts/rabbitmqctl.bat +++ b/scripts/rabbitmqctl.bat @@ -49,6 +49,8 @@ if not defined ERL_CRASH_DUMP_SECONDS ( -boot !CLEAN_BOOT_FILE! ^ -noinput -noshell -hidden -smp enable ^ !RABBITMQ_CTL_ERL_ARGS! ^ +-kernel inet_dist_listen_min !RABBITMQ_CTL_DIST_PORT_MIN! ^ +-kernel inet_dist_listen_max !RABBITMQ_CTL_DIST_PORT_MAX! ^ -sasl errlog_type error ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ -ra data_dir \""!RABBITMQ_QUORUM_DIR:\=/!"\" ^ diff --git a/src/rabbit.erl b/src/rabbit.erl index 6cb9569484..26c7471360 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -407,7 +407,8 @@ sd_notify_socat(Unit) -> end. sd_current_unit() -> - case catch re:run(os:cmd("systemctl status " ++ os:getpid()), "([-.@0-9a-zA-Z]+)", [unicode, {capture, all_but_first, list}]) of + CmdOut = os:cmd("ps -o unit= -p " ++ os:getpid()), + case catch re:run(CmdOut, "([-.@0-9a-zA-Z]+)", [unicode, {capture, all_but_first, list}]) of {'EXIT', _} -> error; {match, [Unit]} -> @@ -430,7 +431,7 @@ sd_wait_activation(_, _, 0) -> io:format(standard_error, "Service still in 'activating' state, bailing out~n", []), false; sd_wait_activation(Port, Unit, AttemptsLeft) -> - case os:cmd("systemctl show --property=ActiveState " ++ Unit) of + case os:cmd("systemctl show --property=ActiveState -- '" ++ Unit ++ "'") of "ActiveState=activating\n" -> timer:sleep(1000), sd_wait_activation(Port, Unit, AttemptsLeft - 1); diff --git a/src/rabbit_amqqueue.erl b/src/rabbit_amqqueue.erl index 04cb95c63c..9b1ba11bb9 100644 --- a/src/rabbit_amqqueue.erl +++ b/src/rabbit_amqqueue.erl @@ -620,8 +620,7 @@ declare_args() -> {<<"x-max-length-bytes">>, fun check_non_neg_int_arg/2}, {<<"x-max-priority">>, fun check_non_neg_int_arg/2}, {<<"x-overflow">>, fun check_overflow/2}, - {<<"x-queue-mode">>, fun check_queue_mode/2}, - {<<"x-queue-type">>, fun check_queue_type/2}]. + {<<"x-queue-mode">>, fun check_queue_mode/2}]. consume_args() -> [{<<"x-priority">>, fun check_int_arg/2}, {<<"x-cancel-on-ha-failover">>, fun check_bool_arg/2}]. @@ -684,14 +683,6 @@ check_queue_mode({longstr, Val}, _Args) -> check_queue_mode({Type, _}, _Args) -> {error, {unacceptable_type, Type}}. -check_queue_type({longstr, Val}, _Args) -> - case lists:member(Val, [<<"classic">>, <<"quorum">>]) of - true -> ok; - false -> {error, invalid_queue_type} - end; -check_queue_type({Type, _}, _Args) -> - {error, {unacceptable_type, Type}}. - list() -> mnesia:dirty_match_object(rabbit_queue, #amqqueue{_ = '_'}). list_names() -> mnesia:dirty_all_keys(rabbit_queue). diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl index ecd7261e60..b854ff5c33 100644 --- a/src/rabbit_channel.erl +++ b/src/rabbit_channel.erl @@ -364,13 +364,29 @@ emit_info(PidList, InfoItems, Ref, AggregatorPid) -> refresh_config_local() -> rabbit_misc:upmap( - fun (C) -> gen_server2:call(C, refresh_config, infinity) end, + fun (C) -> + try + gen_server2:call(C, refresh_config, infinity) + catch _:Reason -> + rabbit_log:error("Failed to refresh channel config " + "for channel ~p. Reason ~p", + [C, Reason]) + end + end, list_local()), ok. refresh_interceptors() -> rabbit_misc:upmap( - fun (C) -> gen_server2:call(C, refresh_interceptors, ?REFRESH_TIMEOUT) end, + fun (C) -> + try + gen_server2:call(C, refresh_interceptors, ?REFRESH_TIMEOUT) + catch _:Reason -> + rabbit_log:error("Failed to refresh channel interceptors " + "for channel ~p. Reason ~p", + [C, Reason]) + end + end, list_local()), ok. @@ -867,24 +883,22 @@ check_internal_exchange(#exchange{name = Name, internal = true}) -> check_internal_exchange(_) -> ok. +check_topic_authorisation(Resource = #exchange{type = topic}, + User, none, RoutingKey, Permission) -> + %% Called from outside the channel by mgmt API + AmqpParams = [], + check_topic_authorisation(Resource, User, AmqpParams, RoutingKey, Permission); +check_topic_authorisation(Resource = #exchange{type = topic}, + User, ConnPid, RoutingKey, Permission) when is_pid(ConnPid) -> + AmqpParams = get_amqp_params(ConnPid), + check_topic_authorisation(Resource, User, AmqpParams, RoutingKey, Permission); check_topic_authorisation(#exchange{name = Name = #resource{virtual_host = VHost}, type = topic}, User = #user{username = Username}, - ConnPid, - RoutingKey, - Permission) -> + AmqpParams, RoutingKey, Permission) -> Resource = Name#resource{kind = topic}, - Timeout = get_operation_timeout(), - AmqpParams = case ConnPid of - none -> - %% Called from outside the channel by mgmt API - []; - _ -> - rabbit_amqp_connection:amqp_params(ConnPid, Timeout) - end, VariableMap = build_topic_variable_map(AmqpParams, VHost, Username), - Context = #{routing_key => RoutingKey, - variable_map => VariableMap - }, + Context = #{routing_key => RoutingKey, + variable_map => VariableMap}, Cache = case get(topic_permission_cache) of undefined -> []; Other -> Other @@ -899,6 +913,18 @@ check_topic_authorisation(#exchange{name = Name = #resource{virtual_host = VHost check_topic_authorisation(_, _, _, _, _) -> ok. +get_amqp_params(ConnPid) when is_pid(ConnPid) -> + Timeout = get_operation_timeout(), + get_amqp_params(ConnPid, rabbit_misc:is_process_alive(ConnPid), Timeout). + +get_amqp_params(ConnPid, false, _Timeout) -> + %% Connection process is dead + rabbit_log_channel:debug("file ~p, line ~p - connection process not alive: ~p~n", + [?FILE, ?LINE, ConnPid]), + []; +get_amqp_params(ConnPid, true, Timeout) -> + rabbit_amqp_connection:amqp_params(ConnPid, Timeout). + build_topic_variable_map(AmqpParams, VHost, Username) -> VariableFromAmqpParams = extract_topic_variable_map_from_amqp_params(AmqpParams), maps:merge(VariableFromAmqpParams, #{<<"vhost">> => VHost, <<"username">> => Username}). diff --git a/src/rabbit_config.erl b/src/rabbit_config.erl index a3f7d19136..de22d298be 100644 --- a/src/rabbit_config.erl +++ b/src/rabbit_config.erl @@ -72,13 +72,10 @@ update_app_config(ConfigFile) -> %% For application config to be updated, applications should %% be unloaded first. %% If an application is already running, print an error. - lists:foreach(fun({App, _Config}) -> + lists:foreach(fun({App, AppConfig}) -> case lists:member(App, RunningApps) of true -> - io:format(standard_error, - "~nUnable to update config for app ~p from *.conf file." - " App is already running. Use advanced.config instead.~n", - [App]); + maybe_print_warning_for_running_app(App, AppConfig); false -> case lists:member(App, LoadedApps) of true -> application:unload(App); @@ -87,11 +84,48 @@ update_app_config(ConfigFile) -> end end, Config), + maybe_set_net_ticktime(proplists:get_value(kernel, Config)), ok = application_controller:change_application_data([], [ConfigFile]), %% Make sure to load all the applications we're unloaded lists:foreach(fun(App) -> application:load(App) end, LoadedApps), ok. +maybe_print_warning_for_running_app(kernel, Config) -> + ConfigWithoutSupportedEntry = proplists:delete(net_ticktime, Config), + case length(ConfigWithoutSupportedEntry) > 0 of + true -> io:format(standard_error, + "~nUnable to update config for app ~p from a .conf file." + " The app is already running. Use advanced.config instead.~n", [kernel]); + false -> ok + end; +maybe_print_warning_for_running_app(App, _Config) -> + io:format(standard_error, + "~nUnable to update config for app ~p from a .conf file: " + " The app is already running.~n", + [App]). + +maybe_set_net_ticktime(undefined) -> + ok; +maybe_set_net_ticktime(KernelConfig) -> + case proplists:get_value(net_ticktime, KernelConfig) of + undefined -> + ok; + NetTickTime -> + case net_kernel:set_net_ticktime(NetTickTime, 0) of + unchanged -> + ok; + change_initiated -> + ok; + {ongoing_change_to, NewNetTicktime} -> + io:format(standard_error, + "~nCouldn't set net_ticktime to ~p " + "as net_kernel is busy changing net_ticktime to ~p seconds ~n", + [NetTickTime, NewNetTicktime]); + _ -> + ok + end + end. + generate_config_file(ConfFiles, ConfDir, ScriptDir) -> generate_config_file(ConfFiles, ConfDir, ScriptDir, schema_dir(), get_advanced_config()). diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl index 10b6aef609..793d365bf0 100644 --- a/src/rabbit_mnesia.erl +++ b/src/rabbit_mnesia.erl @@ -138,6 +138,7 @@ init_with_lock(0, _, InitFromConfig) -> init_with_lock(Retries, Timeout, InitFromConfig) -> case rabbit_peer_discovery:lock() of not_supported -> + rabbit_log:info("Peer discovery backend does not support locking, falling back to randomized delay"), %% See rabbitmq/rabbitmq-server#1202 for details. rabbit_peer_discovery:maybe_inject_randomized_delay(), InitFromConfig(), diff --git a/src/rabbit_priority_queue.erl b/src/rabbit_priority_queue.erl index 7c7bd8fbe6..5786bed6ba 100644 --- a/src/rabbit_priority_queue.erl +++ b/src/rabbit_priority_queue.erl @@ -393,6 +393,8 @@ handle_pre_hibernate(State = #state{bq = BQ}) -> handle_pre_hibernate(State = #passthrough{bq = BQ, bqs = BQS}) -> ?passthrough1(handle_pre_hibernate(BQS)). +handle_info(Msg, State = #state{bq = BQ}) -> + foreach1(fun (_P, BQSN) -> BQ:handle_info(Msg, BQSN) end, State); handle_info(Msg, State = #passthrough{bq = BQ, bqs = BQS}) -> ?passthrough1(handle_info(Msg, BQS)). @@ -408,6 +410,7 @@ msg_rates(#state{bq = BQ, bqss = BQSs}) -> end, {0.0, 0.0}, BQSs); msg_rates(#passthrough{bq = BQ, bqs = BQS}) -> BQ:msg_rates(BQS). + info(backing_queue_status, #state{bq = BQ, bqss = BQSs}) -> fold0(fun (P, BQSN, Acc) -> combine_status(P, BQ:info(backing_queue_status, BQSN), Acc) @@ -481,9 +484,9 @@ add0(Fun, BQSs) -> fold0(fun (P, BQSN, Acc) -> Acc + Fun(P, BQSN) end, 0, BQSs). %% Apply for all states foreach1(Fun, State = #state{bqss = BQSs}) -> a(State#state{bqss = foreach1(Fun, BQSs, [])}). -foreach1(Fun, [{P, BQSN} | Rest], BQSAcc) -> - BQSN1 = Fun(P, BQSN), - foreach1(Fun, Rest, [{P, BQSN1} | BQSAcc]); +foreach1(Fun, [{Priority, BQSN} | Rest], BQSAcc) -> + BQSN1 = Fun(Priority, BQSN), + foreach1(Fun, Rest, [{Priority, BQSN1} | BQSAcc]); foreach1(_Fun, [], BQSAcc) -> lists:reverse(BQSAcc). diff --git a/src/rabbit_queue_location_min_masters.erl b/src/rabbit_queue_location_min_masters.erl index 5d6f568d4a..c532714d41 100644 --- a/src/rabbit_queue_location_min_masters.erl +++ b/src/rabbit_queue_location_min_masters.erl @@ -57,23 +57,26 @@ count_masters(Node, Masters) -> get_bound_queue_masters_per_vhost([], Acc) -> lists:flatten(Acc); get_bound_queue_masters_per_vhost([VHost|RemVHosts], Acc) -> - Bindings = rabbit_binding:list(VHost), - BoundQueueMasters = get_queue_master_per_binding(VHost, Bindings, []), + BoundQueueNames = + lists:filtermap( + fun(#binding{destination =#resource{kind = queue, + name = QueueName}}) -> + {true, QueueName}; + (_) -> + false + end, + rabbit_binding:list(VHost)), + UniqQueueNames = lists:usort(BoundQueueNames), + BoundQueueMasters = get_queue_masters(VHost, UniqQueueNames, []), get_bound_queue_masters_per_vhost(RemVHosts, [BoundQueueMasters|Acc]). -get_queue_master_per_binding(_VHost, [], BoundQueueNodes) -> BoundQueueNodes; -get_queue_master_per_binding(VHost, [#binding{destination= - #resource{kind=queue, - name=QueueName}}| - RemBindings], - QueueMastersAcc) -> +get_queue_masters(_VHost, [], BoundQueueNodes) -> BoundQueueNodes; +get_queue_masters(VHost, [QueueName | RemQueueNames], QueueMastersAcc) -> QueueMastersAcc0 = case rabbit_queue_master_location_misc:lookup_master( QueueName, VHost) of {ok, Master} when is_atom(Master) -> [Master|QueueMastersAcc]; _ -> QueueMastersAcc end, - get_queue_master_per_binding(VHost, RemBindings, QueueMastersAcc0); -get_queue_master_per_binding(VHost, [_|RemBindings], QueueMastersAcc) -> - get_queue_master_per_binding(VHost, RemBindings, QueueMastersAcc). + get_queue_masters(VHost, RemQueueNames, QueueMastersAcc0). diff --git a/src/rabbit_router.erl b/src/rabbit_router.erl index 1f3017fa07..396a20c6b2 100644 --- a/src/rabbit_router.erl +++ b/src/rabbit_router.erl @@ -36,17 +36,12 @@ %%---------------------------------------------------------------------------- -%% TODO: Maybe this should be handled by a cursor instead. -%% TODO: This causes a full scan for each entry with the same source match_bindings(SrcName, Match) -> - Query = qlc:q([DestinationName || - #route{binding = Binding = #binding{ - source = SrcName1, - destination = DestinationName}} <- - mnesia:table(rabbit_route), - SrcName == SrcName1, - Match(Binding)]), - mnesia:async_dirty(fun qlc:e/1, [Query]). + MatchHead = #route{binding = #binding{source = SrcName, + _ = '_'}}, + Routes = ets:select(rabbit_route, [{MatchHead, [], [['$_']]}]), + [Dest || [#route{binding = Binding = #binding{destination = Dest}}] <- + Routes, Match(Binding)]. match_routing_key(SrcName, [RoutingKey]) -> find_routes(#route{binding = #binding{source = SrcName, diff --git a/src/rabbit_vhost_sup_sup.erl b/src/rabbit_vhost_sup_sup.erl index 6275a53e4d..f6c29f5540 100644 --- a/src/rabbit_vhost_sup_sup.erl +++ b/src/rabbit_vhost_sup_sup.erl @@ -183,7 +183,13 @@ start_vhost(VHost, Node) -> start_vhost(VHost) -> case rabbit_vhost:exists(VHost) of false -> {error, {no_such_vhost, VHost}}; - true -> supervisor2:start_child(?MODULE, [VHost]) + true -> + case whereis(?MODULE) of + Pid when is_pid(Pid) -> + supervisor2:start_child(?MODULE, [VHost]); + undefined -> + {error, rabbit_vhost_sup_sup_not_running} + end end. -spec is_vhost_alive(rabbit_types:vhost()) -> boolean(). @@ -221,9 +227,13 @@ save_vhost_process(VHost, VHostProcessPid) -> -spec lookup_vhost_sup_record(rabbit_types:vhost()) -> #vhost_sup{} | not_found. lookup_vhost_sup_record(VHost) -> - case ets:lookup(?MODULE, VHost) of - [] -> not_found; - [#vhost_sup{} = VHostSup] -> VHostSup + case ets:info(?MODULE, name) of + ?MODULE -> + case ets:lookup(?MODULE, VHost) of + [] -> not_found; + [#vhost_sup{} = VHostSup] -> VHostSup + end; + undefined -> not_found end. -spec vhost_sup_pid(rabbit_types:vhost()) -> no_pid | {ok, pid()}. diff --git a/test/channel_interceptor_SUITE.erl b/test/channel_interceptor_SUITE.erl index 0e4948ea3c..4081086f4f 100644 --- a/test/channel_interceptor_SUITE.erl +++ b/test/channel_interceptor_SUITE.erl @@ -29,7 +29,8 @@ all() -> groups() -> [ {non_parallel_tests, [], [ - register_interceptor + register_interceptor, + register_failing_interceptors ]} ]. @@ -71,9 +72,9 @@ end_per_testcase(Testcase, Config) -> register_interceptor(Config) -> passed = rabbit_ct_broker_helpers:rpc(Config, 0, - ?MODULE, register_interceptor1, [Config]). + ?MODULE, register_interceptor1, [Config, dummy_interceptor]). -register_interceptor1(Config) -> +register_interceptor1(Config, Interceptor) -> PredefinedChannels = rabbit_channel:list(), Ch1 = rabbit_ct_client_helpers:open_channel(Config, 0), @@ -89,8 +90,8 @@ register_interceptor1(Config) -> ok = rabbit_registry:register(channel_interceptor, <<"dummy interceptor">>, - dummy_interceptor), - [{interceptors, [{dummy_interceptor, undefined}]}] = + Interceptor), + [{interceptors, [{Interceptor, undefined}]}] = rabbit_channel:info(ChannelProc, [interceptors]), check_send_receive(Ch1, QName, <<"bar">>, <<"">>), @@ -102,6 +103,9 @@ register_interceptor1(Config) -> check_send_receive(Ch1, QName, <<"bar">>, <<"bar">>), passed. +register_failing_interceptors(Config) -> + passed = rabbit_ct_broker_helpers:rpc(Config, 0, + ?MODULE, register_interceptor1, [Config, failing_dummy_interceptor]). check_send_receive(Ch1, QName, Send, Receive) -> amqp_channel:call(Ch1, diff --git a/test/config_schema_SUITE_data/rabbit.snippets b/test/config_schema_SUITE_data/rabbit.snippets index 51a59c3a31..e4dda9f368 100644 --- a/test/config_schema_SUITE_data/rabbit.snippets +++ b/test/config_schema_SUITE_data/rabbit.snippets @@ -405,21 +405,21 @@ tcp_listen_options.exit_on_close = false", "cluster_formation.randomized_startup_delay_range.min = 10 cluster_formation.randomized_startup_delay_range.max = 30", [{rabbit, [{cluster_formation, [ - {randomized_delay_range, {10, 30}} + {randomized_startup_delay_range, {10, 30}} ]}]}], []}, {cluster_formation_randomized_startup_delay_min_only, "cluster_formation.randomized_startup_delay_range.min = 10", [{rabbit, [{cluster_formation, [ - {randomized_delay_range, {10, 60}} + {randomized_startup_delay_range, {10, 60}} ]}]}], []}, {cluster_formation_randomized_startup_delay_max_only, "cluster_formation.randomized_startup_delay_range.max = 30", [{rabbit, [{cluster_formation, [ - {randomized_delay_range, {5, 30}} + {randomized_startup_delay_range, {5, 30}} ]}]}], []}, @@ -522,5 +522,17 @@ credential_validator.regexp = ^abc\\d+", log.channel.file = file_name_channel", [{rabbit,[{log, [{categories, [{connection, [{file, "file_name_connection"}]}, {channel, [{file, "file_name_channel"}]}]}]}]}], - []} + []}, + {delegate_count, + "delegate_count = 64", + [{rabbit, [ + {delegate_count, 64} + ]}], + []}, + {kernel_net_ticktime, + "net_ticktime = 20", + [{kernel, [ + {net_ticktime, 20} + ]}], + []} ]. diff --git a/test/failing_dummy_interceptor.erl b/test/failing_dummy_interceptor.erl new file mode 100644 index 0000000000..62669e7f1f --- /dev/null +++ b/test/failing_dummy_interceptor.erl @@ -0,0 +1,27 @@ +-module(failing_dummy_interceptor). + +-behaviour(rabbit_channel_interceptor). + +-include_lib("rabbit_common/include/rabbit.hrl"). +-include_lib("rabbit_common/include/rabbit_framing.hrl"). + + +-compile(export_all). + +init(_Ch) -> + timer:sleep(15500), + undefined. + +description() -> + [{description, + <<"Empties payload on publish">>}]. + +intercept(#'basic.publish'{} = Method, Content, _IState) -> + Content2 = Content#content{payload_fragments_rev = []}, + {Method, Content2}; + +intercept(Method, Content, _VHost) -> + {Method, Content}. + +applies_to() -> + ['basic.publish']. diff --git a/test/queue_master_location_SUITE.erl b/test/queue_master_location_SUITE.erl index 457cf47b0c..94101567f6 100644 --- a/test/queue_master_location_SUITE.erl +++ b/test/queue_master_location_SUITE.erl @@ -56,6 +56,7 @@ groups() -> declare_policy_exactly, declare_config, calculate_min_master, + calculate_min_master_with_bindings, calculate_random, calculate_client_local ]} @@ -210,6 +211,22 @@ calculate_min_master(Config) -> verify_min_master(Config, Q), ok. +calculate_min_master_with_bindings(Config) -> + setup_test_environment(Config), + QueueName = rabbit_misc:r(<<"/">>, queue, Q = <<"qm.test_bound">>), + Args = [{<<"x-queue-master-locator">>, longstr, <<"min-masters">>}], + declare(Config, QueueName, false, false, Args, none), + verify_min_master(Config, Q), + %% Add 20 bindings to this queue + [ bind(Config, QueueName, integer_to_binary(N)) || N <- lists:seq(1, 20) ], + + QueueName1 = rabbit_misc:r(<<"/">>, queue, Q1 = <<"qm.test_unbound">>), + declare(Config, QueueName1, false, false, Args, none), + % Another queue should still be on the same node, bindings should + % not account for min-masters counting + verify_min_master(Config, Q1), + ok. + calculate_random(Config) -> setup_test_environment(Config), QueueName = rabbit_misc:r(<<"/">>, queue, Q = <<"qm.test">>), @@ -314,6 +331,17 @@ declare(Config, QueueName, Durable, AutoDelete, Args0, Owner) -> {new, Queue} = rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_amqqueue, declare, Args1), Queue. +bind(Config, QueueName, RoutingKey) -> + ExchangeName = rabbit_misc:r(QueueName, exchange, <<"amq.direct">>), + + ok = rabbit_ct_broker_helpers:rpc( + Config, 0, rabbit_binding, add, + [#binding{source = ExchangeName, + destination = QueueName, + key = RoutingKey, + args = []}, + <<"acting-user">>]). + verify_min_master(Config, Q, MinMasterNode) -> Rpc = rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_queue_master_location_misc, diff --git a/test/rabbitmq-env.bats b/test/rabbitmq-env.bats index cbe4a27765..0fccb42c81 100644 --- a/test/rabbitmq-env.bats +++ b/test/rabbitmq-env.bats @@ -1,19 +1,128 @@ -@test "can set RABBITMQ_SCHEDULER_BIND_TYPE from rabbitmq-env.conf" { - declare -r scripts_dir="$BATS_TEST_DIRNAME/../scripts" - export RABBITMQ_SCRIPTS_DIR="$scripts_dir" - export RABBITMQ_CONF_ENV_FILE="$BATS_TMPDIR/rabbitmq-env.conf" - echo 'RABBITMQ_SCHEDULER_BIND_TYPE=u' > "$RABBITMQ_CONF_ENV_FILE" - source "$scripts_dir/rabbitmq-env" - echo "expect RABBITMQ_SERVER_ERL_ARGS to contain '+stbt u' but got '$SERVER_ERL_ARGS'" - [[ $RABBITMQ_SERVER_ERL_ARGS == *+stbt\ u* ]] +#!/usr/bin/env bats + +export RABBITMQ_SCRIPTS_DIR="$BATS_TEST_DIRNAME/../scripts" + +setup() { + export RABBITMQ_CONF_ENV_FILE="$BATS_TMPDIR/rabbitmq-env.$BATS_TEST_NAME.conf" } -@test "can set RABBITMQ_DISTRIBUTION_BUFFER_SIZE from rabbitmq-env.conf" { - declare -r scripts_dir="$BATS_TEST_DIRNAME/../scripts" - export RABBITMQ_SCRIPTS_DIR="$scripts_dir" - export RABBITMQ_CONF_ENV_FILE="$BATS_TMPDIR/rabbitmq-env.conf" - echo 'RABBITMQ_DISTRIBUTION_BUFFER_SIZE=123456' > "$RABBITMQ_CONF_ENV_FILE" - source "$scripts_dir/rabbitmq-env" - echo "expect RABBITMQ_SERVER_ERL_ARGS to contain '+zdbbl 123456' but got '$SERVER_ERL_ARGS'" - [[ $RABBITMQ_SERVER_ERL_ARGS == *+zdbbl\ 123456* ]] +@test "default Erlang scheduler bind type" { + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + echo $RABBITMQ_SCHEDULER_BIND_TYPE + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +stbt db ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +stbt db "* ]] +} + +@test "can configure Erlang scheduler bind type via conf file" { + echo 'SCHEDULER_BIND_TYPE=u' > "$RABBITMQ_CONF_ENV_FILE" + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +stbt u ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +stbt u "* ]] +} + +@test "can configure Erlang scheduler bind type via env" { + RABBITMQ_SCHEDULER_BIND_TYPE=tnnps source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +stbt tnnps ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +stbt tnnps "* ]] +} + +@test "Erlang scheduler bind type env takes precedence over conf file" { + echo 'SCHEDULER_BIND_TYPE=s' > "$RABBITMQ_CONF_ENV_FILE" + RABBITMQ_SCHEDULER_BIND_TYPE=nnps source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +stbt nnps ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +stbt nnps "* ]] +} + +@test "default Erlang distribution buffer size" { + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +zdbbl 1280000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +zdbbl 1280000 "* ]] +} + +@test "can configure Erlang distribution buffer size via conf file" { + echo 'DISTRIBUTION_BUFFER_SIZE=1000000' > "$RABBITMQ_CONF_ENV_FILE" + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +zdbbl 1000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +zdbbl 1000000 "* ]] +} + +@test "can configure Erlang distribution buffer size via env" { + RABBITMQ_DISTRIBUTION_BUFFER_SIZE=2000000 source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +zdbbl 2000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +zdbbl 2000000 "* ]] +} + +@test "Erlang distribution buffer size env takes precedence over conf file" { + echo 'DISTRIBUTION_BUFFER_SIZE=3000000' > "$RABBITMQ_CONF_ENV_FILE" + RABBITMQ_DISTRIBUTION_BUFFER_SIZE=4000000 source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +zdbbl 4000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +zdbbl 4000000 "* ]] +} + +@test "default Erlang maximum number of processes" { + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +P 10485760 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +P 10485760 "* ]] +} + +@test "can configure Erlang maximum number of processes via conf file" { + echo 'MAX_NUMBER_OF_PROCESSES=2000000' > "$RABBITMQ_CONF_ENV_FILE" + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +P 2000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +P 2000000 "* ]] +} + +@test "can configure Erlang maximum number of processes via env" { + RABBITMQ_MAX_NUMBER_OF_PROCESSES=3000000 source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +P 3000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +P 3000000 "* ]] +} + +@test "Erlang maximum number of processes env takes precedence over conf file" { + echo 'MAX_NUMBER_OF_PROCESSES=4000000' > "$RABBITMQ_CONF_ENV_FILE" + RABBITMQ_MAX_NUMBER_OF_PROCESSES=5000000 source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +P 5000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +P 5000000 "* ]] +} + +@test "default Erlang maximum number of atoms" { + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +t 5000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +t 5000000 "* ]] +} + +@test "can configure Erlang maximum number of atoms via conf file" { + echo 'MAX_NUMBER_OF_ATOMS=1000000' > "$RABBITMQ_CONF_ENV_FILE" + source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +t 1000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +t 1000000 "* ]] +} + +@test "can configure Erlang maximum number of atoms via env" { + RABBITMQ_MAX_NUMBER_OF_ATOMS=2000000 source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +t 2000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +t 2000000 "* ]] +} + +@test "Erlang maximum number of atoms env takes precedence over conf file" { + echo 'MAX_NUMBER_OF_ATOMS=3000000' > "$RABBITMQ_CONF_ENV_FILE" + RABBITMQ_MAX_NUMBER_OF_ATOMS=4000000 source "$RABBITMQ_SCRIPTS_DIR/rabbitmq-env" + + echo "expected RABBITMQ_SERVER_ERL_ARGS to contain ' +t 4000000 ', but got: $RABBITMQ_SERVER_ERL_ARGS" + [[ $RABBITMQ_SERVER_ERL_ARGS == *" +t 4000000 "* ]] }