diff -Nru rabbitmq-server-2.7.1/LICENSE rabbitmq-server-2.8.0/LICENSE --- rabbitmq-server-2.7.1/LICENSE 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/LICENSE 2012-03-19 10:36:09.000000000 +0000 @@ -4,12 +4,15 @@ info@rabbitmq.com. The files amqp-rabbitmq-0.8.json and amqp-rabbitmq-0.9.1.json are -"Copyright (C) 2008-2011 VMware", Inc. and are covered by the MIT +"Copyright (C) 2008-2012 VMware", Inc. and are covered by the MIT license. -Mochiweb is "Copyright (c) 2007 Mochi Media, Inc." and is covered by -the MIT license. It was downloaded from -http://github.com/mochi/mochiweb/ +Webmachine is Copyright (c) Basho Technologies and is covered by the +Apache License 2.0. It was downloaded from http://webmachine.basho.com/ + +glMatrix is "Copyright (c) 2011, Brandon Jones" and is covered by the +BSD 2-Clause license. It was downloaded from +http://code.google.com/p/glmatrix/ Eldap is "Copyright (c) 2010, Torbjorn Tornkvist" and is covered by the MIT license. It was downloaded from https://github.com/etnt/eldap @@ -24,12 +27,9 @@ covered by the MIT license. It was downloaded from http://code.quirkey.com/sammy/ -glMatrix is "Copyright (c) 2011, Brandon Jones" and is covered by the -BSD 2-Clause license. It was downloaded from -http://code.google.com/p/glmatrix/ - -Webmachine is Copyright (c) Basho Technologies and is covered by the -Apache License 2.0. It was downloaded from http://webmachine.basho.com/ +Mochiweb is "Copyright (c) 2007 Mochi Media, Inc." and is covered by +the MIT license. It was downloaded from +http://github.com/mochi/mochiweb/ The MIT license is as follows: @@ -89,7 +89,7 @@ Authors and Copyright are as described below: The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2007-2011 VMware, Inc. All rights reserved. + Copyright (c) 2007-2012 VMware, Inc. All rights reserved. MOZILLA PUBLIC LICENSE @@ -541,7 +541,7 @@ The Original Code is RabbitMQ. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2007-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2007-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/LICENSE-MPL-RabbitMQ rabbitmq-server-2.8.0/LICENSE-MPL-RabbitMQ --- rabbitmq-server-2.7.1/LICENSE-MPL-RabbitMQ 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/LICENSE-MPL-RabbitMQ 2012-03-19 10:36:09.000000000 +0000 @@ -447,7 +447,7 @@ The Original Code is RabbitMQ Visualiser. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2011-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2011-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/Makefile rabbitmq-server-2.8.0/Makefile --- rabbitmq-server-2.7.1/Makefile 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/Makefile 2012-03-19 10:36:09.000000000 +0000 @@ -17,7 +17,7 @@ TARGETS=$(EBIN_DIR)/rabbit.app $(INCLUDE_DIR)/rabbit_framing.hrl $(BEAM_TARGETS) plugins WEB_URL=http://www.rabbitmq.com/ MANPAGES=$(patsubst %.xml, %.gz, $(wildcard $(DOCS_DIR)/*.[0-9].xml)) -WEB_MANPAGES=$(patsubst %.xml, %.man.xml, $(wildcard $(DOCS_DIR)/*.[0-9].xml) $(DOCS_DIR)/rabbitmq-service.xml) +WEB_MANPAGES=$(patsubst %.xml, %.man.xml, $(wildcard $(DOCS_DIR)/*.[0-9].xml) $(DOCS_DIR)/rabbitmq-service.xml $(DOCS_DIR)/rabbitmq-echopid.xml) USAGES_XML=$(DOCS_DIR)/rabbitmqctl.1.xml $(DOCS_DIR)/rabbitmq-plugins.1.xml USAGES_ERL=$(foreach XML, $(USAGES_XML), $(call usage_xml_to_erl, $(XML))) QC_MODULES := rabbit_backing_queue_qc @@ -56,7 +56,7 @@ #other args: +native +"{hipe,[o3,verbose]}" -Ddebug=true +debug_info +no_strict_record_tests ERLC_OPTS=-I $(INCLUDE_DIR) -o $(EBIN_DIR) -Wall -v +debug_info $(call boolean_macro,$(USE_SPECS),use_specs) $(call boolean_macro,$(USE_PROPER_QC),use_proper_qc) -VERSION=0.0.0 +VERSION?=0.0.0 PLUGINS_SRC_DIR?=$(shell [ -d "plugins-src" ] && echo "plugins-src" || echo ) PLUGINS_DIR=plugins TARBALL_NAME=rabbitmq-server-$(VERSION) @@ -246,7 +246,8 @@ srcdist: distclean mkdir -p $(TARGET_SRC_DIR)/codegen cp -r ebin src include LICENSE LICENSE-MPL-RabbitMQ INSTALL README $(TARGET_SRC_DIR) - sed -i.save 's/%%VSN%%/$(VERSION)/' $(TARGET_SRC_DIR)/ebin/rabbit_app.in && rm -f $(TARGET_SRC_DIR)/ebin/rabbit_app.in.save + sed 's/%%VSN%%/$(VERSION)/' $(TARGET_SRC_DIR)/ebin/rabbit_app.in > $(TARGET_SRC_DIR)/ebin/rabbit_app.in.tmp && \ + mv $(TARGET_SRC_DIR)/ebin/rabbit_app.in.tmp $(TARGET_SRC_DIR)/ebin/rabbit_app.in cp -r $(AMQP_CODEGEN_DIR)/* $(TARGET_SRC_DIR)/codegen/ cp codegen.py Makefile generate_app generate_deps calculate-relative $(TARGET_SRC_DIR) @@ -315,7 +316,7 @@ cp -r ebin include LICENSE* INSTALL $(TARGET_DIR) chmod 0755 scripts/* - for script in rabbitmq-env rabbitmq-server rabbitmqctl rabbitmq-plugins; do \ + for script in rabbitmq-env rabbitmq-server rabbitmqctl rabbitmq-plugins rabbitmq-defaults; do \ cp scripts/$$script $(TARGET_DIR)/sbin; \ [ -e $(SBIN_DIR)/$$script ] || ln -s $(SCRIPTS_REL_PATH)/$$script $(SBIN_DIR)/$$script; \ done @@ -346,10 +347,10 @@ # Note that all targets which depend on clean must have clean in their # name. Also any target that doesn't depend on clean should not have # clean in its name, unless you know that you don't need any of the -# automatic dependency generation for that target (eg cleandb). +# automatic dependency generation for that target (e.g. cleandb). # We want to load the dep file if *any* target *doesn't* contain -# "clean" - i.e. if removing all clean-like targets leaves something +# "clean" - i.e. if removing all clean-like targets leaves something. ifeq "$(MAKECMDGOALS)" "" TESTABLEGOALS:=$(.DEFAULT_GOAL) diff -Nru rabbitmq-server-2.7.1/codegen/LICENSE-MPL-RabbitMQ rabbitmq-server-2.8.0/codegen/LICENSE-MPL-RabbitMQ --- rabbitmq-server-2.7.1/codegen/LICENSE-MPL-RabbitMQ 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen/LICENSE-MPL-RabbitMQ 2012-03-19 10:36:09.000000000 +0000 @@ -447,7 +447,7 @@ The Original Code is RabbitMQ. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2007-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2007-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/codegen/amqp-rabbitmq-0.8.json rabbitmq-server-2.8.0/codegen/amqp-rabbitmq-0.8.json --- rabbitmq-server-2.7.1/codegen/amqp-rabbitmq-0.8.json 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen/amqp-rabbitmq-0.8.json 2012-03-19 10:36:09.000000000 +0000 @@ -4,7 +4,7 @@ "minor-version": 0, "port": 5672, "copyright": [ - "Copyright (C) 2008-2011 VMware, Inc.\n", + "Copyright (C) 2008-2012 VMware, Inc.\n", "\n", "Permission is hereby granted, free of charge, to any person\n", "obtaining a copy of this file (the \"Software\"), to deal in the\n", diff -Nru rabbitmq-server-2.7.1/codegen/amqp-rabbitmq-0.9.1.json rabbitmq-server-2.8.0/codegen/amqp-rabbitmq-0.9.1.json --- rabbitmq-server-2.7.1/codegen/amqp-rabbitmq-0.9.1.json 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen/amqp-rabbitmq-0.9.1.json 2012-03-19 10:36:09.000000000 +0000 @@ -5,7 +5,7 @@ "revision": 1, "port": 5672, "copyright": [ - "Copyright (C) 2008-2011 VMware, Inc.\n", + "Copyright (C) 2008-2012 VMware, Inc.\n", "\n", "Permission is hereby granted, free of charge, to any person\n", "obtaining a copy of this file (the \"Software\"), to deal in the\n", diff -Nru rabbitmq-server-2.7.1/codegen/amqp_codegen.py rabbitmq-server-2.8.0/codegen/amqp_codegen.py --- rabbitmq-server-2.7.1/codegen/amqp_codegen.py 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen/amqp_codegen.py 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## from __future__ import nested_scopes diff -Nru rabbitmq-server-2.7.1/codegen/demo_extension.json rabbitmq-server-2.8.0/codegen/demo_extension.json --- rabbitmq-server-2.7.1/codegen/demo_extension.json 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen/demo_extension.json 2012-03-19 10:36:09.000000000 +0000 @@ -2,7 +2,7 @@ "extension": { "name": "demo", "version": "1.0", - "copyright": "Copyright (C) 2009-2011 VMware, Inc." + "copyright": "Copyright (C) 2009-2012 VMware, Inc." }, "domains": [ ["foo-domain", "shortstr"] diff -Nru rabbitmq-server-2.7.1/codegen/license_info rabbitmq-server-2.8.0/codegen/license_info --- rabbitmq-server-2.7.1/codegen/license_info 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen/license_info 2012-03-19 10:36:09.000000000 +0000 @@ -1,4 +1,4 @@ The files amqp-rabbitmq-0.8.json and amqp-rabbitmq-0.9.1.json are -"Copyright (C) 2008-2011 VMware", Inc. and are covered by the MIT +"Copyright (C) 2008-2012 VMware", Inc. and are covered by the MIT license. diff -Nru rabbitmq-server-2.7.1/codegen.py rabbitmq-server-2.8.0/codegen.py --- rabbitmq-server-2.7.1/codegen.py 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/codegen.py 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## from __future__ import nested_scopes @@ -118,7 +118,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %%""" def genErl(spec): diff -Nru rabbitmq-server-2.7.1/debian/LICENSE.head rabbitmq-server-2.8.0/debian/LICENSE.head --- rabbitmq-server-2.7.1/debian/LICENSE.head 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/LICENSE.head 2014-01-10 14:48:48.000000000 +0000 @@ -0,0 +1,5 @@ +This package, the RabbitMQ server is licensed under the MPL. + +If you have any questions regarding licensing, please contact us at +info@rabbitmq.com. + diff -Nru rabbitmq-server-2.7.1/debian/LICENSE.tail rabbitmq-server-2.8.0/debian/LICENSE.tail --- rabbitmq-server-2.7.1/debian/LICENSE.tail 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/LICENSE.tail 2014-01-10 14:48:48.000000000 +0000 @@ -0,0 +1,516 @@ + +The MIT license is as follows: + + "Permission is hereby granted, free of charge, to any person + obtaining a copy of this file (the Software), to deal in the + Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE." + + +The BSD 2-Clause license is as follows: + + "Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the + following conditions are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + + +The rest of this package is licensed under the Mozilla Public License 1.1 +Authors and Copyright are as described below: + + The Initial Developer of the Original Code is VMware, Inc. + Copyright (c) 2007-2012 VMware, Inc. All rights reserved. + + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is RabbitMQ. + + The Initial Developer of the Original Code is VMware, Inc. + Copyright (c) 2007-2012 VMware, Inc. All rights reserved.'' + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] diff -Nru rabbitmq-server-2.7.1/debian/changelog rabbitmq-server-2.8.0/debian/changelog --- rabbitmq-server-2.7.1/debian/changelog 2012-03-29 14:47:46.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/changelog 2014-01-11 12:24:14.000000000 +0000 @@ -1,301 +1,216 @@ -rabbitmq-server (2.7.1-0ubuntu4) precise; urgency=low +rabbitmq-server (2.8.0-2~gem02) precise; urgency=low - [ Dave Walker ] - * debian/rabbitmq-script-wrapper: Use start-stop-daemon instead of su - to run the commands. This also allows rabbitmq to start on the - installer if invoke-rc.d is used with --force. (LP: #966269) + * Repackaging for GEM latest-master repository - [ Andres Rodriguez ] - * debian/rabbitmq-server.init: Use --no-wait in initctl emit command to - not stall apt-get installations. (LP: #968124) + -- Matteo Nastasi (GEM Foundation) Fri, 10 Jan 2014 16:07:02 +0100 - -- Andres Rodriguez Thu, 29 Mar 2012 10:46:26 -0400 +rabbitmq-server (2.8.0-1) lucid; urgency=low -rabbitmq-server (2.7.1-0ubuntu3) precise; urgency=low - - * debian/rabbitmq-server.init: emit 'rabbitmq-server-running' signal for - upstart as MAAS needs it. - - -- Andres Rodriguez Tue, 27 Mar 2012 14:49:05 -0400 - -rabbitmq-server (2.7.1-0ubuntu2) precise; urgency=low - - [ Marc Cluet ] - * Add new rabbitmq-erlang-client and rabbitmq-stomp binary packages as - plugins are now part of rabbitmq-server core (LP: #948993): - - d/rules: Refactored to support multiple binary packages, enable - .d style configuration of rabbitmq for plugins. - - d/rabbitmq-stomp.[postinst|postrm|install]: Install configuration - for stomp, enable/disable stomp plugin and restart as required. - - d/rabbitmq-erlang-client.[postinst|postrm]: Enable/disable amqp_client - plugin and restart as required. - - d/rabbitmq-server.*: Renamed to support multiple binary packages. - - d/rabbitmq-server.dirs: Added rabbitmq.conf.d dir for .d configuration - files. - - d/rabbitmq-server.postrm.in: Avoid deletion of rabbitmq user on purge. - * Switched to source/format 3.0 (quilt): - - d/patches/inets-plugins.patch: Fixup path to httpd.hrl. - - [ James Page ] - * d/control: rabbitmq-server needs to Break/Replace - rabbitmq-plugins-common < 2.7.1. - * d/rabbitmq-server.links: Fixup link to point to 2.7.1 install. - * d/rabbitmq-server.init: Restore fix to use start-stop-daemon (LP: #913464). - - -- Marc Cluet Mon, 12 Mar 2012 08:58:42 +0000 - -rabbitmq-server (2.7.1-0ubuntu1) precise; urgency=low - - * New upstream release. (LP: #922600) - * Apply patch to include inets from the appropriate place. Fixes - FTBFS. - * d/control: adding necessary build-deps for 2.7.1 - - -- Clint Byrum Tue, 28 Feb 2012 09:55:49 -0800 - -rabbitmq-server (2.6.1-1ubuntu4) precise; urgency=low - - * Use start-stop-daemon in the init script, removing usage of su - (LP: #913464) + * New Upstream Release - -- Thomas Hervé Fri, 27 Jan 2012 14:58:19 +0100 + -- Simon MacMullen Mon, 19 Mar 2012 10:28:07 +0000 -rabbitmq-server (2.6.1-1ubuntu3) precise; urgency=low +rabbitmq-server (2.7.1-1) natty; urgency=low - * Fix broken init script. + * New Upstream Release - -- Chuck Short Sun, 13 Nov 2011 22:48:59 -0500 + -- Steve Powell Fri, 16 Dec 2011 12:12:36 +0000 -rabbitmq-server (2.6.1-1ubuntu2) precise; urgency=low +rabbitmq-server (2.7.0-1) natty; urgency=low - * close file handles of rabbitmq-server daemon in init script (LP: #878600) - * fix dpkg failure on purge (LP: #878597) + * New Upstream Release - -- Scott Moser Tue, 25 Oct 2011 12:51:20 -0400 + -- Steve Powell Tue, 08 Nov 2011 16:47:50 +0000 -rabbitmq-server (2.6.1-1ubuntu1) precise; urgency=low +rabbitmq-server (2.6.1-1) natty; urgency=low - * Merge from debian unstable. Remaining changes: - - symlink erlang libraries in a rabbit-common specific location. - - Added explicit log line in startup_* and shutdown_* (LP: #838959) + * New Upstream Release - -- Chuck Short Wed, 28 Sep 2011 01:05:54 +0000 + -- Tim Fri, 09 Sep 2011 14:38:45 +0100 -rabbitmq-server (2.6.1-1) unstable; urgency=low +rabbitmq-server (2.6.0-1) natty; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Tue, 27 Sep 2011 17:53:57 +0200 + -- Tim Fri, 26 Aug 2011 16:29:40 +0100 -rabbitmq-server (2.5.0-1ubuntu2) oneiric; urgency=low +rabbitmq-server (2.5.1-1) lucid; urgency=low - * Added explicit log line in startup_* and shutdown_* (LP: #838959) - - Added a log line with a timestamp to indicate either the success or - failure on startup/shutdown + * New Upstream Release - -- Marc Cluet Wed, 14 Sep 2011 17:56:32 +0200 + -- Simon MacMullen Mon, 27 Jun 2011 11:21:49 +0100 -rabbitmq-server (2.5.0-1ubuntu1) oneiric; urgency=low +rabbitmq-server (2.5.0-1) lucid; urgency=low - * Merge from Debian Unstable. Remaining changes: - - symlink erlang libraries in a rabbit-common specific location. + * New Upstream Release - -- Dave Walker (Daviey) Sun, 19 Jun 2011 18:18:49 +0100 + -- Thu, 09 Jun 2011 07:20:29 -0700 -rabbitmq-server (2.5.0-1) unstable; urgency=low +rabbitmq-server (2.4.1-1) lucid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Thu, 16 Jun 2011 09:55:40 +0200 + -- Alexandru Scvortov Thu, 07 Apr 2011 16:49:22 +0100 -rabbitmq-server (2.4.1-1ubuntu2) oneiric; urgency=low +rabbitmq-server (2.4.0-1) lucid; urgency=low - * Fixed libraries soft link for 2.4.1 release + * New Upstream Release - -- Marc Cluet Thu, 26 May 2011 02:39:10 -0700 + -- Alexandru Scvortov Tue, 22 Mar 2011 17:34:31 +0000 -rabbitmq-server (2.4.1-1ubuntu1) oneiric; urgency=low +rabbitmq-server (2.3.1-1) lucid; urgency=low - * Merge from debian unstable. Remaining changes: - - symlink erlang libraries in a rabbit-cmmon specific location. + * New Upstream Release - -- Chuck Short Mon, 02 May 2011 13:15:56 +0100 + -- Simon MacMullen Thu, 03 Feb 2011 12:43:56 +0000 -rabbitmq-server (2.4.1-1) unstable; urgency=low +rabbitmq-server (2.3.0-1) lucid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Sat, 09 Apr 2011 09:34:06 +0200 + -- Simon MacMullen Tue, 01 Feb 2011 12:52:16 +0000 -rabbitmq-server (2.4.0-1) unstable; urgency=low +rabbitmq-server (2.2.0-1) lucid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Wed, 23 Mar 2011 21:11:17 +0200 + -- Rob Harrop Mon, 29 Nov 2010 12:24:48 +0000 -rabbitmq-server (2.3.1-1ubuntu1) natty; urgency=low +rabbitmq-server (2.1.1-1) lucid; urgency=low - * fix rabbitmq-stomp FTBFS, which requires erlang libraries in a - rabbit-common specific location; solve with a symlink + * New Upstream Release - -- Dustin Kirkland Tue, 19 Apr 2011 15:32:28 -0400 + -- Vlad Alexandru Ionescu Tue, 19 Oct 2010 17:20:10 +0100 -rabbitmq-server (2.3.1-1) unstable; urgency=low +rabbitmq-server (2.1.0-1) lucid; urgency=low - * New upstream release, closes: #611253 + * New Upstream Release - -- John Leuner Sat, 05 Feb 2011 10:21:16 +0200 + -- Marek Majkowski Tue, 14 Sep 2010 14:20:17 +0100 -rabbitmq-server (2.2.0-1) unstable; urgency=low +rabbitmq-server (2.0.0-1) karmic; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Thu, 02 Dec 2010 20:41:53 +0200 + -- Michael Bridgen Mon, 23 Aug 2010 14:55:39 +0100 -rabbitmq-server (2.1.0-1) unstable; urgency=low +rabbitmq-server (1.8.1-1) lucid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Mon, 27 Sep 2010 20:28:06 +0200 + -- Emile Joubert Wed, 14 Jul 2010 15:05:24 +0100 -rabbitmq-server (2.0.0-2) unstable; urgency=low +rabbitmq-server (1.8.0-1) intrepid; urgency=low - * Fix various scripts that were not updated correctly in - - the 2.0.0-1 package, closes: #594724 + * New Upstream Release - -- John Leuner Thu, 02 Sep 2010 18:01:37 +0200 + -- Matthew Sackman Tue, 15 Jun 2010 12:48:48 +0100 -rabbitmq-server (2.0.0-1) unstable; urgency=low +rabbitmq-server (1.7.2-1) intrepid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Sat, 28 Aug 2010 11:21:48 +0200 + -- Matthew Sackman Mon, 15 Feb 2010 15:54:47 +0000 -rabbitmq-server (1.8.1-1) unstable; urgency=low +rabbitmq-server (1.7.1-1) intrepid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Sun, 01 Aug 2010 15:47:46 +0200 + -- Matthew Sackman Fri, 22 Jan 2010 14:14:29 +0000 -rabbitmq-server (1.8.0-1) unstable; urgency=low +rabbitmq-server (1.7.0-1) intrepid; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Thu, 24 Jun 2010 18:43:04 +0200 + -- David Wragg Mon, 05 Oct 2009 13:44:41 +0100 -rabbitmq-server (1.7.0-3) unstable; urgency=low +rabbitmq-server (1.6.0-1) hardy; urgency=low - * Add missing entries in rabbitmq-server.init + * New Upstream Release - -- John Leuner Sun, 25 Oct 2009 10:21:25 +0200 + -- Matthias Radestock Tue, 16 Jun 2009 15:02:58 +0100 -rabbitmq-server (1.7.0-2) unstable; urgency=low +rabbitmq-server (1.5.5-1) hardy; urgency=low - * moved debian/init.d to rabbitmq-server.init - * included fixes to rabbitmq-script-wrapper + * New Upstream Release - -- John Leuner Wed, 14 Oct 2009 12:23:52 +0200 + -- Matthias Radestock Tue, 19 May 2009 09:57:54 +0100 -rabbitmq-server (1.7.0-1) unstable; urgency=low +rabbitmq-server (1.5.4-1) hardy; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Sat, 10 Oct 2009 13:28:39 +0200 + -- Matthias Radestock Mon, 06 Apr 2009 09:19:32 +0100 -rabbitmq-server (1.6.0-1) unstable; urgency=low +rabbitmq-server (1.5.3-1) hardy; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Sat, 20 Jun 2009 12:22:17 +0200 + -- Tony Garnock-Jones Tue, 24 Feb 2009 18:23:33 +0000 -rabbitmq-server (1.5.5-3) unstable; urgency=low +rabbitmq-server (1.5.2-1) hardy; urgency=low - * debian/control: Reduce Erlang dependencies to just - erlang-mnesia and erlang-os-mon, closes: #532867 + * New Upstream Release - -- John Leuner Tue, 16 Jun 2009 14:15:20 +0200 + -- Tony Garnock-Jones Mon, 23 Feb 2009 16:03:38 +0000 -rabbitmq-server (1.5.5-2) unstable; urgency=low +rabbitmq-server (1.5.1-1) hardy; urgency=low - * Include updates to debian package by rabbit team: - - quiet log rotate - - update build-depends and depends for new erlang packages - - debian/watch file - - add rabbitmq-script-wrapper - - update init.d scripts - - clean /etc/rabbitmq in postrm + * New Upstream Release - -- John Leuner Wed, 03 Jun 2009 12:23:50 +0200 + -- Simon MacMullen Mon, 19 Jan 2009 15:46:13 +0000 -rabbitmq-server (1.5.5-1) unstable; urgency=low +rabbitmq-server (1.5.0-1) testing; urgency=low - * New upstream release + * New Upstream Release - -- John Leuner Tue, 02 Jun 2009 12:53:32 +0200 + -- Matthias Radestock Wed, 17 Dec 2008 18:23:47 +0000 -rabbitmq-server (1.5.4-4) unstable; urgency=low +rabbitmq-server (1.4.0-1) testing; urgency=low - * Add new dependency on erlang-os-mon to work with new erlang packages in - debian + * New Upstream Release - -- John Leuner Mon, 11 May 2009 21:20:04 +0200 + -- Tony Garnock-Jones Thu, 24 Jul 2008 13:21:48 +0100 -rabbitmq-server (1.5.4-3) unstable; urgency=low +rabbitmq-server (1.3.0-1) testing; urgency=low - * Previous partial upload failed + * New Upstream Release - -- John Leuner Fri, 10 Apr 2009 20:25:51 +0200 + -- Adrien Pierard Mon, 03 Mar 2008 15:34:38 +0000 -rabbitmq-server (1.5.4-2) unstable; urgency=low +rabbitmq-server (1.2.0-2) testing; urgency=low - * Fix incorrect changed-by field in .changes file + * Fixed rabbitmqctl wrapper script - -- John Leuner Fri, 10 Apr 2009 19:40:04 +0200 + -- Simon MacMullen Fri, 05 Oct 2007 11:55:00 +0100 -rabbitmq-server (1.5.4-1) unstable; urgency=low +rabbitmq-server (1.2.0-1) testing; urgency=low * New upstream release - -- John Leuner Fri, 10 Apr 2009 17:54:21 +0200 + -- Simon MacMullen Wed, 26 Sep 2007 11:49:26 +0100 -rabbitmq-server (1.5.0-5) unstable; urgency=low +rabbitmq-server (1.1.1-1) testing; urgency=low - * Include the full license for amqp-0.8.json in debian/copyright - - -- John Leuner Fri, 27 Feb 2009 16:16:54 +0200 - -rabbitmq-server (1.5.0-4) unstable; urgency=low - - * Clarify and explicitly list the license and copyright for - codegen/amqp-0.8.json - - * Explicitly list the authors and copyright for the rest of the codebase - at the top of debian/copyright - - * Clarify the copyright of the files in src/tcp_* . The rabbitmq authors have - confirmed that they are the original authors of this code and that the - files at http://code.google.com/p/cacherl/ were taken without their - knowledge from the rabbitmq project. (Comparing the commit dates in version - control shows that cacherl is newer) + * New upstream release - -- John Leuner Wed, 25 Feb 2009 13:10:15 +0200 + -- Simon MacMullen Wed, 29 Aug 2007 12:03:15 +0100 -rabbitmq-server (1.5.0-3) unstable; urgency=low +rabbitmq-server (1.1.0-alpha-2) testing; urgency=low - * Previous changelog entry had an incorrect Maintainer name + * Fixed erlang-nox dependency - -- John Leuner Wed, 28 Jan 2009 16:45:33 +0200 + -- Simon MacMullen Thu, 02 Aug 2007 11:27:13 +0100 -rabbitmq-server (1.5.0-2) unstable; urgency=low +rabbitmq-server (1.1.0-alpha-1) testing; urgency=low - * Reupload package to unstable. Mistakenly uploaded to testing last time, closes: #507902 + * New upstream release - -- John Leuner Mon, 19 Jan 2009 17:38:43 +0200 + -- Simon MacMullen Fri, 20 Jul 2007 18:17:33 +0100 -rabbitmq-server (1.5.0-1) testing; urgency=low +rabbitmq-server (1.0.0-alpha-1) unstable; urgency=low - * New Upstream Release - * First Debian upload, closes: #507902 + * Initial release - -- John Leuner Wed, 17 Dec 2008 18:23:47 +0000 + -- Tony Garnock-Jones Wed, 31 Jan 2007 19:06:33 +0000 diff -Nru rabbitmq-server-2.7.1/debian/conf/rabbitmq-env.conf rabbitmq-server-2.8.0/debian/conf/rabbitmq-env.conf --- rabbitmq-server-2.7.1/debian/conf/rabbitmq-env.conf 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/conf/rabbitmq-env.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -for CONFIGFILE in `ls /etc/rabbitmq/rabbitmq.conf.d |sort -r`; do - . /etc/rabbitmq/rabbitmq.conf.d/$CONFIGFILE -done diff -Nru rabbitmq-server-2.7.1/debian/conf/rabbitmq.conf.d/50_stomp rabbitmq-server-2.8.0/debian/conf/rabbitmq.conf.d/50_stomp --- rabbitmq-server-2.7.1/debian/conf/rabbitmq.conf.d/50_stomp 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/conf/rabbitmq.conf.d/50_stomp 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -RABBITMQ_SERVER_START_ARGS='-rabbitmq_stomp tcp_listeners [{"0.0.0.0",61613},{"0.0.0.0",6163}]' diff -Nru rabbitmq-server-2.7.1/debian/control rabbitmq-server-2.8.0/debian/control --- rabbitmq-server-2.7.1/debian/control 2012-03-12 09:27:19.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/control 2014-01-10 14:48:48.000000000 +0000 @@ -1,36 +1,15 @@ Source: rabbitmq-server Section: net Priority: extra -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: RabbitMQ Team -Build-Depends: cdbs, debhelper (>= 5), quilt, erlang-dev, python-simplejson, xmlto, xsltproc, git, zip, unzip, erlang-asn1, erlang-inets -Standards-Version: 3.9.3 +Maintainer: RabbitMQ Team +Build-Depends: cdbs, debhelper (>= 5), erlang-dev, python-simplejson, xmlto, xsltproc, erlang-nox (>= 1:12.b.3), erlang-src (>= 1:12.b.3), unzip, zip +Standards-Version: 3.8.0 Package: rabbitmq-server Architecture: all -Breaks: rabbitmq-plugins-common (<< 2.7.1) -Replaces: rabbitmq-plugins-common (<< 2.7.1) Depends: erlang-nox (>= 1:12.b.3), adduser, logrotate, ${misc:Depends} Description: An AMQP server written in Erlang RabbitMQ is an implementation of AMQP, the emerging standard for high performance enterprise messaging. The RabbitMQ server is a robust and scalable implementation of an AMQP broker. Homepage: http://www.rabbitmq.com/ - -Package: rabbitmq-erlang-client -Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends}, rabbitmq-server (= ${binary:Version}) -Description: Erlang client for RabbitMQ - This client offers both a networked version that uses standard TCP-based AMQP - framing and a direct client that uses native Erlang message passing to a - RabbitMQ broker. - -Package: rabbitmq-stomp -Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends}, rabbitmq-server (>= 2.7.1), - rabbitmq-erlang-client (= ${binary:Version}) -Suggests: ruby -Description: A STOMP gateway for RabbitMQ - Gateway for exposing AMQP functionality via the STOMP protocol, as - implemented by many clients for various programming languages, and a few other - servers besides RabbitMQ. diff -Nru rabbitmq-server-2.7.1/debian/copyright rabbitmq-server-2.8.0/debian/copyright --- rabbitmq-server-2.7.1/debian/copyright 2012-03-12 08:58:37.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/copyright 2014-01-10 14:48:48.000000000 +0000 @@ -1,14 +1,41 @@ -This package was debianized by Tony Garnock-Jones on -Wed, 3 Jan 2007 15:43:44 +0000. +This package was debianized by Tony Garnock-Jones on\nWed, 3 Jan 2007 15:43:44 +0000.\n\nIt was downloaded from http://www.rabbitmq.com/\n\n +This package, the RabbitMQ server is licensed under the MPL. -It was downloaded from http://www.rabbitmq.com/ +If you have any questions regarding licensing, please contact us at +info@rabbitmq.com. + +The files amqp-rabbitmq-0.8.json and amqp-rabbitmq-0.9.1.json are +"Copyright (C) 2008-2012 VMware", Inc. and are covered by the MIT +license. + +Webmachine is Copyright (c) Basho Technologies and is covered by the +Apache License 2.0. It was downloaded from http://webmachine.basho.com/ + +glMatrix is "Copyright (c) 2011, Brandon Jones" and is covered by the +BSD 2-Clause license. It was downloaded from +http://code.google.com/p/glmatrix/ + +Eldap is "Copyright (c) 2010, Torbjorn Tornkvist" and is covered by +the MIT license. It was downloaded from https://github.com/etnt/eldap -The files codegen/amqp-rabbitmq-0.8.json and -codegen/amqp-rabbitmq-0.9.1.json are covered by the following terms: +jQuery is "Copyright (c) 2010 John Resig" and is covered by the MIT +license. It was downloaded from http://jquery.com/ - "Copyright (C) 2008-2011 VMware, Inc. +EJS is "Copyright (c) 2007 Edward Benson" and is covered by the MIT +license. It was downloaded from http://embeddedjs.com/ - Permission is hereby granted, free of charge, to any person +Sammy is "Copyright (c) 2008 Aaron Quint, Quirkey NYC, LLC" and is +covered by the MIT license. It was downloaded from +http://code.quirkey.com/sammy/ + +Mochiweb is "Copyright (c) 2007 Mochi Media, Inc." and is covered by +the MIT license. It was downloaded from +http://github.com/mochi/mochiweb/ + + +The MIT license is as follows: + + "Permission is hereby granted, free of charge, to any person obtaining a copy of this file (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, @@ -28,11 +55,42 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + +The BSD 2-Clause license is as follows: + + "Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the + following conditions are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + + The rest of this package is licensed under the Mozilla Public License 1.1 Authors and Copyright are as described below: The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2007-2011 VMware, Inc. All rights reserved. + Copyright (c) 2007-2012 VMware, Inc. All rights reserved. MOZILLA PUBLIC LICENSE @@ -484,19 +542,10 @@ The Original Code is RabbitMQ. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2007-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2007-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] - - - - - -If you have any questions regarding licensing, please contact us at -info@rabbitmq.com. - -The Debian packaging is (C) 2007-2011, VMware, Inc. and is licensed -under the MPL 1.1, see above. +\n\nThe Debian packaging is (C) 2007-2012, VMware, Inc. and is licensed\nunder the MPL 1.1, see above.\n diff -Nru rabbitmq-server-2.7.1/debian/dirs rabbitmq-server-2.8.0/debian/dirs --- rabbitmq-server-2.7.1/debian/dirs 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/dirs 2014-01-10 14:48:48.000000000 +0000 @@ -0,0 +1,9 @@ +usr/lib/rabbitmq/bin +usr/lib/erlang/lib +usr/sbin +usr/share/man +var/lib/rabbitmq/mnesia +var/log/rabbitmq +etc/logrotate.d +etc/rabbitmq + diff -Nru rabbitmq-server-2.7.1/debian/patches/inets-plugins.patch rabbitmq-server-2.8.0/debian/patches/inets-plugins.patch --- rabbitmq-server-2.7.1/debian/patches/inets-plugins.patch 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/patches/inets-plugins.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ ---- rabbitmq-server-2.7.1.orig/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_inets.erl -+++ rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_inets.erl -@@ -88,14 +88,7 @@ - -module(rfc4627_jsonrpc_inets). - -include("rfc4627_jsonrpc.hrl"). - --%% The path to httpd.hrl has changed in OTP R14A and newer. Our --%% Makefile detects the change for us, and supplies a compile-time --%% macro definition to allow us to adapt to the new path. ---ifdef(new_inets). ---include_lib("inets/src/http_server/httpd.hrl"). ---else. ---include_lib("inets/src/httpd.hrl"). ---endif. -+-include_lib("inets/include/httpd.hrl"). - - -export([do/1, load/2]). - diff -Nru rabbitmq-server-2.7.1/debian/patches/series rabbitmq-server-2.8.0/debian/patches/series --- rabbitmq-server-2.7.1/debian/patches/series 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -inets-plugins.patch diff -Nru rabbitmq-server-2.7.1/debian/postinst rabbitmq-server-2.8.0/debian/postinst --- rabbitmq-server-2.7.1/debian/postinst 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/postinst 2014-01-10 14:48:48.000000000 +0000 @@ -0,0 +1,60 @@ +#!/bin/sh +# postinst script for rabbitmq +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +# create rabbitmq group +if ! getent group rabbitmq >/dev/null; then + addgroup --system rabbitmq +fi + +# create rabbitmq user +if ! getent passwd rabbitmq >/dev/null; then + adduser --system --ingroup rabbitmq --home /var/lib/rabbitmq \ + --no-create-home --gecos "RabbitMQ messaging server" \ + --disabled-login rabbitmq +fi + +chown -R rabbitmq:rabbitmq /var/lib/rabbitmq +chown -R rabbitmq:rabbitmq /var/log/rabbitmq + +case "$1" in + configure) + if [ -f /etc/rabbitmq/rabbitmq.conf ] && \ + [ ! -f /etc/rabbitmq/rabbitmq-env.conf ]; then + mv /etc/rabbitmq/rabbitmq.conf /etc/rabbitmq/rabbitmq-env.conf + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff -Nru rabbitmq-server-2.7.1/debian/postrm.in rabbitmq-server-2.8.0/debian/postrm.in --- rabbitmq-server-2.7.1/debian/postrm.in 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/postrm.in 2014-01-10 14:48:48.000000000 +0000 @@ -0,0 +1,70 @@ +#!/bin/sh +# postrm script for rabbitmq +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + +remove_plugin_traces() { + # Remove traces of plugins + rm -rf /var/lib/rabbitmq/plugins-scratch +} + +case "$1" in + purge) + rm -f /etc/default/rabbitmq + if [ -d /var/lib/rabbitmq ]; then + rm -r /var/lib/rabbitmq + fi + if [ -d /var/log/rabbitmq ]; then + rm -r /var/log/rabbitmq + fi + if [ -d /etc/rabbitmq ]; then + rm -r /etc/rabbitmq + fi + remove_plugin_traces + if getent passwd rabbitmq >/dev/null; then + # Stop epmd if run by the rabbitmq user + pkill -u rabbitmq epmd || : + + deluser rabbitmq + fi + if getent group rabbitmq >/dev/null; then + delgroup rabbitmq + fi + ;; + + remove|upgrade) + remove_plugin_traces + ;; + + failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-erlang-client.postinst rabbitmq-server-2.8.0/debian/rabbitmq-erlang-client.postinst --- rabbitmq-server-2.7.1/debian/rabbitmq-erlang-client.postinst 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-erlang-client.postinst 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/bin/sh -e - -/usr/lib/rabbitmq/bin/rabbitmq-plugins enable amqp_client -invoke-rc.d rabbitmq-server restart - -#DEBHELPER# diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-erlang-client.postrm rabbitmq-server-2.8.0/debian/rabbitmq-erlang-client.postrm --- rabbitmq-server-2.7.1/debian/rabbitmq-erlang-client.postrm 2012-03-12 09:43:56.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-erlang-client.postrm 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -#!/bin/sh -# postrm script for rabbitmq -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - -case "$1" in - purge) - ;; - - failed-upgrade|abort-install|abort-upgrade|disappear|remove|upgrade) - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - - -if [ -x /usr/lib/rabbitmq/bin/rabbitmq-plugins ]; then /usr/lib/rabbitmq/bin/rabbitmq-plugins disable amqp_client; fi -if ! /usr/sbin/invoke-rc.d rabbitmq-server restart ; then - RESTART_RESULT=$? - if [ "$RESTART_RESULT" != "100" ] ; then - exit $RESTART_RESULT - fi -fi - -#DEBHELPER# - -exit 0 diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-plugins-common.install rabbitmq-server-2.8.0/debian/rabbitmq-plugins-common.install --- rabbitmq-server-2.7.1/debian/rabbitmq-plugins-common.install 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-plugins-common.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -debian/conf/rabbitmq-env.conf etc/rabbitmq diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-script-wrapper rabbitmq-server-2.8.0/debian/rabbitmq-script-wrapper --- rabbitmq-server-2.7.1/debian/rabbitmq-script-wrapper 2012-03-28 18:34:02.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-script-wrapper 2014-01-10 14:48:48.000000000 +0000 @@ -12,7 +12,7 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## # Escape spaces and quotes, because shell is revolting. @@ -29,10 +29,10 @@ SCRIPT=`basename $0` -if [ `id -u` = 0 ] ; then - start-stop-daemon --start --pidfile /dev/null --startas "/usr/lib/rabbitmq/bin/${SCRIPT}" --chuid rabbitmq -- "$@" -elif [ `id -u` = `id -u rabbitmq` ] ; then +if [ `id -u` = `id -u rabbitmq` -o "$SCRIPT" = "rabbitmq-plugins" ] ; then /usr/lib/rabbitmq/bin/${SCRIPT} "$@" +elif [ `id -u` = 0 ] ; then + su rabbitmq -s /bin/sh -c "/usr/lib/rabbitmq/bin/${SCRIPT} ${CMDLINE}" else /usr/lib/rabbitmq/bin/${SCRIPT} echo diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-server.dirs rabbitmq-server-2.8.0/debian/rabbitmq-server.dirs --- rabbitmq-server-2.7.1/debian/rabbitmq-server.dirs 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-server.dirs 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -usr/lib/rabbitmq/bin -usr/lib/erlang/lib -usr/sbin -usr/share/man -var/lib/rabbitmq/mnesia -var/log/rabbitmq -etc/logrotate.d -etc/rabbitmq -etc/rabbitmq/rabbitmq.conf.d diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-server.init rabbitmq-server-2.8.0/debian/rabbitmq-server.init --- rabbitmq-server-2.7.1/debian/rabbitmq-server.init 2012-03-28 19:12:59.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-server.init 2014-01-10 14:48:48.000000000 +0000 @@ -18,7 +18,7 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin NAME=rabbitmq-server -DAEMON=/usr/lib/rabbitmq/bin/${NAME} +DAEMON=/usr/sbin/${NAME} CONTROL=/usr/sbin/rabbitmqctl DESC=rabbitmq-server USER=rabbitmq @@ -26,6 +26,7 @@ INIT_LOG_DIR=/var/log/rabbitmq PID_FILE=/var/run/rabbitmq/pid +START_PROG="start-stop-daemon -v --chuid rabbitmq --start --exec" LOCK_FILE= test -x $DAEMON || exit 0 @@ -56,7 +57,10 @@ RETVAL=0 ensure_pid_dir set +e - RABBITMQ_PID_FILE=$PID_FILE start-stop-daemon --pidfile=$PID_FILE --chuid rabbitmq --exec $DAEMON --background --start + RABBITMQ_PID_FILE=$PID_FILE $START_PROG $DAEMON \ + > "${INIT_LOG_DIR}/startup_log" \ + 2> "${INIT_LOG_DIR}/startup_err" \ + 0<&- & $CONTROL wait $PID_FILE >/dev/null 2>&1 RETVAL=$? set -e @@ -66,14 +70,10 @@ if [ -n "$LOCK_FILE" ] ; then touch $LOCK_FILE fi - echo "`date` - rabbitmq successfully started" >> ${INIT_LOG_DIR}/startup_log - # only emit the event on boot - [ -n "$UPSTART_JOB" ] && initctl emit --no-wait rabbitmq-server-running || true ;; *) remove_pid echo FAILED - check ${INIT_LOG_DIR}/startup_\{log, _err\} - echo "`date` - rabbitmq failed to start" >> ${INIT_LOG_DIR}/startup_err RETVAL=1 ;; esac @@ -84,7 +84,7 @@ status_rabbitmq quiet if [ $RETVAL = 0 ] ; then set +e - start-stop-daemon --pidfile=$PID_FILE --stop + $CONTROL stop ${PID_FILE} > ${INIT_LOG_DIR}/shutdown_log 2> ${INIT_LOG_DIR}/shutdown_err RETVAL=$? set -e if [ $RETVAL = 0 ] ; then @@ -92,10 +92,8 @@ if [ -n "$LOCK_FILE" ] ; then rm -f $LOCK_FILE fi - echo "`date` - rabbitmq successfully stopped" >> ${INIT_LOG_DIR}/shutdown_log else echo FAILED - check ${INIT_LOG_DIR}/shutdown_log, _err - echo "`date` - rabbitmq failed to stop" >> ${INIT_LOG_DIR}/shutdown_err fi else echo RabbitMQ is not running diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-server.links rabbitmq-server-2.8.0/debian/rabbitmq-server.links --- rabbitmq-server-2.7.1/debian/rabbitmq-server.links 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-server.links 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/rabbitmq/lib/rabbitmq_server-2.7.1 usr/lib/erlang/lib/rabbit_common diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-server.ocf rabbitmq-server-2.8.0/debian/rabbitmq-server.ocf --- rabbitmq-server-2.7.1/debian/rabbitmq-server.ocf 2012-03-12 08:58:37.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-server.ocf 2014-01-10 14:48:48.000000000 +0000 @@ -12,7 +12,7 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## ## diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-server.postinst rabbitmq-server-2.8.0/debian/rabbitmq-server.postinst --- rabbitmq-server-2.7.1/debian/rabbitmq-server.postinst 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-server.postinst 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -#!/bin/sh -# postinst script for rabbitmq -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-remove' -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -# create rabbitmq group -if ! getent group rabbitmq >/dev/null; then - addgroup --system rabbitmq -fi - -# create rabbitmq user -if ! getent passwd rabbitmq >/dev/null; then - adduser --system --ingroup rabbitmq --home /var/lib/rabbitmq \ - --no-create-home --gecos "RabbitMQ messaging server" \ - --disabled-login rabbitmq -fi - -chown -R rabbitmq:rabbitmq /var/lib/rabbitmq -chown -R rabbitmq:rabbitmq /var/log/rabbitmq - -case "$1" in - configure) - if [ -f /etc/rabbitmq/rabbitmq.conf ] && \ - [ ! -f /etc/rabbitmq/rabbitmq-env.conf ]; then - mv /etc/rabbitmq/rabbitmq.conf /etc/rabbitmq/rabbitmq-env.conf - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - - diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-server.postrm.in rabbitmq-server-2.8.0/debian/rabbitmq-server.postrm.in --- rabbitmq-server-2.7.1/debian/rabbitmq-server.postrm.in 2012-03-12 09:52:46.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-server.postrm.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -#!/bin/sh -# postrm script for rabbitmq -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - -remove_plugin_traces() { - # Remove traces of plugins - rm -rf /var/lib/rabbitmq/plugins-scratch -} - -case "$1" in - purge) - rm -f /etc/default/rabbitmq - if [ -d /var/lib/rabbitmq ]; then - rm -r /var/lib/rabbitmq - fi - if [ -d /var/log/rabbitmq ]; then - rm -r /var/log/rabbitmq - fi - if [ -d /etc/rabbitmq ]; then - rm -r /etc/rabbitmq - fi - remove_plugin_traces - ;; - - remove|upgrade) - remove_plugin_traces - ;; - - failed-upgrade|abort-install|abort-upgrade|disappear) - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - - diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-stomp.install rabbitmq-server-2.8.0/debian/rabbitmq-stomp.install --- rabbitmq-server-2.7.1/debian/rabbitmq-stomp.install 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-stomp.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -debian/conf/rabbitmq.conf.d/50_stomp etc/rabbitmq/rabbitmq.conf.d diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-stomp.postinst rabbitmq-server-2.8.0/debian/rabbitmq-stomp.postinst --- rabbitmq-server-2.7.1/debian/rabbitmq-stomp.postinst 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-stomp.postinst 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/bin/sh -e - -/usr/lib/rabbitmq/bin/rabbitmq-plugins enable rabbitmq_stomp -invoke-rc.d rabbitmq-server restart - -#DEBHELPER# diff -Nru rabbitmq-server-2.7.1/debian/rabbitmq-stomp.postrm rabbitmq-server-2.8.0/debian/rabbitmq-stomp.postrm --- rabbitmq-server-2.7.1/debian/rabbitmq-stomp.postrm 2012-03-12 09:43:11.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rabbitmq-stomp.postrm 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -#!/bin/sh -# postrm script for rabbitmq -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - -case "$1" in - purge) - rm -f /etc/rabbitmq/rabbitmq.conf.d/50_stomp - ;; - - failed-upgrade|abort-install|abort-upgrade|disappear|remove|upgrade) - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -if [ -x /usr/lib/rabbitmq/bin/rabbitmq-plugins ]; then /usr/lib/rabbitmq/bin/rabbitmq-plugins disable rabbitmq_stomp; fi -if ! /usr/sbin/invoke-rc.d rabbitmq-server restart ; then - RESTART_RESULT=$? - if [ "$RESTART_RESULT" != "100" ] ; then - exit $RESTART_RESULT - fi -fi - -#DEBHELPER# - -exit 0 diff -Nru rabbitmq-server-2.7.1/debian/rules rabbitmq-server-2.8.0/debian/rules --- rabbitmq-server-2.7.1/debian/rules 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/rules 2014-01-10 14:48:48.000000000 +0000 @@ -3,22 +3,19 @@ include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/makefile.mk -MULTIPACKAGE_DEB_DESTDIR=debian/rabbitmq-server/ +RABBIT_LIB=$(DEB_DESTDIR)usr/lib/rabbitmq/lib/rabbitmq_server-$(DEB_UPSTREAM_VERSION)/ +RABBIT_BIN=$(DEB_DESTDIR)usr/lib/rabbitmq/bin/ -RABBIT_LIB=$(MULTIPACKAGE_DEB_DESTDIR)usr/lib/rabbitmq/lib/rabbitmq_server-$(DEB_UPSTREAM_VERSION)/ -RABBIT_BIN=$(MULTIPACKAGE_DEB_DESTDIR)usr/lib/rabbitmq/bin/ - -DEB_MAKE_INSTALL_TARGET := install TARGET_DIR=$(RABBIT_LIB) SBIN_DIR=$(RABBIT_BIN) MAN_DIR=$(MULTIPACKAGE_DEB_DESTDIR)usr/share/man/ +DEB_MAKE_INSTALL_TARGET := install TARGET_DIR=$(RABBIT_LIB) SBIN_DIR=$(RABBIT_BIN) MAN_DIR=$(DEB_DESTDIR)usr/share/man/ DEB_MAKE_CLEAN_TARGET:= distclean -DOCDIR=$(MULTIPACKAGE_DEB_DESTDIR)usr/share/doc/rabbitmq-server/ +DOCDIR=$(DEB_DESTDIR)usr/share/doc/rabbitmq-server/ install/rabbitmq-server:: mkdir -p $(DOCDIR) rm $(RABBIT_LIB)LICENSE* $(RABBIT_LIB)INSTALL* - for script in rabbitmqctl rabbitmq-server; do \ - install -p -D -m 0755 debian/rabbitmq-script-wrapper $(MULTIPACKAGE_DEB_DESTDIR)usr/sbin/$$script; \ + for script in rabbitmqctl rabbitmq-server rabbitmq-plugins; do \ + install -p -D -m 0755 debian/rabbitmq-script-wrapper $(DEB_DESTDIR)usr/sbin/$$script; \ done - sed -e 's|@RABBIT_LIB@|/usr/lib/rabbitmq/lib/rabbitmq_server-$(DEB_UPSTREAM_VERSION)|g' debian/rabbitmq-server.postrm - install -p -D -m 0755 debian/rabbitmq-server.ocf $(MULTIPACKAGE_DEB_DESTDIR)usr/lib/ocf/resource.d/rabbitmq/rabbitmq-server - install -p -m 0644 debian/conf/rabbitmq-env.conf $(MULTIPACKAGE_DEB_DESTDIR)etc/rabbitmq + sed -e 's|@RABBIT_LIB@|/usr/lib/rabbitmq/lib/rabbitmq_server-$(DEB_UPSTREAM_VERSION)|g' debian/postrm + install -p -D -m 0755 debian/rabbitmq-server.ocf $(DEB_DESTDIR)usr/lib/ocf/resource.d/rabbitmq/rabbitmq-server diff -Nru rabbitmq-server-2.7.1/debian/source/format rabbitmq-server-2.8.0/debian/source/format --- rabbitmq-server-2.7.1/debian/source/format 2014-01-11 12:26:15.100402225 +0000 +++ rabbitmq-server-2.8.0/debian/source/format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -3.0 (quilt) diff -Nru rabbitmq-server-2.7.1/debian/source/options rabbitmq-server-2.8.0/debian/source/options --- rabbitmq-server-2.7.1/debian/source/options 2012-03-12 08:58:39.000000000 +0000 +++ rabbitmq-server-2.8.0/debian/source/options 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -single-debian-patch diff -Nru rabbitmq-server-2.7.1/docs/html-to-website-xml.xsl rabbitmq-server-2.8.0/docs/html-to-website-xml.xsl --- rabbitmq-server-2.7.1/docs/html-to-website-xml.xsl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/docs/html-to-website-xml.xsl 2012-03-19 10:36:09.000000000 +0000 @@ -8,8 +8,6 @@ - - @@ -28,36 +26,30 @@ <xsl:value-of select="document($original)/refentry/refnamediv/refname"/><xsl:if test="document($original)/refentry/refmeta/manvolnum">(<xsl:value-of select="document($original)/refentry/refmeta/manvolnum"/>)</xsl:if> manual page - - - + + -

- This is the manual page for - (). -

-

- See a list of all manual pages. -

+

+ This is the manual page for + (). +

+

+ See a list of all manual pages. +

-

- This is the documentation for - . -

+

+ This is the documentation for + . +

-
-

+ +

For more general documentation, please see the - administrator's guide. -

- - - Table of Contents - + administrator's guide. +

- -
+
diff -Nru rabbitmq-server-2.7.1/docs/rabbitmq-echopid.xml rabbitmq-server-2.8.0/docs/rabbitmq-echopid.xml --- rabbitmq-server-2.7.1/docs/rabbitmq-echopid.xml 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/docs/rabbitmq-echopid.xml 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,71 @@ + + + + + RabbitMQ Server + + The RabbitMQ Team <info@rabbitmq.com> + + + + + rabbitmq-echopid.bat + RabbitMQ Server + + + + rabbitmq-echopid.bat + return the process id of the Erlang runtime hosting RabbitMQ + + + + + rabbitmq-echopid.bat + sname + + + + + Description + + RabbitMQ is an implementation of AMQP, the emerging + standard for high performance enterprise messaging. The + RabbitMQ server is a robust and scalable implementation of + an AMQP broker. + + + Running rabbitmq-echopid will attempt to + discover and echo the process id (PID) of the Erlang runtime + process (erl.exe) that is hosting RabbitMQ. To allow erl.exe + time to start up and load RabbitMQ, the script will wait for + ten seconds before timing out if a suitable PID cannot be + found. + + + If a PID is discovered, the script will echo it to stdout + before exiting with a ERRORLEVEL of 0. If no PID is + discovered before the timeout, nothing is written to stdout + and the script exits setting ERRORLEVEL to 1. + + + Note that this script only exists on Windows due to the need + to wait for erl.exe and possibly time-out. To obtain the PID + on Unix set RABBITMQ_PID_FILE before starting + rabbitmq-server and do not use "-detached". + + + + + Options + + + sname + + +The short-name form of the RabbitMQ node name. + + + + + + diff -Nru rabbitmq-server-2.7.1/docs/rabbitmqctl.1.xml rabbitmq-server-2.8.0/docs/rabbitmqctl.1.xml --- rabbitmq-server-2.7.1/docs/rabbitmqctl.1.xml 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/docs/rabbitmqctl.1.xml 2012-03-19 10:36:09.000000000 +0000 @@ -266,10 +266,9 @@ When the target files do not exist they are created. - target files do not already exist. When - no is specified, the empty log - files are simply created at the original location; no - rotation takes place. + When no is specified, the empty + log files are simply created at the original location; + no rotation takes place. For example: rabbitmqctl rotate_logs .1 @@ -1012,6 +1011,10 @@ Id of the Erlang process associated with the connection. + name + Readable name for the connection. + + address Server IP address. @@ -1067,10 +1070,26 @@ The period for which the peer's SSL certificate is valid. + + + last_blocked_by + The reason for which this connection + was last blocked. One of 'mem' - due to a memory + alarm, 'flow' - due to internal flow control, or + 'none' if the connection was never + blocked. + + + last_blocked_age + Time, in seconds, since this + connection was last blocked, or + 'infinity'. + + state Connection state (one of [starting, tuning, - opening, running, closing, closed]). + opening, running, blocking, blocked, closing, closed]). channels @@ -1127,8 +1146,9 @@ - If no connectioninfoitems are specified then user, peer - address, peer port and connection state are displayed. + If no connectioninfoitems are + specified then user, peer address, peer port, time since + flow control and memory block state are displayed. @@ -1171,6 +1191,10 @@ to which the channel belongs. + name + Readable name for the channel. + + number The number of the channel, which uniquely identifies it within a connection. @@ -1273,9 +1297,10 @@ Displays broker status information such as the running applications on the current Erlang node, RabbitMQ and - Erlang versions, OS name and memory statistics. (See - the cluster_status command to find - out which nodes are clustered and running.) + Erlang versions, OS name, memory and file descriptor + statistics. (See the cluster_status + command to find out which nodes are clustered and + running.) For example: rabbitmqctl status @@ -1403,8 +1428,11 @@ fraction - The new memory threshhold fraction at which flow control is triggered, as a - floating point number between 0.0 and 1.0 with a mandatory fractional part. + + The new memory threshold fraction at which flow + control is triggered, as a floating point number + greater than or equal to 0. + diff -Nru rabbitmq-server-2.7.1/ebin/rabbit_app.in rabbitmq-server-2.8.0/ebin/rabbit_app.in --- rabbitmq-server-2.7.1/ebin/rabbit_app.in 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/ebin/rabbit_app.in 2012-03-19 10:36:09.000000000 +0000 @@ -1,7 +1,7 @@ {application, rabbit, %% -*- erlang -*- [{description, "RabbitMQ"}, {id, "RabbitMQ"}, - {vsn, "2.7.1"}, + {vsn, "2.8.0"}, {modules, []}, {registered, [rabbit_amqqueue_sup, rabbit_log, @@ -37,10 +37,13 @@ {auth_backends, [rabbit_auth_backend_internal]}, {delegate_count, 16}, {trace_vhosts, []}, + {log_levels, [{connection, info}]}, + {ssl_cert_login_from, distinguished_name}, {tcp_listen_options, [binary, {packet, raw}, {reuseaddr, true}, {backlog, 128}, {nodelay, true}, + {linger, {true, 0}}, {exit_on_close, false}]} ]}]}. diff -Nru rabbitmq-server-2.7.1/include/gm_specs.hrl rabbitmq-server-2.8.0/include/gm_specs.hrl --- rabbitmq-server-2.7.1/include/gm_specs.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/gm_specs.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -ifdef(use_specs). diff -Nru rabbitmq-server-2.7.1/include/rabbit.hrl rabbitmq-server-2.8.0/include/rabbit.hrl --- rabbitmq-server-2.7.1/include/rabbit.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -record(user, {username, @@ -56,9 +56,11 @@ -record(binding, {source, key, destination, args = []}). -record(reverse_binding, {destination, key, source, args = []}). +-record(topic_trie_node, {trie_node, edge_count, binding_count}). -record(topic_trie_edge, {trie_edge, node_id}). -record(topic_trie_binding, {trie_binding, value = const}). +-record(trie_node, {exchange_name, node_id}). -record(trie_edge, {exchange_name, node_id, word}). -record(trie_binding, {exchange_name, node_id, destination}). @@ -84,7 +86,7 @@ %%---------------------------------------------------------------------------- --define(COPYRIGHT_MESSAGE, "Copyright (C) 2007-2011 VMware, Inc."). +-define(COPYRIGHT_MESSAGE, "Copyright (C) 2007-2012 VMware, Inc."). -define(INFORMATION_MESSAGE, "Licensed under the MPL. See http://www.rabbitmq.com/"). -define(PROTOCOL_VERSION, "AMQP 0-9-1 / 0-9 / 0-8"). -define(ERTS_MINIMUM, "5.6.3"). @@ -93,16 +95,7 @@ -define(HIBERNATE_AFTER_MIN, 1000). -define(DESIRED_HIBERNATE, 10000). +-define(CREDIT_DISC_BOUND, {2000, 500}). -define(ROUTING_HEADERS, [<<"CC">>, <<"BCC">>]). -define(DELETED_HEADER, <<"BCC">>). - --ifdef(debug). --define(LOGDEBUG0(F), rabbit_log:debug(F)). --define(LOGDEBUG(F,A), rabbit_log:debug(F,A)). --define(LOGMESSAGE(D,C,M,Co), rabbit_log:message(D,C,M,Co)). --else. --define(LOGDEBUG0(F), ok). --define(LOGDEBUG(F,A), ok). --define(LOGMESSAGE(D,C,M,Co), ok). --endif. diff -Nru rabbitmq-server-2.7.1/include/rabbit_auth_backend_spec.hrl rabbitmq-server-2.8.0/include/rabbit_auth_backend_spec.hrl --- rabbitmq-server-2.7.1/include/rabbit_auth_backend_spec.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit_auth_backend_spec.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -ifdef(use_specs). diff -Nru rabbitmq-server-2.7.1/include/rabbit_auth_mechanism_spec.hrl rabbitmq-server-2.8.0/include/rabbit_auth_mechanism_spec.hrl --- rabbitmq-server-2.7.1/include/rabbit_auth_mechanism_spec.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit_auth_mechanism_spec.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -ifdef(use_specs). diff -Nru rabbitmq-server-2.7.1/include/rabbit_backing_queue_spec.hrl rabbitmq-server-2.8.0/include/rabbit_backing_queue_spec.hrl --- rabbitmq-server-2.7.1/include/rabbit_backing_queue_spec.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit_backing_queue_spec.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -type(fetch_result(Ack) :: @@ -25,6 +25,8 @@ -type(async_callback() :: fun ((atom(), fun ((atom(), state()) -> state())) -> 'ok')). -type(duration() :: ('undefined' | 'infinity' | number())). +-type(msg_fun() :: fun((rabbit_types:basic_message(), ack()) -> 'ok')). + -spec(start/1 :: ([rabbit_amqqueue:name()]) -> 'ok'). -spec(stop/0 :: () -> 'ok'). -spec(init/3 :: (rabbit_types:amqqueue(), attempt_recovery(), @@ -42,12 +44,14 @@ rabbit_types:message_properties(), pid(), state()) -> {undefined, state()}). -spec(drain_confirmed/1 :: (state()) -> {[rabbit_guid:guid()], state()}). --spec(dropwhile/2 :: - (fun ((rabbit_types:message_properties()) -> boolean()), state()) +-spec(dropwhile/3 :: + (fun ((rabbit_types:message_properties()) -> boolean()), + msg_fun() | 'undefined', state()) -> state()). -spec(fetch/2 :: (true, state()) -> {fetch_result(ack()), state()}; (false, state()) -> {fetch_result(undefined), state()}). -spec(ack/2 :: ([ack()], state()) -> {[rabbit_guid:guid()], state()}). +-spec(fold/3 :: (msg_fun(), state(), [ack()]) -> state()). -spec(requeue/2 :: ([ack()], state()) -> {[rabbit_guid:guid()], state()}). -spec(len/1 :: (state()) -> non_neg_integer()). diff -Nru rabbitmq-server-2.7.1/include/rabbit_exchange_type_spec.hrl rabbitmq-server-2.8.0/include/rabbit_exchange_type_spec.hrl --- rabbitmq-server-2.7.1/include/rabbit_exchange_type_spec.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit_exchange_type_spec.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -ifdef(use_specs). diff -Nru rabbitmq-server-2.7.1/include/rabbit_msg_store.hrl rabbitmq-server-2.8.0/include/rabbit_msg_store.hrl --- rabbitmq-server-2.7.1/include/rabbit_msg_store.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit_msg_store.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -include("rabbit.hrl"). diff -Nru rabbitmq-server-2.7.1/include/rabbit_msg_store_index.hrl rabbitmq-server-2.8.0/include/rabbit_msg_store_index.hrl --- rabbitmq-server-2.7.1/include/rabbit_msg_store_index.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/include/rabbit_msg_store_index.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -include("rabbit_msg_store.hrl"). diff -Nru rabbitmq-server-2.7.1/plugins-src/Makefile rabbitmq-server-2.8.0/plugins-src/Makefile --- rabbitmq-server-2.7.1/plugins-src/Makefile 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/Makefile 2012-03-19 10:36:09.000000000 +0000 @@ -62,7 +62,7 @@ plugins-dist: release rm -rf $(PLUGINS_DIST_DIR) mkdir -p $(PLUGINS_DIST_DIR) - $(MAKE) -f all-packages.mk copy-releasable VERSION=$(VERSION) $(PLUGINS_DIST_DIR)=$(PLUGINS_DIST_DIR) + $(MAKE) -f all-packages.mk copy-releasable VERSION=$(VERSION) PLUGINS_DIST_DIR=$(PLUGINS_DIST_DIR) plugins-srcdist: rm -rf $(PLUGINS_SRC_DIST_DIR) @@ -74,7 +74,7 @@ rsync -a --exclude '.hg*' rabbitmq-server $(PLUGINS_SRC_DIST_DIR)/ touch $(PLUGINS_SRC_DIST_DIR)/rabbitmq-server/.srcdist_done - $(MAKE) -f all-packages.mk copy-srcdist VERSION=$(VERSION) $(PLUGINS_SRC_DIST_DIR)=$(PLUGINS_SRC_DIST_DIR) + $(MAKE) -f all-packages.mk copy-srcdist VERSION=$(VERSION) PLUGINS_SRC_DIST_DIR=$(PLUGINS_SRC_DIST_DIR) cp Makefile *.mk generate* $(PLUGINS_SRC_DIST_DIR)/ echo "This is the released version of rabbitmq-public-umbrella. \ You can clone the full version with: hg clone http://hg.rabbitmq.com/rabbitmq-public-umbrella" > $(PLUGINS_SRC_DIST_DIR)/README diff -Nru rabbitmq-server-2.7.1/plugins-src/do-package.mk rabbitmq-server-2.8.0/plugins-src/do-package.mk --- rabbitmq-server-2.7.1/plugins-src/do-package.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/do-package.mk 2012-03-19 10:36:09.000000000 +0000 @@ -286,7 +286,7 @@ define run_broker rm -rf $(TEST_TMPDIR) mkdir -p $(foreach D,log plugins $(NODENAME),$(TEST_TMPDIR)/$(D)) - cp -a $(PACKAGE_DIR)/dist/*.ez $(TEST_TMPDIR)/plugins + cp -p $(PACKAGE_DIR)/dist/*.ez $(TEST_TMPDIR)/plugins $(call copy,$(3),$(TEST_TMPDIR)/plugins) rm -f $(TEST_TMPDIR)/plugins/rabbit_common*.ez for plugin in \ @@ -375,7 +375,7 @@ mkdir -p $(APP_DIR)/ebin $(APP_DIR)/include @echo [elided] copy beams to ebin @$(call copy,$(EBIN_BEAMS),$(APP_DIR)/ebin) - cp -a $(APP_FILE) $(APP_DIR)/ebin/$(APP_NAME).app + cp -p $(APP_FILE) $(APP_DIR)/ebin/$(APP_NAME).app $(call copy,$(INCLUDE_HRLS),$(APP_DIR)/include) $(construct_app_commands) touch $$@ @@ -414,8 +414,8 @@ @echo [elided] generate deps @$$(if $$^,echo $$(subst : ,:,$$(foreach F,$$^,$$(abspath $$(F)):)) | escript $(abspath $(UMBRELLA_BASE_DIR)/generate_deps) $$@ '$$$$(EBIN_DIR)',echo >$$@) @echo [elided] fix test deps - @$$(foreach F,$(TEST_EBIN_BEAMS),sed -i -e 's|^$$$$(EBIN_DIR)/$$(notdir $$(F)):|$$$$(TEST_EBIN_DIR)/$$(notdir $$(F)):|' $$@ && ) : - sed -i -e 's|$$@|$$$$(DEPS_FILE)|' $$@ + @$$(foreach F,$(TEST_EBIN_BEAMS),sed -e 's|^$$$$(EBIN_DIR)/$$(notdir $$(F)):|$$$$(TEST_EBIN_DIR)/$$(notdir $$(F)):|' $$@ > $$@.tmp && mv $$@.tmp $$@ && ) : + sed -e 's|$$@|$$$$(DEPS_FILE)|' $$@ > $$@.tmp && mv $$@.tmp $$@ $(eval $(call safe_include,$(DEPS_FILE))) diff -Nru rabbitmq-server-2.7.1/plugins-src/erlando/README.md rabbitmq-server-2.8.0/plugins-src/erlando/README.md --- rabbitmq-server-2.7.1/plugins-src/erlando/README.md 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlando/README.md 2012-03-19 10:36:09.000000000 +0000 @@ -278,7 +278,8 @@ comma(foo(), fun (A) -> comma(bar(A, dog), - fun (B) -> ok end)). + fun (B) -> ok end) + end). Thus the function `comma/2` takes all results from the previous expression, and controls how and whether they are passed to the next @@ -303,7 +304,8 @@ Monad:'>>='(foo(), fun (A) -> Monad:'>>='(bar(A, dog), - fun (B) -> ok end)). + fun (B) -> ok end) + end). There is no intention that this latter form is any more readable than the `comma/2` form - it is not. However, it should be clear that the @@ -624,4 +626,4 @@ The Original Code is Erlando. The Initial Developer of the Original Code is VMware, Inc. -Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +Copyright (c) 2011-2012 VMware, Inc. All rights reserved. diff -Nru rabbitmq-server-2.7.1/plugins-src/erlando/package.mk rabbitmq-server-2.8.0/plugins-src/erlando/package.mk --- rabbitmq-server-2.7.1/plugins-src/erlando/package.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlando/package.mk 2012-03-19 10:36:09.000000000 +0000 @@ -1,2 +1 @@ STANDALONE_TEST_COMMANDS:=test_do:test() test_cut:test() test_import_as:test() - diff -Nru rabbitmq-server-2.7.1/plugins-src/erlando/src/monad.erl rabbitmq-server-2.8.0/plugins-src/erlando/src/monad.erl --- rabbitmq-server-2.7.1/plugins-src/erlando/src/monad.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlando/src/monad.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is Erlando. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(monad). @@ -39,8 +39,10 @@ Y]). sequence(Monad, Xs) -> - lists:foldr(fun (X, Acc) -> - do([Monad || E <- X, - Es <- Acc, - return([E|Es])]) - end, Monad:return([]), Xs). + sequence(Monad, Xs, []). + +sequence(Monad, [], Acc) -> + do([Monad || return(lists:reverse(Acc))]); +sequence(Monad, [X|Xs], Acc) -> + do([Monad || E <- X, + sequence(Monad, Xs, [E|Acc])]). diff -Nru rabbitmq-server-2.7.1/plugins-src/erlando/test/erlando_test.erl rabbitmq-server-2.8.0/plugins-src/erlando/test/erlando_test.erl --- rabbitmq-server-2.7.1/plugins-src/erlando/test/erlando_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlando/test/erlando_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is Erlando. %% %% The Initial Developer of the Original Code is Alex Kropivny. -%% Copyright (c) 2011-2011 Alex Kropivny; VMware, Inc. +%% Copyright (c) 2011-2012 Alex Kropivny; VMware, Inc. %% All rights reserved. %% diff -Nru rabbitmq-server-2.7.1/plugins-src/erlando/test/src/test_do.erl rabbitmq-server-2.8.0/plugins-src/erlando/test/src/test_do.erl --- rabbitmq-server-2.7.1/plugins-src/erlando/test/src/test_do.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlando/test/src/test_do.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is Erlando. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(test_do). diff -Nru rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_registry.erl rabbitmq-server-2.8.0/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_registry.erl --- rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_registry.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_registry.erl 2012-03-19 10:36:09.000000000 +0000 @@ -81,7 +81,7 @@ case ets:lookup(?TABLE_NAME, {service_pid, DownPid}) of [] -> {noreply, State}; - [ServiceName] -> + [{_, ServiceName}] -> ets:delete(?TABLE_NAME, {service_pid, DownPid}), ets:delete(?TABLE_NAME, {service, ServiceName}), {noreply, State} diff -Nru rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/fix-ets-leak.patch rabbitmq-server-2.8.0/plugins-src/erlang-rfc4627-wrapper/fix-ets-leak.patch --- rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/fix-ets-leak.patch 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlang-rfc4627-wrapper/fix-ets-leak.patch 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,13 @@ +diff --git a/src/rfc4627_jsonrpc_registry.erl b/src/rfc4627_jsonrpc_registry.erl +index 7065a7a..f9c8289 100644 +--- a/src/rfc4627_jsonrpc_registry.erl ++++ b/src/rfc4627_jsonrpc_registry.erl +@@ -81,7 +81,7 @@ handle_info({'DOWN', _MonitorRef, process, DownPid, _Reason}, State) -> + case ets:lookup(?TABLE_NAME, {service_pid, DownPid}) of + [] -> + {noreply, State}; +- [ServiceName] -> ++ [{_, ServiceName}] -> + ets:delete(?TABLE_NAME, {service_pid, DownPid}), + ets:delete(?TABLE_NAME, {service, ServiceName}), + {noreply, State} diff -Nru rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/package.mk rabbitmq-server-2.8.0/plugins-src/erlang-rfc4627-wrapper/package.mk --- rabbitmq-server-2.7.1/plugins-src/erlang-rfc4627-wrapper/package.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/erlang-rfc4627-wrapper/package.mk 2012-03-19 10:36:09.000000000 +0000 @@ -3,6 +3,8 @@ UPSTREAM_GIT:=http://github.com/tonyg/erlang-rfc4627.git UPSTREAM_REVISION:=30c84984f86a1d67083f +WRAPPER_PATCHES:=fix-ets-leak.patch + ORIGINAL_APP_FILE=$(CLONE_DIR)/ebin/$(APP_NAME).app DO_NOT_GENERATE_APP_FILE=true diff -Nru rabbitmq-server-2.7.1/plugins-src/licensing/LICENSE-MPL-RabbitMQ rabbitmq-server-2.8.0/plugins-src/licensing/LICENSE-MPL-RabbitMQ --- rabbitmq-server-2.7.1/plugins-src/licensing/LICENSE-MPL-RabbitMQ 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/licensing/LICENSE-MPL-RabbitMQ 2012-03-19 10:36:09.000000000 +0000 @@ -447,7 +447,7 @@ The Original Code is RabbitMQ Visualiser. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2011-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2011-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request.erl.orig rabbitmq-server-2.8.0/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request.erl.orig --- rabbitmq-server-2.7.1/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request.erl.orig 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request.erl.orig 1970-01-01 00:00:00.000000000 +0000 @@ -1,715 +0,0 @@ -%% @author Bob Ippolito -%% @copyright 2007 Mochi Media, Inc. - -%% @doc MochiWeb HTTP Request abstraction. - --module(mochiweb_request, [Socket, Method, RawPath, Version, Headers]). --author('bob@mochimedia.com'). - --include_lib("kernel/include/file.hrl"). --include("internal.hrl"). - --define(QUIP, "Any of you quaids got a smint?"). - --export([get_header_value/1, get_primary_header_value/1, get/1, dump/0]). --export([send/1, recv/1, recv/2, recv_body/0, recv_body/1, stream_body/3]). --export([start_response/1, start_response_length/1, start_raw_response/1]). --export([respond/1, ok/1]). --export([not_found/0, not_found/1]). --export([parse_post/0, parse_qs/0]). --export([should_close/0, cleanup/0]). --export([parse_cookie/0, get_cookie_value/1]). --export([serve_file/2, serve_file/3]). --export([accepted_encodings/1]). - --define(SAVE_QS, mochiweb_request_qs). --define(SAVE_PATH, mochiweb_request_path). --define(SAVE_RECV, mochiweb_request_recv). --define(SAVE_BODY, mochiweb_request_body). --define(SAVE_BODY_LENGTH, mochiweb_request_body_length). --define(SAVE_POST, mochiweb_request_post). --define(SAVE_COOKIE, mochiweb_request_cookie). --define(SAVE_FORCE_CLOSE, mochiweb_request_force_close). - -%% @type iolist() = [iolist() | binary() | char()]. -%% @type iodata() = binary() | iolist(). -%% @type key() = atom() | string() | binary() -%% @type value() = atom() | string() | binary() | integer() -%% @type headers(). A mochiweb_headers structure. -%% @type response(). A mochiweb_response parameterized module instance. -%% @type ioheaders() = headers() | [{key(), value()}]. - -% 10 second default idle timeout --define(IDLE_TIMEOUT, 10000). - -% Maximum recv_body() length of 1MB --define(MAX_RECV_BODY, (1024*1024)). - -%% @spec get_header_value(K) -> undefined | Value -%% @doc Get the value of a given request header. -get_header_value(K) -> - mochiweb_headers:get_value(K, Headers). - -get_primary_header_value(K) -> - mochiweb_headers:get_primary_value(K, Headers). - -%% @type field() = socket | scheme | method | raw_path | version | headers | peer | path | body_length | range - -%% @spec get(field()) -> term() -%% @doc Return the internal representation of the given field. If -%% socket is requested on a HTTPS connection, then -%% an ssl socket will be returned as {ssl, SslSocket}. -%% You can use SslSocket with the ssl -%% application, eg: ssl:peercert(SslSocket). -get(socket) -> - Socket; -get(scheme) -> - case mochiweb_socket:type(Socket) of - plain -> - http; - ssl -> - https - end; -get(method) -> - Method; -get(raw_path) -> - RawPath; -get(version) -> - Version; -get(headers) -> - Headers; -get(peer) -> - case mochiweb_socket:peername(Socket) of - {ok, {Addr={10, _, _, _}, _Port}} -> - case get_header_value("x-forwarded-for") of - undefined -> - inet_parse:ntoa(Addr); - Hosts -> - string:strip(lists:last(string:tokens(Hosts, ","))) - end; - {ok, {{127, 0, 0, 1}, _Port}} -> - case get_header_value("x-forwarded-for") of - undefined -> - "127.0.0.1"; - Hosts -> - string:strip(lists:last(string:tokens(Hosts, ","))) - end; - {ok, {Addr, _Port}} -> - inet_parse:ntoa(Addr); - {error, enotconn} -> - exit(normal) - end; -get(path) -> - case erlang:get(?SAVE_PATH) of - undefined -> - {Path0, _, _} = mochiweb_util:urlsplit_path(RawPath), - Path = mochiweb_util:unquote(Path0), - put(?SAVE_PATH, Path), - Path; - Cached -> - Cached - end; -get(body_length) -> - case erlang:get(?SAVE_BODY_LENGTH) of - undefined -> - BodyLength = body_length(), - put(?SAVE_BODY_LENGTH, {cached, BodyLength}), - BodyLength; - {cached, Cached} -> - Cached - end; -get(range) -> - case get_header_value(range) of - undefined -> - undefined; - RawRange -> - mochiweb_http:parse_range_request(RawRange) - end. - -%% @spec dump() -> {mochiweb_request, [{atom(), term()}]} -%% @doc Dump the internal representation to a "human readable" set of terms -%% for debugging/inspection purposes. -dump() -> - {?MODULE, [{method, Method}, - {version, Version}, - {raw_path, RawPath}, - {headers, mochiweb_headers:to_list(Headers)}]}. - -%% @spec send(iodata()) -> ok -%% @doc Send data over the socket. -send(Data) -> - case mochiweb_socket:send(Socket, Data) of - ok -> - ok; - _ -> - exit(normal) - end. - -%% @spec recv(integer()) -> binary() -%% @doc Receive Length bytes from the client as a binary, with the default -%% idle timeout. -recv(Length) -> - recv(Length, ?IDLE_TIMEOUT). - -%% @spec recv(integer(), integer()) -> binary() -%% @doc Receive Length bytes from the client as a binary, with the given -%% Timeout in msec. -recv(Length, Timeout) -> - case mochiweb_socket:recv(Socket, Length, Timeout) of - {ok, Data} -> - put(?SAVE_RECV, true), - Data; - _ -> - exit(normal) - end. - -%% @spec body_length() -> undefined | chunked | unknown_transfer_encoding | integer() -%% @doc Infer body length from transfer-encoding and content-length headers. -body_length() -> - case get_header_value("transfer-encoding") of - undefined -> - case get_header_value("content-length") of - undefined -> - undefined; - Length -> - list_to_integer(Length) - end; - "chunked" -> - chunked; - Unknown -> - {unknown_transfer_encoding, Unknown} - end. - - -%% @spec recv_body() -> binary() -%% @doc Receive the body of the HTTP request (defined by Content-Length). -%% Will only receive up to the default max-body length of 1MB. -recv_body() -> - recv_body(?MAX_RECV_BODY). - -%% @spec recv_body(integer()) -> binary() -%% @doc Receive the body of the HTTP request (defined by Content-Length). -%% Will receive up to MaxBody bytes. -recv_body(MaxBody) -> - case erlang:get(?SAVE_BODY) of - undefined -> - % we could use a sane constant for max chunk size - Body = stream_body(?MAX_RECV_BODY, fun - ({0, _ChunkedFooter}, {_LengthAcc, BinAcc}) -> - iolist_to_binary(lists:reverse(BinAcc)); - ({Length, Bin}, {LengthAcc, BinAcc}) -> - NewLength = Length + LengthAcc, - if NewLength > MaxBody -> - exit({body_too_large, chunked}); - true -> - {NewLength, [Bin | BinAcc]} - end - end, {0, []}, MaxBody), - put(?SAVE_BODY, Body), - Body; - Cached -> Cached - end. - -stream_body(MaxChunkSize, ChunkFun, FunState) -> - stream_body(MaxChunkSize, ChunkFun, FunState, undefined). - -stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength) -> - Expect = case get_header_value("expect") of - undefined -> - undefined; - Value when is_list(Value) -> - string:to_lower(Value) - end, - case Expect of - "100-continue" -> - start_raw_response({100, gb_trees:empty()}); - _Else -> - ok - end, - case body_length() of - undefined -> - undefined; - {unknown_transfer_encoding, Unknown} -> - exit({unknown_transfer_encoding, Unknown}); - chunked -> - % In this case the MaxBody is actually used to - % determine the maximum allowed size of a single - % chunk. - stream_chunked_body(MaxChunkSize, ChunkFun, FunState); - 0 -> - <<>>; - Length when is_integer(Length) -> - case MaxBodyLength of - MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length -> - exit({body_too_large, content_length}); - _ -> - stream_unchunked_body(Length, ChunkFun, FunState) - end; - Length -> - exit({length_not_integer, Length}) - end. - - -%% @spec start_response({integer(), ioheaders()}) -> response() -%% @doc Start the HTTP response by sending the Code HTTP response and -%% ResponseHeaders. The server will set header defaults such as Server -%% and Date if not present in ResponseHeaders. -start_response({Code, ResponseHeaders}) -> - HResponse = mochiweb_headers:make(ResponseHeaders), - HResponse1 = mochiweb_headers:default_from_list(server_headers(), - HResponse), - start_raw_response({Code, HResponse1}). - -%% @spec start_raw_response({integer(), headers()}) -> response() -%% @doc Start the HTTP response by sending the Code HTTP response and -%% ResponseHeaders. -start_raw_response({Code, ResponseHeaders}) -> - F = fun ({K, V}, Acc) -> - [mochiweb_util:make_io(K), <<": ">>, V, <<"\r\n">> | Acc] - end, - End = lists:foldl(F, [<<"\r\n">>], - mochiweb_headers:to_list(ResponseHeaders)), - send([make_version(Version), make_code(Code), <<"\r\n">> | End]), - mochiweb:new_response({THIS, Code, ResponseHeaders}). - - -%% @spec start_response_length({integer(), ioheaders(), integer()}) -> response() -%% @doc Start the HTTP response by sending the Code HTTP response and -%% ResponseHeaders including a Content-Length of Length. The server -%% will set header defaults such as Server -%% and Date if not present in ResponseHeaders. -start_response_length({Code, ResponseHeaders, Length}) -> - HResponse = mochiweb_headers:make(ResponseHeaders), - HResponse1 = mochiweb_headers:enter("Content-Length", Length, HResponse), - start_response({Code, HResponse1}). - -%% @spec respond({integer(), ioheaders(), iodata() | chunked | {file, IoDevice}}) -> response() -%% @doc Start the HTTP response with start_response, and send Body to the -%% client (if the get(method) /= 'HEAD'). The Content-Length header -%% will be set by the Body length, and the server will insert header -%% defaults. -respond({Code, ResponseHeaders, {file, IoDevice}}) -> - Length = mochiweb_io:iodevice_size(IoDevice), - Response = start_response_length({Code, ResponseHeaders, Length}), - case Method of - 'HEAD' -> - ok; - _ -> - mochiweb_io:iodevice_stream(fun send/1, IoDevice) - end, - Response; -respond({Code, ResponseHeaders, chunked}) -> - HResponse = mochiweb_headers:make(ResponseHeaders), - HResponse1 = case Method of - 'HEAD' -> - %% This is what Google does, http://www.google.com/ - %% is chunked but HEAD gets Content-Length: 0. - %% The RFC is ambiguous so emulating Google is smart. - mochiweb_headers:enter("Content-Length", "0", - HResponse); - _ when Version >= {1, 1} -> - %% Only use chunked encoding for HTTP/1.1 - mochiweb_headers:enter("Transfer-Encoding", "chunked", - HResponse); - _ -> - %% For pre-1.1 clients we send the data as-is - %% without a Content-Length header and without - %% chunk delimiters. Since the end of the document - %% is now ambiguous we must force a close. - put(?SAVE_FORCE_CLOSE, true), - HResponse - end, - start_response({Code, HResponse1}); -respond({Code, ResponseHeaders, Body}) -> - Response = start_response_length({Code, ResponseHeaders, iolist_size(Body)}), - case Method of - 'HEAD' -> - ok; - _ -> - send(Body) - end, - Response. - -%% @spec not_found() -> response() -%% @doc Alias for not_found([]). -not_found() -> - not_found([]). - -%% @spec not_found(ExtraHeaders) -> response() -%% @doc Alias for respond({404, [{"Content-Type", "text/plain"} -%% | ExtraHeaders], <<"Not found.">>}). -not_found(ExtraHeaders) -> - respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders], - <<"Not found.">>}). - -%% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}) -> -%% response() -%% @doc respond({200, [{"Content-Type", ContentType} | Headers], Body}). -ok({ContentType, Body}) -> - ok({ContentType, [], Body}); -ok({ContentType, ResponseHeaders, Body}) -> - HResponse = mochiweb_headers:make(ResponseHeaders), - case THIS:get(range) of - X when (X =:= undefined orelse X =:= fail) orelse Body =:= chunked -> - %% http://code.google.com/p/mochiweb/issues/detail?id=54 - %% Range header not supported when chunked, return 200 and provide - %% full response. - HResponse1 = mochiweb_headers:enter("Content-Type", ContentType, - HResponse), - respond({200, HResponse1, Body}); - Ranges -> - {PartList, Size} = range_parts(Body, Ranges), - case PartList of - [] -> %% no valid ranges - HResponse1 = mochiweb_headers:enter("Content-Type", - ContentType, - HResponse), - %% could be 416, for now we'll just return 200 - respond({200, HResponse1, Body}); - PartList -> - {RangeHeaders, RangeBody} = - mochiweb_multipart:parts_to_body(PartList, ContentType, Size), - HResponse1 = mochiweb_headers:enter_from_list( - [{"Accept-Ranges", "bytes"} | - RangeHeaders], - HResponse), - respond({206, HResponse1, RangeBody}) - end - end. - -%% @spec should_close() -> bool() -%% @doc Return true if the connection must be closed. If false, using -%% Keep-Alive should be safe. -should_close() -> - ForceClose = erlang:get(mochiweb_request_force_close) =/= undefined, - DidNotRecv = erlang:get(mochiweb_request_recv) =:= undefined, - ForceClose orelse Version < {1, 0} - %% Connection: close - orelse get_header_value("connection") =:= "close" - %% HTTP 1.0 requires Connection: Keep-Alive - orelse (Version =:= {1, 0} - andalso get_header_value("connection") =/= "Keep-Alive") - %% unread data left on the socket, can't safely continue - orelse (DidNotRecv - andalso get_header_value("content-length") =/= undefined - andalso list_to_integer(get_header_value("content-length")) > 0) - orelse (DidNotRecv - andalso get_header_value("transfer-encoding") =:= "chunked"). - -%% @spec cleanup() -> ok -%% @doc Clean up any junk in the process dictionary, required before continuing -%% a Keep-Alive request. -cleanup() -> - [erase(K) || K <- [?SAVE_QS, - ?SAVE_PATH, - ?SAVE_RECV, - ?SAVE_BODY, - ?SAVE_POST, - ?SAVE_COOKIE, - ?SAVE_FORCE_CLOSE]], - ok. - -%% @spec parse_qs() -> [{Key::string(), Value::string()}] -%% @doc Parse the query string of the URL. -parse_qs() -> - case erlang:get(?SAVE_QS) of - undefined -> - {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath), - Parsed = mochiweb_util:parse_qs(QueryString), - put(?SAVE_QS, Parsed), - Parsed; - Cached -> - Cached - end. - -%% @spec get_cookie_value(Key::string) -> string() | undefined -%% @doc Get the value of the given cookie. -get_cookie_value(Key) -> - proplists:get_value(Key, parse_cookie()). - -%% @spec parse_cookie() -> [{Key::string(), Value::string()}] -%% @doc Parse the cookie header. -parse_cookie() -> - case erlang:get(?SAVE_COOKIE) of - undefined -> - Cookies = case get_header_value("cookie") of - undefined -> - []; - Value -> - mochiweb_cookies:parse_cookie(Value) - end, - put(?SAVE_COOKIE, Cookies), - Cookies; - Cached -> - Cached - end. - -%% @spec parse_post() -> [{Key::string(), Value::string()}] -%% @doc Parse an application/x-www-form-urlencoded form POST. This -%% has the side-effect of calling recv_body(). -parse_post() -> - case erlang:get(?SAVE_POST) of - undefined -> - Parsed = case recv_body() of - undefined -> - []; - Binary -> - case get_primary_header_value("content-type") of - "application/x-www-form-urlencoded" ++ _ -> - mochiweb_util:parse_qs(Binary); - _ -> - [] - end - end, - put(?SAVE_POST, Parsed), - Parsed; - Cached -> - Cached - end. - -%% @spec stream_chunked_body(integer(), fun(), term()) -> term() -%% @doc The function is called for each chunk. -%% Used internally by read_chunked_body. -stream_chunked_body(MaxChunkSize, Fun, FunState) -> - case read_chunk_length() of - 0 -> - Fun({0, read_chunk(0)}, FunState); - Length when Length > MaxChunkSize -> - NewState = read_sub_chunks(Length, MaxChunkSize, Fun, FunState), - stream_chunked_body(MaxChunkSize, Fun, NewState); - Length -> - NewState = Fun({Length, read_chunk(Length)}, FunState), - stream_chunked_body(MaxChunkSize, Fun, NewState) - end. - -stream_unchunked_body(0, Fun, FunState) -> - Fun({0, <<>>}, FunState); -stream_unchunked_body(Length, Fun, FunState) when Length > 0 -> - PktSize = case Length > ?RECBUF_SIZE of - true -> - ?RECBUF_SIZE; - false -> - Length - end, - Bin = recv(PktSize), - NewState = Fun({PktSize, Bin}, FunState), - stream_unchunked_body(Length - PktSize, Fun, NewState). - -%% @spec read_chunk_length() -> integer() -%% @doc Read the length of the next HTTP chunk. -read_chunk_length() -> - mochiweb_socket:setopts(Socket, [{packet, line}]), - case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of - {ok, Header} -> - mochiweb_socket:setopts(Socket, [{packet, raw}]), - Splitter = fun (C) -> - C =/= $\r andalso C =/= $\n andalso C =/= $ - end, - {Hex, _Rest} = lists:splitwith(Splitter, binary_to_list(Header)), - mochihex:to_int(Hex); - _ -> - exit(normal) - end. - -%% @spec read_chunk(integer()) -> Chunk::binary() | [Footer::binary()] -%% @doc Read in a HTTP chunk of the given length. If Length is 0, then read the -%% HTTP footers (as a list of binaries, since they're nominal). -read_chunk(0) -> - mochiweb_socket:setopts(Socket, [{packet, line}]), - F = fun (F1, Acc) -> - case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of - {ok, <<"\r\n">>} -> - Acc; - {ok, Footer} -> - F1(F1, [Footer | Acc]); - _ -> - exit(normal) - end - end, - Footers = F(F, []), - mochiweb_socket:setopts(Socket, [{packet, raw}]), - put(?SAVE_RECV, true), - Footers; -read_chunk(Length) -> - case mochiweb_socket:recv(Socket, 2 + Length, ?IDLE_TIMEOUT) of - {ok, <>} -> - Chunk; - _ -> - exit(normal) - end. - -read_sub_chunks(Length, MaxChunkSize, Fun, FunState) when Length > MaxChunkSize -> - Bin = recv(MaxChunkSize), - NewState = Fun({size(Bin), Bin}, FunState), - read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState); - -read_sub_chunks(Length, _MaxChunkSize, Fun, FunState) -> - Fun({Length, read_chunk(Length)}, FunState). - -%% @spec serve_file(Path, DocRoot) -> Response -%% @doc Serve a file relative to DocRoot. -serve_file(Path, DocRoot) -> - serve_file(Path, DocRoot, []). - -%% @spec serve_file(Path, DocRoot, ExtraHeaders) -> Response -%% @doc Serve a file relative to DocRoot. -serve_file(Path, DocRoot, ExtraHeaders) -> - case mochiweb_util:safe_relative_path(Path) of - undefined -> - not_found(ExtraHeaders); - RelPath -> - FullPath = filename:join([DocRoot, RelPath]), - case filelib:is_dir(FullPath) of - true -> - maybe_redirect(RelPath, FullPath, ExtraHeaders); - false -> - maybe_serve_file(FullPath, ExtraHeaders) - end - end. - -%% Internal API - -%% This has the same effect as the DirectoryIndex directive in httpd -directory_index(FullPath) -> - filename:join([FullPath, "index.html"]). - -maybe_redirect([], FullPath, ExtraHeaders) -> - maybe_serve_file(directory_index(FullPath), ExtraHeaders); - -maybe_redirect(RelPath, FullPath, ExtraHeaders) -> - case string:right(RelPath, 1) of - "/" -> - maybe_serve_file(directory_index(FullPath), ExtraHeaders); - _ -> - Host = mochiweb_headers:get_value("host", Headers), - Location = "http://" ++ Host ++ "/" ++ RelPath ++ "/", - LocationBin = list_to_binary(Location), - MoreHeaders = [{"Location", Location}, - {"Content-Type", "text/html"} | ExtraHeaders], - Top = <<"" - "" - "301 Moved Permanently" - "" - "

Moved Permanently

" - "

The document has moved >, - Bottom = <<">here.

\n">>, - Body = <>, - respond({301, MoreHeaders, Body}) - end. - -maybe_serve_file(File, ExtraHeaders) -> - case file:read_file_info(File) of - {ok, FileInfo} -> - LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime), - case get_header_value("if-modified-since") of - LastModified -> - respond({304, ExtraHeaders, ""}); - _ -> - case file:open(File, [raw, binary]) of - {ok, IoDevice} -> - ContentType = mochiweb_util:guess_mime(File), - Res = ok({ContentType, - [{"last-modified", LastModified} - | ExtraHeaders], - {file, IoDevice}}), - file:close(IoDevice), - Res; - _ -> - not_found(ExtraHeaders) - end - end; - {error, _} -> - not_found(ExtraHeaders) - end. - -server_headers() -> - [{"Server", "MochiWeb/1.0 (" ++ ?QUIP ++ ")"}, - {"Date", httpd_util:rfc1123_date()}]. - -make_code(X) when is_integer(X) -> - [integer_to_list(X), [" " | httpd_util:reason_phrase(X)]]; -make_code(Io) when is_list(Io); is_binary(Io) -> - Io. - -make_version({1, 0}) -> - <<"HTTP/1.0 ">>; -make_version(_) -> - <<"HTTP/1.1 ">>. - -range_parts({file, IoDevice}, Ranges) -> - Size = mochiweb_io:iodevice_size(IoDevice), - F = fun (Spec, Acc) -> - case mochiweb_http:range_skip_length(Spec, Size) of - invalid_range -> - Acc; - V -> - [V | Acc] - end - end, - LocNums = lists:foldr(F, [], Ranges), - {ok, Data} = file:pread(IoDevice, LocNums), - Bodies = lists:zipwith(fun ({Skip, Length}, PartialBody) -> - {Skip, Skip + Length - 1, PartialBody} - end, - LocNums, Data), - {Bodies, Size}; -range_parts(Body0, Ranges) -> - Body = iolist_to_binary(Body0), - Size = size(Body), - F = fun(Spec, Acc) -> - case mochiweb_http:range_skip_length(Spec, Size) of - invalid_range -> - Acc; - {Skip, Length} -> - <<_:Skip/binary, PartialBody:Length/binary, _/binary>> = Body, - [{Skip, Skip + Length - 1, PartialBody} | Acc] - end - end, - {lists:foldr(F, [], Ranges), Size}. - -%% @spec accepted_encodings([encoding()]) -> [encoding()] | bad_accept_encoding_value -%% @type encoding() = string(). -%% -%% @doc Returns a list of encodings accepted by a request. Encodings that are -%% not supported by the server will not be included in the return list. -%% This list is computed from the "Accept-Encoding" header and -%% its elements are ordered, descendingly, according to their Q values. -%% -%% Section 14.3 of the RFC 2616 (HTTP 1.1) describes the "Accept-Encoding" -%% header and the process of determining which server supported encodings -%% can be used for encoding the body for the request's response. -%% -%% Examples -%% -%% 1) For a missing "Accept-Encoding" header: -%% accepted_encodings(["gzip", "identity"]) -> ["identity"] -%% -%% 2) For an "Accept-Encoding" header with value "gzip, deflate": -%% accepted_encodings(["gzip", "identity"]) -> ["gzip", "identity"] -%% -%% 3) For an "Accept-Encoding" header with value "gzip;q=0.5, deflate": -%% accepted_encodings(["gzip", "deflate", "identity"]) -> -%% ["deflate", "gzip", "identity"] -%% -accepted_encodings(SupportedEncodings) -> - AcceptEncodingHeader = case get_header_value("Accept-Encoding") of - undefined -> - ""; - Value -> - Value - end, - case mochiweb_util:parse_qvalues(AcceptEncodingHeader) of - invalid_qvalue_string -> - bad_accept_encoding_value; - QList -> - mochiweb_util:pick_accepted_encodings( - QList, SupportedEncodings, "identity" - ) - end. - -%% -%% Tests -%% --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). --endif. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/README 2012-03-19 10:36:09.000000000 +0000 @@ -62,23 +62,54 @@ user_dn_pattern --------------- -Default: "cn=${username},ou=People,dc=example,dc=com" +Default: "${username}" -Pattern for a user's DN. Must contain exactly one instance of -"${username}". This will be where the username supplied by the client -is substituted. You almost certainly want to change this. +There are two ways to convert a username as provided through AMQP to a +Distinguished Name. The simplest way is via string substitution with +user_dn_pattern. To do this, set user_dn_pattern to a string +containing exactly one instance of "${username}". + +For example, setting user_dn_pattern to: + "cn=${username},ou=People,dc=example,dc=com" + +would cause the username "simon" to be converted to the DN + "cn=simon,ou=People,dc=example,dc=com" + +dn_lookup_attribute and dn_lookup_base +-------------------------------------- + +Default: 'none' and 'none' + +The other way to convert a username to a Distinguished Name is via an +LDAP lookup after binding. In order for this to work your LDAP server +needs to be configured to allow binding with the unadorned username +(Microsoft Active Directory typically does this). + +To do this, set dn_lookup_attribute to the name of the attribute the +represents the user name, and dn_lookup_base to the base DN for the +query. + +For example, if I set + + {dn_lookup_attribute, "userPrincipalName"}, + {dn_lookup_base, "DC=vmware,DC=com"} + +I can authenticate as "smacmullen@vmware.com" and have my local Active +Directory server return my real DN. other_bind ---------- -Default: anon +Default: as_user -Normally for authentication this plugin binds to the LDAP server as +For authentication this plugin binds to the LDAP server as the user it is trying to authenticate. This option controls how to bind for authorisation queries, and to retrieve the details of a user who is logging in without presenting a password (e.g. SASL EXTERNAL). -This option must either be the atom anon, or a tuple {UserDN, Password}. +This option must either be one of the atoms 'as_user' or 'anon', or a +tuple {UserDN, Password}. 'as_user' means to bind as the authenticated +user. use_ssl ------- @@ -102,7 +133,7 @@ Set to true to cause LDAP traffic to be written to the RabbitMQ log. You probably only want to use this for debugging, since it will -usually cause passwords to be written to the logs. +usually cause passwords to be written to the logs, and is rather verbose. Example configuration file ========================== diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/package.mk rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/package.mk --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/package.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/package.mk 2012-03-19 10:36:09.000000000 +0000 @@ -1,7 +1,7 @@ RELEASABLE:=true DEPS:=rabbitmq-server rabbitmq-erlang-client eldap-wrapper -ifeq ($(shell nmap -p 389 localhost | grep '389/tcp open' > /dev/null && echo true),true) +ifeq ($(shell nc -z localhost 389 && echo true),true) WITH_BROKER_TEST_COMMANDS:=eunit:test(rabbit_auth_backend_ldap_test,[verbose]) WITH_BROKER_TEST_CONFIG:=$(PACKAGE_DIR)/etc/rabbit-test endif diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. +%% 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 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-2010 LShift -%% Ltd. Portions created by Cohesive Financial Technologies LLC are -%% Copyright (C) 2007-2010 Cohesive Financial Technologies -%% LLC. Portions created by Rabbit Technologies Ltd are Copyright -%% (C) 2007-2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend_ldap). @@ -52,6 +37,8 @@ -record(state, { servers, user_dn_pattern, + dn_lookup_attribute, + dn_lookup_base, other_bind, vhost_access_query, resource_access_query, @@ -60,6 +47,8 @@ log, port }). +-record(impl, { user_dn, password }). + %%-------------------------------------------------------------------- description() -> @@ -81,13 +70,14 @@ exit({unknown_auth_props, Username, AuthProps}). check_vhost_access(User = #user{username = Username, - impl = UserDN}, VHost) -> + impl = #impl{user_dn = UserDN}}, VHost) -> gen_server:call(?SERVER, {check_vhost, [{username, Username}, {user_dn, UserDN}, {vhost, VHost}], User}, infinity). -check_resource_access(User = #user{username = Username, impl = UserDN}, +check_resource_access(User = #user{username = Username, + impl = #impl{user_dn = UserDN}}, #resource{virtual_host = VHost, kind = Type, name = Name}, Permission) -> gen_server:call(?SERVER, {check_resource, [{username, Username}, @@ -118,7 +108,8 @@ Filter = eldap:present("objectClass"), object_exists(DNPattern, Filter, Args, LDAP); -evaluate({in_group, DNPattern}, Args, #user{impl = UserDN}, LDAP) -> +evaluate({in_group, DNPattern}, Args, #user{impl = #impl{user_dn = UserDN}}, + LDAP) -> Filter = eldap:equalityMatch("member", UserDN), object_exists(DNPattern, Filter, Args, LDAP); @@ -143,11 +134,12 @@ case eldap:search(LDAP, [{base, DN}, {filter, Filter}, + {attributes, ["objectClass"]}, %% Reduce verbiage {scope, eldap:baseObject()}]) of {ok, #eldap_search_result{entries = Entries}} -> length(Entries) > 0; - {error, _} -> - false + {error, _} = E -> + E end. attribute(DNPattern, AttributeName, Args, LDAP) -> @@ -161,25 +153,22 @@ Attr; {ok, #eldap_search_result{entries = _}} -> false; - {error, _} -> - false + {error, _} = E -> + E end. evaluate_ldap(Q, Args, User, State) -> - with_ldap(fun(LDAP) -> evaluate(Q, Args, User, LDAP) end, State). + with_ldap(creds(User, State), + fun(LDAP) -> evaluate(Q, Args, User, LDAP) end, State). %%-------------------------------------------------------------------- -with_ldap(Fun, State = #state{ other_bind = BindOpts }) -> - with_ldap(BindOpts, Fun, State). - %% TODO - ATM we create and destroy a new LDAP connection on every %% call. This could almost certainly be more efficient. -with_ldap(BindOpts, Fun, - State = #state{ servers = Servers, - use_ssl = SSL, - log = Log, - port = Port }) -> +with_ldap(Creds, Fun, State = #state{servers = Servers, + use_ssl = SSL, + log = Log, + port = Port}) -> Opts0 = [{ssl, SSL}, {port, Port}], Opts = case Log of true -> @@ -194,7 +183,7 @@ case eldap:open(Servers, Opts) of {ok, LDAP} -> Reply = try - case BindOpts of + case Creds of anon -> Fun(LDAP); {UserDN, Password} -> @@ -220,11 +209,13 @@ {ok, V} = application:get_env(F), V. -do_login(Username, LDAP, State = #state{ tag_queries = TagQueries }) -> - UserDN = username_to_dn(Username, State), +do_login(Username, Password, LDAP, + State = #state{ tag_queries = TagQueries }) -> + UserDN = username_to_dn(Username, LDAP, State), User = #user{username = Username, auth_backend = ?MODULE, - impl = UserDN}, + impl = #impl{user_dn = UserDN, + password = Password}}, TagRes = [{Tag, evaluate(Q, [{username, Username}, {user_dn, UserDN}], User, LDAP)} || {Tag, Q} <- TagQueries], @@ -233,9 +224,38 @@ [E | _] -> E end. -username_to_dn(Username, #state{ user_dn_pattern = UserDNPattern }) -> +username_to_dn(Username, _LDAP, State = #state{dn_lookup_attribute = none}) -> + fill_user_dn_pattern(Username, State); + +username_to_dn(Username, LDAP, State = #state{dn_lookup_attribute = Attr, + dn_lookup_base = Base}) -> + Filled = fill_user_dn_pattern(Username, State), + case eldap:search(LDAP, + [{base, Base}, + {filter, eldap:equalityMatch(Attr, Filled)}, + {attributes, ["distinguishedName"]}]) of + {ok, #eldap_search_result{entries = [#eldap_entry{attributes = A}]}} -> + [DN] = proplists:get_value("distinguishedName", A), + DN; + {ok, #eldap_search_result{entries = Entries}} -> + rabbit_log:warning("Searching for DN for ~s, got back ~p~n", + [Filled, Entries]), + Filled; + {error, _} = E -> + exit(E) + end. + +fill_user_dn_pattern(Username, #state{user_dn_pattern = UserDNPattern}) -> rabbit_auth_backend_ldap_util:fill(UserDNPattern, [{username, Username}]). +creds(none, #state{other_bind = as_user}) -> + exit(as_user_no_password); +creds(#user{impl = #impl{user_dn = UserDN, password = Password}}, + #state{other_bind = as_user}) -> + {UserDN, Password}; +creds(_, #state{other_bind = Creds}) -> + Creds. + %%-------------------------------------------------------------------- init([]) -> @@ -244,11 +264,13 @@ handle_call({login, Username}, _From, State) -> %% Without password, e.g. EXTERNAL - with_ldap(fun(LDAP) -> do_login(Username, LDAP, State) end, State); + with_ldap(creds(none, State), + fun(LDAP) -> do_login(Username, none, LDAP, State) end, State); handle_call({login, Username, Password}, _From, State) -> - with_ldap({username_to_dn(Username, State), Password}, - fun(LDAP) -> do_login(Username, LDAP, State) end, State); + with_ldap({fill_user_dn_pattern(Username, State), Password}, + fun(LDAP) -> do_login(Username, Password, LDAP, State) end, + State); handle_call({check_vhost, Args, User}, _From, State = #state{vhost_access_query = Q}) -> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 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-2010 LShift -%% Ltd. Portions created by Cohesive Financial Technologies LLC are -%% Copyright (C) 2007-2010 Cohesive Financial Technologies -%% LLC. Portions created by Rabbit Technologies Ltd are Copyright -%% (C) 2007-2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend_ldap_app). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 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-2010 LShift -%% Ltd. Portions created by Cohesive Financial Technologies LLC are -%% Copyright (C) 2007-2010 Cohesive Financial Technologies -%% LLC. Portions created by Rabbit Technologies Ltd are Copyright -%% (C) 2007-2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend_ldap_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 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-2010 LShift -%% Ltd. Portions created by Cohesive Financial Technologies LLC are -%% Copyright (C) 2007-2010 Cohesive Financial Technologies -%% LLC. Portions created by Rabbit Technologies Ltd are Copyright -%% (C) 2007-2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend_ldap_util). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbitmq_auth_backend_ldap.app.src rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbitmq_auth_backend_ldap.app.src --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/src/rabbitmq_auth_backend_ldap.app.src 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/src/rabbitmq_auth_backend_ldap.app.src 2012-03-19 10:36:09.000000000 +0000 @@ -6,8 +6,10 @@ {registered, []}, {mod, {rabbit_auth_backend_ldap_app, []}}, {env, [ {servers, ["ldap"]}, - {user_dn_pattern, "cn=${username},ou=People,dc=example,dc=com"}, - {other_bind, anon}, + {user_dn_pattern, "${username}"}, + {dn_lookup_attribute, none}, + {dn_lookup_base, none}, + {other_bind, as_user}, {vhost_access_query, {constant, true}}, {resource_access_query, {constant, true}}, {tag_queries, [{administrator, {constant, false}}]}, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/test/src/rabbit_auth_backend_ldap_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/test/src/rabbit_auth_backend_ldap_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-backend-ldap/test/src/rabbit_auth_backend_ldap_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-backend-ldap/test/src/rabbit_auth_backend_ldap_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend_ldap_test). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/README 2012-03-19 10:36:09.000000000 +0000 @@ -1,5 +1,5 @@ -Authenticates the user taking the Common Name of the client's SSL -certificate as the username. The user's password is not checked. +Authenticates the user, obtaining the username from the client's +SSL certificate. The user's password is not checked. In order to use this mechanism the client must connect over SSL, and present a client certificate. @@ -8,6 +8,24 @@ fail_if_no_peer_cert set to true and verify set to verify_peer, to force all SSL clients to have a verifiable client certificate. +By default this will set the username to an RFC4514-ish string form of +the certificate's subject's Distinguished Name, similar to that +produced by OpenSSL's "-nameopt RFC2253" option. + +You can obtain this string form from a certificate with a command like: + +$ openssl x509 -in path/to/cert.pem -nameopt RFC2253 -subject -noout + +or from an existing amqps connection with commands like: + +$ rabbitmqctl list_connections peer_cert_subject + +To use the Common Name instead, set: + +{rabbit, [{ssl_cert_login_from, common_name}]} + +in your configuration. + Note that the authenticated user will then be looked up in the configured authentication / authorisation backend(s) - this will be the mnesia-based user database by default, but could include other diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,34 +1,20 @@ -%% 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/ +%% 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. %% -%% 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 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-2010 LShift -%% Ltd. Portions created by Cohesive Financial Technologies LLC are -%% Copyright (C) 2007-2010 Cohesive Financial Technologies -%% LLC. Portions created by Rabbit Technologies Ltd are Copyright -%% (C) 2007-2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_auth_mechanism_ssl). -behaviour(rabbit_auth_mechanism). @@ -66,14 +52,10 @@ init(Sock) -> Username = case rabbit_net:peercert(Sock) of {ok, C} -> - CN = case rabbit_ssl:peer_cert_subject_item( - C, ?'id-at-commonName') of - not_found -> {refused, "no CN found", []}; - CN0 -> list_to_binary(CN0) - end, - case config_sane() of - true -> CN; - false -> {refused, "configuration unsafe", []} + case rabbit_ssl:peer_cert_auth_name(C) of + unsafe -> {refused, "configuration unsafe", []}; + not_found -> {refused, "no name found", []}; + Name -> Name end; {error, no_peercert} -> {refused, "no peer certificate", []}; @@ -89,17 +71,3 @@ _ -> rabbit_access_control:check_user_login(Username, []) end. - -%%-------------------------------------------------------------------------- -config_sane() -> - {ok, Opts} = application:get_env(ssl_options), - case {proplists:get_value(fail_if_no_peer_cert, Opts), - proplists:get_value(verify, Opts)} of - {true, verify_peer} -> - true; - {F, V} -> - rabbit_log:warning("EXTERNAL mechanism disabled, " - "fail_if_no_peer_cert=~p; " - "verify=~p~n", [F, V]), - false - end. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 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-2010 LShift -%% Ltd. Portions created by Cohesive Financial Technologies LLC are -%% Copyright (C) 2007-2010 Cohesive Financial Technologies -%% LLC. Portions created by Rabbit Technologies Ltd are Copyright -%% (C) 2007-2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_mechanism_ssl_app). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbitmq_auth_mechanism_ssl.app.src rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbitmq_auth_mechanism_ssl.app.src --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbitmq_auth_mechanism_ssl.app.src 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbitmq_auth_mechanism_ssl.app.src 2012-03-19 10:36:09.000000000 +0000 @@ -5,5 +5,5 @@ {modules, []}, {registered, []}, {mod, {rabbit_auth_mechanism_ssl_app, []}}, - {env, [] }, + {env, [{name_from, distinguished_name}] }, {applications, [kernel, stdlib]}]}. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-consistent-hash-exchange/LICENSE-MPL-RabbitMQ rabbitmq-server-2.8.0/plugins-src/rabbitmq-consistent-hash-exchange/LICENSE-MPL-RabbitMQ --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-consistent-hash-exchange/LICENSE-MPL-RabbitMQ 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-consistent-hash-exchange/LICENSE-MPL-RabbitMQ 2012-03-19 10:36:09.000000000 +0000 @@ -447,7 +447,7 @@ The Original Code is RabbitMQ Consistent Hash Exchange. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2011-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2011-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-consistent-hash-exchange/src/rabbit_exchange_type_consistent_hash.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-consistent-hash-exchange/src/rabbit_exchange_type_consistent_hash.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-consistent-hash-exchange/src/rabbit_exchange_type_consistent_hash.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-consistent-hash-exchange/src/rabbit_exchange_type_consistent_hash.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Consistent Hash Exchange. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type_consistent_hash). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-consistent-hash-exchange/test/src/rabbit_exchange_type_consistent_hash_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-consistent-hash-exchange/test/src/rabbit_exchange_type_consistent_hash_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-consistent-hash-exchange/test/src/rabbit_exchange_type_consistent_hash_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-consistent-hash-exchange/test/src/rabbit_exchange_type_consistent_hash_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Consistent Hash Exchange. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type_consistent_hash_test). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/Makefile rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/Makefile --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/Makefile 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/Makefile 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is VMware, Inc. -# Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +# Copyright (c) 2007-2012 VMware, Inc. All rights reserved. # VERSION=0.0.0 @@ -26,6 +26,8 @@ INFILES=$(shell find . -name '*.app.in') INTARGETS=$(patsubst %.in, %, $(INFILES)) +WEB_URL=http://www.rabbitmq.com/ + include common.mk run_in_broker: compile $(BROKER_DEPS) $(EBIN_DIR)/$(PACKAGE).app @@ -39,7 +41,7 @@ %.app: %.app.in $(SOURCES) $(BROKER_DIR)/generate_app escript $(BROKER_DIR)/generate_app $< $@ $(SOURCE_DIR) - sed -i.save 's/%%VSN%%/$(VERSION)/' $@ && rm $@.save + sed 's/%%VSN%%/$(VERSION)/' $@ > $@.tmp && mv $@.tmp $@ ############################################################################### ## Dialyzer @@ -65,7 +67,7 @@ sed -e 's:%%VERSION%%:$(VERSION):g' < $< > $@ $(DOC_DIR)/index.html: $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) $(DOC_DIR)/overview.edoc $(SOURCES) - $(LIBS_PATH) erl -noshell -eval 'edoc:application(amqp_client, ".", [{preprocess, true}])' -run init stop + $(LIBS_PATH) erl -noshell -eval 'edoc:application(amqp_client, ".", [{preprocess, true}, {macros, [{edoc, true}]}])' -run init stop ############################################################################### ## Testing @@ -103,7 +105,8 @@ source_tarball: $(DIST_DIR)/$(COMMON_PACKAGE_EZ) $(EBIN_DIR)/$(PACKAGE).app | $(DIST_DIR) mkdir -p $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(DIST_DIR) $(COPY) $(DIST_DIR)/$(COMMON_PACKAGE_EZ) $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(DIST_DIR)/ - $(COPY) README $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/ + $(COPY) README.in $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/README + elinks -dump -no-references -no-numbering $(WEB_URL)build-erlang-client.html >> $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/README $(COPY) common.mk $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/ $(COPY) test.mk $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/ sed 's/%%VSN%%/$(VERSION)/' Makefile.in > $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/Makefile diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/Makefile.in rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/Makefile.in --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/Makefile.in 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/Makefile.in 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is VMware, Inc. -# Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +# Copyright (c) 2007-2012 VMware, Inc. All rights reserved. # VERSION=%%VSN%% diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ -AMQP client for Erlang -====================== -This code implements a client for AMQP in the Erlang programming -language. - -This client offers both a networked version that uses standard -TCP-based AMQP framing and a direct client that uses native Erlang -message passing to a RabbitMQ broker. - -The API exposed to the user is common to both clients, so each version -can be used interchangeably without having to modify any client code. - -The TCP networked client has been tested with RabbitMQ server 1.4.0, -but should theoretically work with any 0-8 compliant AMQP server. - -The direct client is bound to an 0-8 compliant broker using native -Erlang message passing, which in the absence of an alternative Erlang -AMQP implementation means that it only works with RabbitMQ. - -It does however provide a level of abstraction above the internal -server API of RabbitMQ, meaning that you can write client code in -Erlang and still remain isolated from any API changes in the -underlying broker. - -It also provides a client-orientated API into RabbitMQ, allowing the -user to reuse AMQP knowledge gained by using AMQP clients in other -languages. - -The advantage of the direct client is that it eliminates the network -overhead as well as the marshaling to and from the AMQP wire format, -so that neither side has to decode or encode any AMQP frames. - -Prerequisites -------------- -In order to compile/run this code you must have the following -installed: - -- Erlang/OTP, R11B-5 or later, http://www.erlang.org/download.html -- The RabbitMQ server, 93cc2ca0ba62 or later -- Eunit, the Erlang unit testing framework - currently the whole build process - depends on eunit because all of the modules are compiled together. - A future version of the build process could remove this dependency when you - only want to compile the core libraries. - -Getting Eunit -------------- -The test suite uses eunit which is either available bundled with OTP from -release R12B-5 onwards or as a separate download that you will need to build -yourself if you are using an older version of Erlang. - -* If you are using R12B-5 or newer: - -Just skip to the next section. - -* If you are using R12B-4 or older: - -Check out eunit from their Subversion repository and build it: - - $ svn co http://svn.process-one.net/contribs/trunk/eunit eunit - $ cd eunit - $ make - -After this has sucessfully been built, you will need to create a symlink to -the eunit directory in your OTP installation directory: - - $ cd $OTP_HOME/lib/erlang/lib - $ ln -sf PATH_TO_EUNIT eunit - -where $OTP_HOME is the location of your Erlang/OTP installation. - -Compiling the Erlang client -------------------------- -You will need to get a copy of the server in order to be able to use it's -header files and runtime libraries. A good place to put this is in the sibling -directory to the Erlang client (i.e: ../rabbitmq-server), which is the default -that the Makefile expects. In this case, you can just run make: - - $ make - -If the source tree for the server is not in the sibling directory, you will -need to specify the path to this directory: - - $ make BROKER_DIR=/path/to/server - -In this case, make sure you specify BROKER_DIR every time you run a make target. - -Running the network client, direct client and packaging tests -------------------------------------------------------------- -The direct client has to be run in the same Erlang VM instance as the -RabbitMQ server. In order to use the makefile to run tests, you will need to -shutdown any other running instance of RabbitMQ server that you may have on -your machine. This is because the Makefile test targets boot their own instance -of RabbitMQ with settings depending on the test. -To run these tests, use either of the following targets: - - $ make test_network - $ make test_direct - $ make test_common_package - -Or to run all tests: - - $ make all_tests - -If any test fails, the make command will return a non-zero exit code. The reason -is logged by the server in /tmp/rabbit-sasl.log by default. - -The network client test can also be run from a separate Erlang VM instance from -RabbitMQ server. You can *start an instance of the server* and then, in the -rabbitmq-erlang-client folder, type - - rabbitmq-erlang-client $ make compile_tests - rabbitmq-erlang-client $ make run - erl -pa ebin ../rabbitmq-server/ebin tests - Erlang (BEAM) emulator version 5.6.5 [source] [64-bit] [smp:4] \ - [async-threads:0] [hipe] [kernel-poll:false] - - Eshell V5.6.5 (abort with ^G) - 1> network_client_SUITE:test(). - -To get more examples of the API, look at the functions in the test_util module. - -Make targets ------------- -Interesting rabbitmq-erlang-client make targets include - -all - The default target. Builds the client (does not compile the tests). - -compile - Builds the client. - -compile_tests - Builds the client test modules. - -run - Builds the client and starts an Erlang shell with both the client and the - server in the load path. - -run_in_broker - Builds the client and starts RabbitMQ server with shell and the client - included in load path. - -clean - Removes build products and wipes all files produced by any other - rabbitmq-erlang-client make targets or client errors. - -dialyze - Analyses the client source code with dialyzer. Uses PLT file from default - location: ~/.dialyzer_plt. Use - - $ make PLT=/path/to/plt dialyze - - to override this. Add broker to PLT beforehand, otherwise you will a lot - of 'unknown function' warnings. See add_broker_to_plt make target. - -dialyze_all - Same as dialyze, except that this also analyses tests source code. - -add_broker_to_plt - Adds broker .beam files to default plt. Use - - $ make PLT=/path/to/plt add_broker_to_plt - - to override default plt location ( ~/.dialyzer_plt ). - -source_tarball - Creates tarball of all the client source code. - -package - Creates an erlang archive of the client. - -common_package - Creates an erlang archive of the server modules required by the erlang - client. - -all_tests - Clean compiles the client and client tests source code and runs - network_client_SUITE, direct_client_SUITE and packaging tests. During the - testing, this make target runs an instance of the broker, so make sure - there is no other instance of RabbitMQ server running. - diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/README.in rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/README.in --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/README.in 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/README.in 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,12 @@ +README.in: + +Please see http://www.rabbitmq.com/build-erlang-client.html for build +instructions. + +For your convenience, a text copy of these instructions is available +below. Please be aware that the instructions here may not be as up to +date as those at the above URL. + +=========================================================================== + + diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/common.mk rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/common.mk --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/common.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/common.mk 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is VMware, Inc. -# Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +# Copyright (c) 2007-2012 VMware, Inc. All rights reserved. # # The client library can either be built from source control or by downloading @@ -32,7 +32,6 @@ # tarball version. This avoids duplicating make definitions and rules and # helps keep the Makefile maintenence well factored. - ifndef TMPDIR TMPDIR := /tmp endif diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/include/amqp_client.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/include/amqp_client.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/include/amqp_client.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/include/amqp_client.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -ifndef(AMQP_CLIENT_HRL). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/include/amqp_gen_consumer_spec.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/include/amqp_gen_consumer_spec.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/include/amqp_gen_consumer_spec.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/include/amqp_gen_consumer_spec.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,11 +11,12 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -include("amqp_client.hrl"). +-ifndef(edoc). -type(state() :: any()). -type(consume() :: #'basic.consume'{}). -type(consume_ok() :: #'basic.consume_ok'{}). @@ -38,3 +39,4 @@ {reply, any(), state()} | {noreply, state()} | {error, reason(), state()}). -spec(terminate/2 :: (any(), state()) -> state()). +-endif. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/rabbit_common.app.in rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/rabbit_common.app.in --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/rabbit_common.app.in 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/rabbit_common.app.in 2012-03-19 10:36:09.000000000 +0000 @@ -20,6 +20,7 @@ rabbit_misc, rabbit_msg_store_index, rabbit_net, + rabbit_nodes, rabbit_reader, rabbit_writer, rabbit_queue_collector, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_auth_mechanisms.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_auth_mechanisms.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_auth_mechanisms.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_auth_mechanisms.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channel.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channel.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channel.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channel.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @type close_reason(Type) = {shutdown, amqp_reason(Type)}. @@ -66,13 +66,13 @@ -behaviour(gen_server). --export([call/2, call/3, cast/2, cast/3]). +-export([call/2, call/3, cast/2, cast/3, cast_flow/3]). -export([close/1, close/3]). -export([register_return_handler/2, register_flow_handler/2, register_confirm_handler/2]). -export([call_consumer/2, subscribe/3]). --export([next_publish_seqno/1, wait_for_confirms/1, - wait_for_confirms_or_die/1]). +-export([next_publish_seqno/1, wait_for_confirms/1, wait_for_confirms/2, + wait_for_confirms_or_die/1, wait_for_confirms_or_die/2]). -export([start_link/5, connection_closing/3, open/1]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, @@ -158,7 +158,7 @@ %% @spec (Channel, Method) -> ok %% @doc This is equivalent to amqp_channel:cast(Channel, Method, none). cast(Channel, Method) -> - gen_server:cast(Channel, {cast, Method, none, self()}). + gen_server:cast(Channel, {cast, Method, none, self(), noflow}). %% @spec (Channel, Method, Content) -> ok %% where @@ -170,7 +170,17 @@ %% This function is not recommended with synchronous methods, since there is no %% way to verify that the server has received the method. cast(Channel, Method, Content) -> - gen_server:cast(Channel, {cast, Method, Content, self()}). + gen_server:cast(Channel, {cast, Method, Content, self(), noflow}). + +%% @spec (Channel, Method, Content) -> ok +%% where +%% Channel = pid() +%% Method = amqp_method() +%% Content = amqp_msg() | none +%% @doc Like cast/3, with flow control. +cast_flow(Channel, Method, Content) -> + credit_flow:send(Channel), + gen_server:cast(Channel, {cast, Method, Content, self(), flow}). %% @spec (Channel) -> ok | closing %% where @@ -198,14 +208,25 @@ next_publish_seqno(Channel) -> gen_server:call(Channel, next_publish_seqno, infinity). -%% @spec (Channel) -> boolean() +%% @spec (Channel) -> boolean() | 'timeout' %% where %% Channel = pid() %% @doc Wait until all messages published since the last call have %% been either ack'd or nack'd by the broker. Note, when called on a %% non-Confirm channel, waitForConfirms returns true immediately. wait_for_confirms(Channel) -> - gen_server:call(Channel, wait_for_confirms, infinity). + wait_for_confirms(Channel, infinity). + +%% @spec (Channel, Timeout) -> boolean() | 'timeout' +%% where +%% Channel = pid() +%% Timeout = non_neg_integer() | 'infinity' +%% @doc Wait until all messages published since the last call have +%% been either ack'd or nack'd by the broker or the timeout expires. +%% Note, when called on a non-Confirm channel, waitForConfirms returns +%% true immediately. +wait_for_confirms(Channel, Timeout) -> + gen_server:call(Channel, {wait_for_confirms, Timeout}, infinity). %% @spec (Channel) -> true %% where @@ -214,7 +235,24 @@ %% received, the calling process is immediately sent an %% exit(nack_received). wait_for_confirms_or_die(Channel) -> - gen_server:call(Channel, {wait_for_confirms_or_die, self()}, infinity). + wait_for_confirms_or_die(Channel, infinity). + +%% @spec (Channel, Timeout) -> true +%% where +%% Channel = pid() +%% Timeout = non_neg_integer() | 'infinity' +%% @doc Behaves the same as wait_for_confirms/1, but if a nack is +%% received, the calling process is immediately sent an +%% exit(nack_received). If the timeout expires, the calling process is +%% sent an exit(timeout). +wait_for_confirms_or_die(Channel, Timeout) -> + case wait_for_confirms(Channel, Timeout) of + timeout -> close(Channel, 200, <<"Confirm Timeout">>), + exit(timeout); + false -> close(Channel, 200, <<"Nacks Received">>), + exit(nacks_received); + true -> true + end. %% @spec (Channel, ReturnHandler) -> ok %% where @@ -296,13 +334,13 @@ %% @private handle_call(open, From, State) -> - {noreply, rpc_top_half(#'channel.open'{}, none, From, none, State)}; + {noreply, rpc_top_half(#'channel.open'{}, none, From, none, noflow, State)}; %% @private handle_call({close, Code, Text}, From, State) -> handle_close(Code, Text, From, State); %% @private handle_call({call, Method, AmqpMsg, Sender}, From, State) -> - handle_method_to_server(Method, AmqpMsg, From, Sender, State); + handle_method_to_server(Method, AmqpMsg, From, Sender, noflow, State); %% Handles the delivery of messages from a direct channel %% @private handle_call({send_command_sync, Method, Content}, From, State) -> @@ -319,25 +357,23 @@ handle_call(next_publish_seqno, _From, State = #state{next_pub_seqno = SeqNo}) -> {reply, SeqNo, State}; - -handle_call(wait_for_confirms, From, State) -> - handle_wait_for_confirms(From, none, true, State); - -%% Lets the channel know that the process should be sent an exit -%% signal if a nack is received. -handle_call({wait_for_confirms_or_die, Pid}, From, State) -> - handle_wait_for_confirms(From, Pid, ok, State); +handle_call({wait_for_confirms, Timeout}, From, State) -> + handle_wait_for_confirms(From, Timeout, State); %% @private handle_call({call_consumer, Msg}, _From, State = #state{consumer = Consumer}) -> {reply, amqp_gen_consumer:call_consumer(Consumer, Msg), State}; %% @private handle_call({subscribe, BasicConsume, Subscriber}, From, State) -> - handle_method_to_server(BasicConsume, none, From, Subscriber, State). + handle_method_to_server(BasicConsume, none, From, Subscriber, noflow, + State). %% @private -handle_cast({cast, Method, AmqpMsg, Sender}, State) -> - handle_method_to_server(Method, AmqpMsg, none, Sender, State); +handle_cast({cast, Method, AmqpMsg, Sender, noflow}, State) -> + handle_method_to_server(Method, AmqpMsg, none, Sender, noflow, State); +handle_cast({cast, Method, AmqpMsg, Sender, flow}, State) -> + credit_flow:ack(Sender), + handle_method_to_server(Method, AmqpMsg, none, Sender, flow, State); %% @private handle_cast({register_return_handler, ReturnHandler}, State) -> erlang:monitor(process, ReturnHandler), @@ -352,7 +388,7 @@ {noreply, State#state{flow_handler_pid = FlowHandler}}; %% Received from channels manager %% @private -handle_cast({method, Method, Content}, State) -> +handle_cast({method, Method, Content, noflow}, State) -> handle_method_from_server(Method, Content, State); %% Handles the situation when the connection closes without closing the channel %% beforehand. The channel must block all further RPCs, @@ -387,6 +423,10 @@ ok = rabbit_channel:ready_for_close(ChPid), {noreply, State}; %% @private +handle_info({bump_credit, Msg}, State) -> + credit_flow:handle_bump_msg(Msg), + {noreply, State}; +%% @private handle_info(timed_out_flushing_channel, State) -> ?LOG_WARN("Channel (~p) closing: timed out flushing while " "connection closing~n", [self()]), @@ -408,7 +448,18 @@ State = #state{flow_handler_pid = FlowHandler}) -> ?LOG_WARN("Channel (~p): Unregistering flow handler ~p because it died. " "Reason: ~p~n", [self(), FlowHandler, Reason]), - {noreply, State#state{flow_handler_pid = none}}. + {noreply, State#state{flow_handler_pid = none}}; +handle_info({'DOWN', _, process, QPid, _Reason}, State) -> + rabbit_amqqueue:notify_sent_queue_down(QPid), + {noreply, State}; +handle_info({confirm_timeout, From}, State = #state{waiting_set = WSet}) -> + case gb_trees:lookup(From, WSet) of + none -> + {noreply, State}; + {value, _} -> + gen_server:reply(From, timeout), + {noreply, State#state{waiting_set = gb_trees:delete(From, WSet)}} + end. %% @private terminate(_Reason, State) -> @@ -422,7 +473,7 @@ %% RPC mechanism %%--------------------------------------------------------------------------- -handle_method_to_server(Method, AmqpMsg, From, Sender, +handle_method_to_server(Method, AmqpMsg, From, Sender, Flow, State = #state{unconfirmed_set = USet}) -> case {check_invalid_method(Method), From, check_block(Method, AmqpMsg, State)} of @@ -440,7 +491,7 @@ State end, {noreply, rpc_top_half(Method, build_content(AmqpMsg), - From, Sender, State1)}; + From, Sender, Flow, State1)}; {ok, none, BlockReply} -> ?LOG_WARN("Channel (~p): discarding method ~p in cast.~n" "Reason: ~p~n", [self(), Method, BlockReply]), @@ -461,22 +512,23 @@ class_id = 0, method_id = 0}, case check_block(Close, none, State) of - ok -> {noreply, rpc_top_half(Close, none, From, none, State)}; + ok -> {noreply, rpc_top_half(Close, none, From, none, noflow, + State)}; BlockReply -> {reply, BlockReply, State} end. -rpc_top_half(Method, Content, From, Sender, +rpc_top_half(Method, Content, From, Sender, Flow, State0 = #state{rpc_requests = RequestQueue}) -> State1 = State0#state{ - rpc_requests = - queue:in({From, Sender, Method, Content}, RequestQueue)}, + rpc_requests = queue:in({From, Sender, Method, Content, Flow}, + RequestQueue)}, IsFirstElement = queue:is_empty(RequestQueue), if IsFirstElement -> do_rpc(State1); true -> State1 end. rpc_bottom_half(Reply, State = #state{rpc_requests = RequestQueue}) -> - {{value, {From, _Sender, _Method, _Content}}, RequestQueue1} = + {{value, {From, _Sender, _Method, _Content, _Flow}}, RequestQueue1} = queue:out(RequestQueue), case From of none -> ok; @@ -487,9 +539,9 @@ do_rpc(State = #state{rpc_requests = Q, closing = Closing}) -> case queue:out(Q) of - {{value, {From, Sender, Method, Content}}, NewQ} -> + {{value, {From, Sender, Method, Content, Flow}}, NewQ} -> State1 = pre_do(Method, Content, Sender, State), - DoRet = do(Method, Content, State1), + DoRet = do(Method, Content, Flow, State1), case ?PROTOCOL:is_method_synchronous(Method) of true -> State1; false -> case {From, DoRet} of @@ -513,7 +565,7 @@ end. pending_rpc_method(#state{rpc_requests = Q}) -> - {value, {_From, _Sender, Method, _Content}} = queue:peek(Q), + {value, {_From, _Sender, Method, _Content, _Flow}} = queue:peek(Q), Method. pre_do(#'channel.open'{}, none, _Sender, State) -> @@ -562,13 +614,13 @@ State = #state{closing = {just_channel, _}}) -> %% Both client and server sent close at the same time. Don't shutdown yet, %% wait for close_ok. - do(#'channel.close_ok'{}, none, State), + do(#'channel.close_ok'{}, none, noflow, State), {noreply, State#state{ closing = {just_channel, {server_initiated_close, Code, Text}}}}; handle_method_from_server1(#'channel.close'{reply_code = Code, reply_text = Text}, none, State) -> - do(#'channel.close_ok'{}, none, State), + do(#'channel.close_ok'{}, none, noflow, State), handle_shutdown({server_initiated_close, Code, Text}, State); handle_method_from_server1(#'channel.close_ok'{}, none, State = #state{closing = Closing}) -> @@ -604,7 +656,7 @@ %% flushed beforehand. Methods that made it to the queue are not %% blocked in any circumstance. {noreply, rpc_top_half(#'channel.flow_ok'{active = Active}, none, none, - none, State#state{flow_active = Active})}; + none, noflow, State#state{flow_active = Active})}; handle_method_from_server1( #'basic.return'{} = BasicReturn, AmqpMsg, State = #state{return_handler_pid = ReturnHandler}) -> @@ -629,12 +681,12 @@ #state{confirm_handler_pid = none} = State) -> ?LOG_WARN("Channel (~p): received ~p but there is no " "confirm handler registered~n", [self(), BasicNack]), - {noreply, update_confirm_set(BasicNack, handle_nack(State))}; + {noreply, update_confirm_set(BasicNack, State)}; handle_method_from_server1( #'basic.nack'{} = BasicNack, none, #state{confirm_handler_pid = ConfirmHandler} = State) -> ConfirmHandler ! BasicNack, - {noreply, update_confirm_set(BasicNack, handle_nack(State))}; + {noreply, update_confirm_set(BasicNack, State)}; handle_method_from_server1(Method, none, State) -> {noreply, rpc_bottom_half(Method, State)}; @@ -693,14 +745,15 @@ %% Internal plumbing %%--------------------------------------------------------------------------- -do(Method, Content, #state{driver = Driver, writer = W}) -> +do(Method, Content, Flow, #state{driver = Driver, writer = W}) -> %% Catching because it expects the {channel_exit, _, _} message on error - catch case {Driver, Content} of - {network, none} -> rabbit_writer:send_command_sync(W, Method); - {network, _} -> rabbit_writer:send_command_sync(W, Method, - Content); - {direct, none} -> rabbit_channel:do(W, Method); - {direct, _} -> rabbit_channel:do(W, Method, Content) + catch case {Driver, Content, Flow} of + {network, none, _} -> rabbit_writer:send_command_sync(W, Method); + {network, _, _} -> rabbit_writer:send_command_sync(W, Method, + Content); + {direct, none, _} -> rabbit_channel:do(W, Method); + {direct, _, flow} -> rabbit_channel:do_flow(W, Method, Content); + {direct, _, noflow} -> rabbit_channel:do(W, Method, Content) end. start_writer(State = #state{start_writer_fun = SWF}) -> @@ -757,14 +810,6 @@ {noreply, State} end. -handle_nack(State = #state{waiting_set = WSet}) -> - DyingPids = [Pid || {_, Pid} <- gb_trees:to_list(WSet), Pid =/= none], - case DyingPids of - [] -> State; - _ -> [exit(Pid, nack_received) || Pid <- DyingPids], - close(self(), 200, <<"Nacks Received">>) - end. - update_confirm_set(#'basic.ack'{delivery_tag = SeqNo, multiple = Multiple}, State = #state{unconfirmed_set = USet}) -> @@ -796,20 +841,33 @@ true -> notify_confirm_waiters(State) end. -notify_confirm_waiters(State = #state{waiting_set = WSet, +notify_confirm_waiters(State = #state{waiting_set = WSet, only_acks_received = OAR}) -> - [gen_server:reply(From, OAR) || {From, _} <- gb_trees:to_list(WSet)], - State#state{waiting_set = gb_trees:empty(), + [begin + safe_cancel_timer(TRef), + gen_server:reply(From, OAR) + end || {From, TRef} <- gb_trees:to_list(WSet)], + State#state{waiting_set = gb_trees:empty(), only_acks_received = true}. -handle_wait_for_confirms(From, Notify, EmptyReply, +handle_wait_for_confirms(From, Timeout, State = #state{unconfirmed_set = USet, waiting_set = WSet}) -> case gb_sets:is_empty(USet) of - true -> {reply, EmptyReply, State}; - false -> {noreply, State#state{waiting_set = - gb_trees:insert(From, Notify, WSet)}} + true -> + {reply, true, State}; + false -> + TRef = case Timeout of + infinity -> undefined; + _ -> erlang:send_after(Timeout * 1000, self(), + {confirm_timeout, From}) + end, + {noreply, + State#state{waiting_set = gb_trees:insert(From, TRef, WSet)}} end. call_to_consumer(Method, Args, #state{consumer = Consumer}) -> amqp_gen_consumer:call_consumer(Consumer, Method, Args). + +safe_cancel_timer(undefined) -> ok; +safe_cancel_timer(TRef) -> erlang:cancel_timer(TRef). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private @@ -44,12 +44,13 @@ %% Internal plumbing %%--------------------------------------------------------------------------- -start_writer_fun(_Sup, direct, [ConnectionPid, Node, User, VHost, Collector], +start_writer_fun(_Sup, direct, [ConnPid, ConnName, Node, User, VHost, + Collector], ChNumber) -> fun () -> {ok, RabbitCh} = rpc:call(Node, rabbit_direct, start_channel, - [ChNumber, self(), ConnectionPid, ?PROTOCOL, User, + [ChNumber, self(), ConnPid, ConnName, ?PROTOCOL, User, VHost, ?CLIENT_CAPABILITIES, Collector]), link(RabbitCh), {ok, RabbitCh} diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channels_manager.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channels_manager.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_channels_manager.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_channels_manager.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private @@ -22,7 +22,8 @@ -behaviour(gen_server). -export([start_link/2, open_channel/4, set_channel_max/2, is_empty/1, - num_channels/1, pass_frame/3, signal_connection_closing/3]). + num_channels/1, pass_frame/3, signal_connection_closing/3, + process_channel_frame/4]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). @@ -59,6 +60,19 @@ signal_connection_closing(ChMgr, ChannelCloseType, Reason) -> gen_server:cast(ChMgr, {connection_closing, ChannelCloseType, Reason}). +process_channel_frame(Frame, Channel, ChPid, AState) -> + case rabbit_command_assembler:process(Frame, AState) of + {ok, NewAState} -> NewAState; + {ok, Method, NewAState} -> rabbit_channel:do(ChPid, Method), + NewAState; + {ok, Method, Content, NewAState} -> rabbit_channel:do(ChPid, Method, + Content), + NewAState; + {error, Reason} -> ChPid ! {channel_exit, Channel, + Reason}, + AState + end. + %%--------------------------------------------------------------------------- %% gen_server callbacks %%--------------------------------------------------------------------------- @@ -195,10 +209,10 @@ case internal_lookup_npa(Number, State) of undefined -> ?LOG_INFO("Dropping frame ~p for invalid or closed " - "channel number ~p~n", [Frame, Number]); + "channel number ~p~n", [Frame, Number]), + State; {ChPid, AState} -> - NewAState = rabbit_reader:process_channel_frame( - Frame, ChPid, Number, ChPid, AState), + NewAState = process_channel_frame(Frame, Number, ChPid, AState), internal_update_npa(Number, ChPid, NewAState, State) end. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_client.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_client.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_client.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_client.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_connection.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_connection.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_connection.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_connection.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @type close_reason(Type) = {shutdown, amqp_reason(Type)}. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_connection_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_connection_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_connection_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_connection_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_connection_type_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_connection_type_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_connection_type_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_connection_type_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_direct_connection.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_direct_connection.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_direct_connection.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_direct_connection.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private @@ -21,6 +21,8 @@ -behaviour(amqp_gen_connection). +-export([server_close/3]). + -export([init/1, terminate/2, connect/4, do/2, open_channel_args/1, i/2, info_keys/0, handle_message/2, closing/3, channels_terminated/1]). @@ -41,14 +43,24 @@ %%--------------------------------------------------------------------------- +%% amqp_connection:close() logically closes from the client end. We may +%% want to close from the server end. +server_close(ConnectionPid, Code, Text) -> + Close = #'connection.close'{reply_text = Text, + reply_code = Code, + class_id = 0, + method_id = 0}, + amqp_gen_connection:server_close(ConnectionPid, Close). + init([]) -> {ok, #state{}}. open_channel_args(#state{node = Node, user = User, vhost = VHost, + adapter_info = Info, collector = Collector}) -> - [self(), Node, User, VHost, Collector]. + [self(), Info#adapter_info.name, Node, User, VHost, Collector]. do(_Method, _State) -> ok. @@ -129,9 +141,7 @@ ensure_adapter_info(A#adapter_info{protocol = {'Direct', ?PROTOCOL:version()}}); -ensure_adapter_info(A = #adapter_info{name = unknown, - peer_address = unknown, - peer_port = unknown}) -> +ensure_adapter_info(A = #adapter_info{name = unknown}) -> Name = list_to_binary(rabbit_misc:pid_to_string(self())), ensure_adapter_info(A#adapter_info{name = Name}); diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_direct_consumer.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_direct_consumer.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_direct_consumer.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_direct_consumer.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% %% @doc This module is an implementation of the amqp_gen_consumer diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_gen_connection.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_gen_connection.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_gen_connection.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_gen_connection.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private @@ -23,7 +23,7 @@ -export([start_link/5, connect/1, open_channel/3, hard_error_in_channel/3, channel_internal_error/3, server_misbehaved/2, channels_terminated/1, - close/2, info/2, info_keys/0, info_keys/1]). + close/2, server_close/2, info/2, info_keys/0, info_keys/1]). -export([behaviour_info/1]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). @@ -83,6 +83,9 @@ close(Pid, Close) -> gen_server:call(Pid, {command, {close, Close}}, infinity). +server_close(Pid, Close) -> + gen_server:cast(Pid, {server_close, Close}). + info(Pid, Items) -> gen_server:call(Pid, {info, Items}, infinity). @@ -176,10 +179,10 @@ {error, _} = Error -> {stop, {shutdown, Error}, Error, State0} end; -handle_call({command, Command}, From, State = #state{closing = Closing}) -> - case Closing of false -> handle_command(Command, From, State); - _ -> {reply, closing, State} - end; +handle_call({command, Command}, From, State = #state{closing = false}) -> + handle_command(Command, From, State); +handle_call({command, _Command}, _From, State) -> + {reply, closing, State}; handle_call({info, Items}, _From, State) -> {reply, [{Item, i(Item, State)} || Item <- Items], State}; handle_call(info_keys, _From, State = #state{module = Mod}) -> @@ -195,7 +198,7 @@ channel_max = ChannelMax, module_state = NewMState}. -handle_cast({method, Method, none}, State) -> +handle_cast({method, Method, none, noflow}, State) -> handle_method(Method, State); handle_cast(channels_terminated, State) -> handle_channels_terminated(State); @@ -206,7 +209,9 @@ [self(), Pid, Reason]), internal_error(State); handle_cast({server_misbehaved, AmqpError}, State) -> - server_misbehaved_close(AmqpError, State). + server_misbehaved_close(AmqpError, State); +handle_cast({server_close, #'connection.close'{} = Close}, State) -> + server_initiated_close(Close, State). handle_info(Info, State) -> callback(handle_message, [Info], State). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_gen_consumer.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_gen_consumer.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_gen_consumer.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_gen_consumer.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% %% @doc A behaviour module for implementing consumers for diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_main_reader.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_main_reader.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_main_reader.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_main_reader.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private @@ -60,35 +60,33 @@ handle_cast(Cast, State) -> {stop, {unexpected_cast, Cast}, State}. -handle_info({inet_async, _, _, _} = InetAsync, State) -> - handle_inet_async(InetAsync, State). +handle_info({inet_async, Sock, _, {ok, <>}}, + State = #state{sock = Sock, message = none}) -> + {ok, _Ref} = rabbit_net:async_recv(Sock, Length + 1, infinity), + {noreply, State#state{message = {Type, Channel, Length}}}; +handle_info({inet_async, Sock, _, {ok, Data}}, + State = #state{sock = Sock, message = {Type, Channel, L}}) -> + <> = Data, + State1 = process_frame(Type, Channel, Payload, State), + {ok, _Ref} = rabbit_net:async_recv(Sock, 7, infinity), + {noreply, State1#state{message = none}}; +handle_info({inet_async, Sock, _, {error, closed}}, + State = #state{sock = Sock, connection = Conn}) -> + Conn ! socket_closed, + {noreply, State}; +handle_info({inet_async, Sock, _, {error, Reason}}, + State = #state{sock = Sock, connection = Conn}) -> + Conn ! {socket_error, Reason}, + {stop, {socket_error, Reason}, State}. %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- -handle_inet_async({inet_async, Sock, _, Msg}, - State = #state{sock = Sock, message = CurMessage}) -> - {Type, Number, Length} = case CurMessage of {T, N, L} -> {T, N, L}; - none -> {none, none, none} - end, - case Msg of - {ok, <>} -> - State1 = process_frame(Type, Number, Payload, State), - {ok, _Ref} = rabbit_net:async_recv(Sock, 7, infinity), - {noreply, State1#state{message = none}}; - {ok, <>} -> - {ok, _Ref} = rabbit_net:async_recv(Sock, NewLength + 1, infinity), - {noreply, State#state{message={NewType, NewChannel, NewLength}}}; - {error, closed} -> - State#state.connection ! socket_closed, - {noreply, State}; - {error, Reason} -> - State#state.connection ! {socket_error, Reason}, - {stop, {socket_error, Reason}, State} - end. - -process_frame(Type, ChNumber, Payload, State = #state{connection = Connection}) -> +process_frame(Type, ChNumber, Payload, + State = #state{connection = Connection, + channels_manager = ChMgr, + astate = AState}) -> case rabbit_command_assembler:analyze_frame(Type, Payload, ?PROTOCOL) of heartbeat when ChNumber /= 0 -> amqp_gen_connection:server_misbehaved( @@ -99,13 +97,10 @@ %% Match heartbeats but don't do anything with them heartbeat -> State; + AnalyzedFrame when ChNumber /= 0 -> + amqp_channels_manager:pass_frame(ChMgr, ChNumber, AnalyzedFrame), + State; AnalyzedFrame -> - pass_frame(ChNumber, AnalyzedFrame, State) + State#state{astate = amqp_channels_manager:process_channel_frame( + AnalyzedFrame, 0, Connection, AState)} end. - -pass_frame(0, Frame, State = #state{connection = Conn, astate = AState}) -> - State#state{astate = rabbit_reader:process_channel_frame(Frame, Conn, - 0, Conn, AState)}; -pass_frame(Number, Frame, State = #state{channels_manager = ChMgr}) -> - amqp_channels_manager:pass_frame(ChMgr, Number, Frame), - State. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_network_connection.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_network_connection.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_network_connection.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_network_connection.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private @@ -245,7 +245,7 @@ {<<"version">>, longstr, list_to_binary(Vsn)}, {<<"platform">>, longstr, <<"Erlang">>}, {<<"copyright">>, longstr, - <<"Copyright (c) 2007-2011 VMware, Inc.">>}, + <<"Copyright (c) 2007-2012 VMware, Inc.">>}, {<<"information">>, longstr, <<"Licensed under the MPL. " "See http://www.rabbitmq.com/">>}, @@ -256,7 +256,7 @@ handshake_recv(Expecting) -> receive - {'$gen_cast', {method, Method, none}} -> + {'$gen_cast', {method, Method, none, noflow}} -> case {Expecting, element(1, Method)} of {E, M} when E =:= M -> Method; diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_client.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_client.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_client.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_client.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @doc This module allows the simple execution of an asynchronous RPC over diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_server.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_server.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_server.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_server.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @doc This is a utility module that is used to expose an arbitrary function diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_selective_consumer.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_selective_consumer.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_selective_consumer.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_selective_consumer.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% %% @doc This module is an implementation of the amqp_gen_consumer diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% @private diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_uri.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_uri.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/amqp_uri.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/amqp_uri.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(amqp_uri). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/overview.edoc.in rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/overview.edoc.in --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/overview.edoc.in 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/overview.edoc.in 2012-03-19 10:36:09.000000000 +0000 @@ -1,6 +1,6 @@ @title AMQP Client for Erlang @author VMware Inc. -@copyright 2007-2011 VMware, Inc. +@copyright 2007-2012 VMware, Inc. @version %%VERSION%% diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/uri_parser.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/uri_parser.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/src/uri_parser.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/src/uri_parser.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,7 +1,7 @@ %% This file is a copy of http_uri.erl from the R13B-1 Erlang/OTP %% distribution with several modifications. -%% All modifications are Copyright (c) 2009-2011 VMware, Ltd. +%% All modifications are Copyright (c) 2009-2012 VMware, Ltd. %% ``The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/Makefile rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/Makefile --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/Makefile 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/Makefile 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is VMware, Inc. -# Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +# Copyright (c) 2007-2012 VMware, Inc. All rights reserved. # TEST_SOURCES=$(wildcard *.erl) diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/amqp_client_SUITE.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/amqp_client_SUITE.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/amqp_client_SUITE.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/amqp_client_SUITE.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(amqp_client_SUITE). @@ -23,7 +23,10 @@ -define(FUNCTION, begin catch throw(x), - [{_, Fun, _} | _] = erlang:get_stacktrace(), + Fun = case erlang:get_stacktrace() of + [{_, F, _} | _] -> F; %% < R15 + [{_, F, _, _} | _] -> F %% >= R15 + end, list_to_atom(string:strip(atom_to_list(Fun), right, $_)) end). @@ -62,6 +65,8 @@ confirm_test_() -> ?RUN([]). confirm_barrier_test_() -> ?RUN([]). confirm_barrier_nop_test_() -> ?RUN([]). +confirm_barrier_timeout_test_() -> ?RUN([]). +confirm_barrier_die_timeout_test_() -> ?RUN([]). default_consumer_test() -> ?RUN([]). subscribe_nowait_test_() -> ?RUN([]). @@ -93,7 +98,7 @@ true -> negative_test_util; false -> test_util end, - {timeout, proplists:get_value(timeout, Props, 5), + {timeout, proplists:get_value(timeout, Props, 10), fun () -> lists:foreach( fun (_) -> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/amqp_dbg.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/amqp_dbg.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/amqp_dbg.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/amqp_dbg.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(amqp_dbg). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/negative_test_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/negative_test_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/negative_test_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/negative_test_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(negative_test_util). @@ -151,7 +151,7 @@ case amqp_connection:info(Connection, [type]) of [{type, direct}] -> Channel ! {send_command, #'connection.open'{}}; [{type, network}] -> gen_server:cast(Channel, - {method, #'connection.open'{}, none}) + {method, #'connection.open'{}, none, noflow}) end, assert_down_with_error(MonitorRef, command_invalid), ?assertNot(is_process_alive(Channel)), @@ -162,7 +162,7 @@ %% command_invalid - this only applies to the network case command_invalid_over_channel0_test() -> {ok, Connection} = test_util:new_connection(just_network), - gen_server:cast(Connection, {method, #'basic.ack'{}, none}), + gen_server:cast(Connection, {method, #'basic.ack'{}, none, noflow}), MonitorRef = erlang:monitor(process, Connection), assert_down_with_error(MonitorRef, command_invalid), ok. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/test_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/test_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test/test_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test/test_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(test_util). @@ -632,6 +632,34 @@ true = amqp_channel:wait_for_confirms(Channel), teardown(Connection, Channel). +confirm_barrier_timeout_test() -> + {ok, Connection} = new_connection(), + {ok, Channel} = amqp_connection:open_channel(Connection), + #'confirm.select_ok'{} = amqp_channel:call(Channel, #'confirm.select'{}), + [amqp_channel:call(Channel, #'basic.publish'{routing_key = <<"whoosh">>}, + #amqp_msg{payload = <<"foo">>}) + || _ <- lists:seq(1, 1000)], + case amqp_channel:wait_for_confirms(Channel, 0) of + true -> ok; + timeout -> ok + end, + teardown(Connection, Channel). + +confirm_barrier_die_timeout_test() -> + {ok, Connection} = new_connection(), + {ok, Channel} = amqp_connection:open_channel(Connection), + #'confirm.select_ok'{} = amqp_channel:call(Channel, #'confirm.select'{}), + [amqp_channel:call(Channel, #'basic.publish'{routing_key = <<"whoosh">>}, + #amqp_msg{payload = <<"foo">>}) + || _ <- lists:seq(1, 1000)], + try amqp_channel:wait_for_confirms_or_die(Channel, 0) of + true -> ok + catch + exit:timeout -> ok + end, + amqp_connection:close(Connection), + wait_for_death(Connection). + default_consumer_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), @@ -939,7 +967,7 @@ {verify, verify_peer}, {fail_if_no_peer_cert, true}]}] ++ Params); {_, "direct"} -> - make_direct_params([{node, rabbit_misc:makenode(rabbit)}] ++ + make_direct_params([{node, rabbit_nodes:make(rabbit)}] ++ Params) end, amqp_connection:start(Params1). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test.mk rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test.mk --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-erlang-client/test.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-erlang-client/test.mk 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is VMware, Inc. -# Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +# Copyright (c) 2007-2012 VMware, Inc. All rights reserved. # IS_SUCCESS:=egrep "All .+ tests (successful|passed)." diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/README 2012-03-19 10:36:09.000000000 +0000 @@ -1,273 +1,4 @@ -Purpose -======= +Generic build instructions are at: + http://www.rabbitmq.com/plugin-development.html -The high level goal is to transmit messages between brokers without -requiring clustering. This is useful for the following reasons: - -1) Federated brokers may be in different administrative - domains. Clustered brokers form a single administrative domain. - - a) Federated brokers may have different users and virtual hosts. - Federated brokers only need to partially trust each other. - - b) Federated brokers may run different versions of RabbitMQ and - Erlang. - -2) Federated brokers only speak AMQP to each other, and the federation - mechanism is designed to deal with intermittent connectivity. - Federation is therefore much more WAN-friendly. - -3) Brokers can contain federated and local-only components - you don't - need to federate everything if you don't want to. - -4) Ultimately, greater scalability should be possible, since more complex - routing topologies avoid the need for n^2 connections between n - brokers. - -For the time being, federation is primarily useful in pub/sub scenarios. - - -Limitations -=========== - -You can't federate headers exchanges. You can't make a broker federate -with a new upstream without restarting it. There's no status -reporting. These will likely get fixed. - - -HOWTO -===== - -The plugin provides a federated exchange type. A federated exchange -has type 'x-federation'. However, this type does not provide any -routing logic. The routing logic is implemented by a backing type, -provided to the exchange as an argument. - -Messages can be published to a federated exchange like any -other. However, a federated exchange also receives messages from -one or more "upstream" exchanges, located on remote brokers. - -(Well, you don't need to have upstream exchanges, and they don't need -to be remote. But then you don't get anything very useful.) - -An upstream exchange can be a regular exchange or a federation -exchange. It is expected that upstream and downstream exchanges have -the same type (or backing type). Mixing types will lead to strange -routing behaviour. - -Inter-broker communication is implemented using AMQP (optionally -secured with SSL). Bindings are grouped together and bind / unbind -commands are sent to the upstream exchange. Therefore the federation -plugin only receives messages over the wire for which the downstream -exchange has a subscription. To promote scalability the bindings are -sent upstream asynchronously - so the effect of adding or removing a -binding is only guaranteed to be seen eventually. - -A typical use would be to have the same "logical" exchange distributed -over many brokers. This would be achieved by having the exchange -declared as a federated exchange in each broker, with upstreams -corresponding to all the other brokers. - -Another would be massive fanout - a single "root" exchange in one -broker can be treated as an upstream by many other brokers. In turn -each of these can be the upstream for many more downstreams, and so -on. - -Other topologies are of course possible. - -Federated exchanges can be set up statically via broker configuration, -or declared dynamically over AMQP. - - -Static Configuration -==================== - -A verbose static configuration might look like: - - {rabbitmq_federation, - [ {exchanges, [[{exchange, "my-exchange"}, - {virtual_host, "/"}, - {type, "topic"}, - {durable, true}, - {auto_delete, false}, - {internal, false}, - {upstream_set, "my-upstreams"}] - ]}, - {upstream_sets, [{"my-upstreams", [[{connection, "upstream-server"}, - {exchange, "my-upstream-x"}, - {max_hops, 2}], - [{connection, "another-server"}] - ]} - ]}, - {connections, [{"upstream-server", [{host, "upstream-server"}, - {protocol, "amqps"}, - {port, 5671}, - {virtual_host, "/"}, - {username, "myusername"}, - {password, "secret"}, - {mechanism, default}, - {prefetch_count, 1000}, - {reconnect_delay, 5}, - {heartbeat, 1}, - {queue_expires, 30000}, - {message_ttl, 10000}, - {ssl_options, - [{cacertfile, "/path/to/cacert.pem"}, - {certfile, "/path/to/cert.pem"}, - {keyfile, "/path/to/key.pem"}, - {verify, verify_peer}, - {fail_if_no_peer_cert, true} - ]} - ]}, - {"another-server", [...elided...]} - ]}, - {local_username, "myusername"}, - {local_nodename, "my-server"} - ] - } - -The list of exchanges looks like a set of exchange.declares for the -most part, but with each declaration including the name of an -"upstream_set", representing a list of remote exchanges whose messages -should be federated to the local exchange. Note that the type -parameter must match the type of the upstream exchanges for routing to -work at all sensibly. - -Each element in the upstream_set contains a mapping from a name to a -list of upstreams. Each element in this list can contain the following -properties: - -connection - - name of a connection from the connection list. Mandatory. - -exchange - - name for exchange to connect to. Default is to use the same name - as the downstream exchange. (Therefore one upstream_set can be - refered to by many local exchanges as long as exchange names are - the same across all the nodes in your federation.) - -max_hops - - the maximum number of times a message received over this link may - have been forwarded (including traversing this link). The default - for max_hops is 1. This prevents messages from looping forever - when there are circular topologies, and can reduce or prevent - message duplication. - -Note that the static configuration will declare the downstream -exchanges (on the local broker). It does not ensure the upstream -exchanges exist. - -The connections list provides information on how to connect to brokers -mentioned in the upstream sets. It can contain the following properties: - -host - - hostname to connect to - -protocol - - "amqp" or "amqps". Default is "amqp". - -port - - port to connect to. Default is 5672, or 5671 when using SSL. - -virtual_host - - virtual host to connect to. Default is to use the virtual host for - the downstream exchange. - -username - - user to connect as. Default is "guest". The user will need the - ability to create exchanges and queues with names beginning with - "federation:". It will also need to be able to bind to the upstream - exchange. - -password - - password to use. Default is "guest". - -mechanism - - SASL mechanism to use. One of: - 'default' - to use PLAIN or AMQPLAIN by negotiation (this is the default) - 'EXTERNAL' - to use SASL EXTERNAL authentication - e.g. - rabbitmq-auth-mechanism-ssl - -prefetch_count - - limit on the maximum number of unacknowledged messages in flight - per link. Default is 'none'. - -reconnect_delay - - time in seconds to wait to reconnect to the broker after being - disconnected. Default is 1. - -heartbeat - - AMQP heartbeat interval (in seconds) on the connection, or none. Default - is 'none'. - -expires - - Messages are buffered in the upstream broker in a queue before being - sent downstream. This setting controls how long the upstream queue - lasts before being deleted if the downstream is disconnected (i.e. - it controls the "x-expires" argument for the upstream queue). The - value is in milliseconds. Default is 'none', meaning the queue should - never expire. - -message_ttl - - Controls how long to keep upstream messages buffered, in milliseconds - (i.e. the "x-message-ttl" argument for the upstream queue). Default is - 'none', meaning messages should never expire. - -ssl_options - - Specifies how to make client SSL connections. See the Erlang - client documentation for more details. - -The local_username parameter specifies how to connect to the local -broker. The default is "guest". This user will need the ability to -publish messages to the downstream exchange. - -The local_nodename parameter specifies the name this node should use -to identify itself in the federation. If not specified it will attempt -to build a "long form" version of the usual Erlang node name (but -using the machine's FQDN). You should only have to specify this if -your DNS will not give each machine in the federation unique names. - -Declaring Federation Exchanges Over AMQP -======================================== - -This is a less common case, but in case you want to do this: - - * Declare the downstream exchange with type "x-federation". - - * Give it arguments "type" and "upstream-set", both of type "long - string". "type" should refer to its backing type; the type of the - upstream exchanges. "upstream-set" should be the name of an - upstream_set from the static configuration (note that it's a hyphen - over AMQP but an underscore in the configuration). - -Example using the Java API: - -Map args = new HashMap(); -args.put("type", "topic"); -args.put("upstream-set", "my-upstream-set"); - -Channel ch = ...; -ch.exchangeDeclare("my-federated-exchange", "x-federation", true, false, args); - -Note On Clustering -================== - -When using federation with clustering, all cluster nodes must have the -federation plugin installed. Any node may establish connections to -upstream exchanges. If a node fails, any upstream links will fail over -to a surviving node. - -Possible Future Enhancements -============================ - -* Simple status reporting, similar to the shovel - -* Modify upstream sets dynamically - -* Mode to federate all exchanges - -* Status information and control in the management plugin - -* Smarter routing logic - -* Support for RPC-like patterns +See http://www.rabbitmq.com/federation.html diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/include/rabbit_federation.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/include/rabbit_federation.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/include/rabbit_federation.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/include/rabbit_federation.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -record(upstream, {params, @@ -21,6 +21,7 @@ reconnect_delay, expires, message_ttl, + ha_policy, connection_name}). -define(SUPERVISOR, rabbit_federation_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_app). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_db.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_db.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_db.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_db.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_db). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_exchange.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_exchange.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_exchange.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_exchange.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_exchange). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_link.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_link.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_link.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_link.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_link). @@ -30,8 +30,6 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --export([add_routing_to_headers/2]). - -define(ROUTING_HEADER, <<"x-received-from">>). -record(state, {upstream, @@ -132,7 +130,8 @@ case should_forward(Headers0, MaxHops) of true -> {table, Info0} = rabbit_federation_upstream:to_table(Upstream), Info = Info0 ++ [{<<"redelivered">>, bool, Redelivered}], - Headers = add_routing_to_headers(Headers0, Info), + Headers = rabbit_basic:append_table_header( + ?ROUTING_HEADER, Info, Headers0), Seq = amqp_channel:next_publish_seqno(DCh), amqp_channel:cast(DCh, #'basic.publish'{exchange = XNameBin, routing_key = Key}, @@ -367,9 +366,12 @@ prefetch_count = Prefetch, expires = Expiry, message_ttl = TTL, + ha_policy = HA, params = #amqp_params_network{virtual_host = VHost}} = Upstream, Q = upstream_queue_name(XNameBin, VHost, DownXName), + %% TODO it would be nice to just pass through args, but let's do that as + %% part of bug 23908. ExpiryArg = case Expiry of none -> []; _ -> [{<<"x-expires">>, long, Expiry}] @@ -378,7 +380,11 @@ none -> []; _ -> [{<<"x-message-ttl">>, long, TTL}] end, - Args = ExpiryArg ++ TTLArg, + HAArg = case HA of + none -> []; + _ -> [{<<"x-ha-policy">>, longstr, list_to_binary(HA)}] + end, + Args = ExpiryArg ++ TTLArg ++ HAArg, amqp_channel:call(Ch, #'queue.declare'{queue = Q, durable = true, arguments = Args}), @@ -443,11 +449,11 @@ local_nodename() -> {ok, Explicit} = application:get_env(rabbitmq_federation, local_nodename), case Explicit of - automatic -> {ID, _} = rabbit_misc:nodeparts(node()), + automatic -> {ID, _} = rabbit_nodes:parts(node()), {ok, Host} = inet:gethostname(), {ok, #hostent{h_name = FQDN}} = inet:gethostbyname(Host), list_to_binary(atom_to_list( - rabbit_misc:makenode({ID, FQDN}))); + rabbit_nodes:make({ID, FQDN}))); _ -> list_to_binary(Explicit) end. @@ -499,13 +505,3 @@ update_headers(Headers, Msg = #amqp_msg{props = Props}) -> Msg#amqp_msg{props = Props#'P_basic'{headers = Headers}}. - -add_routing_to_headers(undefined, Info) -> - add_routing_to_headers([], Info); -add_routing_to_headers(Headers, Info) -> - Prior = case rabbit_misc:table_lookup(Headers, ?ROUTING_HEADER) of - undefined -> []; - {array, Existing} -> Existing - end, - rabbit_misc:set_table_value( - Headers, ?ROUTING_HEADER, array, [{table, Info} | Prior]). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_link_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_link_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_link_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_link_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_link_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_upstream.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_upstream.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_upstream.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_upstream.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_upstream). @@ -101,6 +101,7 @@ max_hops = pget(max_hops, Upst, 1), expires = pget(expires, Conn, none), message_ttl = pget(message_ttl, Conn, none), + ha_policy = pget(ha_policy, Conn, none), connection_name = ConnName} end. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/src/rabbit_federation_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/src/rabbit_federation_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_util). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/test/src/rabbit_federation_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/test/src/rabbit_federation_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/test/src/rabbit_federation_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/test/src/rabbit_federation_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_test). @@ -193,8 +193,8 @@ ok. suffix({Nodename, _}, X) -> - {_, NodeHost} = rabbit_misc:nodeparts(node()), - Node = rabbit_misc:makenode({Nodename, NodeHost}), + {_, NodeHost} = rabbit_nodes:parts(node()), + Node = rabbit_nodes:make({Nodename, NodeHost}), rpc:call(Node, rabbit_federation_db, get_active_suffix, [rabbit_misc:r(<<"/">>, exchange, <<"downstream">>), #upstream{connection_name = Nodename, @@ -364,7 +364,7 @@ publish(Ch, X, Key, Payload) -> %% The trouble is that we transmit bindings upstream asynchronously... - timer:sleep(200), + timer:sleep(1000), amqp_channel:call(Ch, #'basic.publish'{exchange = X, routing_key = Key}, #amqp_msg{payload = Payload}). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/test/src/rabbit_federation_unit_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/test/src/rabbit_federation_unit_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-federation/test/src/rabbit_federation_unit_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-federation/test/src/rabbit_federation_unit_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,14 +11,11 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_federation_unit_test). --define(INFO, [{<<"baz">>, longstr, <<"bam">>}]). --define(H, <<"x-received-from">>). - -define(US_NAME, <<"upstream">>). -define(DS_NAME, <<"downstream">>). @@ -26,26 +23,6 @@ -include_lib("eunit/include/eunit.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). -%% Test that we add routing information to message headers sensibly. -routing_test() -> - ?assertEqual([{?H, array, [{table, ?INFO}]}], - add(undefined)), - - ?assertEqual([{?H, array, [{table, ?INFO}]}], - add([])), - - ?assertEqual([{<<"foo">>, longstr, <<"bar">>}, - {?H, array, [{table, ?INFO}]}], - add([{<<"foo">>, longstr, <<"bar">>}])), - - ?assertEqual([{?H, array, [{table, ?INFO}, - {table, ?INFO}]}], - add([{?H, array, [{table, ?INFO}]}])), - ok. - -add(Table) -> - rabbit_federation_link:add_routing_to_headers(Table, ?INFO). - %% Test that we apply binding changes in the correct order even when %% they arrive out of order. serialisation_test() -> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc/src/rabbit_jsonrpc.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc/src/rabbit_jsonrpc.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc/src/rabbit_jsonrpc.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc/src/rabbit_jsonrpc.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_jsonrpc). -behaviour(application). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/README 2012-03-19 10:36:09.000000000 +0000 @@ -3,6 +3,12 @@ rabbitmq-plugins enable rabbitmq_jsonrpc_channel +You may wish to also use: + + rabbitmq-plugins enable rabbitmq_jsonrpc_channel_examples + +to serve a couple of demo webapps. + You can also compile and install it like any other plugin (see http://www.rabbitmq.com/plugin-development.html). @@ -14,11 +20,11 @@ Once the server starts successfully, you should be able to point your web browser at - http://localhost:55672/rpc/rabbitmq + http://localhost:55670/rpc/rabbitmq and get an error along the lines of - {"version":"1.1","id":null,"error":{"name":"JSONRPCError","code":404,"message":"Procedure not found","error":["http://localhost:55672/rpc/rabbitmq",""]}} + {"version":"1.1","id":null,"error":{"name":"JSONRPCError","code":404,"message":"Procedure not found","error":["http://localhost:55670/rpc/rabbitmq",""]}} which confirms that the RabbitMQ JSON-RPC channel is ready to accept requests. @@ -30,10 +36,10 @@ with the examples configured. You should be able to point your web browser at - http://localhost:55672/ + http://localhost:55670/ and get a webpage. Clicking on "Simple JSONRPC test" will run a small -test application. Successful output of http://localhost:55672/test/index.html +test application. Successful output of http://localhost:55670/test/index.html at the time of writing is: test_main diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/jsonrpc.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/jsonrpc.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/jsonrpc.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/jsonrpc.js 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -// 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/ +// 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. // -// 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 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): ______________________________________. +// The Initial Developer of the Original Code is VMware, Inc. +// Copyright (c) 2007-2012 VMware, Inc. All rights reserved. // function JsonRpc_ModuleFactory(Support) { diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-jquery.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-jquery.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-jquery.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-jquery.js 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,17 @@ -// 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/ +// 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. // -// 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): ______________________________________. +// The Original Code is RabbitMQ. // +// The Initial Developer of the Original Code is VMware, Inc. +// Copyright (c) 2007-2012 VMware, Inc. All rights reserved. // var JsonRpc; diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-prototype.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-prototype.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-prototype.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq-prototype.js 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,17 @@ -// 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/ +// 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. // -// 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): ______________________________________. +// The Original Code is RabbitMQ. // +// The Initial Developer of the Original Code is VMware, Inc. +// Copyright (c) 2007-2012 VMware, Inc. All rights reserved. // var JsonRpc; diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/priv/www/rabbitmq.js 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,17 @@ -// 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/ +// 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. +// 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): ______________________________________. +// The Original Code is RabbitMQ. // +// The Initial Developer of the Original Code is VMware, Inc. +// Copyright (c) 2007-2012 VMware, Inc. All rights reserved. // function RabbitMQ_ModuleFactory(JsonRpc, Support) { diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,19 @@ -%% 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/ +%% 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. +%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_jsonrpc_channel). -behaviour(gen_server). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_jsonrpc_channel_app). -behaviour(application). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_app_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,19 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_jsonrpc_channel_app_sup). -behaviour(supervisor). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_factory.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_factory.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_factory.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_factory.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,19 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_jsonrpc_channel_factory). -behaviour(gen_server). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel/src/rabbit_jsonrpc_channel_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,19 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_jsonrpc_channel_sup). -behaviour(supervisor). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbit_jsonrpc_channel_test_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbit_jsonrpc_channel_test_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbit_jsonrpc_channel_test_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbit_jsonrpc_channel_test_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_jsonrpc_channel_test_app). -behaviour(application). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/LICENSE-MPL-RabbitMQ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/LICENSE-MPL-RabbitMQ --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/LICENSE-MPL-RabbitMQ 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/LICENSE-MPL-RabbitMQ 2012-03-19 10:36:09.000000000 +0000 @@ -447,7 +447,7 @@ The Original Code is RabbitMQ Management Plugin. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2010-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2010-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/Makefile rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/Makefile --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/Makefile 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/Makefile 2012-03-19 10:36:09.000000000 +0000 @@ -2,24 +2,27 @@ RABBITMQCTL=../rabbitmq-server/scripts/rabbitmqctl TEST_TMPDIR=/tmp/rabbitmq-test +OTHER_NODE=undefined +OTHER_PORT=undefined - -start-second-node: - rm -f $(TEST_TMPDIR)/rabbitmq-hare-pid - RABBITMQ_MNESIA_BASE=$(TEST_TMPDIR)/rabbitmq-hare-mnesia \ - RABBITMQ_PID_FILE=$(TEST_TMPDIR)/rabbitmq-hare-pid \ +start-other-node: + rm -f $(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-pid + RABBITMQ_MNESIA_BASE=$(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-mnesia \ + RABBITMQ_PID_FILE=$(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-pid \ RABBITMQ_LOG_BASE=$(TEST_TMPDIR)/log \ - RABBITMQ_NODENAME=hare \ - RABBITMQ_NODE_PORT=5673 \ - RABBITMQ_CONFIG_FILE=etc/hare \ + RABBITMQ_NODENAME=$(OTHER_NODE) \ + RABBITMQ_NODE_PORT=$(OTHER_PORT) \ + RABBITMQ_CONFIG_FILE=etc/$(OTHER_NODE) \ RABBITMQ_PLUGINS_DIR=$(TEST_TMPDIR)/plugins \ - RABBITMQ_PLUGINS_EXPAND_DIR=$(TEST_TMPDIR)/hare-plugins-expand \ - ../rabbitmq-server/scripts/rabbitmq-server & - $(RABBITMQCTL) -n hare wait $(TEST_TMPDIR)/rabbitmq-hare-pid - $(RABBITMQCTL) -n hare stop_app - $(RABBITMQCTL) -n hare reset - $(RABBITMQCTL) -n hare cluster rabbit-test@`hostname -s` - $(RABBITMQCTL) -n hare start_app + RABBITMQ_PLUGINS_EXPAND_DIR=$(TEST_TMPDIR)/$(OTHER_NODE)-plugins-expand \ + ../rabbitmq-server/scripts/rabbitmq-server >/tmp/$(OTHER_NODE).out 2>/tmp/$(OTHER_NODE).err & + $(RABBITMQCTL) -n $(OTHER_NODE) wait $(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-pid + +cluster-other-node: + $(RABBITMQCTL) -n $(OTHER_NODE) stop_app + $(RABBITMQCTL) -n $(OTHER_NODE) reset + $(RABBITMQCTL) -n $(OTHER_NODE) cluster rabbit-test@`hostname -s` + $(RABBITMQCTL) -n $(OTHER_NODE) start_app -stop-second-node: - $(RABBITMQCTL) -n hare stop \ No newline at end of file +stop-other-node: + $(RABBITMQCTL) -n $(OTHER_NODE) stop \ No newline at end of file diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/bin/rabbitmqadmin rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/bin/rabbitmqadmin --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/bin/rabbitmqadmin 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/bin/rabbitmqadmin 2012-03-19 10:36:09.000000000 +0000 @@ -13,9 +13,11 @@ # The Original Code is RabbitMQ Management Plugin. # # The Initial Developer of the Original Code is VMware, Inc. -# Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +# Copyright (c) 2010-2012 VMware, Inc. All rights reserved. -from optparse import OptionParser +from ConfigParser import ConfigParser +from ConfigParser import Error as ConfigParserError +from optparse import OptionParser, TitledHelpFormatter import sys import httplib import urllib @@ -24,10 +26,11 @@ import os import socket -LISTABLE = ['connections', 'channels', 'exchanges', 'queues', 'bindings', - 'users', 'vhosts', 'permissions', 'nodes'] +LISTABLE = {'connections': False, 'channels': False, 'exchanges': True, + 'queues': True, 'bindings': True, 'users': False, + 'vhosts': False, 'permissions': False, 'nodes': False} -SHOWABLE = ['overview'] +SHOWABLE = {'overview': False} PROMOTE_COLUMNS = ['vhost', 'name', 'type', 'source', 'destination', 'destination_type', 'routing_key'] @@ -47,7 +50,8 @@ 'optional': {'auto_delete': 'false', 'durable': 'true', 'internal': 'false'}}, 'queue': {'mandatory': ['name'], - 'optional': {'auto_delete': 'false', 'durable': 'true'}}, + 'optional': {'auto_delete': 'false', 'durable': 'true', + 'node': None}}, 'binding': {'mandatory': ['source', 'destination_type', 'destination', 'routing_key'], 'optional': {}}, @@ -89,7 +93,7 @@ 'uri': '/exchanges/{vhost}/{exchange}/publish'}, 'get': {'mandatory': ['queue'], 'optional': {'count': '1', 'requeue': 'true', - 'payload_file': None}, + 'payload_file': None, 'encoding': 'auto'}, 'uri': '/queues/{vhost}/{queue}/get'} } @@ -101,32 +105,89 @@ DELETABLE[k]['optional'] = {} DELETABLE['binding']['uri'] = URIS['binding_del'] -def make_usage(): - usage = """usage: %prog [options] cmd -where cmd is one of: +def short_usage(): + return "rabbitmqadmin [options] subcommand" + +def title(name): + return "\n%s\n%s\n\n" % (name, '=' * len(name)) + +def subcommands_usage(): + usage = """Usage +===== + """ + short_usage() + """ + + where subcommand is one of: +""" + title("Display") -""" for l in LISTABLE: usage += " list {0} [...]\n".format(l) for s in SHOWABLE: usage += " show {0} [...]\n".format(s) + usage += title("Object Manipulation") usage += fmt_usage_stanza(DECLARABLE, 'declare') usage += fmt_usage_stanza(DELETABLE, 'delete') usage += fmt_usage_stanza(CLOSABLE, 'close') usage += fmt_usage_stanza(PURGABLE, 'purge') + usage += title("Broker Definitions") + usage += """ export + import +""" + usage += title("Publishing and Consuming") usage += fmt_usage_stanza(EXTRA_VERBS, '') usage += """ - export - import - * If payload is not specified on publish, standard input is used * If payload_file is not specified on get, the payload will be shown on standard output along with the message metadata - * If payload_file is specified on get, count must not be set""" + * If payload_file is specified on get, count must not be set +""" + return usage + +def config_usage(): + usage = "Usage\n=====\n" + short_usage() + usage += "\n" + title("Configuration File") + usage += """ It is possible to specify a configuration file from the command line. + Hosts can be configured easily in a configuration file and called + from the command line. +""" + usage += title("Example") + usage += """ # rabbitmqadmin.conf.example START + + [host_normal] + hostname = localhost + port = 55672 + username = guest + password = guest + declare_vhost = / # Used as default for declare / delete only + vhost = / # Used as default for declare / delete / list + + [host_ssl] + hostname = otherhost + port = 55672 + username = guest + password = guest + ssl = True + ssl_key_file = /path/to/key.pem + ssl_cert_file = /path/to/cert.pem + + # rabbitmqadmin.conf.example END +""" + usage += title("Use") + usage += """ rabbitmqadmin -c rabbitmqadmin.conf.example -N host_normal ...""" return usage +def more_help(): + return """ +More Help +========= + +For more help use the help subcommand: + + rabbitmqadmin help subcommands # For a list of available subcommands + rabbitmqadmin help config # For help with the configuration file +""" + def fmt_usage_stanza(root, verb): def fmt_args(args): res = " ".join(["{0}=...".format(a) for a in args['mandatory']]) @@ -135,46 +196,108 @@ res += " [{0}]".format(opts) return res - text = "\n" + text = "" if verb != "": verb = " " + verb for k in root.keys(): text += " {0} {1} {2}\n".format(verb, k, fmt_args(root[k])) return text -parser = OptionParser(usage=make_usage()) +default_options = { "hostname" : "localhost", + "port" : "55672", + "declare_vhost" : "/", + "username" : "guest", + "password" : "guest", + "ssl" : False, + "verbose" : True, + "format" : "table", + "depth" : 1, + "bash_completion" : False } + + +class MyFormatter(TitledHelpFormatter): + def format_epilog(self, epilog): + return epilog + +parser = OptionParser(usage=short_usage(), + formatter=MyFormatter(), + epilog=more_help()) def make_parser(): - parser.add_option("-H", "--host", dest="hostname", default="localhost", - help="connect to host HOST [default: %default]", - metavar="HOST") - parser.add_option("-P", "--port", dest="port", default="55672", - help="connect to port PORT [default: %default]", - metavar="PORT") - parser.add_option("-V", "--vhost", dest="vhost", - help="connect to vhost VHOST [default: all vhosts for list, '/' for declare]", - metavar="VHOST") - parser.add_option("-u", "--username", dest="username", default="guest", - help="connect using username USERNAME [default: %default]", - metavar="USERNAME") - parser.add_option("-p", "--password", dest="password", default="guest", - help="connect using password PASSWORD [default: %default]", - metavar="PASSWORD") - parser.add_option("-q", "--quiet", action="store_false", dest="verbose", - default=True, help="suppress status messages") - parser.add_option("-s", "--ssl", action="store_true", dest="ssl", - default=False, help="connect with ssl") - parser.add_option("--ssl-key-file", dest="ssl_key_file", default=None, - help="PEM format key file for SSL [default: none]") - parser.add_option("--ssl-cert-file", dest="ssl_cert_file", default=None, - help="PEM format certificate file for SSL [default: none]") - parser.add_option("-f", "--format", dest="format", default="table", - help="format for listing commands - one of [" + ", ".join(FORMATS.keys()) + "] [default: %default]") - parser.add_option("-d", "--depth", dest="depth", default="1", - help="maximum depth to recurse for listing tables [default: %default]") - parser.add_option("--bash-completion", action="store_true", - dest="bash_completion", default=False, - help="Print bash completion script") + def add(*args, **kwargs): + key = kwargs['dest'] + if key in default_options: + default = " [default: %s]" % default_options[key] + kwargs['help'] = kwargs['help'] + default + parser.add_option(*args, **kwargs) + + add("-c", "--config", dest="config", + help="configuration file [default: ~/.rabbitmqadmin.conf]", + metavar="CONFIG") + add("-N", "--node", dest="node", + help="node described in the configuration file [default: 'default'" + \ + " only if configuration file is specified]", + metavar="NODE") + add("-H", "--host", dest="hostname", + help="connect to host HOST" , + metavar="HOST") + add("-P", "--port", dest="port", + help="connect to port PORT", + metavar="PORT") + add("-V", "--vhost", dest="vhost", + help="connect to vhost VHOST [default: all vhosts for list, '/' for declare]", + metavar="VHOST") + add("-u", "--username", dest="username", + help="connect using username USERNAME", + metavar="USERNAME") + add("-p", "--password", dest="password", + help="connect using password PASSWORD", + metavar="PASSWORD") + add("-q", "--quiet", action="store_false", dest="verbose", + help="suppress status messages") + add("-s", "--ssl", action="store_true", dest="ssl", + help="connect with ssl") + add("--ssl-key-file", dest="ssl_key_file", + help="PEM format key file for SSL") + add("--ssl-cert-file", dest="ssl_cert_file", + help="PEM format certificate file for SSL") + add("-f", "--format", dest="format", + help="format for listing commands - one of [" + ", ".join(FORMATS.keys()) + "]") + add("-d", "--depth", dest="depth", + help="maximum depth to recurse for listing tables") + add("--bash-completion", action="store_true", + dest="bash_completion", + help="Print bash completion script") + +def make_configuration(): + make_parser() + (options, args) = parser.parse_args() + setattr(options, "declare_vhost", None) + if options.node is None and options.config: + options.node = "default" + elif options.node and options.config is None: + home = os.getenv('USERPROFILE') or os.getenv('HOME') + setattr(options, "config", home + os.sep + ".rabbitmqadmin.conf") + if options.node: + config = ConfigParser() + try: + config.read(options.config) + new_conf = dict(config.items(options.node)) + except ConfigParserError as error: + assert_usage(False, ("Could not read section '%s' in config file" + + " '%s':\n %s") % + (options.node, options.config, error)) + new_opts = default_options.copy() + for (key, val) in new_conf.items(): + new_opts[key] = val + for (key, val) in new_opts.items(): + if getattr(options, key) is None: + setattr(options, key, val) + else: + for (key, val) in default_options.items(): + if getattr(options, key) is None: + setattr(options, key, val) + return (options, args) def assert_usage(expr, error): if not expr: @@ -189,8 +312,7 @@ return (2, col) def main(): - make_parser() - (options, args) = parser.parse_args() + (options, args) = make_configuration() if options.bash_completion: print_bash_completion() exit(0) @@ -206,7 +328,7 @@ print maybe_utf8(s, sys.stdout) def die(s): - sys.stderr.write(maybe_utf8("*** {0}".format(s), sys.stderr)) + sys.stderr.write(maybe_utf8("*** {0}\n".format(s), sys.stderr)) exit(1) def maybe_utf8(s, stream): @@ -272,10 +394,23 @@ assert_usage(len(self.args) == 1, 'Exactly one argument required') return self.args[0] + def invoke_help(self): + help_cmd = self.get_arg() + if help_cmd == 'subcommands': + usage = subcommands_usage() + elif help_cmd == 'config': + usage = config_usage() + else: + assert_usage(False, """help topic must be one of: + subcommands + config""") + print usage + exit(0) + def invoke_publish(self): (uri, upload) = self.parse_args(self.args, EXTRA_VERBS['publish']) upload['properties'] = {} # TODO do we care here? - if not upload['payload']: + if not 'payload' in upload: data = sys.stdin.read() upload['payload'] = base64.b64encode(data) upload['payload_encoding'] = 'base64' @@ -287,7 +422,7 @@ def invoke_get(self): (uri, upload) = self.parse_args(self.args, EXTRA_VERBS['get']) - payload_file = upload['payload_file'] + payload_file = 'payload_file' in upload and upload['payload_file'] or None assert_usage(not payload_file or upload['count'] == '1', 'Cannot get multiple messages using payload_file') result = self.post(uri, json.dumps(upload)) @@ -329,8 +464,9 @@ obj_type = self.args[0] assert_usage(obj_type in obj_types, "Don't know how to {0} {1}".format(verb, obj_type)) + vhostable = obj_types[obj_type] uri = "/%s" % obj_type - if self.options.vhost: + if vhostable and self.options.vhost: uri += "/%s" % urllib.quote_plus(self.options.vhost) if cols != []: uri += "?columns=" + ",".join(cols) @@ -374,7 +510,8 @@ uri_template = obj['uri'] upload = {} for k in optional.keys(): - upload[k] = optional[k] + if optional[k]: + upload[k] = optional[k] for arg in args: assert_usage("=" in arg, 'Argument "{0}" not in format name=value'.format(arg)) @@ -386,7 +523,8 @@ assert_usage(m in upload.keys(), 'mandatory argument "{0}" required'.format(m)) upload['arguments'] = {} - upload['vhost'] = self.options.vhost or '/' + if 'vhost' not in mandatory: + upload['vhost'] = self.options.vhost or self.options.declare_vhost uri_args = {} for k in upload: v = upload[k] @@ -438,15 +576,22 @@ def add(prefix, depth, item, fun): for key in item: column = prefix == '' and key or (prefix + '.' + key) - if type(item[key]) == dict: + subitem = item[key] + if type(subitem) == dict: if depth < max_depth: - add(column, depth + 1, item[key], fun) - elif type(item[key]) == list: - # TODO - ATM this is only applications inside nodes. Not - # sure how to handle this sensibly. - pass + add(column, depth + 1, subitem, fun) + elif type(subitem) == list: + # The first branch has slave nodes in queues in + # mind (which come out looking decent); the second + # one has applications in nodes (which look less + # so, but what would look good?). + if [x for x in subitem if type(x) != unicode] == []: + serialised = " ".join(subitem) + else: + serialised = json.dumps(subitem) + fun(column, serialised) else: - fun(column, item[key]) + fun(column, subitem) def add_to_columns(col, val): columns[col] = True @@ -478,15 +623,11 @@ self.options = options def display_list(self, columns, table): - head = "" - for col in columns: - head += col + "\t" + head = "\t".join(columns) self.verbose(head) for row in table: - line = "" - for cell in row: - line += cell + "\t" + line = "\t".join(row) output(line) class LongList(Lister): @@ -603,7 +744,7 @@ cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="list show declare delete close purge import export get publish" + opts="list show declare delete close purge import export get publish help" fargs="--help --host --port --vhost --username --password --format --depth" case "${prev}" in @@ -639,6 +780,11 @@ COMPREPLY=( $(compgen -f ${cur}) ) return 0 ;; + help) + opts="subcommands config" + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + ;; -@(H|-host)) COMPREPLY=( $(compgen -A hostname ${cur}) ) return 0 diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/etc/bunny.config rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/etc/bunny.config --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/etc/bunny.config 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/etc/bunny.config 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1 @@ +[{rabbitmq_mochiweb, [{listeners,[{mgmt, [{port, 55674}]}]}]}]. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/include/rabbit_mgmt.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/include/rabbit_mgmt.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/include/rabbit_mgmt.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/include/rabbit_mgmt.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -record(context, {user}). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/package.mk rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/package.mk --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/package.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/package.mk 2012-03-19 10:36:09.000000000 +0000 @@ -2,6 +2,7 @@ DEPS:=rabbitmq-mochiweb webmachine-wrapper rabbitmq-server rabbitmq-erlang-client rabbitmq-management-agent WITH_BROKER_TEST_COMMANDS:=rabbit_mgmt_test_all:all_tests() WITH_BROKER_TEST_CONFIG:=$(PACKAGE_DIR)/etc/rabbit-test +WITH_BROKER_TEST_SCRIPTS:=$(PACKAGE_DIR)/test/src/rabbitmqadmin-test.py CONSTRUCT_APP_PREREQS:=$(shell find $(PACKAGE_DIR)/priv -type f) $(PACKAGE_DIR)/bin/rabbitmqadmin define construct_app_commands diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/css/main.css rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/css/main.css --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/css/main.css 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/css/main.css 2012-03-19 10:36:09.000000000 +0000 @@ -33,6 +33,7 @@ table.list th, table.list td { border-left: 1px solid #ccc; border-right: 1px solid #ccc; } table.list th { text-align: center; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.list td a { display: block; width: 100%; } +table.list td.status a { display: inline; } table.list th a.sort { display: block; width: 100%; cursor: pointer; } table.list th a.sort .arrow { color: #888; } table.list td p { margin: 0; padding: 1px 0 0 0; } @@ -145,6 +146,8 @@ acronym.warning { background: #daa; } +.status acronym, small acronym { background: none; color: inherit; padding: 0; border-bottom: 1px dotted; cursor: default; } + table.bindings { margin-bottom: 1em; } td.binding-endpoint span.object { border: 1px solid #bbb; padding: 10px; border-radius: 10px; -moz-border-radius: 10px; } td.binding-endpoint span.arrow { font-size: 200%; } diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/dispatcher.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/dispatcher.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/dispatcher.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/dispatcher.js 2012-03-19 10:36:09.000000000 +0000 @@ -127,11 +127,16 @@ 'vhosts': '/vhosts/'}, 'user', '#/users'); }); - sammy.put('#/users', function() { + sammy.put('#/users-add', function() { if (sync_put(this, '/users/:username')) update(); return false; }); + sammy.put('#/users-modify', function() { + if (sync_put(this, '/users/:username')) + go_to('#/users'); + return false; + }); sammy.del('#/users', function() { if (sync_delete(this, '/users/:username')) go_to('#/users'); diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/formatters.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/formatters.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/formatters.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/formatters.js 2012-03-19 10:36:09.000000000 +0000 @@ -11,11 +11,6 @@ return fmt_escape_html("" + str); } -function fmt_num(num) { - if (num == undefined) return UNKNOWN_REPR; - return num.toFixed(0); -} - function fmt_bytes(bytes) { if (bytes == undefined) return UNKNOWN_REPR; @@ -43,7 +38,7 @@ } return d.getFullYear() + "-" + f(d.getMonth() + 1) + "-" + - f(d.getDay() + 1) + " " + f(d.getHours()) + ":" + f(d.getMinutes()) + + f(d.getDate()) + " " + f(d.getHours()) + ":" + f(d.getMinutes()) + ":" + f(d.getSeconds()); } @@ -141,7 +136,7 @@ } function fmt_rate(obj, name, show_total, cssClass) { - var res = fmt_rate0(obj, name, fmt_num, show_total); + var res = fmt_rate0(obj, name, fmt_rate_num, show_total); if (cssClass == undefined || res == '') { return res; } @@ -150,6 +145,13 @@ } } +function fmt_rate_num(num) { + if (num == undefined) return UNKNOWN_REPR; + else if (num < 1) return num.toFixed(2); + else if (num < 10) return num.toFixed(1); + else return num.toFixed(0); +} + function fmt_rate_bytes(obj, name) { return fmt_rate0(obj, name, fmt_bytes, true); } @@ -197,6 +199,17 @@ return name == '' ? '(AMQP default)' : fmt_escape_html(name); } +function fmt_exchange_type(type) { + for (var i in exchange_types) { + if (exchange_types[i].name == type) { + return fmt_escape_html(type); + } + } + return '
' + fmt_escape_html(type) + + '
'; +} + function fmt_exchange_url(name) { return name == '' ? 'amq.default' : fmt_escape_html(name); } @@ -207,6 +220,15 @@ (now.getMonth() + 1) + "-" + now.getDate() + ".json"; } +function fmt_fd_used(used) { + if (used == 'install_handle_from_sysinternals') { + return '?'; + } + else { + return used; + } +} + function fmt_table_short(table) { return '' + fmt_table_body(table, ':') + '
'; } @@ -307,7 +329,8 @@ } function fmt_escape_html(txt) { - return txt.replace(//g, '>') .replace(/\n/g, '
') .replace(/\"/g, '"'); @@ -340,6 +363,39 @@ return host + ' (' + node_host + ')'; } +function fmt_connection_state(conn) { + if (conn.state == undefined) return ''; + + var colour = 'green'; + var text = conn.state; + var explanation; + + if (conn.last_blocked_by == 'mem' && conn.state == 'blocked') { + colour = 'red'; + explanation = 'Memory alarm: Connection blocked.'; + } + else if (conn.state == 'blocking') { + colour = 'yellow'; + explanation = 'Memory alarm: Connection will block on publish.'; + } + else if (conn.last_blocked_by == 'flow') { + var age = conn.last_blocked_age.toFixed(); + if (age < 5) { + colour = 'yellow'; + text = 'flow'; + explanation = 'Publishing rate recently restricted by server.'; + } + } + + if (explanation) { + return '
' + text + '
'; + } + else { + return '
' + text + '
'; + } +} + function alt_rows(i) { return (i % 2 == 0) ? ' class="alt1"' : ' class="alt2"'; } @@ -349,36 +405,36 @@ } function link_conn(name) { - return link_to(name, '#/connections/' + esc(name)) + return _link_to(fmt_escape_html(name), '#/connections/' + esc(name)) } function link_channel(name) { - return link_to(name, '#/channels/' + esc(name)) + return _link_to(fmt_escape_html(name), '#/channels/' + esc(name)) } function link_exchange(vhost, name) { var url = esc(vhost) + '/' + (name == '' ? 'amq.default' : esc(name)); - return link_to(fmt_exchange(name), '#/exchanges/' + url) + return _link_to(fmt_exchange(name), '#/exchanges/' + url) } function link_queue(vhost, name) { - return link_to(name, '#/queues/' + esc(vhost) + '/' + esc(name)) + return _link_to(fmt_escape_html(name), '#/queues/' + esc(vhost) + '/' + esc(name)) } function link_vhost(name) { - return link_to(name, '#/vhosts/' + esc(name)) + return _link_to(fmt_escape_html(name), '#/vhosts/' + esc(name)) } function link_user(name) { - return link_to(name, '#/users/' + esc(name)) + return _link_to(fmt_escape_html(name), '#/users/' + esc(name)) } function link_node(name) { - return link_to(name, '#/nodes/' + esc(name)) + return _link_to(fmt_escape_html(name), '#/nodes/' + esc(name)) } -function link_to(name, url) { - return '' + fmt_escape_html(name) + ''; +function _link_to(name, url) { + return '' + name + ''; } function message_rates(stats) { @@ -397,7 +453,7 @@ var key = items[i][1] + '_details'; if (key in stats) { res += '
' + name; - res += '' + Math.round(stats[key].rate) + ''; + res += '' + fmt_rate_num(stats[key].rate) + ''; res += 'msg/s
'; } } @@ -417,9 +473,9 @@ var rateMsg = ' '; var detail = stats[key + '_details'] if (detail != undefined) { - var rate = Math.round(detail.rate); - if (rate > 0) rateMsg = '+' + rate + ' msg/s'; - else if (rate < 0) rateMsg = rate + ' msg/s'; + var rate = detail.rate; + if (rate > 0) rateMsg = '+' + fmt_rate_num(rate) + ' msg/s'; + else if (rate < 0) rateMsg = '-' + fmt_rate_num(-rate) + ' msg/s'; } return '
' + name + diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/global.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/global.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/global.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/global.js 2012-03-19 10:36:09.000000000 +0000 @@ -21,10 +21,12 @@ '/queues', '/exchanges']); // Extension arguments that we know about and present specially in the UI. -var KNOWN_ARGS = {'alternate-exchange': {'short': 'AE', 'type': 'string'}, - 'x-message-ttl': {'short': 'TTL', 'type': 'int'}, - 'x-expires': {'short': 'Exp', 'type': 'int'}, - 'x-ha-policy': {'short': 'HA', 'type': 'string'}}; +var KNOWN_ARGS = {'alternate-exchange': {'short': 'AE', 'type': 'string'}, + 'x-message-ttl': {'short': 'TTL', 'type': 'int'}, + 'x-expires': {'short': 'Exp', 'type': 'int'}, + 'x-ha-policy': {'short': 'HA', 'type': 'string'}, + 'x-dead-letter-exchange': {'short': 'DLX', 'type': 'string'}, + 'x-dead-letter-routing-key': {'short': 'DLK', 'type': 'string'}}; // Things that are like arguments that we format the same way in listings. var IMPLICIT_ARGS = {'durable': {'short': 'D', 'type': 'boolean'}, @@ -59,19 +61,27 @@ // The dispatcher needs access to the Sammy app var app; +var exchange_types; + // Set up the above vars function setup_global_vars() { - statistics_level = JSON.parse(sync_get('/overview')).statistics_level; + var overview = JSON.parse(sync_get('/overview')); + var nodes = JSON.parse(sync_get('/nodes')); + statistics_level = overview.statistics_level; var user = JSON.parse(sync_get('/whoami')); replace_content('login', '

User: ' + user.name + '

'); var tags = user.tags.split(","); user_administrator = jQuery.inArray("administrator", tags) != -1; user_monitor = user_administrator || jQuery.inArray("monitoring", tags) != -1; - nodes_interesting = user_monitor && - JSON.parse(sync_get('/nodes')).length > 1; + nodes_interesting = user_monitor && nodes.length > 1; vhosts_interesting = JSON.parse(sync_get('/vhosts')).length > 1; current_vhost = get_pref('vhost'); + for (var i in nodes) { + if (nodes[i].name == overview.node) { + exchange_types = nodes[i].exchange_types; + } + } } //////////////////////////////////////////////////// diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/help.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/help.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/help.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/help.js 2012-03-19 10:36:09.000000000 +0000 @@ -17,6 +17,12 @@ 'queue-auto-delete': 'If yes, the queue will delete itself after at least one consumer has connected, and then all consumers have disconnected.', + 'queue-dead-letter-exchange': + 'Optional name of an exchange to which messages will be republished if they are rejected or expire.
(Sets the "x-dead-letter-exchange" argument.)', + + 'queue-dead-letter-routing-key': + 'Optional replacement routing key to use when a message is dead-lettered. If this is not set, the message\'s original routing key will be used.
(Sets the "x-dead-letter-routing-key" argument.)', + 'internal-users-only': 'Only users within the internal RabbitMQ database are shown here. Other users (e.g. those authenticated over LDAP) will not appear.', diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/main.js rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/main.js --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/main.js 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/main.js 2012-03-19 10:36:09.000000000 +0000 @@ -272,7 +272,7 @@ update_multifields(); }); $('.controls-appearance').change(function() { - var controls = $(this).attr('controls'); + var controls = $(this).attr('controls-divs'); if ($(this).val() == 'true') { $('#' + controls + '-yes').slideDown(100); $('#' + controls + '-no').slideUp(100); @@ -644,6 +644,9 @@ function check_password(params) { if (params['password'] != undefined) { + if (params['password'] == '') { + throw("Please specify a password."); + } if (params['password'] != params['password_confirm']) { throw("Passwords do not match."); } diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/channels-list.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/channels-list.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/channels-list.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/channels-list.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -97,11 +97,10 @@ <% } %> <%= fmt_string(channel.user) %> <% } %> - + <%= fmt_channel_mode(channel) %> <% if (channel.transactional) { %> - <%= channel.messages_uncommitted %> uncommitted messages - <%= channel.acks_uncommitted %> uncommitted acks + <%= channel.messages_uncommitted %>m/<%= channel.acks_uncommitted %>a <% } %> <%= channel.prefetch_count %> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/connection.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/connection.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/connection.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/connection.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -66,11 +66,15 @@ - + - + + + + +
State<%= connection.state %><%= fmt_connection_state(connection) %>
Timeout<%= connection.timeout %><% if (connection.timeout != 0) { %><%= connection.timeout %>s<% } %>
Frame max<%= connection.frame_max %> bytes
<% } %> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/connections.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/connections.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/connections.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/connections.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -5,17 +5,18 @@ - - + + - + <% if (nodes_interesting) { %> <% } %> + <% if (vhosts_interesting) { %> @@ -42,12 +43,13 @@ <% } %> + <% if (vhosts_interesting) { %> <% } %> - + <% } %> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchange.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchange.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchange.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchange.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -6,7 +6,7 @@
NetworkOverviewNetworkOverview
<%= fmt_sort('Protocol', 'protocol') %><%= fmt_sort('Peer address', 'name') %><%= fmt_sort('Name', 'name') %><%= fmt_sort('Node', 'node') %><%= fmt_sort('From client', 'recv_oct_details.rate') %> <%= fmt_sort('To client', 'send_oct_details.rate') %><%= fmt_sort('Timeout', 'timeout') %> <%= fmt_sort('Channels', 'channels') %><%= fmt_sort('Virtual host', 'vhost') %><%= fmt_rate_bytes(connection, 'recv_oct') %> <%= fmt_rate_bytes(connection, 'send_oct') %><% if (connection.timeout != undefined) { %><%= connection.timeout %>s<% } %> <%= connection.channels %><%= fmt_string(connection.vhost) %><%= fmt_string(connection.user) %><%= connection.state %><%= fmt_connection_state(connection) %>
- + @@ -93,58 +93,7 @@ <% if (!exchange.internal) { %> -
-

Publish message

-
-
- - - -
Type<%= fmt_string(exchange.type) %><%= fmt_exchange_type(exchange.type) %>
Parameters
- - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- - - -
- - -
- +<%= format('publish', {'mode': 'exchange', 'exchange': exchange}) %> <% } %> <% if (exchange.name != "") { %> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchanges.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchanges.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchanges.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchanges.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -27,7 +27,7 @@ <%= fmt_string(exchange.vhost) %> <% } %> <%= link_exchange(exchange.vhost, exchange.name) %> - <%= fmt_string(exchange.type) %> + <%= fmt_exchange_type(exchange.type) %> <%= fmt_parameters_short(exchange) %> <%= fmt_rate(exchange.message_stats_in, 'publish', false) %> @@ -62,7 +62,13 @@ - * + + + diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/node.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/node.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/node.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/node.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -17,7 +17,7 @@
- <%= node.fd_used %> / <%= node.fd_total %> + <%= fmt_fd_used(node.fd_used) %> / <%= node.fd_total %>
diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/overview.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/overview.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/overview.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/overview.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -4,14 +4,14 @@

Totals

<% if (overview.statistics_db_node != 'not_running') { %> -

Queued messages

+

Queued messages

<%= queue_length(overview.queue_totals, 'Ready', 'messages_ready') %> <%= queue_length(overview.queue_totals, 'Unacknowledged', 'messages_unacknowledged') %> <%= queue_length(overview.queue_totals, 'Total', 'messages') %>
<% if (statistics_level == 'fine') { %> -

Message rates

+

Message rates

<%= message_rates(overview.message_stats) %>
@@ -75,7 +75,7 @@
- <%= node.fd_used %> / <%= node.fd_total %> + <%= fmt_fd_used(node.fd_used) %> / <%= node.fd_total %>
diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/permissions.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/permissions.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/permissions.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/permissions.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -1,7 +1,8 @@ -<% if (permissions.length > 0) { %>

Permissions

+

Current permissions

+ <% if (permissions.length > 0) { %> @@ -23,9 +24,9 @@ %> > <% if (mode == 'vhost') { %> - + <% } else { %> - + <% } %> @@ -41,13 +42,11 @@ <% } %>
<%= link_to(permission.user, '#/users/' + esc(permission.user)) %><%= link_user(permission.user) %><%= link_to(permission.vhost, '#/vhosts/' + esc(permission.vhost)) %><%= link_vhost(permission.vhost) %><%= fmt_string(permission.configure) %> <%= fmt_string(permission.write) %>
-
-
-<% } %> + <% } else { %> +

... no permissions ...

+ <% } %> -
-

Set permission

-
+

Set permission

diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/publish.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/publish.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/publish.ejs 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/publish.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,63 @@ +
+

Publish message

+
+ +<% if (mode == 'queue') { %> + + +<% } else { %> + + +<% } %> + +
+<% if (mode == 'queue') { %> + + + +<% } else { %> + + + + +<% } %> + + + + + + + + + + + + + + + + +
Message will be published to the default exchange with routing key <%= fmt_string(queue.name) %>, routing it to this queue.
+ +
+ + + +
+ + + +
+ +
+
+
diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/queue.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/queue.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/queue.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/queue.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -129,6 +129,8 @@
+<%= format('publish', {'mode': 'queue', 'queue': queue}) %> +

Get messages

diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/queues.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/queues.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/queues.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/queues.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -143,7 +143,7 @@ <% } %> - + ms - + ms + + + + + + + + diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/user.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/user.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/user.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/user.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -26,6 +26,54 @@ <%= format('permissions', {'mode': 'user', 'permissions': permissions, 'vhosts': vhosts, 'parent': user}) %>
+

Update this user

+
+
+ + + + + + + + + + +
+ + +
+ + *
+ + * + (confirm) +
+ +
+ + + + [Admin] + [Monitoring] + [Management] + [None] + +
+ +
+
+
+ + +

Delete this user

diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/users.ejs rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/users.ejs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/priv/www/js/tmpl/users.ejs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/priv/www/js/tmpl/users.ejs 2012-03-19 10:36:09.000000000 +0000 @@ -8,6 +8,7 @@ <%= fmt_sort('Name', 'name') %> <%= fmt_sort('Tags', 'tags') %> Can access virtual hosts + Has password @@ -20,6 +21,7 @@ <%= fmt_string(user.tags) %> <%= fmt_permissions(user, permissions, 'user', 'vhost', '

No access

') %> + <%= fmt_boolean(user.password_hash.length > 0) %> <% } %> @@ -29,9 +31,9 @@
-

Add / update a user

+

Add a user

- + @@ -43,7 +45,7 @@ diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_app). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_db.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_db.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_db.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_db.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_db). @@ -314,9 +314,8 @@ handle_deleted(queue_stats, Event, State); handle_event(#event{type = connection_created, props = Stats}, State) -> - Name = rabbit_mgmt_format:connection(Stats), handle_created( - connection_stats, [{name, Name} | proplists:delete(name, Stats)], + connection_stats, Stats, [{fun rabbit_mgmt_format:addr/1, [address, peer_address]}, {fun rabbit_mgmt_format:port/1, [port, peer_port]}, {fun rabbit_mgmt_format:protocol/1, [protocol]}, @@ -331,14 +330,8 @@ handle_event(Event = #event{type = connection_closed}, State) -> handle_deleted(connection_stats, Event, State); -handle_event(#event{type = channel_created, props = Stats}, - State = #state{tables = Tables}) -> - ConnTable = orddict:fetch(connection_stats, Tables), - Conn = lookup_element(ConnTable, {id(pget(connection, Stats)), create}), - Name = rabbit_mgmt_format:print("~s:~w", - [pget(name, Conn), - pget(number, Stats)]), - handle_created(channel_stats, [{name, Name}|Stats], [], State); +handle_event(#event{type = channel_created, props = Stats}, State) -> + handle_created(channel_stats, Stats, [], State); handle_event(#event{type = channel_stats, props = Stats, timestamp = Timestamp}, State) -> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_dispatcher.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_dispatcher.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_dispatcher.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_dispatcher.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_dispatcher). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_extension.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_extension.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_extension.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_extension.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_extension). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_format.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_format.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_format.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_format.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_format). @@ -23,7 +23,7 @@ -export([pack_binding_props/2, unpack_binding_props/1, tokenise/1]). -export([to_amqp_table/1, listener/1, properties/1, basic_properties/1]). -export([record/2, to_basic_properties/1]). --export([connection/1, addr/1, port/1]). +-export([addr/1, port/1]). -include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("rabbit_common/include/rabbit_framing.hrl"). @@ -129,7 +129,7 @@ unknown; timestamp(Timestamp) -> {{Y, M, D}, {H, Min, S}} = calendar:now_to_local_time(Timestamp), - print("~w-~w-~w ~w:~w:~w", [Y, M, D, H, Min, S]). + print("~w-~2.2.0w-~2.2.0w ~w:~2.2.0w:~2.2.0w", [Y, M, D, H, Min, S]). resource(unknown) -> unknown; resource(Res) -> resource(name, Res). @@ -237,14 +237,6 @@ url(Fmt, Vals) -> print(Fmt, [mochiweb_util:quote_plus(V) || V <- Vals]). -connection(Props) -> - case proplists:get_value(name, Props, unknown) of - unknown -> print("~s:~w", - [addr(proplists:get_value(peer_address, Props)), - port(proplists:get_value(peer_port, Props))]); - Name -> Name - end. - exchange(X) -> format(X, [{fun resource/1, [name]}, {fun amqp_table/1, [arguments]}]). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_load_definitions.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_load_definitions.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_load_definitions.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_load_definitions.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,48 @@ +%% 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 Management Plugin. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + +-module(rabbit_mgmt_load_definitions). + +-export([maybe_load_definitions/0]). + +%% We want to A) make sure we apply defintions before being open for +%% business (hence why we don't do this in the mgmt app startup) and +%% B) in fact do it before empty_db_check (so the defaults will not +%% get created if we don't need 'em). + +-rabbit_boot_step({load_definitions, + [{description, "configured definitions"}, + {mfa, {rabbit_mgmt_load_definitions, + maybe_load_definitions, + []}}, + {requires, recovery}, + {enables, empty_db_check}]}). + +maybe_load_definitions() -> + {ok, File} = application:get_env(rabbitmq_management, load_definitions), + case File of + none -> ok; + _ -> case file:read_file(File) of + {ok, Body} -> rabbit_log:info( + "Applying definitions from: ~s~n", [File]), + load_definitions(Body); + {error, E} -> exit({could_not_read_defs, {File, E}}) + end + end. + +load_definitions(Body) -> + rabbit_mgmt_wm_definitions:apply_defs( + Body, fun rabbit_misc:const_ok/0, fun (E) -> exit(E) end). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_util). @@ -27,7 +27,8 @@ -export([with_channel/4, with_channel/5]). -export([props_to_method/2, props_to_method/4]). -export([all_or_one_vhost/2, http_to_amqp/5, reply/3, filter_vhost/3]). --export([filter_conn_ch_list/3, with_decode/5, decode/1, redirect/2, args/1]). +-export([filter_conn_ch_list/3, with_decode/5, decode/1, decode/2, redirect/2, + args/1]). -export([reply_list/3, reply_list/4, sort_list/2, destination_type/1]). -export([post_respond/1, columns/1, want_column/2, is_monitor/1]). -export([list_visible_vhosts/1, b64decode_or_throw/1]). @@ -265,7 +266,7 @@ try Node = case pget(<<"node">>, Props) of undefined -> node(); - N -> rabbit_misc:makenode( + N -> rabbit_nodes:make( binary_to_list(N)) end, amqp_request(VHost, ReqData, Context, Node, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_aliveness_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_aliveness_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_aliveness_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_aliveness_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_aliveness_test). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_binding.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_binding.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_binding.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_binding.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_binding). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_bindings.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_bindings.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_bindings.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_bindings.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_bindings). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channel.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channel.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channel.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channel.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_channel). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channels.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channels.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channels.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channels.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_channels). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_connection). @@ -48,7 +48,7 @@ Pid = proplists:get_value(pid, Conn), Reason = "Closed via management plugin", case proplists:get_value(type, Conn) of - direct -> amqp_connection:close(Pid, 200, Reason); + direct -> amqp_direct_connection:server_close(Pid, 320, Reason); network -> rabbit_networking:close_connection(Pid, Reason) end, {true, ReqData, Context}. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection_channels.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection_channels.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection_channels.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection_channels.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_connection_channels). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connections.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connections.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connections.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connections.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_connections). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_definitions.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_definitions.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_definitions.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_definitions.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_definitions). @@ -20,6 +20,8 @@ -export([content_types_accepted/2, allowed_methods/2, accept_json/2]). -export([post_is_create/2, create_path/2, accept_multipart/2]). +-export([apply_defs/3]). + -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). @@ -100,23 +102,27 @@ %%-------------------------------------------------------------------- accept(Body, ReqData, Context) -> - rabbit_mgmt_util:with_decode( - [users, vhosts, permissions, queues, exchanges, bindings], - Body, ReqData, Context, - fun([Users, VHosts, Permissions, Queues, Exchanges, Bindings], _) -> - try - for_all(Users, fun add_user/1), - for_all(VHosts, fun add_vhost/1), - for_all(Permissions, fun add_permission/1), - for_all(Queues, fun add_queue/1), - for_all(Exchanges, fun add_exchange/1), - for_all(Bindings, fun add_binding/1), - {true, ReqData, Context} - catch - exit:E -> - rabbit_mgmt_util:bad_request(E, ReqData, Context) - end - end). + apply_defs(Body, fun() -> {true, ReqData, Context} end, + fun(E) -> rabbit_mgmt_util:bad_request(E, ReqData, Context) end). + +apply_defs(Body, SuccessFun, ErrorFun) -> + case rabbit_mgmt_util:decode( + [users, vhosts, permissions, queues, exchanges, bindings], Body) of + {error, E} -> + ErrorFun(E); + {ok, [Users, VHosts, Permissions, Queues, Exchanges, Bindings], _} -> + try + for_all(Users, fun add_user/1), + for_all(VHosts, fun add_vhost/1), + for_all(Permissions, fun add_permission/1), + for_all(Queues, fun add_queue/1), + for_all(Exchanges, fun add_exchange/1), + for_all(Bindings, fun add_binding/1), + SuccessFun() + catch {error, E} -> ErrorFun(E); + exit:E -> ErrorFun(E) + end + end. get_part(Name, Parts) -> Filtered = [Value || {N, _Meta, Value} <- Parts, N == Name], diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_exchange). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange_publish.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange_publish.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange_publish.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange_publish.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_exchange_publish). @@ -80,6 +80,10 @@ erlang:demonitor(MRef), rabbit_mgmt_util:reply([{routed, Routed}], ReqData, Context). +bad({shutdown, {connection_closing, + {server_initiated_close, Code, Reason}}}, ReqData, Context) -> + rabbit_mgmt_util:bad_request_exception(Code, Reason, ReqData, Context); + bad({shutdown, {server_initiated_close, Code, Reason}}, ReqData, Context) -> rabbit_mgmt_util:bad_request_exception(Code, Reason, ReqData, Context). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchanges.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchanges.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchanges.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchanges.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_exchanges). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_extensions.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_extensions.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_extensions.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_extensions.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_extensions). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_node.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_node.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_node.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_node.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_node). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_nodes.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_nodes.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_nodes.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_nodes.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_nodes). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_overview.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_overview.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_overview.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_overview.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_overview). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permission.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permission.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permission.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permission.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permission). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permissions). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_user.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_user.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_user.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_user.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permissions_user). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_vhost.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_vhost.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_vhost.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_vhost.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permissions_vhost). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_get.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_get.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_get.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_get.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue_get). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_purge.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_purge.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_purge.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_purge.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue_purge). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queues.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queues.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queues.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queues.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queues). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_user.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_user.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_user.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_user.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_user). @@ -86,19 +86,22 @@ put_user(User, PWArg, PWFun) -> Username = pget(name, User), - Tags = case pget(tags, User) of - undefined -> case rabbit_mgmt_util:parse_bool( - pget(administrator, User)) of - true -> [administrator]; - false -> [] - end; - TagsS -> [list_to_atom(string:strip(T)) || - T <- string:tokens(binary_to_list(TagsS), ",")] + Tags = case {pget(tags, User), pget(administrator, User)} of + {undefined, undefined} -> + throw({error, tags_not_present}); + {undefined, AdminS} -> + case rabbit_mgmt_util:parse_bool(AdminS) of + true -> [administrator]; + false -> [] + end; + {TagsS, _} -> + [list_to_atom(string:strip(T)) || + T <- string:tokens(binary_to_list(TagsS), ",")] end, case rabbit_auth_backend_internal:lookup_user(Username) of {error, not_found} -> rabbit_auth_backend_internal:add_user( - Username, rabbit_guid:binstring_guid("tmp")); + Username, rabbit_guid:binary(rabbit_guid:gen_secure(), "tmp")); _ -> ok end, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_users.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_users.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_users.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_users.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_users). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhost.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhost.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhost.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhost.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_vhost). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhosts.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhosts.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhosts.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhosts.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_vhosts). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_whoami.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_whoami.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_whoami.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_whoami.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_whoami). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbitmq_management.app.src rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbitmq_management.app.src --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/src/rabbitmq_management.app.src 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/src/rabbitmq_management.app.src 2012-03-19 10:36:09.000000000 +0000 @@ -4,6 +4,7 @@ {modules, []}, {registered, []}, {mod, {rabbit_mgmt_app, []}}, - {env, [{http_log_dir, none}]}, + {env, [{http_log_dir, none}, + {load_definitions, none}]}, {applications, [kernel, stdlib, rabbit, rabbitmq_mochiweb, amqp_client, rabbitmq_management_agent]}]}. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_all.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_all.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_all.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_all.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_test_all). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_clustering.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_clustering.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_clustering.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_clustering.erl 2012-03-19 10:36:09.000000000 +0000 @@ -29,14 +29,26 @@ %%---------------------------------------------------------------------------- -start_second_node() -> +start_second_node() -> start_other_node(hare, 5673), + cluster_other_node(hare). +stop_second_node() -> stop_other_node(hare). + +start_other_node(Name, Port) -> %% ?assertCmd seems to hang if you background anything. Bah! - Res = os:cmd("make -C " ++ plugin_dir() ++ " start-second-node ; echo $?"), + Res = os:cmd("make -C " ++ plugin_dir() ++ " OTHER_NODE=" ++ + atom_to_list(Name) ++ + " OTHER_PORT=" ++ integer_to_list(Port) ++ + " start-other-node ; echo $?"), LastLine = hd(lists:reverse(string:tokens(Res, "\n"))), ?assertEqual("0", LastLine). -stop_second_node() -> - ?assertCmd("make -C " ++ plugin_dir() ++ " stop-second-node"). +cluster_other_node(Name) -> + ?assertCmd("make -C " ++ plugin_dir() ++ " OTHER_NODE=" ++ + atom_to_list(Name) ++ " cluster-other-node"). + +stop_other_node(Name) -> + ?assertCmd("make -C " ++ plugin_dir() ++ " OTHER_NODE=" ++ + atom_to_list(Name) ++ " stop-other-node"). plugin_dir() -> {ok, [[File]]} = init:get_argument(config), @@ -96,9 +108,17 @@ ?assertEqual(1, length(Act)), assert_node(Exp, hd(Act)). +assert_nodes(Exp, Act0) -> + Act = [read_node(A) || A <- Act0], + ?debugVal({Exp, Act}), + ?assertEqual(length(Exp), length(Act)), + [?assert(lists:member(E, Act)) || E <- Exp]. + assert_node(Exp, Act) -> - ?assertEqual(Exp, - list_to_atom(hd(string:tokens(binary_to_list(Act), "@")))). + ?assertEqual(Exp, read_node(Act)). + +read_node(N) -> + list_to_atom(hd(string:tokens(binary_to_list(N), "@"))). restart_node() -> stop_second_node(), diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_db.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_db.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_db.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_db.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_test_db). @@ -193,6 +193,9 @@ X2 = <<"channel-aggregation-exch2">>, declare_exchange(Chan, X1), declare_exchange(Chan, X2), + Q = declare_queue(Chan), + bind_queue(Chan, X1, Q), + bind_queue(Chan, X2, Q), publish(Chan, X1, <<"">>, 10), publish(Chan, X2, <<"">>, 100), @@ -266,8 +269,8 @@ get_channel(C, Number) -> Port = local_port(C), hd(rabbit_mgmt_db:get_channels( - [list_to_binary("127.0.0.1:" ++ integer_to_list(Port) ++ ":" ++ - integer_to_list(Number))], full)). + [rabbit_mgmt_format:print( + "127.0.0.1:~w -> 127.0.0.1:5672 (~w)", [Port, Number])], full)). get_exchange(XName) -> X = rabbit_mgmt_wm_exchange:exchange(<<"/">>, XName), diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_http.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_http.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_http.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_http.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_test_http). @@ -104,6 +104,17 @@ http_get("/users/myuser", ?NOT_FOUND), ok. +users_legacy_administrator_test() -> + http_put("/users/myuser1", [{administrator, <<"true">>}], ?NO_CONTENT), + http_put("/users/myuser2", [{administrator, <<"false">>}], ?NO_CONTENT), + assert_item([{name, <<"myuser1">>}, {tags, <<"administrator">>}], + http_get("/users/myuser1")), + assert_item([{name, <<"myuser2">>}, {tags, <<"">>}], + http_get("/users/myuser2")), + http_delete("/users/myuser1", ?NO_CONTENT), + http_delete("/users/myuser2", ?NO_CONTENT), + ok. + permissions_validation_test() -> Good = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/permissions/wrong/guest", Good, ?BAD_REQUEST), @@ -178,7 +189,8 @@ LocalPort = rabbit_mgmt_test_db:local_port(Conn), Path = binary_to_list( rabbit_mgmt_format:print( - "/connections/127.0.0.1%3A~w", [LocalPort])), + "/connections/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672", + [LocalPort])), http_get(Path, ?OK), http_delete(Path, ?NO_CONTENT), %% TODO rabbit_reader:shutdown/2 returns before the connection is @@ -473,10 +485,12 @@ LocalPort = rabbit_mgmt_test_db:local_port(Conn), ConnPath = binary_to_list( rabbit_mgmt_format:print( - "/connections/127.0.0.1%3A~w", [LocalPort])), + "/connections/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672", + [LocalPort])), ChPath = binary_to_list( rabbit_mgmt_format:print( - "/channels/127.0.0.1%3A~w%3A1", [LocalPort])), + "/channels/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672%20(1)", + [LocalPort])), {Conn, ConnPath, ChPath}. permissions_connection_channel_test() -> diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_unit.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_unit.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_unit.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_unit.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_test_unit). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbitmqadmin-test.py rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbitmqadmin-test.py --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management/test/src/rabbitmqadmin-test.py 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management/test/src/rabbitmqadmin-test.py 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +import unittest +import os +import os.path +import socket +import subprocess +import sys + +# TODO test: SSL, depth, config file, encodings(?), completion(???) + +class TestRabbitMQAdmin(unittest.TestCase): + def test_no_args(self): + self.run_fail([]) + + def test_help(self): + self.run_success(['--help']) + self.run_success(['help', 'subcommands']) + self.run_success(['help', 'config']) + self.run_fail(['help', 'astronomy']) + + def test_host(self): + self.run_success(['show', 'overview']) + self.run_success(['--host', 'localhost', 'show', 'overview']) + self.run_success(['--host', socket.gethostname(), 'show', 'overview']) + self.run_fail(['--host', 'some-host-that-does-not-exist', 'show', 'overview']) + + def test_port(self): + self.run_success(['--port', '55672', 'show', 'overview']) + self.run_fail(['--port', '55673', 'show', 'overview']) + self.run_fail(['--port', '5672', 'show', 'overview']) + + def test_user(self): + self.run_success(['--user', 'guest', '--password', 'guest', 'show', 'overview']) + self.run_fail(['--user', 'no', '--password', 'guest', 'show', 'overview']) + self.run_fail(['--user', 'guest', '--password', 'no', 'show', 'overview']) + + def test_fmt_long(self): + self.assert_output(""" +-------------------------------------------------------------------------------- + + name: / +tracing: False + +-------------------------------------------------------------------------------- + +""", ['--format', 'long', 'list', 'vhosts']) + + def test_fmt_kvp(self): + self.assert_output("""name="/" tracing="False" +""", ['--format', 'kvp', 'list', 'vhosts']) + + def test_fmt_tsv(self): + self.assert_output("""name tracing +/ False +""", ['--format', 'tsv', 'list', 'vhosts']) + + def test_fmt_table(self): + out = """+------+---------+ +| name | tracing | ++------+---------+ +| / | False | ++------+---------+ +""" + self.assert_output(out, ['list', 'vhosts']) + self.assert_output(out, ['--format', 'table', 'list', 'vhosts']) + + def test_fmt_bash(self): + self.assert_output("""/ +""", ['--format', 'bash', 'list', 'vhosts']) + + def test_vhosts(self): + self.assert_list(['/'], l('vhosts')) + self.run_success(['declare', 'vhost', 'name=foo']) + self.assert_list(['/', 'foo'], l('vhosts')) + self.run_success(['delete', 'vhost', 'name=foo']) + self.assert_list(['/'], l('vhosts')) + + def test_users(self): + self.assert_list(['guest'], l('users')) + self.run_fail(['declare', 'user', 'name=foo']) + self.run_success(['declare', 'user', 'name=foo', 'password=pass', 'tags=']) + self.assert_list(['foo', 'guest'], l('users')) + self.run_success(['delete', 'user', 'name=foo']) + self.assert_list(['guest'], l('users')) + + def test_permissions(self): + self.run_success(['declare', 'vhost', 'name=foo']) + self.run_success(['declare', 'user', 'name=bar', 'password=pass', 'tags=']) + self.assert_table([['guest', '/']], ['list', 'permissions', 'user', 'vhost']) + self.run_success(['declare', 'permission', 'user=bar', 'vhost=foo', 'configure=.*', 'write=.*', 'read=.*']) + self.assert_table([['guest', '/'], ['bar', 'foo']], ['list', 'permissions', 'user', 'vhost']) + self.run_success(['delete', 'user', 'name=bar']) + self.run_success(['delete', 'vhost', 'name=foo']) + + def test_alt_vhost(self): + self.run_success(['declare', 'vhost', 'name=foo']) + self.run_success(['declare', 'permission', 'user=guest', 'vhost=foo', 'configure=.*', 'write=.*', 'read=.*']) + self.run_success(['declare', 'queue', 'name=in_/']) + self.run_success(['--vhost', 'foo', 'declare', 'queue', 'name=in_foo']) + self.assert_table([['/', 'in_/'], ['foo', 'in_foo']], ['list', 'queues', 'vhost', 'name']) + self.run_success(['--vhost', 'foo', 'delete', 'queue', 'name=in_foo']) + self.run_success(['delete', 'queue', 'name=in_/']) + self.run_success(['delete', 'vhost', 'name=foo']) + + def test_exchanges(self): + self.run_success(['declare', 'exchange', 'name=foo', 'type=direct']) + self.assert_list(['', 'amq.direct', 'amq.fanout', 'amq.headers', 'amq.match', 'amq.rabbitmq.log', 'amq.rabbitmq.trace', 'amq.topic', 'foo'], l('exchanges')) + self.run_success(['delete', 'exchange', 'name=foo']) + + def test_queues(self): + self.run_success(['declare', 'queue', 'name=foo']) + self.assert_list(['foo'], l('queues')) + self.run_success(['delete', 'queue', 'name=foo']) + + def test_bindings(self): + self.run_success(['declare', 'queue', 'name=foo']) + self.run_success(['declare', 'binding', 'source=amq.direct', 'destination=foo', 'destination_type=queue', 'routing_key=test']) + self.assert_table([['', 'foo', 'queue', 'foo'], ['amq.direct', 'foo', 'queue', 'test']], ['list', 'bindings', 'source', 'destination', 'destination_type', 'routing_key']) + self.run_success(['delete', 'queue', 'name=foo']) + + def test_publish(self): + self.run_success(['declare', 'queue', 'name=test']) + self.run_success(['publish', 'routing_key=test', 'payload=test_1']) + self.run_success(['publish', 'routing_key=test', 'payload=test_2']) + self.run_success(['publish', 'routing_key=test'], stdin='test_3') + self.assert_table([exp_msg('test', 2, False, 'test_1')], ['get', 'queue=test', 'requeue=false']) + self.assert_table([exp_msg('test', 1, False, 'test_2')], ['get', 'queue=test', 'requeue=true']) + self.assert_table([exp_msg('test', 1, True, 'test_2')], ['get', 'queue=test', 'requeue=false']) + self.assert_table([exp_msg('test', 0, False, 'test_3')], ['get', 'queue=test', 'requeue=false']) + self.run_success(['publish', 'routing_key=test'], stdin='test_4') + filename = '/tmp/rabbitmq-test/get.txt' + self.run_success(['get', 'queue=test', 'requeue=false', 'payload_file=' + filename]) + with open(filename) as f: + self.assertEqual('test_4', f.read()) + os.remove(filename) + self.run_success(['delete', 'queue', 'name=test']) + + def test_ignore_vhost(self): + self.run_success(['--vhost', '/', 'show', 'overview']) + self.run_success(['--vhost', '/', 'list', 'users']) + self.run_success(['--vhost', '/', 'list', 'vhosts']) + self.run_success(['--vhost', '/', 'list', 'nodes']) + self.run_success(['--vhost', '/', 'list', 'permissions']) + self.run_success(['--vhost', '/', 'declare', 'user', 'name=foo', 'password=pass', 'tags=']) + self.run_success(['delete', 'user', 'name=foo']) + + # --------------------------------------------------------------------------- + + def run_success(self, args, **kwargs): + self.assertEqual(0, run(args, **kwargs)[1]) + + def run_fail(self, args): + self.assertNotEqual(0, run(args)[1]) + + def assert_output(self, expected, args): + self.assertEqual(expected, run(args)[0]) + + def assert_list(self, expected, args0): + args = ['-f', 'tsv', '-q'] + args.extend(args0) + self.assertEqual(expected, run(args)[0].splitlines()) + + def assert_table(self, expected, args0): + args = ['-f', 'tsv', '-q'] + args.extend(args0) + self.assertEqual(expected, [l.split('\t') for l in run(args)[0].splitlines()]) + +def run(args, stdin=None): + path = os.path.normpath(os.path.join(os.getcwd(), sys.argv[0], '../../../bin/rabbitmqadmin')) + cmdline = [path] + cmdline.extend(args) + proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = proc.communicate(stdin) + returncode = proc.returncode + return (stdout, returncode) + +def l(thing): + return ['list', thing, 'name'] + +def exp_msg(key, count, redelivered, payload): + # routing_key, exchange, message_count, payload, payload_bytes, payload_encoding, properties, redelivered + return [key, '', str(count), payload, str(len(payload)), 'string', '', str(redelivered)] + +if __name__ == '__main__': + print "\nrabbitmqadmin tests\n===================\n" + suite = unittest.TestLoader().loadTestsFromTestCase(TestRabbitMQAdmin) + unittest.TextTestRunner(verbosity=2).run(suite) diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_agent_app). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_agent_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_db_handler.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_db_handler.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_db_handler.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_db_handler.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_db_handler). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_external_stats.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_external_stats.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_external_stats.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_external_stats.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mgmt_external_stats). @@ -69,6 +69,16 @@ {error, _} -> get_used_fd({unix, generic}) end; +get_used_fd({unix, BSD}) + when BSD == openbsd; BSD == freebsd; BSD == netbsd -> + Digit = fun (D) -> lists:member(D, "0123456789*") end, + length( + lists:filter( + fun (Line) -> + lists:all(Digit, (lists:nth(4, string:tokens(Line, " ")))) + end, + string:tokens(os:cmd("fstat -p " ++ os:getpid()), "\n"))); + get_used_fd({unix, _}) -> get_used_fd_lsof(); @@ -137,9 +147,9 @@ i(fd_used, #state{fd_used = FdUsed}) -> FdUsed; i(fd_total, #state{fd_total = FdTotal}) -> FdTotal; i(sockets_used, _State) -> - proplists:get_value(obtain_count, file_handle_cache:info([obtain_count])); + proplists:get_value(sockets_used, file_handle_cache:info([sockets_used])); i(sockets_total, _State) -> - proplists:get_value(obtain_limit, file_handle_cache:info([obtain_limit])); + proplists:get_value(sockets_limit, file_handle_cache:info([sockets_limit])); i(os_pid, _State) -> list_to_binary(os:getpid()); i(mem_ets, _State) -> erlang:memory(ets); i(mem_binary, _State) -> erlang:memory(binary); diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-visualiser/LICENSE-MPL-RabbitMQ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-visualiser/LICENSE-MPL-RabbitMQ --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-visualiser/LICENSE-MPL-RabbitMQ 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-visualiser/LICENSE-MPL-RabbitMQ 2012-03-19 10:36:09.000000000 +0000 @@ -447,7 +447,7 @@ The Original Code is RabbitMQ Visualiser. The Initial Developer of the Original Code is VMware, Inc. - Copyright (c) 2011-2011 VMware, Inc. All rights reserved.'' + Copyright (c) 2011-2012 VMware, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-visualiser/src/rabbit_mgmt_wm_all.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-visualiser/src/rabbit_mgmt_wm_all.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-visualiser/src/rabbit_mgmt_wm_all.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-visualiser/src/rabbit_mgmt_wm_all.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Visualiser. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. -module(rabbit_mgmt_wm_all). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-visualiser/src/rabbit_visualiser_mgmt.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-visualiser/src/rabbit_visualiser_mgmt.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-management-visualiser/src/rabbit_visualiser_mgmt.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-management-visualiser/src/rabbit_visualiser_mgmt.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Visualiser. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_visualiser_mgmt). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_mochiweb). -export([all_listeners/0]). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_mochiweb_app). -behaviour(application). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_registry.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_registry.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_registry.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_registry.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_mochiweb_registry). -behaviour(gen_server). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_mochiweb_sup). -behaviour(supervisor). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,22 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 Original Code is RabbitMQ Mochiweb Embedding. -%% -%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. -%% -%% Copyright (C) 2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mochiweb_util). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_web.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_web.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_web.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_mochiweb_web.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_mochiweb_web). -export([start/1, stop/1]). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_webmachine.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_webmachine.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/src/rabbit_webmachine.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/src/rabbit_webmachine.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,7 +1,7 @@ %% This file contains an adapted version of webmachine_mochiweb:loop/1 %% from webmachine (revision 0c4b60ac68b4). -%% All modifications are (C) 2011 VMware, Inc. +%% All modifications are (C) 2011-2012 VMware, Inc. -module(rabbit_webmachine). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,3 +1,19 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. +%% + -module(rabbit_mochiweb_test). -include_lib("eunit/include/eunit.hrl"). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test_unit.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test_unit.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test_unit.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-mochiweb/test/src/rabbit_mochiweb_test_unit.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,22 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 Original Code is RabbitMQ Mochiweb Embedding. -%% -%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. -%% -%% Copyright (C) 2011 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mochiweb_test_unit). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/README 2012-03-19 10:36:09.000000000 +0000 @@ -109,18 +109,19 @@ needs specifying. Using 'brokers' allows a list of brokers to be specified: whenever the connection to a broker is lost, another one is chosen at random from the list and a connection attempt is made to -that. The syntax for broker URIs is: +that. The syntax for broker URIs is amqp://username:password@host:port/vhost?key1=value1&key2=value2... -If username or password are omitted, the default values of guest and -guest are used. If the vhost is omitted, the default value of / is -used. If the host is omitted, then the plugin uses the "direct" -connection internally rather than a network connection: this means it -connects to the RabbitMQ-server node on which it is running without -going through the network stack. This is much more efficient. If port -is omitted then the default value is used (5672 or 5671 if SSL is -used). +and is based on the AMQP URI scheme specified at +http://www.rabbitmq.com/uri-spec.html. If username or password are +omitted, the default values of guest and guest are used. If the vhost +is omitted, the default value of / is used. If the host is omitted, +then the plugin uses the "direct" connection internally rather than a +network connection: this means it connects to the RabbitMQ-server node +on which it is running without going through the network stack. This +is much more efficient. If port is omitted then the default value is +used (5672 or 5671 if SSL is used). SSL is implemented, for which additional parameters are needed: @@ -263,11 +264,14 @@ Obtaining shovel statuses ------------------------- -From the broker Erlang prompt, call -rabbit_shovel_status:status(). This will return a list, with one row -for each configured shovel. Each row has three fields: the shovel -name, the shovel status, and the timestamp (a local calendar time of -{{YYYY,MM,DD},{HH,MM,SS}}). There are 3 possible statuses: +Invoke: + +$ rabbitmqctl eval 'rabbit_shovel_status:status().' + +This will return a list, with one row for each configured shovel. Each +row has three fields: the shovel name, the shovel status, and the +timestamp (a local calendar time of {{YYYY,MM,DD},{HH,MM,SS}}). There +are 3 possible statuses: 'starting': The shovel is starting up, connecting and creating resources. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/include/rabbit_shovel.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/include/rabbit_shovel.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/include/rabbit_shovel.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/include/rabbit_shovel.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -record(endpoint, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_shovel). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel_status.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel_status.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel_status.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel_status.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_shovel_status). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_shovel_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel_worker.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel_worker.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/src/rabbit_shovel_worker.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/src/rabbit_shovel_worker.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_shovel_worker). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/test/src/rabbit_shovel_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/test/src/rabbit_shovel_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel/test/src/rabbit_shovel_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel/test/src/rabbit_shovel_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_shovel_test). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel-management/README rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel-management/README --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel-management/README 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel-management/README 2012-03-19 10:36:09.000000000 +0000 @@ -1,6 +1,5 @@ Adds information on shovel status to the management plugin. Build it -like any other plugin. You need branch bug23890 of rabbitmq-mochiweb -and rabbitmq-management. +like any other plugin. If you have a heterogenous cluster (where the nodes have different plugins installed), this should be installed on the same nodes as the diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel-management/src/rabbit_shovel_mgmt.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel-management/src/rabbit_shovel_mgmt.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-shovel-management/src/rabbit_shovel_mgmt.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-shovel-management/src/rabbit_shovel_mgmt.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_shovel_mgmt). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/compat rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/compat --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/compat 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -5 diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/control rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/control --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/control 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/control 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -Source: rabbitmq-stomp -Section: net -Priority: extra -Maintainer: Tony Garnock-Jones -Build-Depends: debhelper (>= 7), erlang-dev, ejabberd -Standards-Version: 3.8.1 -Homepage: http://www.rabbitmq.com/ -Vcs-Browser: http://hg.rabbitmq.com/rabbitmq-stomp - -Package: rabbitmq-stomp -Architecture: all -Depends: rabbitmq-server -Description: A STOMP (Simple Text-Oriented Messaging Protocol) gateway for RabbitMQ diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/copyright rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/copyright --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/copyright 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/copyright 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -This package was debianized by Tony Garnock-Jones on -Tue, 14 Jul 2009 17:35:50 +0100. - -Upstream Author: Tony Garnock-Jones - -Copyright: 2009 Tony Garnock-Jones, 2009 LShift Ltd. - -License: The RabbitMQ STOMP gateway is open-source software, licensed under -the MPL 1.1: - - 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): ______________________________________. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.docs rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.docs --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.docs 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -README -examples diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.install rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.install --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.install 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/rabbitmq-stomp.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/rules rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/rules --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/debian/rules 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/debian/rules 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#!/usr/bin/make -f - -# Common useful variables (from cdbs) -DEB_SOURCE_PACKAGE := $(strip $(shell egrep '^Source: ' debian/control | cut -f 2 -d ':')) -DEB_VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ') -DEB_NOEPOCH_VERSION := $(shell echo $(DEB_VERSION) | cut -d: -f2-) -DEB_UPSTREAM_VERSION := $(shell echo $(DEB_NOEPOCH_VERSION) | sed 's/-[^-]*$$//') -DEB_ISNATIVE := $(shell dpkg-parsechangelog | egrep '^Version:' | perl -ne 'print if not /^Version:\s*.*-/;') - -DESTDIR=$(CURDIR)/debian/tmp -TARGET_DIR=usr/lib/erlang/lib/rabbitmq-stomp-$(DEB_UPSTREAM_VERSION) - -build: build-stamp -build-stamp: - dh build --before auto_test - dh build --after auto_test - touch build-stamp - -clean: - dh clean - rm -f build-stamp - rm -f install-stamp - -install: build install-stamp -install-stamp: - dh install --sourcedir=$(DESTDIR) --before=auto_install - install -d $(DESTDIR)/$(TARGET_DIR)/ebin - install -d $(DESTDIR)/$(TARGET_DIR)/include - install ebin/*.beam $(DESTDIR)/$(TARGET_DIR)/ebin - install include/*.hrl $(DESTDIR)/$(TARGET_DIR)/include - dh install --sourcedir=$(DESTDIR) --after=auto_install - touch install-stamp - -binary-arch: install - dh binary-arch - -binary-indep: install - dh binary-indep - -binary: binary-arch binary-indep diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,8 +11,10 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -record(stomp_configuration, {default_login, default_passcode, - implicit_connect}). + implicit_connect, + ssl_cert_login}). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp_frame.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp_frame.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp_frame.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp_frame.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -1,31 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -record(stomp_frame, {command, headers, body_iolist}). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp_headers.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp_headers.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp_headers.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp_headers.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -define(HEADER_ACCEPT_VERSION, "accept-version"). @@ -31,9 +31,11 @@ -define(HEADER_PRIORITY, "priority"). -define(HEADER_RECEIPT, "receipt"). -define(HEADER_REPLY_TO, "reply-to"). +-define(HEADER_SERVER, "server"). -define(HEADER_SESSION, "session"). -define(HEADER_VERSION, "version"). -define(MESSAGE_ID_SEPARATOR, "@@"). --define(HEADERS_NOT_ON_SEND, [?HEADER_MESSAGE_ID]). \ No newline at end of file +-define(HEADERS_NOT_ON_SEND, [?HEADER_MESSAGE_ID]). + diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp_prefixes.hrl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp_prefixes.hrl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/include/rabbit_stomp_prefixes.hrl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/include/rabbit_stomp_prefixes.hrl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -define(QUEUE_PREFIX, "/queue"). @@ -25,3 +25,5 @@ -define(VALID_DEST_PREFIXES, [?EXCHANGE_PREFIX, ?TOPIC_PREFIX, ?QUEUE_PREFIX, ?AMQQUEUE_PREFIX, ?TEMP_QUEUE_PREFIX, ?REPLY_QUEUE_PREFIX]). + +-define(TEMP_QUEUE_ID_PREFIX, "/temp-queue/"). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/package.mk rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/package.mk --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/package.mk 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/package.mk 2012-03-19 10:36:09.000000000 +0000 @@ -2,7 +2,7 @@ DEPS:=rabbitmq-server rabbitmq-erlang-client STANDALONE_TEST_COMMANDS:=eunit:test([rabbit_stomp_test_util,rabbit_stomp_test_frame],[verbose]) WITH_BROKER_TEST_SCRIPTS:=$(PACKAGE_DIR)/test/src/test.py $(PACKAGE_DIR)/test/src/test_connect_options.py -WITH_BROKER_TEST_COMMANDS:=rabbit_stomp_amqqueue_test:all_tests() +WITH_BROKER_TEST_COMMANDS:=rabbit_stomp_test:all_tests() rabbit_stomp_amqqueue_test:all_tests() RABBITMQ_TEST_PATH=$(PACKAGE_DIR)/../../rabbitmq-test ABS_PACKAGE_DIR:=$(abspath $(PACKAGE_DIR)) @@ -13,13 +13,15 @@ TEST_CONFIG_PATH=$(TEST_EBIN_DIR)/test.config WITH_BROKER_TEST_CONFIG:=$(TEST_EBIN_DIR)/test +.PHONY: $(TEST_CONFIG_PATH) + ifeq ($(CAN_RUN_SSL),true) WITH_BROKER_TEST_SCRIPTS += $(PACKAGE_DIR)/test/src/test_ssl.py $(TEST_CONFIG_PATH): $(CERTS_DIR) $(ABS_PACKAGE_DIR)/test/src/ssl.config sed -e "s|%%CERTS_DIR%%|$(CERTS_DIR)|g" < $(ABS_PACKAGE_DIR)/test/src/ssl.config > $@ - @echo "Running SSL tests" $(WITH_BROKER_TEST_CONFIG) + @echo "\nRunning SSL tests\n" $(CERTS_DIR): mkdir -p $(CERTS_DIR) @@ -28,7 +30,7 @@ else $(TEST_CONFIG_PATH): $(ABS_PACKAGE_DIR)/test/src/non_ssl.config cp $(ABS_PACKAGE_DIR)/test/src/non_ssl.config $@ - @echo "NOT running SSL tests" $(WITH_BROKER_TEST_CONFIG) + @echo "\nNOT running SSL tests - looked in $(RABBITMQ_TEST_PATH) \n" endif diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,33 +1,19 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp). -include("rabbit_stomp.hrl"). @@ -39,41 +25,31 @@ #stomp_configuration{ default_login = undefined, default_passcode = undefined, - implicit_connect = false}). + implicit_connect = false, + ssl_cert_login = false}). start(normal, []) -> Config = parse_configuration(), Listeners = parse_listener_configuration(), - io:format("starting ~s (binding to ~p) ...", - ["STOMP Adapter", Listeners]), - {ok, SupPid} = rabbit_stomp_sup:start_link(Listeners, Config), - io:format("done~n"), - {ok, SupPid}. + rabbit_stomp_sup:start_link(Listeners, Config). stop(_State) -> ok. parse_listener_configuration() -> - case application:get_env(tcp_listeners) of - undefined -> - throw({error, {stomp_configuration_not_found}}); - {ok, Listeners} -> - case application:get_env(ssl_listeners) of - undefined -> {Listeners, []}; - {ok, SslListeners} -> {Listeners, SslListeners} - end - end. + {ok, Listeners} = application:get_env(tcp_listeners), + {ok, SslListeners} = application:get_env(ssl_listeners), + {Listeners, SslListeners}. parse_configuration() -> - Configuration = - case application:get_env(default_user) of - undefined -> - ?DEFAULT_CONFIGURATION; - {ok, UserConfig} -> - parse_default_user(UserConfig, ?DEFAULT_CONFIGURATION) - end, - report_configuration(Configuration), - Configuration. + {ok, UserConfig} = application:get_env(default_user), + Conf0 = parse_default_user(UserConfig, ?DEFAULT_CONFIGURATION), + {ok, SSLLogin} = application:get_env(ssl_cert_login), + {ok, ImplicitConnect} = application:get_env(implicit_connect), + Conf = Conf0#stomp_configuration{ssl_cert_login = SSLLogin, + implicit_connect = ImplicitConnect}, + report_configuration(Conf), + Conf. parse_default_user([], Configuration) -> Configuration; @@ -83,29 +59,29 @@ parse_default_user([{passcode, Passcode} | Rest], Configuration) -> parse_default_user(Rest, Configuration#stomp_configuration{ default_passcode = Passcode}); -parse_default_user([implicit_connect | Rest], Configuration) -> - parse_default_user(Rest, Configuration#stomp_configuration{ - implicit_connect = true}); parse_default_user([Unknown | Rest], Configuration) -> - error_logger:error_msg("Invalid default_user configuration option: ~p~n", - [Unknown]), + rabbit_log:warning("rabbit_stomp: ignoring invalid default_user " + "configuration option: ~p~n", [Unknown]), parse_default_user(Rest, Configuration). report_configuration(#stomp_configuration{ default_login = Login, - implicit_connect = ImplicitConnect}) -> + implicit_connect = ImplicitConnect, + ssl_cert_login = SSLCertLogin}) -> case Login of - undefined -> - ok; - _ -> - error_logger:info_msg("Default user '~s' enabled~n", [Login]) + undefined -> ok; + _ -> rabbit_log:info("rabbit_stomp: default user '~s' " + "enabled~n", [Login]) end, case ImplicitConnect of - true -> error_logger:info_msg("Implicit connect enabled~n"); + true -> rabbit_log:info("rabbit_stomp: implicit connect enabled~n"); false -> ok end, - ok. - + case SSLCertLogin of + true -> rabbit_log:info("rabbit_stomp: ssl_cert_login enabled~n"); + false -> ok + end, + ok. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_client_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_client_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_client_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_client_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,59 +1,50 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_client_sup). -behaviour(supervisor2). -define(MAX_WAIT, 16#ffffffff). --export([start_link/2, init/1]). +-export([start_link/1, start_processor/2, init/1]). -start_link(Sock, Configuration) -> +start_link(Configuration) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), - {ok, ProcessorPid} = - supervisor2:start_child(SupPid, - {rabbit_stomp_processor, - {rabbit_stomp_processor, start_link, - [Sock, - rabbit_heartbeat:start_heartbeat_fun(SupPid), - Configuration]}, - intrinsic, ?MAX_WAIT, worker, - [rabbit_stomp_processor]}), + %% We want the reader to be transient since when it exits normally + %% the processor may have some work still to do (and the reader + %% tells the processor to exit). However, if the reader terminates + %% abnormally then we want to take everything down. + %% + %% The *processor* however is intrinsic, so when it exits, the + %% supervisor goes too. {ok, ReaderPid} = supervisor2:start_child(SupPid, {rabbit_stomp_reader, {rabbit_stomp_reader, - start_link, [ProcessorPid]}, - temporary, ?MAX_WAIT, worker, + start_link, [SupPid, Configuration]}, + transient, ?MAX_WAIT, worker, [rabbit_stomp_reader]}), {ok, SupPid, ReaderPid}. +start_processor(SupPid, Args) -> + supervisor2:start_child(SupPid, + {rabbit_stomp_processor, + {rabbit_stomp_processor, start_link, [Args]}, + intrinsic, ?MAX_WAIT, worker, + [rabbit_stomp_processor]}). + init([]) -> {ok, {{one_for_all, 0, 1}, []}}. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_frame.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_frame.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_frame.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_frame.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% stomp_frame implements the STOMP framing protocol "version 1.0", as diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_processor.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_processor.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_processor.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_processor.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,37 +1,23 @@ -%% 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/ +%% 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. +%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_processor). -behaviour(gen_server2). --export([start_link/3, process_frame/2, flush_and_die/1]). +-export([start_link/1, process_frame/2, flush_and_die/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]). @@ -41,10 +27,10 @@ -include("rabbit_stomp_prefixes.hrl"). -include("rabbit_stomp_headers.hrl"). --record(state, {socket, session_id, channel, - connection, subscriptions, version, - start_heartbeat_fun, pending_receipts, - config, reply_queues, frame_transformer}). +-record(state, {session_id, channel, connection, subscriptions, + version, start_heartbeat_fun, pending_receipts, + config, dest_queues, reply_queues, frame_transformer, + adapter_info, send_fun, ssl_login_name}). -record(subscription, {dest_hdr, channel, multi_ack, description}). @@ -54,12 +40,14 @@ %%---------------------------------------------------------------------------- %% Public API %%---------------------------------------------------------------------------- -start_link(Sock, StartHeartbeatFun, Configuration) -> - gen_server2:start_link(?MODULE, [Sock, StartHeartbeatFun, Configuration], - []). +start_link(Args) -> + gen_server2:start_link(?MODULE, Args, []). +process_frame(Pid, Frame = #stomp_frame{command = "SEND"}) -> + credit_flow:send(Pid), + gen_server2:cast(Pid, {"SEND", Frame, self()}); process_frame(Pid, Frame = #stomp_frame{command = Command}) -> - gen_server2:cast(Pid, {Command, Frame}). + gen_server2:cast(Pid, {Command, Frame, noflow}). flush_and_die(Pid) -> gen_server2:cast(Pid, flush_and_die). @@ -68,11 +56,10 @@ %% Basic gen_server2 callbacks %%---------------------------------------------------------------------------- -init([Sock, StartHeartbeatFun, Configuration]) -> +init([SendFun, AdapterInfo, StartHeartbeatFun, SSLLoginName, Configuration]) -> process_flag(trap_exit, true), {ok, #state { - socket = Sock, session_id = none, channel = none, connection = none, @@ -81,8 +68,12 @@ start_heartbeat_fun = StartHeartbeatFun, pending_receipts = undefined, config = Configuration, + dest_queues = sets:new(), reply_queues = dict:new(), - frame_transformer = undefined}, + frame_transformer = undefined, + adapter_info = AdapterInfo, + send_fun = SendFun, + ssl_login_name = SSLLoginName}, hibernate, {backoff, 1000, 1000, 10000} }. @@ -93,18 +84,21 @@ handle_cast(flush_and_die, State) -> {stop, normal, close_connection(State)}; -handle_cast({"STOMP", Frame}, State) -> +handle_cast({"STOMP", Frame, noflow}, State) -> process_connect(no_implicit, Frame, State); -handle_cast({"CONNECT", Frame}, State) -> +handle_cast({"CONNECT", Frame, noflow}, State) -> process_connect(no_implicit, Frame, State); handle_cast(Request, State = #state{channel = none, config = #stomp_configuration{ implicit_connect = true}}) -> - {noreply, State1, _} = + {noreply, State1 = #state{channel = Ch}, _} = process_connect(implicit, #stomp_frame{headers = []}, State), - handle_cast(Request, State1); + case Ch of + none -> {stop, normal, State1}; + _ -> handle_cast(Request, State1) + end; handle_cast(_Request, State = #state{channel = none, config = #stomp_configuration{ @@ -115,7 +109,12 @@ State), hibernate}; -handle_cast({Command, Frame}, State = #state{frame_transformer = FT}) -> +handle_cast({Command, Frame, FlowPid}, + State = #state{frame_transformer = FT}) -> + case FlowPid of + noflow -> ok; + _ -> credit_flow:ack(FlowPid) + end, Frame1 = FT(Frame), process_request( fun(StateN) -> @@ -139,8 +138,19 @@ handle_info({Delivery = #'basic.deliver'{}, #amqp_msg{props = Props, payload = Payload}}, State) -> {noreply, send_delivery(Delivery, Props, Payload, State), hibernate}; +handle_info({'EXIT', Conn, + {shutdown, {server_initiated_close, Code, Explanation}}}, + State = #state{connection = Conn}) -> + amqp_death(Code, Explanation, State); +handle_info({'EXIT', Conn, Reason}, State = #state{connection = Conn}) -> + send_error("AMQP connection died", "Reason: ~p", [Reason], State), + {stop, {conn_died, Reason}, State}; handle_info({inet_reply, _, ok}, State) -> {noreply, State, hibernate}; +handle_info({bump_credit, Msg}, State) -> + credit_flow:handle_bump_msg(Msg), + {noreply, State, hibernate}; + handle_info({inet_reply, _, Status}, State) -> {stop, Status, State}. @@ -171,39 +181,28 @@ {stop, R, NewState} end. -process_connect(Implicit, - Frame, - State = #state{ - channel = none, - socket = Sock, - config = #stomp_configuration{ - default_login = DefaultLogin, - default_passcode = DefaultPasscode}}) -> +process_connect(Implicit, Frame, + State = #state{channel = none, + config = Config, + ssl_login_name = SSLLoginName, + adapter_info = AdapterInfo}) -> process_request( fun(StateN) -> case negotiate_version(Frame) of {ok, Version} -> FT = frame_transformer(Version), Frame1 = FT(Frame), + {Username, Creds} = creds(Frame1, SSLLoginName, Config), {ok, DefaultVHost} = application:get_env(rabbit, default_vhost), + {ProtoName, _} = AdapterInfo#adapter_info.protocol, Res = do_login( - rabbit_stomp_frame:header(Frame1, - ?HEADER_LOGIN, - DefaultLogin), - rabbit_stomp_frame:header(Frame1, - ?HEADER_PASSCODE, - DefaultPasscode), - rabbit_stomp_frame:header(Frame1, - ?HEADER_HOST, - binary_to_list( - DefaultVHost)), - rabbit_stomp_frame:header(Frame1, - ?HEADER_HEART_BEAT, - "0,0"), - adapter_info(Sock, Version), - Version, - StateN#state{frame_transformer = FT}), + Username, Creds, + login_header(Frame1, ?HEADER_HOST, DefaultVHost), + login_header(Frame1, ?HEADER_HEART_BEAT, "0,0"), + AdapterInfo#adapter_info{ + protocol = {ProtoName, Version}}, Version, + StateN#state{frame_transformer = FT}), case {Res, Implicit} of {{ok, _, StateN1}, implicit} -> ok(StateN1); _ -> Res @@ -218,6 +217,26 @@ fun(StateM) -> StateM end, State). +creds(Frame, SSLLoginName, + #stomp_configuration{default_login = DefLogin, + default_passcode = DefPasscode}) -> + PasswordCreds = {login_header(Frame, ?HEADER_LOGIN, DefLogin), + [{password, login_header( + Frame, ?HEADER_PASSCODE, DefPasscode)}]}, + case {rabbit_stomp_frame:header(Frame, ?HEADER_LOGIN), SSLLoginName} of + {not_found, none} -> PasswordCreds; + {not_found, SSLName} -> {SSLName, []}; + _ -> PasswordCreds + end. + +login_header(Frame, Key, Default) when is_binary(Default) -> + login_header(Frame, Key, binary_to_list(Default)); +login_header(Frame, Key, Default) -> + case rabbit_stomp_frame:header(Frame, Key, Default) of + undefined -> undefined; + Hdr -> list_to_binary(Hdr) + end. + %%---------------------------------------------------------------------------- %% Frame Transformation %%---------------------------------------------------------------------------- @@ -257,8 +276,8 @@ handle_frame("SEND", Frame, State) -> without_headers(?HEADERS_NOT_ON_SEND, "SEND", Frame, State, - fun (Command, Frame, State) -> - with_destination("SEND", Frame, State, fun do_send/4) + fun (_Command, Frame1, State1) -> + with_destination("SEND", Frame1, State1, fun do_send/4) end); handle_frame("ACK", Frame, State) -> @@ -321,6 +340,12 @@ %% Internal helpers for processing frames callbacks %%---------------------------------------------------------------------------- +cancel_subscription({error, invalid_prefix}, _Frame, State) -> + error("Invalid id", + "UNSUBSCRIBE 'id' may not start with ~s~n", + [?TEMP_QUEUE_ID_PREFIX], + State); + cancel_subscription({error, _}, _Frame, State) -> error("Missing destination or id", "UNSUBSCRIBE must include a 'destination' or 'id' header\n", @@ -423,90 +448,54 @@ do_login(undefined, _, _, _, _, _, State) -> error("Bad CONNECT", "Missing login or passcode header(s)\n", State); - -do_login(Username0, Password0, VirtualHost0, Heartbeat, AdapterInfo, - Version, State) -> - Username = list_to_binary(Username0), - Password = list_to_binary(Password0), - VirtualHost = list_to_binary(VirtualHost0), - case rabbit_access_control:check_user_pass_login(Username, Password) of +do_login(Username, Creds, VirtualHost, Heartbeat, AdapterInfo, Version, + State) -> + case rabbit_access_control:check_user_login(Username, Creds) of {ok, _User} -> case amqp_connection:start( #amqp_params_direct{username = Username, virtual_host = VirtualHost, adapter_info = AdapterInfo}) of {ok, Connection} -> + link(Connection), {ok, Channel} = amqp_connection:open_channel(Connection), - SessionId = rabbit_guid:string_guid("session"), + SessionId = + rabbit_guid:string(rabbit_guid:gen_secure(), "session"), {{SendTimeout, ReceiveTimeout}, State1} = ensure_heartbeats(Heartbeat, State), ok("CONNECTED", [{?HEADER_SESSION, SessionId}, {?HEADER_HEART_BEAT, io_lib:format("~B,~B", [SendTimeout, ReceiveTimeout])}, + {?HEADER_SERVER, server_header()}, {?HEADER_VERSION, Version}], "", State1#state{session_id = SessionId, channel = Channel, connection = Connection}); {error, auth_failure} -> + rabbit_log:error("STOMP login failed - auth_failure " + "(user vanished)~n"), error("Bad CONNECT", "Authentication failure\n", State); {error, access_refused} -> + rabbit_log:warning("STOMP login failed - access_refused " + "(vhost access not allowed)~n"), error("Bad CONNECT", "Authentication failure\n", State) end; - {refused, _Msg, _Args} -> + {refused, Msg, Args} -> + rabbit_log:warning("STOMP login failed: " ++ Msg ++ "\n", Args), error("Bad CONNECT", "Authentication failure\n", State) end. -adapter_info(Sock, Version) -> - {Addr, Port} = case rabbit_net:sockname(Sock) of - {ok, Res} -> Res; - _ -> {unknown, unknown} - end, - {PeerAddr, PeerPort} = case rabbit_net:peername(Sock) of - {ok, Res2} -> Res2; - _ -> {unknown, unknown} - end, - #adapter_info{protocol = {'STOMP', Version}, - address = Addr, - port = Port, - peer_address = PeerAddr, - peer_port = PeerPort, - additional_info = maybe_ssl_info(Sock)}. - -maybe_ssl_info(Sock) -> - case rabbit_net:is_ssl(Sock) of - true -> [{ssl, true}] ++ ssl_info(Sock) ++ ssl_cert_info(Sock); - false -> [{ssl, false}] - end. - -ssl_info(Sock) -> - {Protocol, KeyExchange, Cipher, Hash} = - case rabbit_net:ssl_info(Sock) of - {ok, {P, {K, C, H}}} -> {P, K, C, H}; - {ok, {P, {K, C, H, _}}} -> {P, K, C, H}; - _ -> {unknown, unknown, unknown, unknown} - end, - [{ssl_protocol, Protocol}, - {ssl_key_exchange, KeyExchange}, - {ssl_cipher, Cipher}, - {ssl_hash, Hash}]. - -ssl_cert_info(Sock) -> - case rabbit_net:peercert(Sock) of - {ok, Cert} -> - [{peer_cert_issuer, list_to_binary( - rabbit_ssl:peer_cert_issuer(Cert))}, - {peer_cert_subject, list_to_binary( - rabbit_ssl:peer_cert_subject(Cert))}, - {peer_cert_validity, list_to_binary( - rabbit_ssl:peer_cert_validity(Cert))}]; - _ -> - [] - end. +server_header() -> + Props = rabbit_reader:server_properties(?PROTOCOL), + {_, Product} = rabbit_misc:table_lookup(Props, <<"product">>), + {_, Version} = rabbit_misc:table_lookup(Props, <<"version">>), + rabbit_misc:format("~s/~s", [Product, Version]). do_subscribe(Destination, DestHdr, Frame, State = #state{subscriptions = Subs, + dest_queues = DestQs, connection = Connection, channel = MainChannel}) -> Prefetch = @@ -526,7 +515,8 @@ {AckMode, IsMulti} = rabbit_stomp_util:ack_mode(Frame), - {ok, Queue} = ensure_queue(subscribe, Destination, Frame, Channel), + {ok, Queue, DestQs1} = ensure_queue(subscribe, Destination, Frame, Channel, + DestQs), {ok, ConsumerTag, Description} = rabbit_stomp_util:consumer_tag(Frame), @@ -547,14 +537,16 @@ channel = Channel, multi_ack = IsMulti, description = Description}, - Subs)}). + Subs), + dest_queues = DestQs1}). do_send(Destination, _DestHdr, Frame = #stomp_frame{body_iolist = BodyFragments}, - State = #state{channel = Channel}) -> - {ok, _Q} = ensure_queue(send, Destination, Frame, Channel), + State = #state{channel = Channel, dest_queues = DestQs}) -> + {ok, _Q, DestQs1} = ensure_queue(send, Destination, Frame, Channel, DestQs), - {Frame1, State1} = ensure_reply_to(Frame, State), + {Frame1, State1} = + ensure_reply_to(Frame, State#state{dest_queues = DestQs1}), Props = rabbit_stomp_util:message_properties(Frame1), @@ -625,8 +617,9 @@ State = #state{channel = Channel}) -> send_method(Method, Channel, Properties, BodyFragments, State). -send_method(Method, Channel, Properties, BodyFragments, State) -> - amqp_channel:call( +send_method(Method = #'basic.publish'{}, Channel, Properties, BodyFragments, + State) -> + amqp_channel:cast_flow( Channel, Method, #amqp_msg{props = Properties, payload = list_to_binary(BodyFragments)}), @@ -673,12 +666,14 @@ #'queue.declare'{auto_delete = true, exclusive = true}), - #'basic.consume_ok'{consumer_tag = ConsumerTag} = + ConsumerTag = rabbit_stomp_util:consumer_tag_reply_to(TempQueueId), + #'basic.consume_ok'{} = amqp_channel:subscribe(Channel, #'basic.consume'{ - queue = Queue, - no_ack = true, - nowait = false}, + queue = Queue, + consumer_tag = ConsumerTag, + no_ack = true, + nowait = false}, self()), Destination = reply_to_destination(Queue), @@ -847,18 +842,19 @@ %%-------------------------------------------------------------------- ensure_heartbeats(Heartbeats, - State = #state{socket = Sock, start_heartbeat_fun = SHF}) -> + State = #state{start_heartbeat_fun = SHF, + send_fun = RawSendFun}) -> [CX, CY] = [list_to_integer(X) || X <- re:split(Heartbeats, ",", [{return, list}])], - SendFun = fun() -> catch rabbit_net:send(Sock, <<$\n>>) end, + SendFun = fun() -> RawSendFun(sync, <<$\n>>) end, Pid = self(), ReceiveFun = fun() -> gen_server2:cast(Pid, client_timeout) end, {SendTimeout, ReceiveTimeout} = {millis_to_seconds(CY), millis_to_seconds(CX)}, - SHF(Sock, SendTimeout, SendFun, ReceiveTimeout, ReceiveFun), + SHF(SendTimeout, SendFun, ReceiveTimeout, ReceiveFun), {{SendTimeout * 1000 , ReceiveTimeout * 1000}, State}. @@ -870,24 +866,29 @@ %% Queue and Binding Setup %%---------------------------------------------------------------------------- -ensure_queue(subscribe, {exchange, _}, _Frame, Channel) -> +ensure_queue(subscribe, {exchange, _}, _Frame, Channel, DestQs) -> %% Create anonymous, exclusive queue for SUBSCRIBE on /exchange destinations #'queue.declare_ok'{queue = Queue} = amqp_channel:call(Channel, #'queue.declare'{auto_delete = true, exclusive = true}), - {ok, Queue}; -ensure_queue(send, {exchange, _}, _Frame, _Channel) -> + {ok, Queue, DestQs}; +ensure_queue(send, {exchange, _}, _Frame, _Channel, DestQs) -> %% Don't create queues on SEND for /exchange destinations - {ok, undefined}; -ensure_queue(_, {queue, Name}, _Frame, Channel) -> - %% Always create named queue for /queue destinations + {ok, undefined, DestQs}; +ensure_queue(_, {queue, Name}, _Frame, Channel, DestQs) -> + %% Always create named queue for /queue destinations the first + %% time we encounter it Queue = list_to_binary(Name), - amqp_channel:cast(Channel, - #'queue.declare'{durable = true, - queue = Queue, - nowait = true}), - {ok, Queue}; -ensure_queue(subscribe, {topic, Name}, Frame, Channel) -> + DestQs1 = case sets:is_element(Queue, DestQs) of + true -> DestQs; + false -> amqp_channel:cast(Channel, + #'queue.declare'{durable = true, + queue = Queue, + nowait = true}), + sets:add_element(Queue, DestQs) + end, + {ok, Queue, DestQs1}; +ensure_queue(subscribe, {topic, Name}, Frame, Channel, DestQs) -> %% Create queue for SUBSCRIBE on /topic destinations Queues are %% anonymous, auto_delete and exclusive for transient %% subscriptions. Durable subscriptions get shared, named, durable @@ -905,13 +906,13 @@ #'queue.declare_ok'{queue = Queue} = amqp_channel:call(Channel, Method), - {ok, Queue}; -ensure_queue(send, {topic, _}, _Frame, _Channel) -> + {ok, Queue, DestQs}; +ensure_queue(send, {topic, _}, _Frame, _Channel, DestQs) -> %% Don't create queues on SEND for /topic destinations - {ok, undefined}; -ensure_queue(_, {Type, Name}, _Frame, _Channel) + {ok, undefined, DestQs}; +ensure_queue(_, {Type, Name}, _Frame, _Channel, DestQs) when Type =:= reply_queue orelse Type =:= amqqueue -> - {ok, list_to_binary(Name)}. + {ok, list_to_binary(Name), DestQs}. ensure_queue_binding(QueueBin, {"", Queue}, _Channel) -> %% i.e., we should only be asked to bind to the default exchange a @@ -940,10 +941,9 @@ amqp_death(ReplyCode, Explanation, State) -> ErrorName = ?PROTOCOL:amqp_exception(ReplyCode), - {stop, amqp_death, - send_error(atom_to_list(ErrorName), - format_detail("~s~n", [Explanation]), - State)}. + ErrorDesc = rabbit_misc:format("~s~n", [Explanation]), + log_error(ErrorName, ErrorDesc, none), + {stop, normal, send_error(atom_to_list(ErrorName), ErrorDesc, State)}. error(Message, Detail, State) -> priv_error(Message, Detail, none, State). @@ -952,19 +952,20 @@ priv_error(Message, Format, Args, none, State). priv_error(Message, Detail, ServerPrivateDetail, State) -> - error_logger:error_msg("STOMP error frame sent:~n" ++ - "Message: ~p~n" ++ - "Detail: ~p~n" ++ - "Server private detail: ~p~n", - [Message, Detail, ServerPrivateDetail]), + log_error(Message, Detail, ServerPrivateDetail), {error, Message, Detail, State}. priv_error(Message, Format, Args, ServerPrivateDetail, State) -> - priv_error(Message, format_detail(Format, Args), - ServerPrivateDetail, State). + priv_error(Message, rabbit_misc:format(Format, Args), ServerPrivateDetail, + State). + +log_error(Message, Detail, ServerPrivateDetail) -> + rabbit_log:error("STOMP error frame sent:~n" + "Message: ~p~n" + "Detail: ~p~n" + "Server private detail: ~p~n", + [Message, Detail, ServerPrivateDetail]). -format_detail(Format, Args) -> - lists:flatten(io_lib:format(Format, Args)). %%---------------------------------------------------------------------------- %% Frame sending utilities %%---------------------------------------------------------------------------- @@ -974,11 +975,8 @@ body_iolist = BodyFragments}, State). -send_frame(Frame, State = #state{socket = Sock}) -> - %% We ignore certain errors here, as we will be receiving an - %% asynchronous notification of the same (or a related) fault - %% shortly anyway. See bug 21365. - catch rabbit_net:port_command(Sock, rabbit_stomp_frame:serialize(Frame)), +send_frame(Frame, State = #state{send_fun = SendFun}) -> + SendFun(async, rabbit_stomp_frame:serialize(Frame)), State. send_error(Message, Detail, State) -> @@ -988,7 +986,7 @@ Detail, State). send_error(Message, Format, Args, State) -> - send_error(Message, format_detail(Format, Args), State). + send_error(Message, rabbit_misc:format(Format, Args), State). %%---------------------------------------------------------------------------- %% Skeleton gen_server2 callbacks @@ -998,4 +996,3 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. - diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_reader.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_reader.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_reader.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_reader.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,68 +1,69 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_reader). --export([start_link/1]). --export([init/1]). +-export([start_link/2]). +-export([init/2]). -export([conserve_memory/2]). +-include("rabbit_stomp.hrl"). -include("rabbit_stomp_frame.hrl"). +-include_lib("amqp_client/include/amqp_client.hrl"). + +-record(reader_state, {socket, parse_state, processor, state, iterations, + conserve_memory}). --record(reader_state, {socket, parse_state, processor, state, iterations}). +%%---------------------------------------------------------------------------- -start_link(ProcessorPid) -> - {ok, proc_lib:spawn_link(?MODULE, init, [ProcessorPid])}. +start_link(SupPid, Configuration) -> + {ok, proc_lib:spawn_link(?MODULE, init, [SupPid, Configuration])}. -init(ProcessorPid) -> +log(Level, Fmt, Args) -> rabbit_log:log(connection, Level, Fmt, Args). + +init(SupPid, Configuration) -> receive - {go, Sock} -> - {ok, {PeerAddress, PeerPort}} = rabbit_net:peername(Sock), - PeerAddressS = inet_parse:ntoa(PeerAddress), - error_logger:info_msg("starting STOMP connection ~p from ~s:~p~n", - [self(), PeerAddressS, PeerPort]), + {go, Sock0, SockTransform} -> + {ok, Sock} = SockTransform(Sock0), + {ok, ProcessorPid} = start_processor(SupPid, Configuration, Sock), + {ok, ConnStr} = rabbit_net:connection_string(Sock, inbound), + log(info, "accepting STOMP connection ~p (~s)~n", + [self(), ConnStr]), ParseState = rabbit_stomp_frame:initial_state(), try mainloop( - register_memory_alarm( - #reader_state{socket = Sock, - parse_state = ParseState, - processor = ProcessorPid, - state = running, - iterations = 0}), 0) + control_throttle( + register_memory_alarm( + #reader_state{socket = Sock, + parse_state = ParseState, + processor = ProcessorPid, + state = running, + iterations = 0, + conserve_memory = false})), 0), + log(info, "closing STOMP connection ~p (~s)~n", + [self(), ConnStr]) + catch + Ex -> log(error, "closing STOMP connection ~p (~s):~n~p~n", + [self(), ConnStr, Ex]) after - rabbit_stomp_processor:flush_and_die(ProcessorPid), - error_logger:info_msg("ending STOMP connection ~p from ~s:~p~n", - [self(), PeerAddressS, PeerPort]) - end + rabbit_stomp_processor:flush_and_die(ProcessorPid) + end, + + done end. mainloop(State = #reader_state{socket = Sock}, ByteCount) -> @@ -70,16 +71,17 @@ receive {inet_async, Sock, _Ref, {ok, Data}} -> process_received_bytes(Data, State); - {inet_async, Sock, _Ref, {error, closed}} -> - error_logger:info_msg("Socket ~p closed by client~n", [Sock]), - ok; - {inet_async, Sock, _Ref, {error, Reason}} -> - error_logger:error_msg("Socket ~p closed abruptly with " - "error code ~p~n", - [Sock, Reason]), + {inet_async, _Sock, _Ref, {error, closed}} -> ok; + {inet_async, _Sock, _Ref, {error, Reason}} -> + throw({inet_error, Reason}); {conserve_memory, Conserve} -> - mainloop(internal_conserve_memory(Conserve, State), ByteCount) + mainloop( + control_throttle( + State#reader_state{conserve_memory = Conserve}), ByteCount); + {bump_credit, Msg} -> + credit_flow:handle_bump_msg(Msg), + mainloop(control_throttle(State), ByteCount) end. process_received_bytes([], State) -> @@ -96,9 +98,10 @@ rabbit_stomp_processor:process_frame(Processor, Frame), PS = rabbit_stomp_frame:initial_state(), process_received_bytes(Rest, - State#reader_state{ - parse_state = PS, - state = next_state(S, Frame)}) + control_throttle( + State#reader_state{ + parse_state = PS, + state = next_state(S, Frame)})) end. conserve_memory(Pid, Conserve) -> @@ -106,15 +109,16 @@ ok. register_memory_alarm(State) -> - internal_conserve_memory( - rabbit_alarm:register(self(), {?MODULE, conserve_memory, []}), State). + rabbit_alarm:register(self(), {?MODULE, conserve_memory, []}), State. -internal_conserve_memory(true, State = #reader_state{state = running}) -> - State#reader_state{state = blocking}; -internal_conserve_memory(false, State) -> - State#reader_state{state = running}; -internal_conserve_memory(_Conserve, State) -> - State. +control_throttle(State = #reader_state{state = CS, + conserve_memory = Mem}) -> + case {CS, Mem orelse credit_flow:blocked()} of + {running, true} -> State#reader_state{state = blocking}; + {blocking, false} -> State#reader_state{state = running}; + {blocked, false} -> State#reader_state{state = running}; + {_, _} -> State + end. next_state(blocking, #stomp_frame{command = "SEND"}) -> blocked; @@ -126,3 +130,94 @@ run_socket(#reader_state{socket = Sock}, ByteCount) -> rabbit_net:async_recv(Sock, ByteCount, infinity), ok. + +%%---------------------------------------------------------------------------- + +start_processor(SupPid, Configuration, Sock) -> + SendFun = fun (sync, IoData) -> + %% no messages emitted + catch rabbit_net:send(Sock, IoData); + (async, IoData) -> + %% {inet_reply, _, _} will appear soon + %% We ignore certain errors here, as we will be + %% receiving an asynchronous notification of the + %% same (or a related) fault shortly anyway. See + %% bug 21365. + catch rabbit_net:port_command(Sock, IoData) + end, + + StartHeartbeatFun = + fun (SendTimeout, SendFin, ReceiveTimeout, ReceiveFun) -> + SHF = rabbit_heartbeat:start_heartbeat_fun(SupPid), + SHF(Sock, SendTimeout, SendFin, ReceiveTimeout, ReceiveFun) + end, + + rabbit_stomp_client_sup:start_processor( + SupPid, [SendFun, adapter_info(Sock), StartHeartbeatFun, + ssl_login_name(Sock, Configuration), Configuration]). + + +adapter_info(Sock) -> + {Addr, Port} = case rabbit_net:sockname(Sock) of + {ok, Res} -> Res; + _ -> {unknown, unknown} + end, + {PeerAddr, PeerPort} = case rabbit_net:peername(Sock) of + {ok, Res2} -> Res2; + _ -> {unknown, unknown} + end, + Name = case rabbit_net:connection_string(Sock, inbound) of + {ok, Res3} -> Res3; + _ -> unknown + end, + #adapter_info{protocol = {'STOMP', 0}, + name = list_to_binary(Name), + address = Addr, + port = Port, + peer_address = PeerAddr, + peer_port = PeerPort, + additional_info = maybe_ssl_info(Sock)}. + +maybe_ssl_info(Sock) -> + case rabbit_net:is_ssl(Sock) of + true -> [{ssl, true}] ++ ssl_info(Sock) ++ ssl_cert_info(Sock); + false -> [{ssl, false}] + end. + +ssl_info(Sock) -> + {Protocol, KeyExchange, Cipher, Hash} = + case rabbit_net:ssl_info(Sock) of + {ok, {P, {K, C, H}}} -> {P, K, C, H}; + {ok, {P, {K, C, H, _}}} -> {P, K, C, H}; + _ -> {unknown, unknown, unknown, unknown} + end, + [{ssl_protocol, Protocol}, + {ssl_key_exchange, KeyExchange}, + {ssl_cipher, Cipher}, + {ssl_hash, Hash}]. + +ssl_cert_info(Sock) -> + case rabbit_net:peercert(Sock) of + {ok, Cert} -> + [{peer_cert_issuer, list_to_binary( + rabbit_ssl:peer_cert_issuer(Cert))}, + {peer_cert_subject, list_to_binary( + rabbit_ssl:peer_cert_subject(Cert))}, + {peer_cert_validity, list_to_binary( + rabbit_ssl:peer_cert_validity(Cert))}]; + _ -> + [] + end. + +ssl_login_name(_Sock, #stomp_configuration{ssl_cert_login = false}) -> + none; +ssl_login_name(Sock, #stomp_configuration{ssl_cert_login = true}) -> + case rabbit_net:peercert(Sock) of + {ok, C} -> case rabbit_ssl:peer_cert_auth_name(C) of + unsafe -> none; + not_found -> none; + Name -> Name + end; + {error, no_peercert} -> none; + nossl -> none + end. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,40 +1,25 @@ -%% 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/ +%% 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. %% -%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_sup). -behaviour(supervisor). -export([start_link/2, init/1]). --export([listener_started/3, listener_stopped/3, - start_client/2, start_ssl_client/3]). +-export([start_client/2, start_ssl_client/3]). start_link(Listeners, Configuration) -> supervisor:start_link({local, ?MODULE}, ?MODULE, @@ -62,46 +47,34 @@ listener_specs(Fun, Args, Listeners) -> [Fun([Address | Args]) || Listener <- Listeners, - Address <- rabbit_networking:check_tcp_listener_address( - rabbit_stomp_listener_sup, Listener)]. + Address <- rabbit_networking:tcp_listener_addresses(Listener)]. tcp_listener_spec([Address, SocketOpts, Configuration]) -> - listener_spec(Address, SocketOpts, stomp, - {?MODULE, start_client, [Configuration]}, - "STOMP TCP Listener"). + rabbit_networking:tcp_listener_spec( + rabbit_stomp_listener_sup, Address, SocketOpts, + stomp, "STOMP TCP Listener", + {?MODULE, start_client, [Configuration]}). ssl_listener_spec([Address, SocketOpts, SslOpts, Configuration]) -> - listener_spec(Address, SocketOpts, 'stomp/ssl', - {?MODULE, start_ssl_client, [Configuration, SslOpts]}, - "STOMP SSL Listener"). - -listener_spec({IPAddress, Port, Family, Name}, - SocketOpts, Protocol, OnConnect, Label) -> - {Name, - {tcp_listener_sup, start_link, - [IPAddress, Port, - [Family | SocketOpts], - {?MODULE, listener_started, [Protocol]}, - {?MODULE, listener_stopped, [Protocol]}, - OnConnect, Label]}, - transient, infinity, supervisor, [tcp_listener_sup]}. + rabbit_networking:tcp_listener_spec( + rabbit_stomp_listener_sup, Address, SocketOpts, + 'stomp/ssl', "STOMP SSL Listener", + {?MODULE, start_ssl_client, [Configuration, SslOpts]}). + +start_client(Configuration, Sock, SockTransform) -> + {ok, _Child, Reader} = supervisor:start_child(rabbit_stomp_client_sup_sup, + [Configuration]), + ok = rabbit_net:controlling_process(Sock, Reader), + Reader ! {go, Sock, SockTransform}, -listener_started(Protocol, IPAddress, Port) -> - rabbit_networking:tcp_listener_started(Protocol, IPAddress, Port). + %% see comment in rabbit_networking:start_client/2 + gen_event:which_handlers(error_logger), -listener_stopped(Protocol, IPAddress, Port) -> - rabbit_networking:tcp_listener_stopped(Protocol, IPAddress, Port). + Reader. start_client(Configuration, Sock) -> - {ok, SupPid, ReaderPid} = - supervisor:start_child(rabbit_stomp_client_sup_sup, - [Sock, Configuration]), - ok = rabbit_net:controlling_process(Sock, ReaderPid), - ReaderPid ! {go, Sock}, - SupPid. + start_client(Configuration, Sock, fun (S) -> {ok, S} end). start_ssl_client(Configuration, SslOpts, Sock) -> Transform = rabbit_networking:ssl_transform_fun(SslOpts), - {ok, SslSock} = Transform(Sock), - start_client(Configuration, SslSock). - + start_client(Configuration, Sock, Transform). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbit_stomp_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbit_stomp_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,32 +1,17 @@ -%% 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/ +%% 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. +%% 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 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): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_stomp_util). @@ -34,7 +19,8 @@ -export([parse_destination/1, parse_routing_information/1, parse_message_id/1, durable_subscription_queue/2]). -export([longstr_field/2]). --export([ack_mode/1, consumer_tag/1, message_headers/4, message_properties/1]). +-export([ack_mode/1, consumer_tag_reply_to/1, consumer_tag/1, message_headers/4, + message_properties/1]). -export([negotiate_version/2]). -export([trim_headers/1]). -export([valid_dest_prefixes/0]). @@ -44,18 +30,27 @@ -include("rabbit_stomp_prefixes.hrl"). -include("rabbit_stomp_headers.hrl"). +-define(INTERNAL_TAG_PREFIX, "T_"). +-define(QUEUE_TAG_PREFIX, "Q_"). + %%-------------------------------------------------------------------- %% Frame and Header Parsing %%-------------------------------------------------------------------- +consumer_tag_reply_to(QueueId) -> + internal_tag(?TEMP_QUEUE_ID_PREFIX ++ QueueId). + consumer_tag(Frame) -> case rabbit_stomp_frame:header(Frame, ?HEADER_ID) of - {ok, Str} -> - {ok, list_to_binary("T_" ++ Str), "id='" ++ Str ++ "'"}; + {ok, Id} -> + case lists:prefix(?TEMP_QUEUE_ID_PREFIX, Id) of + false -> {ok, internal_tag(Id), "id='" ++ Id ++ "'"}; + true -> {error, invalid_prefix} + end; not_found -> case rabbit_stomp_frame:header(Frame, ?HEADER_DESTINATION) of {ok, DestHdr} -> - {ok, list_to_binary("Q_" ++ DestHdr), + {ok, queue_tag(DestHdr), "destination='" ++ DestHdr ++ "'"}; not_found -> {error, missing_destination_header} @@ -105,7 +100,7 @@ maybe_header(Header, element(Index, Props), Acc) end, case ConsumerTag of - <<"T_", Id/binary>> -> + <> -> [{"subscription", binary_to_list(Id)} | Basic]; _ -> Basic @@ -211,6 +206,12 @@ trim_headers(Frame = #stomp_frame{headers = Hdrs}) -> Frame#stomp_frame{headers = [{K, string:strip(V, left)} || {K, V} <- Hdrs]}. +internal_tag(Base) -> + list_to_binary(?INTERNAL_TAG_PREFIX ++ Base). + +queue_tag(Base) -> + list_to_binary(?QUEUE_TAG_PREFIX ++ Base). + %%-------------------------------------------------------------------- %% Destination Parsing %%-------------------------------------------------------------------- @@ -251,8 +252,13 @@ valid_dest_prefixes() -> ?VALID_DEST_PREFIXES. durable_subscription_queue(Destination, SubscriptionId) -> - <<(list_to_binary("stomp.dsub." ++ Destination ++ "."))/binary, - (erlang:md5(SubscriptionId))/binary>>. + %% We need a queue name that a) can be derived from the + %% Destination and SubscriptionId, and b) meets the constraints on + %% AMQP queue names. It doesn't need to be secure; we use md5 here + %% simply as a convenient means to bound the length. + rabbit_guid:binary( + erlang:md5(term_to_binary({Destination, SubscriptionId})), + "stomp.dsub"). %% ---- Destination parsing helpers ---- @@ -285,7 +291,7 @@ take_prefix([Char | Prefix], [Char | List]) -> take_prefix(Prefix, List); take_prefix([], List) -> {ok, List}; -take_prefix(_Prefix, List) -> not_found. +take_prefix(_Prefix, _List) -> not_found. unescape(Str) -> unescape(Str, []). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbitmq_stomp.app.src rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbitmq_stomp.app.src --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/src/rabbitmq_stomp.app.src 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/src/rabbitmq_stomp.app.src 2012-03-19 10:36:09.000000000 +0000 @@ -7,6 +7,8 @@ {env, [{default_user, [{login, "guest"}, {passcode, "guest"}]}, + {ssl_cert_login, false}, + {implicit_connect, false}, {tcp_listeners, [61613]}, {ssl_listeners, []}, {tcp_listen_options, [binary, diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/connect_options.py rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/connect_options.py --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/connect_options.py 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/connect_options.py 2012-03-19 10:36:09.000000000 +0000 @@ -1,12 +1,14 @@ import unittest import stomp import base +import test_util class TestConnectOptions(base.BaseTest): def test_implicit_connect(self): ''' Implicit connect with receipt on first command ''' self.conn.disconnect() + test_util.enable_implicit_connect() listener = base.WaitableListener() new_conn = stomp.Connection(user="", passcode="") new_conn.set_listener('', listener) @@ -21,6 +23,7 @@ self.assertEquals('implicit', listener.receipts[0]['headers']['receipt-id']) finally: new_conn.disconnect() + test_util.disable_implicit_connect() def test_default_user(self): ''' Default user connection ''' @@ -31,4 +34,4 @@ try: self.assertTrue(new_conn.is_connected()) finally: - new_conn.disconnect() \ No newline at end of file + new_conn.disconnect() diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/non_ssl.config rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/non_ssl.config --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/non_ssl.config 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/non_ssl.config 2012-03-19 10:36:09.000000000 +0000 @@ -1,7 +1,6 @@ -[ - {rabbitmq_stomp, [ - {default_user, - [{login,"guest"}, - {passcode, "guest"}, - implicit_connect]}]} +[{rabbitmq_stomp, [{default_user, [{login, "guest"}, + {passcode, "guest"} + ]}, + {implicit_connect, true} + ]} ]. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/parsing.py rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/parsing.py --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/parsing.py 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/parsing.py 2012-03-19 10:36:09.000000000 +0000 @@ -19,6 +19,7 @@ resp = ('CONNECTED\n' 'session:(.*)\n' 'heart-beat:0,0\n' + 'server:RabbitMQ/(.*)\n' 'version:1.0\n' '\n\x00') def w(m): diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_amqqueue_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_amqqueue_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_amqqueue_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_amqqueue_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,23 +1,19 @@ -%% 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/ +%% 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. %% -%% 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 Original Code is RabbitMQ Management Console. -%% -%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. -%% -%% Copyright (C) 2011 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_amqqueue_test). -export([all_tests/0]). @@ -36,32 +32,35 @@ run_test(TestFun) -> {ok, Connection} = amqp_connection:start(#amqp_params_direct{}), {ok, Channel} = amqp_connection:open_channel(Connection), - {ok, Sock} = stomp_connect(), + {ok, Client} = rabbit_stomp_client:connect(), - Result = (catch TestFun(Channel, Sock)), + Result = (catch TestFun(Channel, Client)), - stomp_disconnect(Sock), + rabbit_stomp_client:disconnect(Client), amqp_channel:close(Channel), amqp_connection:close(Connection), Result. -test_subscribe_error(_Channel, Sock) -> +test_subscribe_error(_Channel, Client) -> %% SUBSCRIBE to missing queue - stomp_send(Sock, "SUBSCRIBE", [{"destination", ?DESTINATION}]), - #stomp_frame{command = "ERROR", headers = Hdrs} = stomp_recv(Sock), + rabbit_stomp_client:send( + Client, "SUBSCRIBE", [{"destination", ?DESTINATION}]), + {#stomp_frame{command = "ERROR", + headers = Hdrs}, _} = rabbit_stomp_client:recv(Client), "not_found" = proplists:get_value("message", Hdrs), ok. -test_subscribe(Channel, Sock) -> +test_subscribe(Channel, Client) -> #'queue.declare_ok'{} = amqp_channel:call(Channel, #'queue.declare'{queue = ?QUEUE, auto_delete = true}), %% subscribe and wait for receipt - stomp_send(Sock, "SUBSCRIBE", [{"destination", ?DESTINATION}, - {"receipt", "foo"}]), - #stomp_frame{command = "RECEIPT"} = stomp_recv(Sock), - + rabbit_stomp_client:send(Client, "SUBSCRIBE", + [{"destination", ?DESTINATION}, + {"receipt", "foo"}]), + {#stomp_frame{command = "RECEIPT"}, Client1} = + rabbit_stomp_client:recv(Client), %% send from amqp Method = #'basic.publish'{ @@ -71,55 +70,27 @@ amqp_channel:call(Channel, Method, #amqp_msg{props = #'P_basic'{}, payload = <<"hello">>}), - #stomp_frame{command = "MESSAGE", - body_iolist = [<<"hello">>]} = stomp_recv(Sock), - + {#stomp_frame{command = "MESSAGE", + body_iolist = [<<"hello">>]}, _Client2} = + rabbit_stomp_client:recv(Client1), ok. -test_send(Channel, Sock) -> +test_send(Channel, Client) -> #'queue.declare_ok'{} = amqp_channel:call(Channel, #'queue.declare'{queue = ?QUEUE, auto_delete = true}), %% subscribe and wait for receipt - stomp_send(Sock, "SUBSCRIBE", [{"destination", ?DESTINATION}, - {"receipt", "foo"}]), - #stomp_frame{command = "RECEIPT"} = stomp_recv(Sock), - + rabbit_stomp_client:send( + Client, "SUBSCRIBE", [{"destination", ?DESTINATION}, {"receipt", "foo"}]), + {#stomp_frame{command = "RECEIPT"}, Client1} = + rabbit_stomp_client:recv(Client), %% send from stomp - stomp_send(Sock, "SEND", [{"destination", ?DESTINATION}], ["hello"]), - - #stomp_frame{command = "MESSAGE", - body_iolist = [<<"hello">>]} = stomp_recv(Sock), + rabbit_stomp_client:send( + Client1, "SEND", [{"destination", ?DESTINATION}], ["hello"]), + {#stomp_frame{command = "MESSAGE", + body_iolist = [<<"hello">>]}, _Client2} = + rabbit_stomp_client:recv(Client1), ok. - -stomp_connect() -> - {ok, Sock} = gen_tcp:connect(localhost, 61613, [{active, false}, binary]), - stomp_send(Sock, "CONNECT"), - #stomp_frame{command = "CONNECTED"} = stomp_recv(Sock), - {ok, Sock}. - -stomp_disconnect(Sock) -> - stomp_send(Sock, "DISCONNECT"). - -stomp_send(Sock, Command) -> - stomp_send(Sock, Command, []). - -stomp_send(Sock, Command, Headers) -> - stomp_send(Sock, Command, Headers, []). - -stomp_send(Sock, Command, Headers, Body) -> - gen_tcp:send(Sock, rabbit_stomp_frame:serialize( - #stomp_frame{command = list_to_binary(Command), - headers = Headers, - body_iolist = Body})). - -stomp_recv(Sock) -> - {ok, Payload} = gen_tcp:recv(Sock, 0), - {ok, Frame, _Rest} = - rabbit_stomp_frame:parse(Payload, - rabbit_stomp_frame:initial_state()), - Frame. - diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_client.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_client.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_client.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_client.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,75 @@ +%% 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 Management Console. +%% +%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. +%% +%% Copyright (C) 2011 Rabbit Technologies Ltd. +%% +%% All Rights Reserved. +%% +%% Contributor(s): ______________________________________. +%% + +%% The stupidest client imaginable, just for testing. + +-module(rabbit_stomp_client). + +-export([connect/0, disconnect/1, send/2, send/3, send/4, recv/1]). + +-include("rabbit_stomp_frame.hrl"). + +connect() -> + {ok, Sock} = gen_tcp:connect(localhost, 61613, [{active, false}, binary]), + Client0 = recv_state(Sock), + send(Client0, "CONNECT", [{"login", "guest"}, {"passcode", "guest"}]), + {#stomp_frame{command = "CONNECTED"}, Client1} = recv(Client0), + {ok, Client1}. + +disconnect(Client = {Sock, _}) -> + send(Client, "DISCONNECT"), + gen_tcp:close(Sock). + +send(Client, Command) -> + send(Client, Command, []). + +send(Client, Command, Headers) -> + send(Client, Command, Headers, []). + +send({Sock, _}, Command, Headers, Body) -> + Frame = rabbit_stomp_frame:serialize( + #stomp_frame{command = list_to_binary(Command), + headers = Headers, + body_iolist = Body}), + gen_tcp:send(Sock, Frame). + +recv_state(Sock) -> + {Sock, []}. + +recv({_Sock, []} = Client) -> + recv(Client, rabbit_stomp_frame:initial_state(), 0); +recv({Sock, [Frame | Frames]}) -> + {Frame, {Sock, Frames}}. + +recv(Client = {Sock, _}, FrameState, Length) -> + {ok, Payload} = gen_tcp:recv(Sock, Length), + parse(Payload, Client, FrameState, Length). + +parse(Payload, Client = {Sock, FramesRev}, FrameState, Length) -> + case rabbit_stomp_frame:parse(Payload, FrameState) of + {ok, Frame, <<>>} -> + recv({Sock, lists:reverse([Frame | FramesRev])}); + {ok, Frame, Rest} -> + parse(Rest, {Sock, [Frame | FramesRev]}, + rabbit_stomp_frame:initial_state(), Length); + {more, NewState, NewLength} -> + recv(Client, NewState, NewLength) + end. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_publish_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_publish_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_publish_test.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_publish_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,88 @@ +%% 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 Management Console. +%% +%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. +%% +%% Copyright (C) 2011 Rabbit Technologies Ltd. +%% +%% All Rights Reserved. +%% +%% Contributor(s): ______________________________________. +%% +-module(rabbit_stomp_publish_test). + +-export([run/0]). + +-include("rabbit_stomp_frame.hrl"). + +-define(DESTINATION, "/queue/test"). + +-define(MICROS_PER_UPDATE, 5000000). +-define(MICROS_PER_UPDATE_MSG, 100000). +-define(MICROS_PER_SECOND, 1000000). + +%% A very simple publish-and-consume-as-fast-as-you-can test. + +run() -> + [put(K, 0) || K <- [sent, recd, last_sent, last_recd]], + put(last_ts, erlang:now()), + {ok, Pub} = rabbit_stomp_client:connect(), + {ok, Recv} = rabbit_stomp_client:connect(), + Self = self(), + spawn(fun() -> publish(Self, Pub, 0, erlang:now()) end), + rabbit_stomp_client:send( + Recv, "SUBSCRIBE", [{"destination", ?DESTINATION}]), + spawn(fun() -> recv(Self, Recv, 0, erlang:now()) end), + report(). + +report() -> + receive + {sent, C} -> put(sent, C); + {recd, C} -> put(recd, C) + end, + Diff = timer:now_diff(erlang:now(), get(last_ts)), + case Diff > ?MICROS_PER_UPDATE of + true -> S = get(sent) - get(last_sent), + R = get(recd) - get(last_recd), + put(last_sent, get(sent)), + put(last_recd, get(recd)), + put(last_ts, erlang:now()), + io:format("Send ~p msg/s | Recv ~p msg/s~n", + [trunc(S * ?MICROS_PER_SECOND / Diff), + trunc(R * ?MICROS_PER_SECOND / Diff)]); + false -> ok + end, + report(). + +publish(Owner, Client, Count, TS) -> + rabbit_stomp_client:send( + Client, "SEND", [{"destination", ?DESTINATION}], + [integer_to_list(Count)]), + Diff = timer:now_diff(erlang:now(), TS), + case Diff > ?MICROS_PER_UPDATE_MSG of + true -> Owner ! {sent, Count + 1}, + publish(Owner, Client, Count + 1, erlang:now()); + false -> publish(Owner, Client, Count + 1, TS) + end. + +recv(Owner, Client0, Count, TS) -> + {#stomp_frame{body_iolist = Body}, Client1} = + rabbit_stomp_client:recv(Client0), + BodyInt = list_to_integer(binary_to_list(iolist_to_binary(Body))), + Count = BodyInt, + Diff = timer:now_diff(erlang:now(), TS), + case Diff > ?MICROS_PER_UPDATE_MSG of + true -> Owner ! {recd, Count + 1}, + recv(Owner, Client1, Count + 1, erlang:now()); + false -> recv(Owner, Client1, Count + 1, TS) + end. + diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,41 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(rabbit_stomp_test). +-export([all_tests/0]). +-import(rabbit_misc, [pget/2]). + +-include_lib("amqp_client/include/amqp_client.hrl"). +-include("rabbit_stomp_frame.hrl"). +-define(DESTINATION, "/queue/bulk-test"). + +all_tests() -> + test_messages_not_dropped_on_disconnect(), + ok. + +test_messages_not_dropped_on_disconnect() -> + {ok, Client} = rabbit_stomp_client:connect(), + [rabbit_stomp_client:send( + Client, "SEND", [{"destination", ?DESTINATION}], + [integer_to_list(Count)]) || Count <- lists:seq(1, 1000)], + rabbit_stomp_client:disconnect(Client), + QName = rabbit_misc:r(<<"/">>, queue, <<"bulk-test">>), + timer:sleep(1000), + rabbit_amqqueue:with( + QName, fun(Q) -> + 1000 = pget(messages, rabbit_amqqueue:info(Q, [messages])) + end), + ok. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_frame.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_frame.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_frame.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_frame.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,23 +1,19 @@ -%% 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/ +%% 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. %% -%% 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 Original Code is RabbitMQ Management Console. -%% -%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. -%% -%% Copyright (C) 2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_test_frame). -include_lib("eunit/include/eunit.hrl"). @@ -116,7 +112,7 @@ {ok, Val} = rabbit_stomp_frame:header(Frame, "header"), ?assertEqual(":\n\\", Val), Serialized = lists:flatten(rabbit_stomp_frame:serialize(Frame)), - ?assertEqual(Content, lists:flatten(io_lib:format("~s", [Serialized]))). + ?assertEqual(Content, rabbit_misc:format("~s", [Serialized])). parse(Content) -> parse(Content, rabbit_stomp_frame:initial_state()). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_util.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_util.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_util.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/rabbit_stomp_test_util.erl 2012-03-19 10:36:09.000000000 +0000 @@ -1,23 +1,19 @@ -%% 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/ +%% 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. +%% 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 Management Console. +%% The Original Code is RabbitMQ. %% -%% The Initial Developers of the Original Code are Rabbit Technologies Ltd. -%% -%% Copyright (C) 2010 Rabbit Technologies Ltd. -%% -%% All Rights Reserved. -%% -%% Contributor(s): ______________________________________. +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% + -module(rabbit_stomp_test_util). -include_lib("eunit/include/eunit.hrl"). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/ssl.config rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/ssl.config --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/ssl.config 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/ssl.config 2012-03-19 10:36:09.000000000 +0000 @@ -1,16 +1,12 @@ -[ - {rabbitmq_stomp, [ - {default_user, - [{login, "guest"}, - {passcode, "guest"}, - implicit_connect]}, - {ssl_listeners, [61614]} - ]}, - {rabbit, [ - {ssl_options, [{cacertfile,"%%CERTS_DIR%%/testca/cacert.pem"}, - {certfile,"%%CERTS_DIR%%/server/cert.pem"}, - {keyfile,"%%CERTS_DIR%%/server/key.pem"}, - {verify,verify_peer}, - {fail_if_no_peer_cert,false}]} - ]} +[{rabbitmq_stomp, [{default_user, []}, + {ssl_cert_login, true}, + {ssl_listeners, [61614]} + ]}, + {rabbit, [{ssl_options, [{cacertfile,"%%CERTS_DIR%%/testca/cacert.pem"}, + {certfile,"%%CERTS_DIR%%/server/cert.pem"}, + {keyfile,"%%CERTS_DIR%%/server/key.pem"}, + {verify,verify_peer}, + {fail_if_no_peer_cert,true} + ]} + ]} ]. diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/ssl_lifecycle.py rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/ssl_lifecycle.py --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/ssl_lifecycle.py 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/ssl_lifecycle.py 2012-03-19 10:36:09.000000000 +0000 @@ -4,13 +4,13 @@ import stomp import base +ssl_key_file = os.path.abspath("test/certs/client/key.pem") +ssl_cert_file = os.path.abspath("test/certs/client/cert.pem") +ssl_ca_certs = os.path.abspath("test/certs/testca/cacert.pem") + class TestSslClient(unittest.TestCase): def __ssl_connect(self): - ssl_key_file = os.path.abspath("test/certs/client/key.pem") - ssl_cert_file = os.path.abspath("test/certs/client/cert.pem") - ssl_ca_certs = os.path.abspath("test/certs/testca/cacert.pem") - conn = stomp.Connection(user="guest", passcode="guest", host_and_ports = [ ('localhost', 61614) ], use_ssl = True, ssl_key_file = ssl_key_file, @@ -21,13 +21,32 @@ conn.connect() return conn + def __ssl_auth_connect(self): + conn = stomp.Connection(host_and_ports = [ ('localhost', 61614) ], + use_ssl = True, ssl_key_file = ssl_key_file, + ssl_cert_file = ssl_cert_file, + ssl_ca_certs = ssl_ca_certs) + conn.start() + conn.connect() + return conn + def test_ssl_connect(self): conn = self.__ssl_connect() conn.stop() + def test_ssl_auth_connect(self): + conn = self.__ssl_auth_connect() + conn.stop() + def test_ssl_send_receive(self): conn = self.__ssl_connect() + self.__test_conn(conn) + + def test_ssl_auth_send_receive(self): + conn = self.__ssl_auth_connect() + self.__test_conn(conn) + def __test_conn(self, conn): try: listener = base.WaitableListener() diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/test_ssl.py rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/test_ssl.py --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/test_ssl.py 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/test_ssl.py 2012-03-19 10:36:09.000000000 +0000 @@ -1,8 +1,10 @@ #!/usr/bin/env python import test_runner +import test_util if __name__ == '__main__': modules = ['ssl_lifecycle'] + test_util.ensure_ssl_auth_user() test_runner.run_unittests(modules) diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/test_util.py rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/test_util.py --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-stomp/test/src/test_util.py 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-stomp/test/src/test_util.py 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,33 @@ +import subprocess +import socket +import sys +import os +import os.path + +def ensure_ssl_auth_user(): + user = 'O=client,CN=%s' % socket.gethostname() + rabbitmqctl(['stop_app']) + rabbitmqctl(['reset']) + rabbitmqctl(['start_app']) + rabbitmqctl(['add_user', user, 'foo']) + rabbitmqctl(['clear_password', user]) + rabbitmqctl(['set_permissions', user, '.*', '.*', '.*']) + +def enable_implicit_connect(): + switch_implicit_connect('true', '[{login, "guest"}, {passcode, "guest"}]') + +def disable_implicit_connect(): + switch_implicit_connect('false', '[]') + +def switch_implicit_connect(implicit_connect, default_user): + cmd = 'application:set_env(rabbitmq_stomp,implicit_connect,' + implicit_connect + '),' + cmd += 'application:set_env(rabbitmq_stomp,default_user,' + default_user + '),' + cmd += 'application:stop(rabbitmq_stomp),' + cmd += 'application:start(rabbitmq_stomp).' + rabbitmqctl(['eval', cmd]) + +def rabbitmqctl(args): + ctl = os.path.normpath(os.path.join(os.getcwd(), sys.argv[0], '../../../../rabbitmq-server/scripts/rabbitmqctl')) + cmdline = [ctl, '-n', 'rabbit-test'] + cmdline.extend(args) + subprocess.check_call(cmdline) diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_app.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_app.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_app.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_app.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_app). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_consumer). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_consumer_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_files.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_files.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_files.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_files.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_files). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_mgmt.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_mgmt.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_mgmt.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_mgmt.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_mgmt). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_sup.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_sup.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_sup). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_traces.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_traces.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_traces.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_traces.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_traces). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_files.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_files.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_files.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_files.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_wm_files). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_traces.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_traces.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_traces.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_traces.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_wm_traces). diff -Nru rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/test/src/rabbit_tracing_test.erl rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/test/src/rabbit_tracing_test.erl --- rabbitmq-server-2.7.1/plugins-src/rabbitmq-tracing/test/src/rabbit_tracing_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/plugins-src/rabbitmq-tracing/test/src/rabbit_tracing_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tracing_test). diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-defaults rabbitmq-server-2.8.0/scripts/rabbitmq-defaults --- rabbitmq-server-2.7.1/scripts/rabbitmq-defaults 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-defaults 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,30 @@ +#!/bin/sh +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is VMware, Inc. +## Copyright (c) 2012 VMware, Inc. All rights reserved. +## + +### next line potentially updated in package install steps +SYS_PREFIX= + +## Set default values + +CONFIG_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmq +LOG_BASE=${SYS_PREFIX}/var/log/rabbitmq +MNESIA_BASE=${SYS_PREFIX}/var/lib/rabbitmq/mnesia +ENABLED_PLUGINS_FILE=${SYS_PREFIX}/etc/rabbitmq/enabled_plugins + +PLUGINS_DIR="${RABBITMQ_HOME}/plugins" + +CONF_ENV_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmq-env.conf diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-echopid.bat rabbitmq-server-2.8.0/scripts/rabbitmq-echopid.bat --- rabbitmq-server-2.7.1/scripts/rabbitmq-echopid.bat 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-echopid.bat 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,49 @@ +@echo off + +REM Usage: rabbitmq-echopid.bat +REM +REM sname of the erlang node to connect to (required) + +setlocal + +if "%1"=="" goto fail + +:: set timeout vars :: +set TIMEOUT=10 +set TIMER=1 + +:: check that wmic exists :: +set WMIC_PATH=%SYSTEMROOT%\System32\Wbem\wmic.exe +if not exist "%WMIC_PATH%" ( + goto fail +) + +:getpid +for /f "usebackq tokens=* skip=1" %%P IN (`%%WMIC_PATH%% process where "name='erl.exe' and commandline like '%%-sname %1%%'" get processid 2^>nul`) do ( + set PID=%%P + goto echopid +) + +:echopid +:: check for pid not found :: +if "%PID%" == "" ( + PING 127.0.0.1 -n 2 > nul + set /a TIMER+=1 + if %TIMEOUT%==%TIMER% goto fail + goto getpid +) + +:: show pid :: +echo %PID% + +:: all done :: +:ok +endlocal +EXIT /B 0 + +:: something went wrong :: +:fail +endlocal +EXIT /B 1 + + diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-env rabbitmq-server-2.8.0/scripts/rabbitmq-env --- rabbitmq-server-2.7.1/scripts/rabbitmq-env 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-env 2012-03-19 10:36:09.000000000 +0000 @@ -12,10 +12,11 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## -# Determine where this script is really located +# Determine where this script is really located (if this script is +# invoked from another script, this is the location of the caller) SCRIPT_PATH="$0" while [ -h "$SCRIPT_PATH" ] ; do FULL_PATH=`readlink -f $SCRIPT_PATH 2>/dev/null` @@ -36,10 +37,19 @@ [ "x" = "x$HOSTNAME" ] && HOSTNAME=`env hostname` NODENAME=rabbit@${HOSTNAME%%.*} -# Load configuration from the rabbitmq.conf file +## Set defaults +. ${SCRIPT_DIR}/rabbitmq-defaults + +## Common defaults +SERVER_ERL_ARGS="+K true +A30 +P 1048576 \ + -kernel inet_default_connect_options [{nodelay,true}]" + +# warn about old rabbitmq.conf file, if no new one if [ -f /etc/rabbitmq/rabbitmq.conf ] && \ - [ ! -f /etc/rabbitmq/rabbitmq-env.conf ] ; then + [ ! -f ${CONF_ENV_FILE} ] ; then echo -n "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- " - echo "location has moved to /etc/rabbitmq/rabbitmq-env.conf" + echo "location has moved to ${CONF_ENV_FILE}" fi -[ -f /etc/rabbitmq/rabbitmq-env.conf ] && . /etc/rabbitmq/rabbitmq-env.conf + +## Get configuration variables from the configure environment file +[ -f ${CONF_ENV_FILE} ] && . ${CONF_ENV_FILE} diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-plugins rabbitmq-server-2.8.0/scripts/rabbitmq-plugins --- rabbitmq-server-2.7.1/scripts/rabbitmq-plugins 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-plugins 2012-03-19 10:36:09.000000000 +0000 @@ -12,16 +12,19 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## +# Get default settings with user overrides for (RABBITMQ_) +# Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env -ENABLED_PLUGINS_FILE=/etc/rabbitmq/enabled_plugins +##--- Set environment vars RABBITMQ_ to defaults if not set [ "x" = "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE=${ENABLED_PLUGINS_FILE} +[ "x" = "x$RABBITMQ_PLUGINS_DIR" ] && RABBITMQ_PLUGINS_DIR=${PLUGINS_DIR} -[ "x" = "x$RABBITMQ_PLUGINS_DIR" ] && RABBITMQ_PLUGINS_DIR="${RABBITMQ_HOME}/plugins" +##--- End of overridden variables exec erl \ -pa "${RABBITMQ_HOME}/ebin" \ diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-plugins.bat rabbitmq-server-2.8.0/scripts/rabbitmq-plugins.bat --- rabbitmq-server-2.7.1/scripts/rabbitmq-plugins.bat 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-plugins.bat 2012-03-19 10:36:09.000000000 +0000 @@ -12,7 +12,7 @@ REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is VMware, Inc. -REM Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +REM Copyright (c) 2007-2012 VMware, Inc. All rights reserved. REM setlocal diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-server rabbitmq-server-2.8.0/scripts/rabbitmq-server --- rabbitmq-server-2.7.1/scripts/rabbitmq-server 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-server 2012-03-19 10:36:09.000000000 +0000 @@ -12,33 +12,23 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## -SERVER_ERL_ARGS="+K true +A30 +P 1048576 \ --kernel inet_default_connect_options [{nodelay,true}]" -CONFIG_FILE=/etc/rabbitmq/rabbitmq -LOG_BASE=/var/log/rabbitmq -MNESIA_BASE=/var/lib/rabbitmq/mnesia -SERVER_START_ARGS= -ENABLED_PLUGINS_FILE=/etc/rabbitmq/enabled_plugins - +# Get default settings with user overrides for (RABBITMQ_) +# Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env +##--- Set environment vars RABBITMQ_ to defaults if not set + DEFAULT_NODE_IP_ADDRESS=auto DEFAULT_NODE_PORT=5672 -[ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && [ "x" != "x$NODE_IP_ADDRESS" ] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS} -[ "x" = "x$RABBITMQ_NODE_PORT" ] && [ "x" != "x$NODE_PORT" ] && RABBITMQ_NODE_PORT=${NODE_PORT} -if [ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] -then - if [ "x" != "x$RABBITMQ_NODE_PORT" ] - then RABBITMQ_NODE_IP_ADDRESS=${DEFAULT_NODE_IP_ADDRESS} - fi -else - if [ "x" = "x$RABBITMQ_NODE_PORT" ] - then RABBITMQ_NODE_PORT=${DEFAULT_NODE_PORT} - fi -fi +[ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS} +[ "x" = "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_PORT=${NODE_PORT} + +[ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && [ "x" != "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_IP_ADDRESS=${DEFAULT_NODE_IP_ADDRESS} +[ "x" != "x$RABBITMQ_NODE_IP_ADDRESS" ] && [ "x" = "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_PORT=${DEFAULT_NODE_PORT} + [ "x" = "x$RABBITMQ_NODENAME" ] && RABBITMQ_NODENAME=${NODENAME} [ "x" = "x$RABBITMQ_SERVER_ERL_ARGS" ] && RABBITMQ_SERVER_ERL_ARGS=${SERVER_ERL_ARGS} [ "x" = "x$RABBITMQ_CONFIG_FILE" ] && RABBITMQ_CONFIG_FILE=${CONFIG_FILE} @@ -48,13 +38,16 @@ [ "x" = "x$RABBITMQ_MNESIA_DIR" ] && RABBITMQ_MNESIA_DIR=${MNESIA_DIR} [ "x" = "x$RABBITMQ_MNESIA_DIR" ] && RABBITMQ_MNESIA_DIR=${RABBITMQ_MNESIA_BASE}/${RABBITMQ_NODENAME} + +[ "x" = "x$RABBITMQ_PID_FILE" ] && RABBITMQ_PID_FILE=${PID_FILE} [ "x" = "x$RABBITMQ_PID_FILE" ] && RABBITMQ_PID_FILE=${RABBITMQ_MNESIA_DIR}.pid [ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${PLUGINS_EXPAND_DIR} [ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${RABBITMQ_MNESIA_BASE}/${RABBITMQ_NODENAME}-plugins-expand [ "x" = "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE=${ENABLED_PLUGINS_FILE} -[ "x" = "x$RABBITMQ_PLUGINS_DIR" ] && RABBITMQ_PLUGINS_DIR="${RABBITMQ_HOME}/plugins" + +[ "x" = "x$RABBITMQ_PLUGINS_DIR" ] && RABBITMQ_PLUGINS_DIR=${PLUGINS_DIR} ## Log rotation [ "x" = "x$RABBITMQ_LOGS" ] && RABBITMQ_LOGS=${LOGS} @@ -62,6 +55,8 @@ [ "x" = "x$RABBITMQ_SASL_LOGS" ] && RABBITMQ_SASL_LOGS=${SASL_LOGS} [ "x" = "x$RABBITMQ_SASL_LOGS" ] && RABBITMQ_SASL_LOGS="${RABBITMQ_LOG_BASE}/${RABBITMQ_NODENAME}-sasl.log" +##--- End of overridden variables + RABBITMQ_START_RABBIT= [ "x" = "x$RABBITMQ_ALLOW_INPUT" ] && RABBITMQ_START_RABBIT='-noinput' @@ -117,7 +112,7 @@ -sasl sasl_error_logger false \ -rabbit error_logger '{file,"'${RABBITMQ_LOGS}'"}' \ -rabbit sasl_error_logger '{file,"'${RABBITMQ_SASL_LOGS}'"}' \ - -os_mon start_cpu_sup true \ + -os_mon start_cpu_sup false \ -os_mon start_disksup false \ -os_mon start_memsup false \ -mnesia dir "\"${RABBITMQ_MNESIA_DIR}\"" \ diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-server.bat rabbitmq-server-2.8.0/scripts/rabbitmq-server.bat --- rabbitmq-server-2.7.1/scripts/rabbitmq-server.bat 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-server.bat 2012-03-19 10:36:09.000000000 +0000 @@ -12,7 +12,7 @@ REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is VMware, Inc. -REM Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +REM Copyright (c) 2007-2012 VMware, Inc. All rights reserved. REM setlocal @@ -139,7 +139,7 @@ -sasl sasl_error_logger false ^ -rabbit error_logger {file,\""!LOGS:\=/!"\"} ^ -rabbit sasl_error_logger {file,\""!SASL_LOGS:\=/!"\"} ^ --os_mon start_cpu_sup true ^ +-os_mon start_cpu_sup false ^ -os_mon start_disksup false ^ -os_mon start_memsup false ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmq-service.bat rabbitmq-server-2.8.0/scripts/rabbitmq-service.bat --- rabbitmq-server-2.7.1/scripts/rabbitmq-service.bat 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmq-service.bat 2012-03-19 10:36:09.000000000 +0000 @@ -12,7 +12,7 @@ REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is VMware, Inc. -REM Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +REM Copyright (c) 2007-2012 VMware, Inc. All rights reserved. REM setlocal @@ -204,7 +204,7 @@ -sasl sasl_error_logger false ^ -rabbit error_logger {file,\""!LOGS:\=/!"\"} ^ -rabbit sasl_error_logger {file,\""!SASL_LOGS:\=/!"\"} ^ --os_mon start_cpu_sup true ^ +-os_mon start_cpu_sup false ^ -os_mon start_disksup false ^ -os_mon start_memsup false ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmqctl rabbitmq-server-2.8.0/scripts/rabbitmqctl --- rabbitmq-server-2.7.1/scripts/rabbitmqctl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmqctl 2012-03-19 10:36:09.000000000 +0000 @@ -12,14 +12,20 @@ ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is VMware, Inc. -## Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +## Copyright (c) 2007-2012 VMware, Inc. All rights reserved. ## +# Get default settings with user overrides for (RABBITMQ_) +# Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env +##--- Set environment vars RABBITMQ_ to defaults if not set + [ "x" = "x$RABBITMQ_NODENAME" ] && RABBITMQ_NODENAME=${NODENAME} [ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS=${CTL_ERL_ARGS} +##--- End of overridden variables + exec erl \ -pa "${RABBITMQ_HOME}/ebin" \ -noinput \ diff -Nru rabbitmq-server-2.7.1/scripts/rabbitmqctl.bat rabbitmq-server-2.8.0/scripts/rabbitmqctl.bat --- rabbitmq-server-2.7.1/scripts/rabbitmqctl.bat 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/scripts/rabbitmqctl.bat 2012-03-19 10:36:09.000000000 +0000 @@ -12,7 +12,7 @@ REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is VMware, Inc. -REM Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +REM Copyright (c) 2007-2012 VMware, Inc. All rights reserved. REM setlocal diff -Nru rabbitmq-server-2.7.1/src/credit_flow.erl rabbitmq-server-2.8.0/src/credit_flow.erl --- rabbitmq-server-2.7.1/src/credit_flow.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/src/credit_flow.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,127 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(credit_flow). + +%% Credit flow is controlled by a credit specification - a +%% {InitialCredit, MoreCreditAfter} tuple. For the message sender, +%% credit starts at InitialCredit and is decremented with every +%% message sent. The message receiver grants more credit to the sender +%% by sending it a {bump_credit, ...} control message after receiving +%% MoreCreditAfter messages. The sender should pass this message in to +%% handle_bump_msg/1. The sender should block when it goes below 0 +%% (check by invoking blocked/0). If a process is both a sender and a +%% receiver it will not grant any more credit to its senders when it +%% is itself blocked - thus the only processes that need to check +%% blocked/0 are ones that read from network sockets. + +-define(DEFAULT_CREDIT, {200, 50}). + +-export([send/1, send/2, ack/1, ack/2, handle_bump_msg/1, blocked/0]). +-export([peer_down/1]). + +%%---------------------------------------------------------------------------- + +-ifdef(use_specs). + +-opaque(bump_msg() :: {pid(), non_neg_integer()}). +-type(credit_spec() :: {non_neg_integer(), non_neg_integer()}). + +-spec(send/1 :: (pid()) -> 'ok'). +-spec(send/2 :: (pid(), credit_spec()) -> 'ok'). +-spec(ack/1 :: (pid()) -> 'ok'). +-spec(ack/2 :: (pid(), credit_spec()) -> 'ok'). +-spec(handle_bump_msg/1 :: (bump_msg()) -> 'ok'). +-spec(blocked/0 :: () -> boolean()). +-spec(peer_down/1 :: (pid()) -> 'ok'). + +-endif. + +%%---------------------------------------------------------------------------- + +%% There are two "flows" here; of messages and of credit, going in +%% opposite directions. The variable names "From" and "To" refer to +%% the flow of credit, but the function names refer to the flow of +%% messages. This is the clearest I can make it (since the function +%% names form the API and want to make sense externally, while the +%% variable names are used in credit bookkeeping and want to make +%% sense internally). + +%% For any given pair of processes, ack/2 and send/2 must always be +%% called with the same credit_spec(). + +send(From) -> send(From, ?DEFAULT_CREDIT). + +send(From, {InitialCredit, _MoreCreditAfter}) -> + update({credit_from, From}, InitialCredit, + fun (1) -> block(From), + 0; + (C) -> C - 1 + end). + +ack(To) -> ack(To, ?DEFAULT_CREDIT). + +ack(To, {_InitialCredit, MoreCreditAfter}) -> + update({credit_to, To}, MoreCreditAfter, + fun (1) -> grant(To, MoreCreditAfter), + MoreCreditAfter; + (C) -> C - 1 + end). + +handle_bump_msg({From, MoreCredit}) -> + update({credit_from, From}, 0, + fun (C) when C =< 0 andalso C + MoreCredit > 0 -> unblock(From), + C + MoreCredit; + (C) -> C + MoreCredit + end). + +blocked() -> get(credit_blocked, []) =/= []. + +peer_down(Peer) -> + %% In theory we could also remove it from credit_deferred here, but it + %% doesn't really matter; at some point later we will drain + %% credit_deferred and thus send messages into the void... + unblock(Peer), + erase({credit_from, Peer}), + erase({credit_to, Peer}). + +%% -------------------------------------------------------------------------- + +grant(To, Quantity) -> + Msg = {bump_credit, {self(), Quantity}}, + case blocked() of + false -> To ! Msg; + true -> update(credit_deferred, [], + fun (Deferred) -> [{To, Msg} | Deferred] end) + end. + +block(From) -> update(credit_blocked, [], fun (Blocks) -> [From | Blocks] end). + +unblock(From) -> + update(credit_blocked, [], fun (Blocks) -> Blocks -- [From] end), + case blocked() of + false -> [To ! Msg || {To, Msg} <- get(credit_deferred, [])], + erase(credit_deferred); + true -> ok + end. + +get(Key, Default) -> + case get(Key) of + undefined -> Default; + Value -> Value + end. + +update(Key, Default, Fun) -> put(Key, Fun(get(Key, Default))), ok. diff -Nru rabbitmq-server-2.7.1/src/delegate.erl rabbitmq-server-2.8.0/src/delegate.erl --- rabbitmq-server-2.7.1/src/delegate.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/delegate.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(delegate). diff -Nru rabbitmq-server-2.7.1/src/delegate_sup.erl rabbitmq-server-2.8.0/src/delegate_sup.erl --- rabbitmq-server-2.7.1/src/delegate_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/delegate_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(delegate_sup). diff -Nru rabbitmq-server-2.7.1/src/file_handle_cache.erl rabbitmq-server-2.8.0/src/file_handle_cache.erl --- rabbitmq-server-2.7.1/src/file_handle_cache.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/file_handle_cache.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(file_handle_cache). @@ -125,8 +125,7 @@ %% requesting process is considered to 'own' one more %% descriptor. release/0 is the inverse operation and releases a %% previously obtained descriptor. transfer/1 transfers ownership of a -%% file descriptor between processes. It is non-blocking. Obtain is -%% used to obtain permission to accept file descriptors. Obtain has a +%% file descriptor between processes. It is non-blocking. Obtain has a %% lower limit, set by the ?OBTAIN_LIMIT/1 macro. File handles can use %% the entire limit, but will be evicted by obtain calls up to the %% point at which no more obtain calls can be satisfied by the obtains @@ -144,9 +143,9 @@ -behaviour(gen_server2). -export([register_callback/3]). --export([open/3, close/1, read/2, append/2, sync/1, position/2, truncate/1, - current_virtual_offset/1, current_raw_offset/1, flush/1, copy/3, - set_maximum_since_use/1, delete/1, clear/1]). +-export([open/3, close/1, read/2, append/2, needs_sync/1, sync/1, position/2, + truncate/1, current_virtual_offset/1, current_raw_offset/1, flush/1, + copy/3, set_maximum_since_use/1, delete/1, clear/1]). -export([obtain/0, release/0, transfer/1, set_limit/1, get_limit/0, info_keys/0, info/0, info/1]). -export([ulimit/0]). @@ -262,7 +261,7 @@ -endif. %%---------------------------------------------------------------------------- --define(INFO_KEYS, [obtain_count, obtain_limit]). +-define(INFO_KEYS, [total_limit, total_used, sockets_limit, sockets_used]). %%---------------------------------------------------------------------------- %% Public API @@ -374,6 +373,13 @@ end end). +needs_sync(Ref) -> + with_handles( + [Ref], + fun ([#handle { is_dirty = false, write_buffer = [] }]) -> false; + ([_Handle]) -> true + end). + position(Ref, NewOffset) -> with_flushed_handles( [Ref], @@ -790,8 +796,10 @@ infos(Items, State) -> [{Item, i(Item, State)} || Item <- Items]. -i(obtain_count, #fhc_state{obtain_count = Count}) -> Count; -i(obtain_limit, #fhc_state{obtain_limit = Limit}) -> Limit; +i(total_limit, #fhc_state{limit = Limit}) -> Limit; +i(total_used, #fhc_state{open_count = C1, obtain_count = C2}) -> C1 + C2; +i(sockets_limit, #fhc_state{obtain_limit = Limit}) -> Limit; +i(sockets_used, #fhc_state{obtain_count = Count}) -> Count; i(Item, _) -> throw({bad_argument, Item}). %%---------------------------------------------------------------------------- diff -Nru rabbitmq-server-2.7.1/src/gatherer.erl rabbitmq-server-2.8.0/src/gatherer.erl --- rabbitmq-server-2.7.1/src/gatherer.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/gatherer.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(gatherer). diff -Nru rabbitmq-server-2.7.1/src/gen_server2.erl rabbitmq-server-2.8.0/src/gen_server2.erl --- rabbitmq-server-2.7.1/src/gen_server2.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/gen_server2.erl 2012-03-19 10:36:09.000000000 +0000 @@ -73,7 +73,7 @@ %% but where the second argument is specifically the priority_queue %% which contains the prioritised message_queue. -%% All modifications are (C) 2009-2011 VMware, Inc. +%% All modifications are (C) 2009-2012 VMware, Inc. %% ``The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff -Nru rabbitmq-server-2.7.1/src/gm.erl rabbitmq-server-2.8.0/src/gm.erl --- rabbitmq-server-2.7.1/src/gm.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/gm.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(gm). diff -Nru rabbitmq-server-2.7.1/src/gm_soak_test.erl rabbitmq-server-2.8.0/src/gm_soak_test.erl --- rabbitmq-server-2.7.1/src/gm_soak_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/gm_soak_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(gm_soak_test). diff -Nru rabbitmq-server-2.7.1/src/gm_speed_test.erl rabbitmq-server-2.8.0/src/gm_speed_test.erl --- rabbitmq-server-2.7.1/src/gm_speed_test.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/gm_speed_test.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(gm_speed_test). diff -Nru rabbitmq-server-2.7.1/src/gm_tests.erl rabbitmq-server-2.8.0/src/gm_tests.erl --- rabbitmq-server-2.7.1/src/gm_tests.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/gm_tests.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(gm_tests). diff -Nru rabbitmq-server-2.7.1/src/lqueue.erl rabbitmq-server-2.8.0/src/lqueue.erl --- rabbitmq-server-2.7.1/src/lqueue.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/lqueue.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(lqueue). diff -Nru rabbitmq-server-2.7.1/src/mirrored_supervisor.erl rabbitmq-server-2.8.0/src/mirrored_supervisor.erl --- rabbitmq-server-2.7.1/src/mirrored_supervisor.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/mirrored_supervisor.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(mirrored_supervisor). @@ -144,32 +144,17 @@ -type child() :: pid() | 'undefined'. -type child_id() :: term(). --type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | 'undefined'}. -type modules() :: [module()] | 'dynamic'. --type restart() :: 'permanent' | 'transient' | 'temporary'. --type shutdown() :: 'brutal_kill' | timeout(). -type worker() :: 'worker' | 'supervisor'. -type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}. -type sup_ref() :: (Name :: atom()) | {Name :: atom(), Node :: node()} | {'global', Name :: atom()} | pid(). --type child_spec() :: {Id :: child_id(), - StartFunc :: mfargs(), - Restart :: restart(), - Shutdown :: shutdown(), - Type :: worker(), - Modules :: modules()}. -type startlink_err() :: {'already_started', pid()} | 'shutdown' | term(). -type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}. --type startchild_err() :: 'already_present' - | {'already_started', Child :: child()} | term(). --type startchild_ret() :: {'ok', Child :: child()} - | {'ok', Child :: child(), Info :: term()} - | {'error', startchild_err()}. - -type group_name() :: any(). -spec start_link(GroupName, Module, Args) -> startlink_ret() when @@ -183,9 +168,9 @@ Module :: module(), Args :: term(). --spec start_child(SupRef, ChildSpec) -> startchild_ret() when +-spec start_child(SupRef, ChildSpec) -> supervisor:startchild_ret() when SupRef :: sup_ref(), - ChildSpec :: child_spec() | (List :: [term()]). + ChildSpec :: supervisor:child_spec() | (List :: [term()]). -spec restart_child(SupRef, Id) -> Result when SupRef :: sup_ref(), @@ -215,12 +200,12 @@ Modules :: modules(). -spec check_childspecs(ChildSpecs) -> Result when - ChildSpecs :: [child_spec()], + ChildSpecs :: [supervisor:child_spec()], Result :: 'ok' | {'error', Error :: term()}. -spec start_internal(Group, ChildSpecs) -> Result when Group :: group_name(), - ChildSpecs :: [child_spec()], + ChildSpecs :: [supervisor:child_spec()], Result :: startlink_ret(). -spec create_tables() -> Result when diff -Nru rabbitmq-server-2.7.1/src/mirrored_supervisor_tests.erl rabbitmq-server-2.8.0/src/mirrored_supervisor_tests.erl --- rabbitmq-server-2.7.1/src/mirrored_supervisor_tests.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/mirrored_supervisor_tests.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(mirrored_supervisor_tests). diff -Nru rabbitmq-server-2.7.1/src/mnesia_sync.erl rabbitmq-server-2.8.0/src/mnesia_sync.erl --- rabbitmq-server-2.7.1/src/mnesia_sync.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/src/mnesia_sync.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,77 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(mnesia_sync). + +%% mnesia:sync_transaction/3 fails to guarantee that the log is flushed to disk +%% at commit. This module is an attempt to minimise the risk of data loss by +%% performing a coalesced log fsync. Unfortunately this is performed regardless +%% of whether or not the log was appended to. + +-behaviour(gen_server). + +-export([sync/0]). + +-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, {waiting, disc_node}). + +%%---------------------------------------------------------------------------- + +-ifdef(use_specs). + +-spec(sync/0 :: () -> 'ok'). + +-endif. + +%%---------------------------------------------------------------------------- + +start_link() -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + +sync() -> + gen_server:call(?SERVER, sync, infinity). + +%%---------------------------------------------------------------------------- + +init([]) -> + {ok, #state{disc_node = mnesia:system_info(use_dir), waiting = []}}. + +handle_call(sync, _From, #state{disc_node = false} = State) -> + {reply, ok, State}; +handle_call(sync, From, #state{waiting = Waiting} = State) -> + {noreply, State#state{waiting = [From | Waiting]}, 0}; +handle_call(Request, _From, State) -> + {stop, {unhandled_call, Request}, State}. + +handle_cast(Request, State) -> + {stop, {unhandled_cast, Request}, State}. + +handle_info(timeout, #state{waiting = Waiting} = State) -> + ok = disk_log:sync(latest_log), + [gen_server:reply(From, ok) || From <- Waiting], + {noreply, State#state{waiting = []}}; +handle_info(Message, State) -> + {stop, {unhandled_info, Message}, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. diff -Nru rabbitmq-server-2.7.1/src/pg_local.erl rabbitmq-server-2.8.0/src/pg_local.erl --- rabbitmq-server-2.7.1/src/pg_local.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/pg_local.erl 2012-03-19 10:36:09.000000000 +0000 @@ -13,7 +13,7 @@ %% versions of Erlang/OTP. The remaining type specs have been %% removed. -%% All modifications are (C) 2010-2011 VMware, Inc. +%% All modifications are (C) 2010-2012 VMware, Inc. %% %CopyrightBegin% %% diff -Nru rabbitmq-server-2.7.1/src/priority_queue.erl rabbitmq-server-2.8.0/src/priority_queue.erl --- rabbitmq-server-2.7.1/src/priority_queue.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/priority_queue.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% Priority queues have essentially the same interface as ordinary diff -Nru rabbitmq-server-2.7.1/src/rabbit.erl rabbitmq-server-2.8.0/src/rabbit.erl --- rabbitmq-server-2.7.1/src/rabbit.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit). @@ -45,6 +45,12 @@ {requires, file_handle_cache}, {enables, external_infrastructure}]}). +-rabbit_boot_step({database_sync, + [{description, "database sync"}, + {mfa, {rabbit_sup, start_child, [mnesia_sync]}}, + {requires, database}, + {enables, external_infrastructure}]}). + -rabbit_boot_step({file_handle_cache, [{description, "file handle cache server"}, {mfa, {rabbit_sup, start_restartable_child, @@ -132,7 +138,7 @@ -rabbit_boot_step({recovery, [{description, "exchange, queue and binding recovery"}, {mfa, {rabbit, recover, []}}, - {requires, empty_db_check}, + {requires, core_initialized}, {enables, routing_ready}]}). -rabbit_boot_step({mirror_queue_slave_sup, @@ -158,8 +164,9 @@ {enables, networking}]}). -rabbit_boot_step({direct_client, - [{mfa, {rabbit_direct, boot, []}}, - {requires, log_relay}]}). + [{description, "direct client"}, + {mfa, {rabbit_direct, boot, []}}, + {requires, log_relay}]}). -rabbit_boot_step({networking, [{mfa, {rabbit_networking, boot, []}}, @@ -190,7 +197,7 @@ rabbit_queue_index, gen, dict, ordsets, file_handle_cache, rabbit_msg_store, array, rabbit_msg_store_ets_index, rabbit_msg_file, rabbit_exchange_type_fanout, rabbit_exchange_type_topic, mnesia, - mnesia_lib, rpc, mnesia_tm, qlc, sofs, proplists]). + mnesia_lib, rpc, mnesia_tm, qlc, sofs, proplists, credit_flow]). %% HiPE compilation uses multiple cores anyway, but some bits are %% IO-bound so we can go faster if we parallelise a bit more. In @@ -205,14 +212,13 @@ -type(file_suffix() :: binary()). %% this really should be an abstract type -type(log_location() :: 'tty' | 'undefined' | file:filename()). +-type(param() :: atom()). -spec(maybe_hipe_compile/0 :: () -> 'ok'). -spec(prepare/0 :: () -> 'ok'). -spec(start/0 :: () -> 'ok'). -spec(stop/0 :: () -> 'ok'). -spec(stop_and_halt/0 :: () -> no_return()). --spec(rotate_logs/1 :: (file_suffix()) -> rabbit_types:ok_or_error(any())). --spec(force_event_refresh/0 :: () -> 'ok'). -spec(status/0 :: () -> [{pid, integer()} | {running_applications, [{atom(), string(), string()}]} | @@ -221,12 +227,11 @@ {memory, any()}]). -spec(is_running/0 :: () -> boolean()). -spec(is_running/1 :: (node()) -> boolean()). --spec(environment/0 :: () -> [{atom() | term()}]). --spec(log_location/1 :: ('sasl' | 'kernel') -> log_location()). +-spec(environment/0 :: () -> [{param() | term()}]). +-spec(rotate_logs/1 :: (file_suffix()) -> rabbit_types:ok_or_error(any())). +-spec(force_event_refresh/0 :: () -> 'ok'). --spec(maybe_insert_default_data/0 :: () -> 'ok'). --spec(boot_delegate/0 :: () -> 'ok'). --spec(recover/0 :: () -> 'ok'). +-spec(log_location/1 :: ('sasl' | 'kernel') -> log_location()). -spec(start/2 :: ('normal',[]) -> {'error', @@ -236,6 +241,10 @@ {'ok',pid()}). -spec(stop/1 :: (_) -> 'ok'). +-spec(maybe_insert_default_data/0 :: () -> 'ok'). +-spec(boot_delegate/0 :: () -> 'ok'). +-spec(recover/0 :: () -> 'ok'). + -endif. %%---------------------------------------------------------------------------- @@ -308,17 +317,28 @@ ok. status() -> - [{pid, list_to_integer(os:getpid())}, - {running_applications, application:which_applications(infinity)}, - {os, os:type()}, - {erlang_version, erlang:system_info(system_version)}, - {memory, erlang:memory()}] ++ - rabbit_misc:filter_exit_map( - fun ({Key, {M, F, A}}) -> {Key, erlang:apply(M, F, A)} end, - [{vm_memory_high_watermark, {vm_memory_monitor, - get_vm_memory_high_watermark, []}}, - {vm_memory_limit, {vm_memory_monitor, - get_memory_limit, []}}]). + S1 = [{pid, list_to_integer(os:getpid())}, + {running_applications, application:which_applications(infinity)}, + {os, os:type()}, + {erlang_version, erlang:system_info(system_version)}, + {memory, erlang:memory()}], + S2 = rabbit_misc:filter_exit_map( + fun ({Key, {M, F, A}}) -> {Key, erlang:apply(M, F, A)} end, + [{vm_memory_high_watermark, {vm_memory_monitor, + get_vm_memory_high_watermark, []}}, + {vm_memory_limit, {vm_memory_monitor, + get_memory_limit, []}}]), + S3 = rabbit_misc:with_exit_handler( + fun () -> [] end, + fun () -> [{file_descriptors, file_handle_cache:info()}] end), + S4 = [{processes, [{limit, erlang:system_info(process_limit)}, + {used, erlang:system_info(process_count)}]}, + {run_queue, erlang:statistics(run_queue)}, + {uptime, begin + {T,_} = erlang:statistics(wall_clock), + T div 1000 + end}], + S1 ++ S2 ++ S3 ++ S4. is_running() -> is_running(node()). @@ -348,10 +368,8 @@ start(normal, []) -> case erts_version_check() of ok -> - ok = rabbit_mnesia:delete_previously_running_nodes(), {ok, SupPid} = rabbit_sup:start_link(), true = register(rabbit, self()), - print_banner(), [ok = run_boot_step(Step) || Step <- boot_steps()], io:format("~nbroker running~n"), @@ -430,8 +448,7 @@ [try apply(M,F,A) catch - _:Reason -> boot_error("FAILED~nReason: ~p~nStacktrace: ~p~n", - [Reason, erlang:get_stacktrace()]) + _:Reason -> boot_step_error(Reason, erlang:get_stacktrace()) end || {M,F,A} <- MFAs], io:format("done~n"), ok @@ -490,8 +507,27 @@ end]) end. +boot_step_error({error, {timeout_waiting_for_tables, _}}, _Stacktrace) -> + {Err, Nodes} = + case rabbit_mnesia:read_previously_running_nodes() of + [] -> {"Timeout contacting cluster nodes. Since RabbitMQ was" + " shut down forcefully~nit cannot determine which nodes" + " are timing out. Details on all nodes will~nfollow.~n", + rabbit_mnesia:all_clustered_nodes() -- [node()]}; + Ns -> {rabbit_misc:format( + "Timeout contacting cluster nodes: ~p.~n", [Ns]), + Ns} + end, + boot_error(Err ++ rabbit_nodes:diagnostics(Nodes) ++ "~n~n", []); + +boot_step_error(Reason, Stacktrace) -> + boot_error("Error description:~n ~p~n~n" + "Log files (may contain more information):~n ~s~n ~s~n~n" + "Stack trace:~n ~p~n~n", + [Reason, log_location(kernel), log_location(sasl), Stacktrace]). + boot_error(Format, Args) -> - io:format("BOOT ERROR: " ++ Format, Args), + io:format("~n~nBOOT FAILED~n===========~n~n" ++ Format, Args), error_logger:error_msg(Format, Args), timer:sleep(1000), exit({?MODULE, failure_during_boot}). @@ -645,7 +681,7 @@ {"app descriptor", app_location()}, {"home dir", home_dir()}, {"config file(s)", config_files()}, - {"cookie hash", rabbit_misc:cookie_hash()}, + {"cookie hash", rabbit_nodes:cookie_hash()}, {"log", log_location(kernel)}, {"sasl log", log_location(sasl)}, {"database dir", rabbit_mnesia:dir()}, @@ -678,6 +714,6 @@ case init:get_argument(config) of {ok, Files} -> [filename:absname( filename:rootname(File, ".config") ++ ".config") || - File <- Files]; + [File] <- Files]; error -> [] end. diff -Nru rabbitmq-server-2.7.1/src/rabbit_access_control.erl rabbitmq-server-2.8.0/src/rabbit_access_control.erl --- rabbitmq-server-2.7.1/src/rabbit_access_control.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_access_control.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_access_control). @@ -66,7 +66,6 @@ check_vhost_access(User = #user{ username = Username, auth_backend = Module }, VHostPath) -> - ?LOGDEBUG("Checking VHost access for ~p to ~p~n", [Username, VHostPath]), check_access( fun() -> rabbit_vhost:exists(VHostPath) andalso diff -Nru rabbitmq-server-2.7.1/src/rabbit_alarm.erl rabbitmq-server-2.8.0/src/rabbit_alarm.erl --- rabbitmq-server-2.7.1/src/rabbit_alarm.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_alarm.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_alarm). @@ -31,10 +31,9 @@ -ifdef(use_specs). --type(mfa_tuple() :: {atom(), atom(), list()}). -spec(start/0 :: () -> 'ok'). -spec(stop/0 :: () -> 'ok'). --spec(register/2 :: (pid(), mfa_tuple()) -> boolean()). +-spec(register/2 :: (pid(), rabbit_types:mfargs()) -> boolean()). -spec(on_node_up/1 :: (node()) -> 'ok'). -spec(on_node_down/1 :: (node()) -> 'ok'). diff -Nru rabbitmq-server-2.7.1/src/rabbit_amqqueue.erl rabbitmq-server-2.8.0/src/rabbit_amqqueue.erl --- rabbitmq-server-2.7.1/src/rabbit_amqqueue.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_amqqueue.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_amqqueue). @@ -20,12 +20,12 @@ -export([pseudo_queue/2]). -export([lookup/1, with/2, with_or_die/2, assert_equivalence/5, check_exclusive_access/2, with_exclusive_access_or_die/3, - stat/1, deliver/2, requeue/3, ack/3, reject/4]). + stat/1, deliver/2, deliver_flow/2, requeue/3, ack/3, reject/4]). -export([list/0, list/1, info_keys/0, info/1, info/2, info_all/1, info_all/2]). -export([force_event_refresh/0]). -export([consumers/1, consumers_all/1, consumer_info_keys/0]). -export([basic_get/3, basic_consume/7, basic_cancel/4]). --export([notify_sent/2, unblock/2, flush_all/2]). +-export([notify_sent/2, notify_sent_queue_down/1, unblock/2, flush_all/2]). -export([notify_down_all/2, limit_all/3]). -export([on_node_down/1]). -export([store_queue/1]). @@ -40,21 +40,25 @@ -define(INTEGER_ARG_TYPES, [byte, short, signedint, long]). +-define(MORE_CONSUMER_CREDIT_AFTER, 50). + +-define(FAILOVER_WAIT_MILLIS, 100). + %%---------------------------------------------------------------------------- -ifdef(use_specs). --export_type([name/0, qmsg/0]). +-export_type([name/0, qmsg/0, routing_result/0]). -type(name() :: rabbit_types:r('queue')). - +-type(qpids() :: [pid()]). -type(qlen() :: rabbit_types:ok(non_neg_integer())). -type(qfun(A) :: fun ((rabbit_types:amqqueue()) -> A | no_return())). -type(qmsg() :: {name(), pid(), msg_id(), boolean(), rabbit_types:message()}). -type(msg_id() :: non_neg_integer()). -type(ok_or_errors() :: 'ok' | {'error', [{'error' | 'exit' | 'throw', any()}]}). - +-type(routing_result() :: 'routed' | 'unroutable' | 'not_delivered'). -type(queue_or_not_found() :: rabbit_types:amqqueue() | 'not_found'). -spec(start/0 :: () -> [name()]). @@ -69,7 +73,8 @@ -> queue_or_not_found() | rabbit_misc:thunk(queue_or_not_found())). -spec(lookup/1 :: (name()) -> rabbit_types:ok(rabbit_types:amqqueue()) | - rabbit_types:error('not_found')). + rabbit_types:error('not_found'); + ([name()]) -> [rabbit_types:amqqueue()]). -spec(with/2 :: (name(), qfun(A)) -> A | rabbit_types:error('not_found')). -spec(with_or_die/2 :: (name(), qfun(A)) -> A | rabbit_types:channel_exit()). @@ -117,12 +122,15 @@ rabbit_types:error('in_use') | rabbit_types:error('not_empty')). -spec(purge/1 :: (rabbit_types:amqqueue()) -> qlen()). --spec(deliver/2 :: (pid(), rabbit_types:delivery()) -> boolean()). +-spec(deliver/2 :: ([rabbit_types:amqqueue()], rabbit_types:delivery()) -> + {routing_result(), qpids()}). +-spec(deliver_flow/2 :: ([rabbit_types:amqqueue()], rabbit_types:delivery()) -> + {routing_result(), qpids()}). -spec(requeue/3 :: (pid(), [msg_id()], pid()) -> 'ok'). -spec(ack/3 :: (pid(), [msg_id()], pid()) -> 'ok'). -spec(reject/4 :: (pid(), [msg_id()], boolean(), pid()) -> 'ok'). --spec(notify_down_all/2 :: ([pid()], pid()) -> ok_or_errors()). --spec(limit_all/3 :: ([pid()], pid(), rabbit_limiter:token()) -> +-spec(notify_down_all/2 :: (qpids(), pid()) -> ok_or_errors()). +-spec(limit_all/3 :: (qpids(), pid(), rabbit_limiter:token()) -> ok_or_errors()). -spec(basic_get/3 :: (rabbit_types:amqqueue(), pid(), boolean()) -> {'ok', non_neg_integer(), qmsg()} | 'empty'). @@ -133,8 +141,9 @@ -spec(basic_cancel/4 :: (rabbit_types:amqqueue(), pid(), rabbit_types:ctag(), any()) -> 'ok'). -spec(notify_sent/2 :: (pid(), pid()) -> 'ok'). +-spec(notify_sent_queue_down/1 :: (pid()) -> 'ok'). -spec(unblock/2 :: (pid(), pid()) -> 'ok'). --spec(flush_all/2 :: ([pid()], pid()) -> 'ok'). +-spec(flush_all/2 :: (qpids(), pid()) -> 'ok'). -spec(internal_delete/1 :: (name()) -> rabbit_types:ok_or_error('not_found') | rabbit_types:connection_exit() | @@ -264,6 +273,10 @@ key = RoutingKey, args = []}). +lookup(Names) when is_list(Names) -> + %% Normally we'd call mnesia:dirty_read/1 here, but that is quite + %% expensive for reasons explained in rabbit_misc:dirty_read/1. + lists:append([ets:lookup(rabbit_queue, Name) || Name <- Names]); lookup(Name) -> rabbit_misc:dirty_read({rabbit_queue, Name}). @@ -323,12 +336,23 @@ precondition_failed, "invalid arg '~s' for ~s: ~255p", [Key, rabbit_misc:rs(QueueName), Error]) - end || {Key, Fun} <- + end || + {Key, Fun} <- [{<<"x-expires">>, fun check_integer_argument/2}, {<<"x-message-ttl">>, fun check_integer_argument/2}, - {<<"x-ha-policy">>, fun check_ha_policy_argument/2}]], + {<<"x-ha-policy">>, fun check_ha_policy_argument/2}, + {<<"x-dead-letter-exchange">>, fun check_string_argument/2}, + {<<"x-dead-letter-routing-key">>, + fun check_dlxrk_argument/2}]], ok. +check_string_argument(undefined, _Args) -> + ok; +check_string_argument({longstr, _}, _Args) -> + ok; +check_string_argument({Type, _}, _) -> + {error, {unacceptable_type, Type}}. + check_integer_argument(undefined, _Args) -> ok; check_integer_argument({Type, Val}, _Args) when Val > 0 -> @@ -339,6 +363,16 @@ check_integer_argument({_Type, Val}, _Args) -> {error, {value_zero_or_less, Val}}. +check_dlxrk_argument(undefined, _Args) -> + ok; +check_dlxrk_argument({longstr, _}, Args) -> + case rabbit_misc:table_lookup(Args, <<"x-dead-letter-exchange">>) of + undefined -> {error, routing_key_but_no_dlx_defined}; + _ -> ok + end; +check_dlxrk_argument({Type, _}, _Args) -> + {error, {unacceptable_type, Type}}. + check_ha_policy_argument(undefined, _Args) -> ok; check_ha_policy_argument({longstr, <<"all">>}, _Args) -> @@ -389,9 +423,26 @@ info_all(VHostPath, Items) -> map(VHostPath, fun (Q) -> info(Q, Items) end). +%% We need to account for the idea that queues may be mid-promotion +%% during force_event_refresh (since it's likely we're doing this in +%% the first place since a node failed). Therefore we keep poking at +%% the list of queues until we were able to talk to a live process or +%% the queue no longer exists. force_event_refresh() -> - [gen_server2:cast(Q#amqqueue.pid, force_event_refresh) || Q <- list()], - ok. + force_event_refresh([Q#amqqueue.name || Q <- list()]). + +force_event_refresh(QNames) -> + Qs = [Q || Q <- list(), lists:member(Q#amqqueue.name, QNames)], + {_, Bad} = rabbit_misc:multi_call( + [Q#amqqueue.pid || Q <- Qs], force_event_refresh), + FailedPids = [Pid || {Pid, _Reason} <- Bad], + Failed = [Name || #amqqueue{name = Name, pid = Pid} <- Qs, + lists:member(Pid, FailedPids)], + case Failed of + [] -> ok; + _ -> timer:sleep(?FAILOVER_WAIT_MILLIS), + force_event_refresh(Failed) + end. consumers(#amqqueue{ pid = QPid }) -> delegate_call(QPid, consumers). @@ -419,14 +470,9 @@ purge(#amqqueue{ pid = QPid }) -> delegate_call(QPid, purge). -deliver(QPid, Delivery = #delivery{immediate = true}) -> - gen_server2:call(QPid, {deliver_immediately, Delivery}, infinity); -deliver(QPid, Delivery = #delivery{mandatory = true}) -> - gen_server2:call(QPid, {deliver, Delivery}, infinity), - true; -deliver(QPid, Delivery) -> - gen_server2:cast(QPid, {deliver, Delivery}), - true. +deliver(Qs, Delivery) -> deliver(Qs, Delivery, noflow). + +deliver_flow(Qs, Delivery) -> deliver(Qs, Delivery, flow). requeue(QPid, MsgIds, ChPid) -> delegate_call(QPid, {requeue, MsgIds, ChPid}). @@ -458,7 +504,21 @@ ok = delegate_call(QPid, {basic_cancel, ChPid, ConsumerTag, OkMsg}). notify_sent(QPid, ChPid) -> - gen_server2:cast(QPid, {notify_sent, ChPid}). + Key = {consumer_credit_to, QPid}, + put(Key, case get(Key) of + 1 -> gen_server2:cast( + QPid, {notify_sent, ChPid, + ?MORE_CONSUMER_CREDIT_AFTER}), + ?MORE_CONSUMER_CREDIT_AFTER; + undefined -> erlang:monitor(process, QPid), + ?MORE_CONSUMER_CREDIT_AFTER - 1; + C -> C - 1 + end), + ok. + +notify_sent_queue_down(QPid) -> + erase({consumer_credit_to, QPid}), + ok. unblock(QPid, ChPid) -> delegate_cast(QPid, {unblock, ChPid}). @@ -518,6 +578,49 @@ slave_pids = [], mirror_nodes = undefined}. +deliver([], #delivery{mandatory = false, immediate = false}, _Flow) -> + %% /dev/null optimisation + {routed, []}; + +deliver(Qs, Delivery = #delivery{mandatory = false, immediate = false}, Flow) -> + %% optimisation: when Mandatory = false and Immediate = false, + %% rabbit_amqqueue:deliver will deliver the message to the queue + %% process asynchronously, and return true, which means all the + %% QPids will always be returned. It is therefore safe to use a + %% fire-and-forget cast here and return the QPids - the semantics + %% is preserved. This scales much better than the non-immediate + %% case below. + QPids = qpids(Qs), + case Flow of + flow -> [credit_flow:send(QPid) || QPid <- QPids]; + noflow -> ok + end, + delegate:invoke_no_result( + QPids, fun (QPid) -> + gen_server2:cast(QPid, {deliver, Delivery, Flow}) + end), + {routed, QPids}; + +deliver(Qs, Delivery = #delivery{mandatory = Mandatory, immediate = Immediate}, + _Flow) -> + QPids = qpids(Qs), + {Success, _} = + delegate:invoke( + QPids, fun (QPid) -> + gen_server2:call(QPid, {deliver, Delivery}, infinity) + end), + case {Mandatory, Immediate, + lists:foldl(fun ({QPid, true}, {_, H}) -> {true, [QPid | H]}; + ({_, false}, {_, H}) -> {true, H} + end, {false, []}, Success)} of + {true, _ , {false, []}} -> {unroutable, []}; + {_ , true, {_ , []}} -> {not_delivered, []}; + {_ , _ , {_ , R}} -> {routed, R} + end. + +qpids(Qs) -> lists:append([[QPid | SPids] || + #amqqueue{pid = QPid, slave_pids = SPids} <- Qs]). + safe_delegate_call_ok(F, Pids) -> case delegate:invoke(Pids, fun (Pid) -> rabbit_misc:with_exit_handler( diff -Nru rabbitmq-server-2.7.1/src/rabbit_amqqueue_process.erl rabbitmq-server-2.8.0/src/rabbit_amqqueue_process.erl --- rabbitmq-server-2.7.1/src/rabbit_amqqueue_process.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_amqqueue_process.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_amqqueue_process). @@ -20,7 +20,7 @@ -behaviour(gen_server2). --define(UNSENT_MESSAGE_LIMIT, 100). +-define(UNSENT_MESSAGE_LIMIT, 200). -define(SYNC_INTERVAL, 25). %% milliseconds -define(RAM_DURATION_UPDATE_INTERVAL, 5000). @@ -49,7 +49,14 @@ stats_timer, msg_id_to_channel, ttl, - ttl_timer_ref + ttl_timer_ref, + publish_seqno, + unconfirmed_mq, + unconfirmed_qm, + delayed_stop, + queue_monitors, + dlx, + dlx_routing_key }). -record(consumer, {tag, ack_required}). @@ -115,7 +122,6 @@ %%---------------------------------------------------------------------------- init(Q) -> - ?LOGDEBUG("Queue starting - ~p~n", [Q]), process_flag(trap_exit, true), State = #q{q = Q#amqqueue{pid = self()}, @@ -129,13 +135,19 @@ rate_timer_ref = undefined, expiry_timer_ref = undefined, ttl = undefined, + dlx = undefined, + dlx_routing_key = undefined, + publish_seqno = 1, + unconfirmed_mq = gb_trees:empty(), + unconfirmed_qm = gb_trees:empty(), + delayed_stop = undefined, + queue_monitors = dict:new(), msg_id_to_channel = gb_trees:empty()}, {ok, rabbit_event:init_stats_timer(State, #q.stats_timer), hibernate, {backoff, ?HIBERNATE_AFTER_MIN, ?HIBERNATE_AFTER_MIN, ?DESIRED_HIBERNATE}}. init_with_backing_queue_state(Q = #amqqueue{exclusive_owner = Owner}, BQ, BQS, RateTRef, AckTags, Deliveries, MTC) -> - ?LOGDEBUG("Queue starting - ~p~n", [Q]), case Owner of none -> ok; _ -> erlang:monitor(process, Owner) @@ -151,6 +163,11 @@ rate_timer_ref = RateTRef, expiry_timer_ref = undefined, ttl = undefined, + publish_seqno = 1, + unconfirmed_mq = gb_trees:empty(), + unconfirmed_qm = gb_trees:empty(), + delayed_stop = undefined, + queue_monitors = dict:new(), msg_id_to_channel = MTC}, State1 = requeue_and_run(AckTags, process_args( rabbit_event:init_stats_timer( @@ -212,18 +229,28 @@ end). process_args(State = #q{q = #amqqueue{arguments = Arguments}}) -> - lists:foldl(fun({Arg, Fun}, State1) -> - case rabbit_misc:table_lookup(Arguments, Arg) of - {_Type, Val} -> Fun(Val, State1); - undefined -> State1 - end - end, State, [{<<"x-expires">>, fun init_expires/2}, - {<<"x-message-ttl">>, fun init_ttl/2}]). + lists:foldl( + fun({Arg, Fun}, State1) -> + case rabbit_misc:table_lookup(Arguments, Arg) of + {_Type, Val} -> Fun(Val, State1); + undefined -> State1 + end + end, State, + [{<<"x-expires">>, fun init_expires/2}, + {<<"x-message-ttl">>, fun init_ttl/2}, + {<<"x-dead-letter-exchange">>, fun init_dlx/2}, + {<<"x-dead-letter-routing-key">>, fun init_dlx_routing_key/2}]). init_expires(Expires, State) -> ensure_expiry_timer(State#q{expires = Expires}). init_ttl(TTL, State) -> drop_expired_messages(State#q{ttl = TTL}). +init_dlx(DLX, State = #q{q = #amqqueue{name = QName}}) -> + State#q{dlx = rabbit_misc:r(QName, exchange, DLX)}. + +init_dlx_routing_key(RoutingKey, State) -> + State#q{dlx_routing_key = RoutingKey}. + terminate_shutdown(Fun, State) -> State1 = #q{backing_queue_state = BQS} = stop_sync_timer(stop_rate_timer(State)), @@ -252,9 +279,9 @@ confirm_messages(MsgIds, State#q{ backing_queue_state = BQS1}))), case BQ:needs_timeout(BQS1) of - false -> {stop_sync_timer(State1), hibernate}; - idle -> {stop_sync_timer(State1), 0 }; - timed -> {ensure_sync_timer(State1), 0 } + false -> {stop_sync_timer(State1), hibernate }; + idle -> {stop_sync_timer(State1), ?SYNC_INTERVAL}; + timed -> {ensure_sync_timer(State1), 0 } end. backing_queue_module(#amqqueue{arguments = Args}) -> @@ -390,34 +417,32 @@ {_, _} -> ok end. -deliver_msgs_to_consumers(Funs = {PredFun, DeliverFun}, FunAcc, +deliver_msgs_to_consumers(_DeliverFun, true, State) -> + {true, State}; +deliver_msgs_to_consumers(DeliverFun, false, State = #q{active_consumers = ActiveConsumers}) -> - case PredFun(FunAcc, State) of - false -> {FunAcc, State}; - true -> case queue:out(ActiveConsumers) of - {empty, _} -> - {FunAcc, State}; - {{value, QEntry}, Tail} -> - {FunAcc1, State1} = - deliver_msg_to_consumer( + case queue:out(ActiveConsumers) of + {empty, _} -> + {false, State}; + {{value, QEntry}, Tail} -> + {Stop, State1} = deliver_msg_to_consumer( DeliverFun, QEntry, - FunAcc, State#q{active_consumers = Tail}), - deliver_msgs_to_consumers(Funs, FunAcc1, State1) - end + State#q{active_consumers = Tail}), + deliver_msgs_to_consumers(DeliverFun, Stop, State1) end. -deliver_msg_to_consumer(DeliverFun, E = {ChPid, Consumer}, FunAcc, State) -> +deliver_msg_to_consumer(DeliverFun, E = {ChPid, Consumer}, State) -> C = ch_record(ChPid), case is_ch_blocked(C) of true -> block_consumer(C, E), - {FunAcc, State}; + {false, State}; false -> case rabbit_limiter:can_send(C#cr.limiter, self(), Consumer#consumer.ack_required) of false -> block_consumer(C#cr{is_limit_active = true}, E), - {FunAcc, State}; + {false, State}; true -> AC1 = queue:in(E, State#q.active_consumers), deliver_msg_to_consumer( - DeliverFun, Consumer, C, FunAcc, + DeliverFun, Consumer, C, State#q{active_consumers = AC1}) end end. @@ -428,9 +453,9 @@ C = #cr{ch_pid = ChPid, acktags = ChAckTags, unsent_message_count = Count}, - FunAcc, State = #q{q = #amqqueue{name = QName}}) -> - {{Message, IsDelivered, AckTag}, FunAcc1, State1} = - DeliverFun(AckRequired, FunAcc, State), + State = #q{q = #amqqueue{name = QName}}) -> + {{Message, IsDelivered, AckTag}, Stop, State1} = + DeliverFun(AckRequired, State), rabbit_channel:deliver(ChPid, ConsumerTag, AckRequired, {QName, self(), AckTag, IsDelivered, Message}), ChAckTags1 = case AckRequired of @@ -439,11 +464,9 @@ end, update_ch_record(C#cr{acktags = ChAckTags1, unsent_message_count = Count + 1}), - {FunAcc1, State1}. - -deliver_from_queue_pred(IsEmpty, _State) -> not IsEmpty. + {Stop, State1}. -deliver_from_queue_deliver(AckRequired, false, State) -> +deliver_from_queue_deliver(AckRequired, State) -> {{Message, IsDelivered, AckTag, Remaining}, State1} = fetch(AckRequired, State), {{Message, IsDelivered, AckTag}, 0 == Remaining, State1}. @@ -455,61 +478,60 @@ lists:foldl( fun(MsgId, {CMs, MTC0}) -> case gb_trees:lookup(MsgId, MTC0) of - {value, {ChPid, MsgSeqNo}} -> - {rabbit_misc:gb_trees_cons(ChPid, MsgSeqNo, CMs), + {value, {SenderPid, MsgSeqNo}} -> + {rabbit_misc:gb_trees_cons(SenderPid, + MsgSeqNo, CMs), gb_trees:delete(MsgId, MTC0)}; none -> {CMs, MTC0} end end, {gb_trees:empty(), MTC}, MsgIds), - rabbit_misc:gb_trees_foreach(fun rabbit_channel:confirm/2, CMs), + rabbit_misc:gb_trees_foreach(fun rabbit_misc:confirm_to_sender/2, CMs), State#q{msg_id_to_channel = MTC1}. should_confirm_message(#delivery{msg_seq_no = undefined}, _State) -> never; -should_confirm_message(#delivery{sender = ChPid, +should_confirm_message(#delivery{sender = SenderPid, msg_seq_no = MsgSeqNo, message = #basic_message { is_persistent = true, id = MsgId}}, #q{q = #amqqueue{durable = true}}) -> - {eventually, ChPid, MsgSeqNo, MsgId}; + {eventually, SenderPid, MsgSeqNo, MsgId}; should_confirm_message(_Delivery, _State) -> immediately. needs_confirming({eventually, _, _, _}) -> true; needs_confirming(_) -> false. -maybe_record_confirm_message({eventually, ChPid, MsgSeqNo, MsgId}, +maybe_record_confirm_message({eventually, SenderPid, MsgSeqNo, MsgId}, State = #q{msg_id_to_channel = MTC}) -> - State#q{msg_id_to_channel = gb_trees:insert(MsgId, {ChPid, MsgSeqNo}, MTC)}; + State#q{msg_id_to_channel = + gb_trees:insert(MsgId, {SenderPid, MsgSeqNo}, MTC)}; maybe_record_confirm_message(_Confirm, State) -> State. run_message_queue(State) -> - Funs = {fun deliver_from_queue_pred/2, - fun deliver_from_queue_deliver/3}, State1 = #q{backing_queue = BQ, backing_queue_state = BQS} = drop_expired_messages(State), - IsEmpty = BQ:is_empty(BQS), - {_IsEmpty1, State2} = deliver_msgs_to_consumers(Funs, IsEmpty, State1), + {_IsEmpty1, State2} = deliver_msgs_to_consumers( + fun deliver_from_queue_deliver/2, + BQ:is_empty(BQS), State1), State2. -attempt_delivery(Delivery = #delivery{sender = ChPid, +attempt_delivery(Delivery = #delivery{sender = SenderPid, message = Message, msg_seq_no = MsgSeqNo}, State = #q{backing_queue = BQ, backing_queue_state = BQS}) -> Confirm = should_confirm_message(Delivery, State), case Confirm of - immediately -> rabbit_channel:confirm(ChPid, [MsgSeqNo]); + immediately -> rabbit_misc:confirm_to_sender(SenderPid, [MsgSeqNo]); _ -> ok end, case BQ:is_duplicate(Message, BQS) of {false, BQS1} -> - PredFun = fun (IsEmpty, _State) -> not IsEmpty end, DeliverFun = - fun (AckRequired, false, - State1 = #q{backing_queue_state = BQS2}) -> + fun (AckRequired, State1 = #q{backing_queue_state = BQS2}) -> %% we don't need an expiry here because %% messages are not being enqueued, so we use %% an empty message_properties. @@ -518,12 +540,12 @@ AckRequired, Message, (?BASE_MESSAGE_PROPERTIES)#message_properties{ needs_confirming = needs_confirming(Confirm)}, - ChPid, BQS2), + SenderPid, BQS2), {{Message, false, AckTag}, true, State1#q{backing_queue_state = BQS3}} end, {Delivered, State2} = - deliver_msgs_to_consumers({ PredFun, DeliverFun }, false, + deliver_msgs_to_consumers(DeliverFun, false, State#q{backing_queue_state = BQS1}), {Delivered, Confirm, State2}; {Duplicate, BQS1} -> @@ -539,7 +561,7 @@ end. deliver_or_enqueue(Delivery = #delivery{message = Message, - sender = ChPid}, State) -> + sender = SenderPid}, State) -> {Delivered, Confirm, State1} = attempt_delivery(Delivery, State), State2 = #q{backing_queue = BQ, backing_queue_state = BQS} = maybe_record_confirm_message(Confirm, State1), @@ -547,7 +569,7 @@ true -> State2; false -> Props = (message_properties(State)) #message_properties{ needs_confirming = needs_confirming(Confirm)}, - BQS1 = BQ:publish(Message, Props, ChPid, BQS), + BQS1 = BQ:publish(Message, Props, SenderPid, BQS), ensure_ttl_timer(State2#q{backing_queue_state = BQS1}) end. @@ -598,6 +620,12 @@ should_auto_delete(State) -> is_unused(State). handle_ch_down(DownPid, State = #q{exclusive_consumer = Holder}) -> + case get({ch_publisher, DownPid}) of + undefined -> ok; + MRef -> erlang:demonitor(MRef), + erase({ch_publisher, DownPid}), + credit_flow:peer_down(DownPid) + end, case lookup_ch(DownPid) of not_found -> {ok, State}; @@ -662,11 +690,11 @@ Fun(State) end. -discard_delivery(#delivery{sender = ChPid, +discard_delivery(#delivery{sender = SenderPid, message = Message}, State = #q{backing_queue = BQ, backing_queue_state = BQS}) -> - State#q{backing_queue_state = BQ:discard(Message, ChPid, BQS)}. + State#q{backing_queue_state = BQ:discard(Message, SenderPid, BQS)}. message_properties(#q{ttl=TTL}) -> #message_properties{expiry = calculate_msg_expiry(TTL)}. @@ -677,10 +705,11 @@ drop_expired_messages(State = #q{ttl = undefined}) -> State; drop_expired_messages(State = #q{backing_queue_state = BQS, - backing_queue = BQ}) -> + backing_queue = BQ}) -> Now = now_micros(), BQS1 = BQ:dropwhile( fun (#message_properties{expiry = Expiry}) -> Now > Expiry end, + dead_letter_fun(expired, State), BQS), ensure_ttl_timer(State#q{backing_queue_state = BQS1}). @@ -697,6 +726,199 @@ ensure_ttl_timer(State) -> State. +dead_letter_fun(_Reason, #q{dlx = undefined}) -> + undefined; +dead_letter_fun(Reason, _State) -> + fun(Msg, AckTag) -> + gen_server2:cast(self(), {dead_letter, {Msg, AckTag}, Reason}) + end. + +dead_letter_msg(Msg, AckTag, Reason, State = #q{dlx = DLX}) -> + case rabbit_exchange:lookup(DLX) of + {error, not_found} -> + noreply(State); + _ -> + dead_letter_msg_existing_dlx(Msg, AckTag, Reason, State) + end. + +dead_letter_msg_existing_dlx(Msg, AckTag, Reason, + State = #q{publish_seqno = MsgSeqNo, + unconfirmed_mq = UMQ, + dlx = DLX, + backing_queue = BQ, + backing_queue_state = BQS}) -> + {ok, _, QPids} = + rabbit_basic:publish( + rabbit_basic:delivery( + false, false, make_dead_letter_msg(DLX, Reason, Msg, State), + MsgSeqNo)), + State1 = lists:foldl(fun monitor_queue/2, State, QPids), + State2 = State1#q{publish_seqno = MsgSeqNo + 1}, + case QPids of + [] -> {_, BQS1} = BQ:ack([AckTag], BQS), + cleanup_after_confirm(State2#q{backing_queue_state = BQS1}); + _ -> State3 = + lists:foldl( + fun(QPid, State0 = #q{unconfirmed_qm = UQM}) -> + UQM1 = rabbit_misc:gb_trees_set_insert( + QPid, MsgSeqNo, UQM), + State0#q{unconfirmed_qm = UQM1} + end, State2, QPids), + noreply(State3#q{ + unconfirmed_mq = + gb_trees:insert( + MsgSeqNo, {gb_sets:from_list(QPids), + AckTag}, UMQ)}) + end. + +monitor_queue(QPid, State = #q{queue_monitors = QMons}) -> + case dict:is_key(QPid, QMons) of + true -> State; + false -> State#q{queue_monitors = + dict:store(QPid, erlang:monitor(process, QPid), + QMons)} + end. + +demonitor_queue(QPid, State = #q{queue_monitors = QMons}) -> + case dict:find(QPid, QMons) of + {ok, MRef} -> erlang:demonitor(MRef), + State#q{queue_monitors = dict:erase(QPid, QMons)}; + error -> State + end. + +handle_queue_down(QPid, Reason, State = #q{queue_monitors = QMons, + unconfirmed_qm = UQM}) -> + case dict:find(QPid, QMons) of + error -> + noreply(State); + {ok, _} -> + #resource{name = QName} = qname(State), + rabbit_log:info("DLQ ~p (for ~p) died~n", [QPid, QName]), + case gb_trees:lookup(QPid, UQM) of + none -> + noreply(State); + {value, MsgSeqNosSet} -> + case rabbit_misc:is_abnormal_termination(Reason) of + true -> rabbit_log:warning( + "Dead queue lost ~p messages~n", + [gb_sets:size(MsgSeqNosSet)]); + false -> ok + end, + handle_confirm(gb_sets:to_list(MsgSeqNosSet), QPid, + State#q{queue_monitors = + dict:erase(QPid, QMons)}) + end + end. + +handle_confirm(MsgSeqNos, QPid, State = #q{unconfirmed_mq = UMQ, + unconfirmed_qm = UQM, + backing_queue = BQ, + backing_queue_state = BQS}) -> + {AckTags1, UMQ3} = + lists:foldl( + fun (MsgSeqNo, {AckTags, UMQ1}) -> + {QPids, AckTag} = gb_trees:get(MsgSeqNo, UMQ1), + QPids1 = gb_sets:delete(QPid, QPids), + case gb_sets:is_empty(QPids1) of + true -> {[AckTag | AckTags], + gb_trees:delete(MsgSeqNo, UMQ1)}; + false -> {AckTags, gb_trees:update( + MsgSeqNo, {QPids1, AckTag}, UMQ1)} + end + end, {[], UMQ}, MsgSeqNos), + {_Guids, BQS1} = BQ:ack(AckTags1, BQS), + MsgSeqNos1 = gb_sets:difference(gb_trees:get(QPid, UQM), + gb_sets:from_list(MsgSeqNos)), + State1 = case gb_sets:is_empty(MsgSeqNos1) of + false -> State#q{ + unconfirmed_qm = + gb_trees:update(QPid, MsgSeqNos1, UQM)}; + true -> demonitor_queue( + QPid, State#q{ + unconfirmed_qm = + gb_trees:delete(QPid, UQM)}) + end, + cleanup_after_confirm(State1#q{unconfirmed_mq = UMQ3, + backing_queue_state = BQS1}). + +stop_later(Reason, State) -> + stop_later(Reason, undefined, noreply, State). + +stop_later(Reason, From, Reply, State = #q{unconfirmed_mq = UMQ}) -> + case {gb_trees:is_empty(UMQ), Reply} of + {true, noreply} -> + {stop, Reason, State}; + {true, _} -> + {stop, Reason, Reply, State}; + {false, _} -> + noreply(State#q{delayed_stop = {Reason, {From, Reply}}}) + end. + +cleanup_after_confirm(State = #q{delayed_stop = DS, + unconfirmed_mq = UMQ}) -> + case gb_trees:is_empty(UMQ) andalso DS =/= undefined of + true -> case DS of + {_, {_, noreply}} -> ok; + {_, {From, Reply}} -> gen_server2:reply(From, Reply) + end, + {Reason, _} = DS, + {stop, Reason, State}; + false -> noreply(State) + end. + +already_been_here(_Delivery, #q{dlx = undefined}) -> + false; +already_been_here(#delivery{message = #basic_message{content = Content}}, + State) -> + #content{properties = #'P_basic'{headers = Headers}} = + rabbit_binary_parser:ensure_content_decoded(Content), + #resource{name = QueueName} = qname(State), + case Headers of + undefined -> + false; + _ -> + case rabbit_misc:table_lookup(Headers, <<"x-death">>) of + {array, DeathTables} -> + OldQueues = [rabbit_misc:table_lookup(D, <<"queue">>) || + {table, D} <- DeathTables], + OldQueues1 = [QName || {longstr, QName} <- OldQueues], + case lists:member(QueueName, OldQueues1) of + true -> [QueueName | OldQueues1]; + _ -> false + end; + _ -> + false + end + end. + +make_dead_letter_msg(DLX, Reason, + Msg = #basic_message{content = Content, + exchange_name = Exchange, + routing_keys = RoutingKeys}, + State = #q{dlx_routing_key = DlxRoutingKey}) -> + Headers = rabbit_basic:extract_headers(Content), + #resource{name = QName} = qname(State), + %% The first routing key is the one specified in the + %% basic.publish; all others are CC or BCC keys. + RoutingKeys1 = [hd(RoutingKeys) | rabbit_basic:header_routes(Headers)], + Info = [{<<"reason">>, longstr, list_to_binary(atom_to_list(Reason))}, + {<<"queue">>, longstr, QName}, + {<<"time">>, timestamp, rabbit_misc:now_ms() div 1000}, + {<<"exchange">>, longstr, Exchange#resource.name}, + {<<"routing-keys">>, array, + [{longstr, Key} || Key <- RoutingKeys1]}], + Headers1 = rabbit_basic:append_table_header(<<"x-death">>, Info, Headers), + {DeathRoutingKeys, Headers2} = + case DlxRoutingKey of + undefined -> {RoutingKeys, Headers1}; + _ -> {[DlxRoutingKey], + lists:keydelete(<<"CC">>, 1, Headers1)} + end, + Content1 = rabbit_basic:replace_headers(Headers2, Content), + Msg#basic_message{exchange_name = DLX, id = rabbit_guid:gen(), + routing_keys = DeathRoutingKeys, content = Content1}. + + now_micros() -> timer:now_diff(now(), {0,0,0}). infos(Items, State) -> @@ -713,15 +935,12 @@ || Item <- (Items1 -- [synchronised_slave_pids])]. slaves_status(#q{q = #amqqueue{name = Name}}) -> - {ok, #amqqueue{mirror_nodes = MNodes, slave_pids = SPids}} = - rabbit_amqqueue:lookup(Name), - case MNodes of - undefined -> + case rabbit_amqqueue:lookup(Name) of + {ok, #amqqueue{mirror_nodes = undefined}} -> [{slave_pids, ''}, {synchronised_slave_pids, ''}]; - _ -> + {ok, #amqqueue{slave_pids = SPids}} -> {Results, _Bad} = - delegate:invoke( - SPids, fun (Pid) -> rabbit_mirror_queue_slave:info(Pid) end), + delegate:invoke(SPids, fun rabbit_mirror_queue_slave:info/1), {SPids1, SSPids} = lists:foldl( fun ({Pid, Infos}, {SPidsN, SSPidsN}) -> @@ -765,11 +984,9 @@ {memory, M} = process_info(self(), memory), M; i(slave_pids, #q{q = #amqqueue{name = Name}}) -> - {ok, #amqqueue{mirror_nodes = MNodes, - slave_pids = SPids}} = rabbit_amqqueue:lookup(Name), - case MNodes of - undefined -> []; - _ -> SPids + case rabbit_amqqueue:lookup(Name) of + {ok, #amqqueue{mirror_nodes = undefined}} -> []; + {ok, #amqqueue{slave_pids = SPids}} -> SPids end; i(backing_queue_status, #q{backing_queue_state = BQS, backing_queue = BQ}) -> BQ:status(BQS); @@ -826,7 +1043,7 @@ {set_maximum_since_use, _Age} -> 8; {ack, _AckTags, _ChPid} -> 7; {reject, _AckTags, _Requeue, _ChPid} -> 7; - {notify_sent, _ChPid} -> 7; + {notify_sent, _ChPid, _Credit} -> 7; {unblock, _ChPid} -> 7; {run_backing_queue, _Mod, _Fun} -> 6; _ -> 0 @@ -843,6 +1060,9 @@ _ -> 0 end. +handle_call(_, _, State = #q{delayed_stop = DS}) when DS =/= undefined -> + noreply(State); + handle_call({init, Recover}, From, State = #q{q = #amqqueue{exclusive_owner = none}}) -> declare(Recover, From, State); @@ -877,9 +1097,7 @@ handle_call(consumers, _From, State) -> reply(consumers(State), State); -handle_call({deliver_immediately, Delivery}, _From, State) -> - %% Synchronous, "immediate" delivery mode - %% +handle_call({deliver, Delivery = #delivery{immediate = true}}, _From, State) -> %% FIXME: Is this correct semantics? %% %% I'm worried in particular about the case where an exchange has @@ -897,20 +1115,19 @@ false -> discard_delivery(Delivery, State1) end); -handle_call({deliver, Delivery}, From, State) -> - %% Synchronous, "mandatory" delivery mode. Reply asap. +handle_call({deliver, Delivery = #delivery{mandatory = true}}, From, State) -> gen_server2:reply(From, true), noreply(deliver_or_enqueue(Delivery, State)); -handle_call({notify_down, ChPid}, _From, State) -> +handle_call({notify_down, ChPid}, From, State) -> %% we want to do this synchronously, so that auto_deleted queues %% are no longer visible by the time we send a response to the %% client. The queue is ultimately deleted in terminate/2; if we %% return stop with a reply, terminate/2 will be called by %% gen_server2 *before* the reply is sent. case handle_ch_down(ChPid, State) of - {ok, NewState} -> reply(ok, NewState); - {stop, NewState} -> {stop, normal, ok, NewState} + {ok, State1} -> reply(ok, State1); + {stop, State1} -> stop_later(normal, From, ok, State1) end; handle_call({basic_get, ChPid, NoAck}, _From, @@ -965,7 +1182,7 @@ reply(ok, State2) end; -handle_call({basic_cancel, ChPid, ConsumerTag, OkMsg}, _From, +handle_call({basic_cancel, ChPid, ConsumerTag, OkMsg}, From, State = #q{exclusive_consumer = Holder}) -> ok = maybe_send_reply(ChPid, OkMsg), case lookup_ch(ChPid) of @@ -985,7 +1202,7 @@ State#q.active_consumers)}, case should_auto_delete(State1) of false -> reply(ok, ensure_expiry_timer(State1)); - true -> {stop, normal, ok, State1} + true -> stop_later(normal, From, ok, State1) end end; @@ -994,20 +1211,18 @@ drop_expired_messages(ensure_expiry_timer(State)), reply({ok, BQ:len(BQS), active_consumer_count()}, State1); -handle_call({delete, IfUnused, IfEmpty}, _From, +handle_call({delete, IfUnused, IfEmpty}, From, State = #q{backing_queue_state = BQS, backing_queue = BQ}) -> IsEmpty = BQ:is_empty(BQS), IsUnused = is_unused(State), if - IfEmpty and not(IsEmpty) -> - reply({error, not_empty}, State); - IfUnused and not(IsUnused) -> - reply({error, in_use}, State); - true -> - {stop, normal, {ok, BQ:len(BQS)}, State} + IfEmpty and not(IsEmpty) -> reply({error, not_empty}, State); + IfUnused and not(IsUnused) -> reply({error, in_use}, State); + true -> stop_later(normal, From, + {ok, BQ:len(BQS)}, State) end; -handle_call(purge, _From, State = #q{backing_queue = BQ, +handle_call(purge, _From, State = #q{backing_queue = BQ, backing_queue_state = BQS}) -> {Count, BQS1} = BQ:purge(BQS), reply({ok, Count}, State#q{backing_queue_state = BQS1}); @@ -1016,14 +1231,47 @@ gen_server2:reply(From, ok), noreply(subtract_acks( ChPid, AckTags, State, - fun (State1) -> requeue_and_run(AckTags, State1) end)). + fun (State1) -> requeue_and_run(AckTags, State1) end)); + +handle_call(force_event_refresh, _From, + State = #q{exclusive_consumer = Exclusive}) -> + rabbit_event:notify(queue_created, infos(?CREATION_EVENT_KEYS, State)), + case Exclusive of + none -> [emit_consumer_created(Ch, CTag, false, AckRequired) || + {Ch, CTag, AckRequired} <- consumers(State)]; + {Ch, CTag} -> [{Ch, CTag, AckRequired}] = consumers(State), + emit_consumer_created(Ch, CTag, true, AckRequired) + end, + reply(ok, State). + +handle_cast({confirm, MsgSeqNos, QPid}, State) -> + handle_confirm(MsgSeqNos, QPid, State); + +handle_cast(_, State = #q{delayed_stop = DS}) when DS =/= undefined -> + noreply(State); handle_cast({run_backing_queue, Mod, Fun}, State) -> noreply(run_backing_queue(Mod, Fun, State)); -handle_cast({deliver, Delivery}, State) -> +handle_cast({deliver, Delivery = #delivery{sender = Sender, + msg_seq_no = MsgSeqNo}, Flow}, + State) -> %% Asynchronous, non-"mandatory", non-"immediate" deliver mode. - noreply(deliver_or_enqueue(Delivery, State)); + case Flow of + flow -> Key = {ch_publisher, Sender}, + case get(Key) of + undefined -> put(Key, erlang:monitor(process, Sender)); + _ -> ok + end, + credit_flow:ack(Sender); + noflow -> ok + end, + case already_been_here(Delivery, State) of + false -> noreply(deliver_or_enqueue(Delivery, State)); + Qs -> log_cycle_once(Qs), + rabbit_misc:confirm_to_sender(Sender, [MsgSeqNo]), + noreply(State) + end; handle_cast({ack, AckTags, ChPid}, State) -> noreply(subtract_acks( @@ -1041,24 +1289,25 @@ backing_queue_state = BQS}) -> case Requeue of true -> requeue_and_run(AckTags, State1); - false -> {_Guids, BQS1} = BQ:ack(AckTags, BQS), + false -> Fun = dead_letter_fun(rejected, State), + BQS1 = BQ:fold(Fun, BQS, AckTags), State1#q{backing_queue_state = BQS1} end end)); handle_cast(delete_immediately, State) -> - {stop, normal, State}; + stop_later(normal, State); handle_cast({unblock, ChPid}, State) -> noreply( possibly_unblock(State, ChPid, fun (C) -> C#cr{is_limit_active = false} end)); -handle_cast({notify_sent, ChPid}, State) -> +handle_cast({notify_sent, ChPid, Credit}, State) -> noreply( possibly_unblock(State, ChPid, fun (C = #cr{unsent_message_count = Count}) -> - C#cr{unsent_message_count = Count - 1} + C#cr{unsent_message_count = Count - Credit} end)); handle_cast({limit, ChPid, Limiter}, State) -> @@ -1090,20 +1339,21 @@ ok = file_handle_cache:set_maximum_since_use(Age), noreply(State); -handle_cast(force_event_refresh, State = #q{exclusive_consumer = Exclusive}) -> - rabbit_event:notify(queue_created, infos(?CREATION_EVENT_KEYS, State)), - case Exclusive of - none -> [emit_consumer_created(Ch, CTag, false, AckRequired) || - {Ch, CTag, AckRequired} <- consumers(State)]; - {Ch, CTag} -> [{Ch, CTag, AckRequired}] = consumers(State), - emit_consumer_created(Ch, CTag, true, AckRequired) - end, - noreply(State). +handle_cast({dead_letter, {Msg, AckTag}, Reason}, State) -> + dead_letter_msg(Msg, AckTag, Reason, State). + +%% We need to not ignore this as we need to remove outstanding +%% confirms due to queue death. +handle_info({'DOWN', _MonitorRef, process, DownPid, Reason}, + State = #q{delayed_stop = DS}) when DS =/= undefined -> + handle_queue_down(DownPid, Reason, State); + +handle_info(_, State = #q{delayed_stop = DS}) when DS =/= undefined -> + noreply(State); handle_info(maybe_expire, State) -> case is_unused(State) of - true -> ?LOGDEBUG("Queue lease expired for ~p~n", [State#q.q]), - {stop, normal, State}; + true -> stop_later(normal, State); false -> noreply(ensure_expiry_timer(State)) end; @@ -1125,11 +1375,12 @@ %% match what people expect (see bug 21824). However we need this %% monitor-and-async- delete in case the connection goes away %% unexpectedly. - {stop, normal, State}; -handle_info({'DOWN', _MonitorRef, process, DownPid, _Reason}, State) -> + stop_later(normal, State); + +handle_info({'DOWN', _MonitorRef, process, DownPid, Reason}, State) -> case handle_ch_down(DownPid, State) of - {ok, NewState} -> noreply(NewState); - {stop, NewState} -> {stop, normal, NewState} + {ok, State1} -> handle_queue_down(DownPid, Reason, State1); + {stop, State1} -> stop_later(normal, State1) end; handle_info(update_ram_duration, State = #q{backing_queue = BQ, @@ -1150,8 +1401,11 @@ handle_info({'EXIT', _Pid, Reason}, State) -> {stop, Reason, State}; +handle_info({bump_credit, Msg}, State) -> + credit_flow:handle_bump_msg(Msg), + noreply(State); + handle_info(Info, State) -> - ?LOGDEBUG("Info in queue: ~p~n", [Info]), {stop, {unhandled_info, Info}, State}. handle_pre_hibernate(State = #q{backing_queue_state = undefined}) -> @@ -1171,3 +1425,14 @@ {hibernate, stop_rate_timer(State1)}. format_message_queue(Opt, MQ) -> rabbit_misc:format_message_queue(Opt, MQ). + +log_cycle_once(Queues) -> + Key = {queue_cycle, Queues}, + case get(Key) of + true -> ok; + undefined -> rabbit_log:warning( + "Message dropped. Dead-letter queues cycle detected" ++ + ": ~p~nThis cycle will NOT be reported again.~n", + [Queues]), + put(Key, true) + end. diff -Nru rabbitmq-server-2.7.1/src/rabbit_amqqueue_sup.erl rabbitmq-server-2.8.0/src/rabbit_amqqueue_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_amqqueue_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_amqqueue_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_amqqueue_sup). diff -Nru rabbitmq-server-2.7.1/src/rabbit_auth_backend.erl rabbitmq-server-2.8.0/src/rabbit_auth_backend.erl --- rabbitmq-server-2.7.1/src/rabbit_auth_backend.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_auth_backend.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend). diff -Nru rabbitmq-server-2.7.1/src/rabbit_auth_backend_internal.erl rabbitmq-server-2.8.0/src/rabbit_auth_backend_internal.erl --- rabbitmq-server-2.7.1/src/rabbit_auth_backend_internal.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_auth_backend_internal.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_backend_internal). diff -Nru rabbitmq-server-2.7.1/src/rabbit_auth_mechanism.erl rabbitmq-server-2.8.0/src/rabbit_auth_mechanism.erl --- rabbitmq-server-2.7.1/src/rabbit_auth_mechanism.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_auth_mechanism.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_mechanism). diff -Nru rabbitmq-server-2.7.1/src/rabbit_auth_mechanism_amqplain.erl rabbitmq-server-2.8.0/src/rabbit_auth_mechanism_amqplain.erl --- rabbitmq-server-2.7.1/src/rabbit_auth_mechanism_amqplain.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_auth_mechanism_amqplain.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_mechanism_amqplain). diff -Nru rabbitmq-server-2.7.1/src/rabbit_auth_mechanism_cr_demo.erl rabbitmq-server-2.8.0/src/rabbit_auth_mechanism_cr_demo.erl --- rabbitmq-server-2.7.1/src/rabbit_auth_mechanism_cr_demo.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_auth_mechanism_cr_demo.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_mechanism_cr_demo). diff -Nru rabbitmq-server-2.7.1/src/rabbit_auth_mechanism_plain.erl rabbitmq-server-2.8.0/src/rabbit_auth_mechanism_plain.erl --- rabbitmq-server-2.7.1/src/rabbit_auth_mechanism_plain.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_auth_mechanism_plain.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_auth_mechanism_plain). diff -Nru rabbitmq-server-2.7.1/src/rabbit_backing_queue.erl rabbitmq-server-2.8.0/src/rabbit_backing_queue.erl --- rabbitmq-server-2.7.1/src/rabbit_backing_queue.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_backing_queue.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_backing_queue). @@ -95,16 +95,24 @@ {drain_confirmed, 1}, %% Drop messages from the head of the queue while the supplied - %% predicate returns true. - {dropwhile, 2}, + %% predicate returns true. A callback function is supplied + %% allowing callers access to messages that are about to be + %% dropped. + {dropwhile, 3}, %% Produce the next message. {fetch, 2}, %% Acktags supplied are for messages which can now be forgotten - %% about. Must return 1 msg_id per Ack, in the same order as Acks. + %% about. Must return 1 msg_id per Ack, in the same order as + %% Acks. {ack, 2}, + %% Acktags supplied are for messages which should be + %% processed. The provided callback function is called with each + %% message. + {fold, 3}, + %% Reinsert messages into the queue which have already been %% delivered and were pending acknowledgement. {requeue, 2}, diff -Nru rabbitmq-server-2.7.1/src/rabbit_backing_queue_qc.erl rabbitmq-server-2.8.0/src/rabbit_backing_queue_qc.erl --- rabbitmq-server-2.7.1/src/rabbit_backing_queue_qc.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_backing_queue_qc.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_backing_queue_qc). diff -Nru rabbitmq-server-2.7.1/src/rabbit_basic.erl rabbitmq-server-2.8.0/src/rabbit_basic.erl --- rabbitmq-server-2.7.1/src/rabbit_basic.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_basic.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_basic). @@ -19,7 +19,8 @@ -include("rabbit_framing.hrl"). -export([publish/4, publish/6, publish/1, - message/3, message/4, properties/1, delivery/4]). + message/3, message/4, properties/1, append_table_header/3, + extract_headers/1, replace_headers/2, delivery/4, header_routes/1]). -export([build_content/2, from_content/1]). %%---------------------------------------------------------------------------- @@ -29,8 +30,9 @@ -type(properties_input() :: (rabbit_framing:amqp_property_record() | [{atom(), any()}])). -type(publish_result() :: - ({ok, rabbit_router:routing_result(), [pid()]} + ({ok, rabbit_amqqueue:routing_result(), [pid()]} | rabbit_types:error('not_found'))). +-type(headers() :: rabbit_framing:amqp_table() | 'undefined'). -type(exchange_input() :: (rabbit_types:exchange() | rabbit_exchange:name())). -type(body_input() :: (binary() | [binary()])). @@ -55,6 +57,17 @@ rabbit_types:ok_or_error2(rabbit_types:message(), any())). -spec(properties/1 :: (properties_input()) -> rabbit_framing:amqp_property_record()). + +-spec(append_table_header/3 :: + (binary(), rabbit_framing:amqp_table(), headers()) -> headers()). + +-spec(extract_headers/1 :: (rabbit_types:content()) -> headers()). + +-spec(replace_headers/2 :: (headers(), rabbit_types:content()) + -> rabbit_types:content()). + +-spec(header_routes/1 :: + (undefined | rabbit_framing:amqp_table()) -> [string()]). -spec(build_content/2 :: (rabbit_framing:amqp_property_record(), binary() | [binary()]) -> rabbit_types:content()). -spec(from_content/1 :: (rabbit_types:content()) -> @@ -88,8 +101,8 @@ end. publish(X, Delivery) -> - {RoutingRes, DeliveredQPids} = - rabbit_router:deliver(rabbit_exchange:route(X, Delivery), Delivery), + Qs = rabbit_amqqueue:lookup(rabbit_exchange:route(X, Delivery)), + {RoutingRes, DeliveredQPids} = rabbit_amqqueue:deliver(Qs, Delivery), {ok, RoutingRes, DeliveredQPids}. delivery(Mandatory, Immediate, Message, MsgSeqNo) -> @@ -139,7 +152,7 @@ {ok, #basic_message{ exchange_name = XName, content = strip_header(DecodedContent, ?DELETED_HEADER), - id = rabbit_guid:guid(), + id = rabbit_guid:gen(), is_persistent = is_message_persistent(DecodedContent), routing_keys = [RoutingKey | header_routes(Props#'P_basic'.headers)]}} @@ -166,6 +179,24 @@ end end, #'P_basic'{}, P). +append_table_header(Name, Info, undefined) -> + append_table_header(Name, Info, []); +append_table_header(Name, Info, Headers) -> + Prior = case rabbit_misc:table_lookup(Headers, Name) of + undefined -> []; + {array, Existing} -> Existing + end, + rabbit_misc:set_table_value(Headers, Name, array, [{table, Info} | Prior]). + +extract_headers(Content) -> + #content{properties = #'P_basic'{headers = Headers}} = + rabbit_binary_parser:ensure_content_decoded(Content), + Headers. + +replace_headers(Headers, Content = #content{properties = Props}) -> + rabbit_binary_generator:clear_encoded_content( + Content#content{properties = Props#'P_basic'{headers = Headers}}). + indexof(L, Element) -> indexof(L, Element, 1). indexof([], _Element, _N) -> 0; diff -Nru rabbitmq-server-2.7.1/src/rabbit_binary_generator.erl rabbitmq-server-2.8.0/src/rabbit_binary_generator.erl --- rabbitmq-server-2.7.1/src/rabbit_binary_generator.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_binary_generator.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_binary_generator). diff -Nru rabbitmq-server-2.7.1/src/rabbit_binary_parser.erl rabbitmq-server-2.8.0/src/rabbit_binary_parser.erl --- rabbitmq-server-2.7.1/src/rabbit_binary_parser.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_binary_parser.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_binary_parser). diff -Nru rabbitmq-server-2.7.1/src/rabbit_binding.erl rabbitmq-server-2.8.0/src/rabbit_binding.erl --- rabbitmq-server-2.7.1/src/rabbit_binding.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_binding.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_binding). @@ -354,8 +354,8 @@ %% For bulk operations we lock the tables we are operating on in order %% to reduce the time complexity. Without the table locks we end up -%% with num_tables*num_bulk_bindings row-level locks. Takiing each -%% lock takes time proportional to the number of existing locks, thus +%% with num_tables*num_bulk_bindings row-level locks. Taking each lock +%% takes time proportional to the number of existing locks, thus %% resulting in O(num_bulk_bindings^2) complexity. %% %% The locks need to be write locks since ultimately we end up diff -Nru rabbitmq-server-2.7.1/src/rabbit_channel.erl rabbitmq-server-2.8.0/src/rabbit_channel.erl --- rabbitmq-server-2.7.1/src/rabbit_channel.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_channel.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_channel). @@ -20,8 +20,8 @@ -behaviour(gen_server2). --export([start_link/10, do/2, do/3, flush/1, shutdown/1]). --export([send_command/2, deliver/4, flushed/2, confirm/2]). +-export([start_link/11, do/2, do/3, do_flow/3, flush/1, shutdown/1]). +-export([send_command/2, deliver/4, flushed/2]). -export([list/0, info_keys/0, info/1, info/2, info_all/0, info_all/1]). -export([refresh_config_local/0, ready_for_close/1]). -export([force_event_refresh/0]). @@ -33,9 +33,9 @@ -export([list_local/0]). -record(ch, {state, protocol, channel, reader_pid, writer_pid, conn_pid, - limiter, tx_status, next_tag, - unacked_message_q, uncommitted_message_q, uncommitted_acks, - user, virtual_host, most_recently_declared_queue, queue_monitors, + conn_name, limiter, tx_status, next_tag, unacked_message_q, + uncommitted_message_q, uncommitted_acks, uncommitted_nacks, user, + virtual_host, most_recently_declared_queue, queue_monitors, consumer_mapping, blocking, queue_consumers, queue_collector_pid, stats_timer, confirm_enabled, publish_seqno, unconfirmed_mq, unconfirmed_qm, confirmed, capabilities, trace_state}). @@ -56,6 +56,7 @@ -define(CREATION_EVENT_KEYS, [pid, + name, connection, number, user, @@ -71,13 +72,16 @@ -type(channel_number() :: non_neg_integer()). --spec(start_link/10 :: - (channel_number(), pid(), pid(), pid(), rabbit_types:protocol(), - rabbit_types:user(), rabbit_types:vhost(), rabbit_framing:amqp_table(), +-spec(start_link/11 :: + (channel_number(), pid(), pid(), pid(), string(), + rabbit_types:protocol(), rabbit_types:user(), rabbit_types:vhost(), + rabbit_framing:amqp_table(), pid(), rabbit_limiter:token()) -> rabbit_types:ok_pid_or_error()). -spec(do/2 :: (pid(), rabbit_framing:amqp_method_record()) -> 'ok'). -spec(do/3 :: (pid(), rabbit_framing:amqp_method_record(), rabbit_types:maybe(rabbit_types:content())) -> 'ok'). +-spec(do_flow/3 :: (pid(), rabbit_framing:amqp_method_record(), + rabbit_types:maybe(rabbit_types:content())) -> 'ok'). -spec(flush/1 :: (pid()) -> 'ok'). -spec(shutdown/1 :: (pid()) -> 'ok'). -spec(send_command/2 :: (pid(), rabbit_framing:amqp_method_record()) -> 'ok'). @@ -85,7 +89,6 @@ (pid(), rabbit_types:ctag(), boolean(), rabbit_amqqueue:qmsg()) -> 'ok'). -spec(flushed/2 :: (pid(), pid()) -> 'ok'). --spec(confirm/2 ::(pid(), [non_neg_integer()]) -> 'ok'). -spec(list/0 :: () -> [pid()]). -spec(list_local/0 :: () -> [pid()]). -spec(info_keys/0 :: () -> rabbit_types:info_keys()). @@ -101,17 +104,21 @@ %%---------------------------------------------------------------------------- -start_link(Channel, ReaderPid, WriterPid, ConnPid, Protocol, User, VHost, - Capabilities, CollectorPid, Limiter) -> +start_link(Channel, ReaderPid, WriterPid, ConnPid, ConnName, Protocol, User, + VHost, Capabilities, CollectorPid, Limiter) -> gen_server2:start_link( - ?MODULE, [Channel, ReaderPid, WriterPid, ConnPid, Protocol, User, - VHost, Capabilities, CollectorPid, Limiter], []). + ?MODULE, [Channel, ReaderPid, WriterPid, ConnPid, ConnName, Protocol, + User, VHost, Capabilities, CollectorPid, Limiter], []). do(Pid, Method) -> do(Pid, Method, none). do(Pid, Method, Content) -> - gen_server2:cast(Pid, {method, Method, Content}). + gen_server2:cast(Pid, {method, Method, Content, noflow}). + +do_flow(Pid, Method, Content) -> + credit_flow:send(Pid), + gen_server2:cast(Pid, {method, Method, Content, flow}). flush(Pid) -> gen_server2:call(Pid, flush, infinity). @@ -128,9 +135,6 @@ flushed(Pid, QPid) -> gen_server2:cast(Pid, {flushed, QPid}). -confirm(Pid, MsgSeqNos) -> - gen_server2:cast(Pid, {confirm, MsgSeqNos, self()}). - list() -> rabbit_misc:append_rpc_all_nodes(rabbit_mnesia:running_clustered_nodes(), rabbit_channel, list_local, []). @@ -169,7 +173,7 @@ %%--------------------------------------------------------------------------- -init([Channel, ReaderPid, WriterPid, ConnPid, Protocol, User, VHost, +init([Channel, ReaderPid, WriterPid, ConnPid, ConnName, Protocol, User, VHost, Capabilities, CollectorPid, Limiter]) -> process_flag(trap_exit, true), ok = pg_local:join(rabbit_channels, self()), @@ -179,16 +183,18 @@ reader_pid = ReaderPid, writer_pid = WriterPid, conn_pid = ConnPid, + conn_name = ConnName, limiter = Limiter, tx_status = none, next_tag = 1, unacked_message_q = queue:new(), uncommitted_message_q = queue:new(), uncommitted_acks = [], + uncommitted_nacks = [], user = User, virtual_host = VHost, most_recently_declared_queue = <<>>, - queue_monitors = dict:new(), + queue_monitors = sets:new(), consumer_mapping = dict:new(), blocking = sets:new(), queue_consumers = dict:new(), @@ -244,7 +250,12 @@ handle_call(_Request, _From, State) -> noreply(State). -handle_cast({method, Method, Content}, State) -> +handle_cast({method, Method, Content, Flow}, + State = #ch{reader_pid = Reader}) -> + case Flow of + flow -> credit_flow:ack(Reader); + noflow -> ok + end, try handle_method(Method, Content, State) of {reply, Reply, NewState} -> ok = rabbit_writer:send_command(NewState#ch.writer_pid, Reply), @@ -284,29 +295,19 @@ handle_cast({deliver, ConsumerTag, AckRequired, Msg = {_QName, QPid, _MsgId, Redelivered, #basic_message{exchange_name = ExchangeName, - routing_keys = [RoutingKey | _CcRoutes], - content = Content}}}, - State = #ch{writer_pid = WriterPid, - next_tag = DeliveryTag, - trace_state = TraceState}) -> - State1 = lock_message(AckRequired, - ack_record(DeliveryTag, ConsumerTag, Msg), - State), - - M = #'basic.deliver'{consumer_tag = ConsumerTag, - delivery_tag = DeliveryTag, - redelivered = Redelivered, - exchange = ExchangeName#resource.name, - routing_key = RoutingKey}, - rabbit_writer:send_command_and_notify(WriterPid, QPid, self(), M, Content), - State2 = maybe_incr_stats([{QPid, 1}], case AckRequired of - true -> deliver; - false -> deliver_no_ack - end, State1), - State3 = maybe_incr_redeliver_stats(Redelivered, QPid, State2), - rabbit_trace:tap_trace_out(Msg, TraceState), - noreply(State3#ch{next_tag = DeliveryTag + 1}); - + routing_keys = [RoutingKey | _CcRoutes], + content = Content}}}, + State = #ch{writer_pid = WriterPid, + next_tag = DeliveryTag}) -> + ok = rabbit_writer:send_command_and_notify( + WriterPid, QPid, self(), + #'basic.deliver'{consumer_tag = ConsumerTag, + delivery_tag = DeliveryTag, + redelivered = Redelivered, + exchange = ExchangeName#resource.name, + routing_key = RoutingKey}, + Content), + noreply(record_sent(ConsumerTag, AckRequired, Msg, State)); handle_cast(force_event_refresh, State) -> rabbit_event:notify(channel_created, infos(?CREATION_EVENT_KEYS, State)), @@ -315,6 +316,10 @@ State1 = #ch{confirmed = C} = confirm(MsgSeqNos, From, State), noreply([send_confirms], State1, case C of [] -> hibernate; _ -> 0 end). +handle_info({bump_credit, Msg}, State) -> + credit_flow:handle_bump_msg(Msg), + noreply(State); + handle_info(timeout, State) -> noreply(State); @@ -327,9 +332,10 @@ State1 = handle_publishing_queue_down(QPid, Reason, State), State2 = queue_blocked(QPid, State1), State3 = handle_consuming_queue_down(QPid, State2), + credit_flow:peer_down(QPid), erase_queue_stats(QPid), noreply(State3#ch{queue_monitors = - dict:erase(QPid, State3#ch.queue_monitors)}); + sets:del_element(QPid, State3#ch.queue_monitors)}); handle_info({'EXIT', _Pid, Reason}, State) -> {stop, Reason, State}. @@ -527,7 +533,7 @@ #'channel.flow_ok'{active = false}); _ -> ok end, - demonitor_queue(QPid, State#ch{blocking = Blocking1}) + State#ch{blocking = Blocking1} end. record_confirm(undefined, _, State) -> @@ -565,8 +571,7 @@ MsgSeqNos1 = gb_sets:delete(MsgSeqNo, MsgSeqNos), case gb_sets:is_empty(MsgSeqNos1) of true -> UQM1 = gb_trees:delete(QPid, UQM), - demonitor_queue( - QPid, State#ch{unconfirmed_qm = UQM1}); + State#ch{unconfirmed_qm = UQM1}; false -> UQM1 = gb_trees:update(QPid, MsgSeqNos1, UQM), State#ch{unconfirmed_qm = UQM1} end; @@ -672,45 +677,36 @@ State1 = State#ch{unacked_message_q = Remaining}, {noreply, case TxStatus of - none -> ack(Acked, State1); + none -> ack(Acked, State1), + State1; in_progress -> State1#ch{uncommitted_acks = Acked ++ State1#ch.uncommitted_acks} end}; handle_method(#'basic.get'{queue = QueueNameBin, no_ack = NoAck}, - _, State = #ch{writer_pid = WriterPid, - conn_pid = ConnPid, - next_tag = DeliveryTag, - trace_state = TraceState}) -> + _, State = #ch{writer_pid = WriterPid, + conn_pid = ConnPid, + next_tag = DeliveryTag}) -> QueueName = expand_queue_name_shortcut(QueueNameBin, State), check_read_permitted(QueueName, State), case rabbit_amqqueue:with_exclusive_access_or_die( QueueName, ConnPid, fun (Q) -> rabbit_amqqueue:basic_get(Q, self(), NoAck) end) of {ok, MessageCount, - Msg = {_QName, QPid, _MsgId, Redelivered, + Msg = {_QName, _QPid, _MsgId, Redelivered, #basic_message{exchange_name = ExchangeName, - routing_keys = [RoutingKey | _CcRoutes], - content = Content}}} -> - State1 = lock_message(not(NoAck), - ack_record(DeliveryTag, none, Msg), - State), - State2 = maybe_incr_stats([{QPid, 1}], case NoAck of - true -> get_no_ack; - false -> get - end, State1), - State3 = maybe_incr_redeliver_stats(Redelivered, QPid, State2), - rabbit_trace:tap_trace_out(Msg, TraceState), + routing_keys = [RoutingKey | _CcRoutes], + content = Content}}} -> ok = rabbit_writer:send_command( WriterPid, - #'basic.get_ok'{delivery_tag = DeliveryTag, - redelivered = Redelivered, - exchange = ExchangeName#resource.name, - routing_key = RoutingKey, + #'basic.get_ok'{delivery_tag = DeliveryTag, + redelivered = Redelivered, + exchange = ExchangeName#resource.name, + routing_key = RoutingKey, message_count = MessageCount}, Content), - {noreply, State3#ch{next_tag = DeliveryTag + 1}}; + {noreply, record_sent(none, not(NoAck), Msg, State)}; empty -> {reply, #'basic.get_empty'{}, State} end; @@ -730,7 +726,8 @@ check_read_permitted(QueueName, State), ActualConsumerTag = case ConsumerTag of - <<>> -> rabbit_guid:binstring_guid("amq.ctag"); + <<>> -> rabbit_guid:binary(rabbit_guid:gen_secure(), + "amq.ctag"); Other -> Other end, @@ -787,9 +784,8 @@ false -> dict:store(QPid, CTags1, QCons) end end, - NewState = demonitor_queue( - Q, State#ch{consumer_mapping = ConsumerMapping1, - queue_consumers = QCons1}), + NewState = State#ch{consumer_mapping = ConsumerMapping1, + queue_consumers = QCons1}, %% In order to ensure that no more messages are sent to %% the consumer after the cancel_ok has been sent, we get %% the queue process to send the cancel_ok on our @@ -960,7 +956,8 @@ false -> none end, ActualNameBin = case QueueNameBin of - <<>> -> rabbit_guid:binstring_guid("amq.gen"); + <<>> -> rabbit_guid:binary(rabbit_guid:gen_secure(), + "amq.gen"); Other -> check_name('queue', Other) end, QueueName = rabbit_misc:r(VHostPath, queue, ActualNameBin), @@ -1068,19 +1065,26 @@ rabbit_misc:protocol_error( precondition_failed, "channel is not transactional", []); -handle_method(#'tx.commit'{}, _, State = #ch{uncommitted_message_q = TMQ, - uncommitted_acks = TAL}) -> - State1 = new_tx(ack(TAL, rabbit_misc:queue_fold(fun deliver_to_queues/2, - State, TMQ))), - {noreply, maybe_complete_tx(State1#ch{tx_status = committing})}; +handle_method(#'tx.commit'{}, _, + State = #ch{uncommitted_message_q = TMQ, + uncommitted_acks = TAL, + uncommitted_nacks = TNL, + limiter = Limiter}) -> + State1 = rabbit_misc:queue_fold(fun deliver_to_queues/2, State, TMQ), + ack(TAL, State1), + lists:foreach( + fun({Requeue, Acked}) -> reject(Requeue, Acked, Limiter) end, TNL), + {noreply, maybe_complete_tx(new_tx(State1#ch{tx_status = committing}))}; handle_method(#'tx.rollback'{}, _, #ch{tx_status = none}) -> rabbit_misc:protocol_error( precondition_failed, "channel is not transactional", []); handle_method(#'tx.rollback'{}, _, State = #ch{unacked_message_q = UAMQ, - uncommitted_acks = TAL}) -> - UAMQ1 = queue:from_list(lists:usort(TAL ++ queue:to_list(UAMQ))), + uncommitted_acks = TAL, + uncommitted_nacks = TNL}) -> + TNL1 = lists:append([L || {_, L} <- TNL]), + UAMQ1 = queue:from_list(lists:usort(TAL ++ TNL1 ++ queue:to_list(UAMQ))), {reply, #'tx.rollback_ok'{}, new_tx(State#ch{unacked_message_q = UAMQ1})}; handle_method(#'confirm.select'{}, _, #ch{tx_status = in_progress}) -> @@ -1111,10 +1115,7 @@ ok = rabbit_limiter:block(Limiter1), case consumer_queues(Consumers) of [] -> {reply, #'channel.flow_ok'{active = false}, State1}; - QPids -> State2 = lists:foldl(fun monitor_queue/2, - State1#ch{blocking = - sets:from_list(QPids)}, - QPids), + QPids -> State2 = State1#ch{blocking = sets:from_list(QPids)}, ok = rabbit_amqqueue:flush_all(QPids, self()), {noreply, State2} end; @@ -1145,31 +1146,12 @@ end. monitor_queue(QPid, State = #ch{queue_monitors = QMons}) -> - case (not dict:is_key(QPid, QMons) andalso - queue_monitor_needed(QPid, State)) of - true -> MRef = erlang:monitor(process, QPid), - State#ch{queue_monitors = dict:store(QPid, MRef, QMons)}; - false -> State - end. - -demonitor_queue(QPid, State = #ch{queue_monitors = QMons}) -> - case (dict:is_key(QPid, QMons) andalso - not queue_monitor_needed(QPid, State)) of - true -> true = erlang:demonitor(dict:fetch(QPid, QMons)), - State#ch{queue_monitors = dict:erase(QPid, QMons)}; - false -> State + case sets:is_element(QPid, QMons) of + false -> erlang:monitor(process, QPid), + State#ch{queue_monitors = sets:add_element(QPid, QMons)}; + true -> State end. -queue_monitor_needed(QPid, #ch{queue_consumers = QCons, - blocking = Blocking, - unconfirmed_qm = UQM} = State) -> - StatsEnabled = rabbit_event:stats_level( - State, #ch.stats_timer) =:= fine, - ConsumerMonitored = dict:is_key(QPid, QCons), - QueueBlocked = sets:is_element(QPid, Blocking), - ConfirmMonitored = gb_trees:is_defined(QPid, UQM), - StatsEnabled or ConsumerMonitored or QueueBlocked or ConfirmMonitored. - handle_publishing_queue_down(QPid, Reason, State = #ch{unconfirmed_qm = UQM}) -> MsgSeqNos = case gb_trees:lookup(QPid, UQM) of {value, MsgSet} -> gb_sets:to_list(MsgSet); @@ -1180,14 +1162,9 @@ %% the set one by one which which would be inefficient State1 = State#ch{unconfirmed_qm = gb_trees:delete_any(QPid, UQM)}, {Nack, SendFun} = - case Reason of - Reason when Reason =:= noproc; Reason =:= noconnection; - Reason =:= normal; Reason =:= shutdown -> - {false, fun record_confirms/2}; - {shutdown, _} -> - {false, fun record_confirms/2}; - _ -> - {true, fun send_nacks/2} + case rabbit_misc:is_abnormal_termination(Reason) of + true -> {true, fun send_nacks/2}; + false -> {false, fun record_confirms/2} end, {MXs, State2} = process_confirms(MsgSeqNos, QPid, Nack, State1), SendFun(MXs, State2). @@ -1266,18 +1243,46 @@ routing_key = RoutingKey}, Content). -reject(DeliveryTag, Requeue, Multiple, State = #ch{unacked_message_q = UAMQ}) -> +reject(DeliveryTag, Requeue, Multiple, + State = #ch{unacked_message_q = UAMQ, tx_status = TxStatus}) -> {Acked, Remaining} = collect_acks(UAMQ, DeliveryTag, Multiple), + State1 = State#ch{unacked_message_q = Remaining}, + {noreply, + case TxStatus of + none -> + reject(Requeue, Acked, State1#ch.limiter), + State1; + in_progress -> + State1#ch{uncommitted_nacks = + [{Requeue, Acked} | State1#ch.uncommitted_nacks]} + end}. + +reject(Requeue, Acked, Limiter) -> ok = fold_per_queue( fun (QPid, MsgIds, ok) -> rabbit_amqqueue:reject(QPid, MsgIds, Requeue, self()) end, ok, Acked), - ok = notify_limiter(State#ch.limiter, Acked), - {noreply, State#ch{unacked_message_q = Remaining}}. + ok = notify_limiter(Limiter, Acked). -ack_record(DeliveryTag, ConsumerTag, - _MsgStruct = {_QName, QPid, MsgId, _Redelivered, _Msg}) -> - {DeliveryTag, ConsumerTag, {QPid, MsgId}}. +record_sent(ConsumerTag, AckRequired, + Msg = {_QName, QPid, MsgId, Redelivered, _Message}, + State = #ch{unacked_message_q = UAMQ, + next_tag = DeliveryTag, + trace_state = TraceState}) -> + maybe_incr_stats([{QPid, 1}], case {ConsumerTag, AckRequired} of + {none, true} -> get; + {none, false} -> get_no_ack; + {_ , true} -> deliver; + {_ , false} -> deliver_no_ack + end, State), + maybe_incr_redeliver_stats(Redelivered, QPid, State), + rabbit_trace:tap_trace_out(Msg, TraceState), + UAMQ1 = case AckRequired of + true -> queue:in({DeliveryTag, ConsumerTag, {QPid, MsgId}}, + UAMQ); + false -> UAMQ + end, + State#ch{unacked_message_q = UAMQ1, next_tag = DeliveryTag + 1}. collect_acks(Q, 0, true) -> {queue:to_list(Q), queue:new()}; @@ -1312,7 +1317,8 @@ maybe_incr_stats(QIncs, ack, State). new_tx(State) -> State#ch{uncommitted_message_q = queue:new(), - uncommitted_acks = []}. + uncommitted_acks = [], + uncommitted_nacks = []}. notify_queues(State = #ch{state = closing}) -> {ok, State}; @@ -1362,22 +1368,25 @@ exchange_name = XName}, msg_seq_no = MsgSeqNo}, QNames}, State) -> - {RoutingRes, DeliveredQPids} = rabbit_router:deliver(QNames, Delivery), - State1 = process_routing_result(RoutingRes, DeliveredQPids, - XName, MsgSeqNo, Message, State), + {RoutingRes, DeliveredQPids} = + rabbit_amqqueue:deliver_flow(rabbit_amqqueue:lookup(QNames), Delivery), + State1 = lists:foldl(fun monitor_queue/2, State, DeliveredQPids), + State2 = process_routing_result(RoutingRes, DeliveredQPids, + XName, MsgSeqNo, Message, State1), maybe_incr_stats([{XName, 1} | [{{QPid, XName}, 1} || - QPid <- DeliveredQPids]], publish, State1). + QPid <- DeliveredQPids]], publish, State2), + State2. process_routing_result(unroutable, _, XName, MsgSeqNo, Msg, State) -> ok = basic_return(Msg, State, no_route), - record_confirm(MsgSeqNo, XName, - maybe_incr_stats([{Msg#basic_message.exchange_name, 1}], - return_unroutable, State)); + maybe_incr_stats([{Msg#basic_message.exchange_name, 1}], + return_unroutable, State), + record_confirm(MsgSeqNo, XName, State); process_routing_result(not_delivered, _, XName, MsgSeqNo, Msg, State) -> ok = basic_return(Msg, State, no_consumers), - record_confirm(MsgSeqNo, XName, - maybe_incr_stats([{XName, 1}], return_not_delivered, State)); + maybe_incr_stats([{XName, 1}], return_not_delivered, State), + record_confirm(MsgSeqNo, XName, State); process_routing_result(routed, [], XName, MsgSeqNo, _, State) -> record_confirm(MsgSeqNo, XName, State); process_routing_result(routed, _, _, undefined, _, State) -> @@ -1395,15 +1404,10 @@ State0#ch{unconfirmed_qm = UQM1}; none -> UQM1 = gb_trees:insert(QPid, SingletonSet, UQM), - monitor_queue(QPid, State0#ch{unconfirmed_qm = UQM1}) + State0#ch{unconfirmed_qm = UQM1} end end, State#ch{unconfirmed_mq = UMQ1}, QPids). -lock_message(true, MsgStruct, State = #ch{unacked_message_q = UAMQ}) -> - State#ch{unacked_message_q = queue:in(MsgStruct, UAMQ)}; -lock_message(false, _MsgStruct, State) -> - State. - send_nacks([], State) -> State; send_nacks(MXs, State = #ch{tx_status = none}) -> @@ -1419,13 +1423,12 @@ send_confirms(State = #ch{tx_status = none, confirmed = []}) -> State; send_confirms(State = #ch{tx_status = none, confirmed = C}) -> - {MsgSeqNos, State1} = - lists:foldl(fun ({MsgSeqNo, ExchangeName}, {MSNs, State0}) -> - {[MsgSeqNo | MSNs], - maybe_incr_stats([{ExchangeName, 1}], confirm, - State0)} - end, {[], State}, lists:append(C)), - send_confirms(MsgSeqNos, State1 #ch{confirmed = []}); + MsgSeqNos = + lists:foldl(fun ({MsgSeqNo, XName}, MSNs) -> + maybe_incr_stats([{XName, 1}], confirm, State), + [MsgSeqNo | MSNs] + end, [], lists:append(C)), + send_confirms(MsgSeqNos, State#ch{confirmed = []}); send_confirms(State) -> maybe_complete_tx(State). @@ -1486,6 +1489,7 @@ i(vhost, #ch{virtual_host = VHost}) -> VHost; i(transactional, #ch{tx_status = TE}) -> TE =/= none; i(confirm, #ch{confirm_enabled = CE}) -> CE; +i(name, State) -> name(State); i(consumer_count, #ch{consumer_mapping = ConsumerMapping}) -> dict:size(ConsumerMapping); i(messages_unconfirmed, #ch{unconfirmed_mq = UMQ}) -> @@ -1503,28 +1507,26 @@ i(Item, _) -> throw({bad_argument, Item}). +name(#ch{conn_name = ConnName, channel = Channel}) -> + list_to_binary(rabbit_misc:format("~s (~p)", [ConnName, Channel])). + maybe_incr_redeliver_stats(true, QPid, State) -> maybe_incr_stats([{QPid, 1}], redeliver, State); -maybe_incr_redeliver_stats(_, _, State) -> - State. +maybe_incr_redeliver_stats(_, _, _State) -> + ok. maybe_incr_stats(QXIncs, Measure, State) -> case rabbit_event:stats_level(State, #ch.stats_timer) of - fine -> lists:foldl(fun ({QX, Inc}, State0) -> - incr_stats(QX, Inc, Measure, State0) - end, State, QXIncs); - _ -> State + fine -> [incr_stats(QX, Inc, Measure) || {QX, Inc} <- QXIncs]; + _ -> ok end. -incr_stats({QPid, _} = QX, Inc, Measure, State) -> - update_measures(queue_exchange_stats, QX, Inc, Measure), - monitor_queue(QPid, State); -incr_stats(QPid, Inc, Measure, State) when is_pid(QPid) -> - update_measures(queue_stats, QPid, Inc, Measure), - monitor_queue(QPid, State); -incr_stats(X, Inc, Measure, State) -> - update_measures(exchange_stats, X, Inc, Measure), - State. +incr_stats({_, _} = QX, Inc, Measure) -> + update_measures(queue_exchange_stats, QX, Inc, Measure); +incr_stats(QPid, Inc, Measure) when is_pid(QPid) -> + update_measures(queue_stats, QPid, Inc, Measure); +incr_stats(X, Inc, Measure) -> + update_measures(exchange_stats, X, Inc, Measure). update_measures(Type, QX, Inc, Measure) -> Measures = case get({Type, QX}) of diff -Nru rabbitmq-server-2.7.1/src/rabbit_channel_sup.erl rabbitmq-server-2.8.0/src/rabbit_channel_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_channel_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_channel_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_channel_sup). @@ -32,10 +32,10 @@ -type(start_link_args() :: {'tcp', rabbit_net:socket(), rabbit_channel:channel_number(), - non_neg_integer(), pid(), rabbit_types:protocol(), rabbit_types:user(), - rabbit_types:vhost(), rabbit_framing:amqp_table(), + non_neg_integer(), pid(), string(), rabbit_types:protocol(), + rabbit_types:user(), rabbit_types:vhost(), rabbit_framing:amqp_table(), pid()} | - {'direct', rabbit_channel:channel_number(), pid(), + {'direct', rabbit_channel:channel_number(), pid(), string(), rabbit_types:protocol(), rabbit_types:user(), rabbit_types:vhost(), rabbit_framing:amqp_table(), pid()}). @@ -45,8 +45,8 @@ %%---------------------------------------------------------------------------- -start_link({tcp, Sock, Channel, FrameMax, ReaderPid, Protocol, User, VHost, - Capabilities, Collector}) -> +start_link({tcp, Sock, Channel, FrameMax, ReaderPid, ConnName, Protocol, User, + VHost, Capabilities, Collector}) -> {ok, SupPid} = supervisor2:start_link(?MODULE, {tcp, Sock, Channel, FrameMax, ReaderPid, Protocol}), @@ -56,14 +56,14 @@ supervisor2:start_child( SupPid, {channel, {rabbit_channel, start_link, - [Channel, ReaderPid, WriterPid, ReaderPid, Protocol, - User, VHost, Capabilities, Collector, + [Channel, ReaderPid, WriterPid, ReaderPid, ConnName, + Protocol, User, VHost, Capabilities, Collector, rabbit_limiter:make_token(LimiterPid)]}, intrinsic, ?MAX_WAIT, worker, [rabbit_channel]}), {ok, AState} = rabbit_command_assembler:init(Protocol), {ok, SupPid, {ChannelPid, AState}}; -start_link({direct, Channel, ClientChannelPid, ConnPid, Protocol, User, VHost, - Capabilities, Collector}) -> +start_link({direct, Channel, ClientChannelPid, ConnPid, ConnName, Protocol, + User, VHost, Capabilities, Collector}) -> {ok, SupPid} = supervisor2:start_link(?MODULE, direct), [LimiterPid] = supervisor2:find_child(SupPid, limiter), {ok, ChannelPid} = @@ -71,7 +71,7 @@ SupPid, {channel, {rabbit_channel, start_link, [Channel, ClientChannelPid, ClientChannelPid, ConnPid, - Protocol, User, VHost, Capabilities, Collector, + ConnName, Protocol, User, VHost, Capabilities, Collector, rabbit_limiter:make_token(LimiterPid)]}, intrinsic, ?MAX_WAIT, worker, [rabbit_channel]}), {ok, SupPid, {ChannelPid, none}}. diff -Nru rabbitmq-server-2.7.1/src/rabbit_channel_sup_sup.erl rabbitmq-server-2.8.0/src/rabbit_channel_sup_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_channel_sup_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_channel_sup_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_channel_sup_sup). diff -Nru rabbitmq-server-2.7.1/src/rabbit_client_sup.erl rabbitmq-server-2.8.0/src/rabbit_client_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_client_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_client_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_client_sup). @@ -28,8 +28,9 @@ -ifdef(use_specs). --spec(start_link/1 :: (mfa()) -> rabbit_types:ok_pid_or_error()). --spec(start_link/2 :: ({'local', atom()}, mfa()) -> +-spec(start_link/1 :: (rabbit_types:mfargs()) -> + rabbit_types:ok_pid_or_error()). +-spec(start_link/2 :: ({'local', atom()}, rabbit_types:mfargs()) -> rabbit_types:ok_pid_or_error()). -endif. diff -Nru rabbitmq-server-2.7.1/src/rabbit_command_assembler.erl rabbitmq-server-2.8.0/src/rabbit_command_assembler.erl --- rabbitmq-server-2.7.1/src/rabbit_command_assembler.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_command_assembler.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_command_assembler). diff -Nru rabbitmq-server-2.7.1/src/rabbit_connection_sup.erl rabbitmq-server-2.8.0/src/rabbit_connection_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_connection_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_connection_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_connection_sup). diff -Nru rabbitmq-server-2.7.1/src/rabbit_control.erl rabbitmq-server-2.8.0/src/rabbit_control.erl --- rabbitmq-server-2.7.1/src/rabbit_control.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_control.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,13 +11,13 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_control). -include("rabbit.hrl"). --export([start/0, stop/0, action/5, diagnostics/1]). +-export([start/0, stop/0, action/5]). -define(RPC_TIMEOUT, infinity). -define(EXTERNAL_CHECK_INTERVAL, 1000). @@ -49,7 +49,6 @@ (atom(), node(), [string()], [{string(), any()}], fun ((string(), [any()]) -> 'ok')) -> 'ok'). --spec(diagnostics/1 :: (node()) -> [{string(), [any()]}]). -spec(usage/0 :: () -> no_return()). -endif. @@ -67,7 +66,7 @@ CmdArgsAndOpts -> CmdArgsAndOpts end, Opts1 = [case K of - ?NODE_OPT -> {?NODE_OPT, rabbit_misc:makenode(V)}; + ?NODE_OPT -> {?NODE_OPT, rabbit_nodes:make(V)}; _ -> {K, V} end || {K, V} <- Opts], Command = list_to_atom(Command0), @@ -79,6 +78,12 @@ io:format(Format ++ " ...~n", Args1) end end, + PrintInvalidCommandError = + fun () -> + print_error("invalid command '~s'", + [string:join([atom_to_list(Command) | Args], " ")]) + end, + %% The reason we don't use a try/catch here is that rpc:call turns %% thrown errors into normal return values case catch action(Command, Node, Args, Opts, Inform) of @@ -88,9 +93,11 @@ false -> io:format("...done.~n") end, rabbit_misc:quit(0); - {'EXIT', {function_clause, [{?MODULE, action, _} | _]}} -> - print_error("invalid command '~s'", - [string:join([atom_to_list(Command) | Args], " ")]), + {'EXIT', {function_clause, [{?MODULE, action, _} | _]}} -> %% < R15 + PrintInvalidCommandError(), + usage(); + {'EXIT', {function_clause, [{?MODULE, action, _, _} | _]}} -> %% >= R15 + PrintInvalidCommandError(), usage(); {'EXIT', {badarg, _}} -> print_error("invalid parameter: ~p", [Args]), @@ -135,26 +142,7 @@ print_error(Format, Args) -> fmt_stderr("Error: " ++ Format, Args). print_badrpc_diagnostics(Node) -> - [fmt_stderr(Fmt, Args) || {Fmt, Args} <- diagnostics(Node)]. - -diagnostics(Node) -> - {_NodeName, NodeHost} = rabbit_misc:nodeparts(Node), - [{"diagnostics:", []}, - case net_adm:names(NodeHost) of - {error, EpmdReason} -> - {"- unable to connect to epmd on ~s: ~w", - [NodeHost, EpmdReason]}; - {ok, NamePorts} -> - {"- nodes and their ports on ~s: ~p", - [NodeHost, [{list_to_atom(Name), Port} || - {Name, Port} <- NamePorts]]} - end, - {"- current node: ~w", [node()]}, - case init:get_argument(home) of - {ok, [[Home]]} -> {"- current node home dir: ~s", [Home]}; - Other -> {"- no current node home dir: ~p", [Other]} - end, - {"- current node cookie hash: ~s", [rabbit_misc:cookie_hash()]}]. + fmt_stderr(rabbit_nodes:diagnostics([Node]), []). stop() -> ok. diff -Nru rabbitmq-server-2.7.1/src/rabbit_direct.erl rabbitmq-server-2.8.0/src/rabbit_direct.erl --- rabbitmq-server-2.7.1/src/rabbit_direct.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_direct.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,13 +11,13 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_direct). -export([boot/0, force_event_refresh/0, list/0, connect/5, - start_channel/8, disconnect/2]). + start_channel/9, disconnect/2]). %% Internal -export([list_local/0]). @@ -36,10 +36,10 @@ rabbit_event:event_props()) -> {'ok', {rabbit_types:user(), rabbit_framing:amqp_table()}}). --spec(start_channel/8 :: - (rabbit_channel:channel_number(), pid(), pid(), rabbit_types:protocol(), - rabbit_types:user(), rabbit_types:vhost(), rabbit_framing:amqp_table(), - pid()) -> {'ok', pid()}). +-spec(start_channel/9 :: + (rabbit_channel:channel_number(), pid(), pid(), string(), + rabbit_types:protocol(), rabbit_types:user(), rabbit_types:vhost(), + rabbit_framing:amqp_table(), pid()) -> {'ok', pid()}). -spec(disconnect/2 :: (pid(), rabbit_event:event_props()) -> 'ok'). @@ -92,13 +92,13 @@ {error, broker_not_found_on_node} end. -start_channel(Number, ClientChannelPid, ConnPid, Protocol, User, VHost, - Capabilities, Collector) -> +start_channel(Number, ClientChannelPid, ConnPid, ConnName, Protocol, User, + VHost, Capabilities, Collector) -> {ok, _, {ChannelPid, _}} = supervisor2:start_child( rabbit_direct_client_sup, - [{direct, Number, ClientChannelPid, ConnPid, Protocol, User, VHost, - Capabilities, Collector}]), + [{direct, Number, ClientChannelPid, ConnPid, ConnName, Protocol, + User, VHost, Capabilities, Collector}]), {ok, ChannelPid}. disconnect(Pid, Infos) -> diff -Nru rabbitmq-server-2.7.1/src/rabbit_error_logger.erl rabbitmq-server-2.8.0/src/rabbit_error_logger.erl --- rabbitmq-server-2.7.1/src/rabbit_error_logger.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_error_logger.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_error_logger). diff -Nru rabbitmq-server-2.7.1/src/rabbit_error_logger_file_h.erl rabbitmq-server-2.8.0/src/rabbit_error_logger_file_h.erl --- rabbitmq-server-2.7.1/src/rabbit_error_logger_file_h.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_error_logger_file_h.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_error_logger_file_h). diff -Nru rabbitmq-server-2.7.1/src/rabbit_event.erl rabbitmq-server-2.8.0/src/rabbit_event.erl --- rabbitmq-server-2.7.1/src/rabbit_event.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_event.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_event). diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange.erl rabbitmq-server-2.8.0/src/rabbit_exchange.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange). @@ -355,11 +355,21 @@ _ -> undefined end. +invalid_module(T) -> + rabbit_log:warning( + "Could not find exchange type ~s.~n", [T]), + put({xtype_to_module, T}, rabbit_exchange_type_invalid), + rabbit_exchange_type_invalid. + %% Used with atoms from records; e.g., the type is expected to exist. type_to_module(T) -> case get({xtype_to_module, T}) of - undefined -> {ok, Module} = rabbit_registry:lookup_module(exchange, T), - put({xtype_to_module, T}, Module), - Module; - Module -> Module + undefined -> + case rabbit_registry:lookup_module(exchange, T) of + {ok, Module} -> put({xtype_to_module, T}, Module), + Module; + {error, not_found} -> invalid_module(T) + end; + Module -> + Module end. diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange_type.erl rabbitmq-server-2.8.0/src/rabbit_exchange_type.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange_type.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange_type.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type). diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange_type_direct.erl rabbitmq-server-2.8.0/src/rabbit_exchange_type_direct.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange_type_direct.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange_type_direct.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type_direct). diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange_type_fanout.erl rabbitmq-server-2.8.0/src/rabbit_exchange_type_fanout.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange_type_fanout.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange_type_fanout.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type_fanout). diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange_type_headers.erl rabbitmq-server-2.8.0/src/rabbit_exchange_type_headers.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange_type_headers.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange_type_headers.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type_headers). diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange_type_invalid.erl rabbitmq-server-2.8.0/src/rabbit_exchange_type_invalid.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange_type_invalid.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange_type_invalid.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,47 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(rabbit_exchange_type_invalid). +-include("rabbit.hrl"). + +-behaviour(rabbit_exchange_type). + +-export([description/0, serialise_events/0, route/2]). +-export([validate/1, create/2, delete/3, + add_binding/3, remove_bindings/3, assert_args_equivalence/2]). +-include("rabbit_exchange_type_spec.hrl"). + +description() -> + [{name, <<"invalid">>}, + {description, + <<"Dummy exchange type, to be used when the intended one is not found.">> + }]. + +serialise_events() -> false. + +route(#exchange{name = Name, type = Type}, _) -> + rabbit_misc:protocol_error( + precondition_failed, + "Cannot route message through ~s: exchange type ~s not found", + [rabbit_misc:rs(Name), Type]). + +validate(_X) -> ok. +create(_Tx, _X) -> ok. +delete(_Tx, _X, _Bs) -> ok. +add_binding(_Tx, _X, _B) -> ok. +remove_bindings(_Tx, _X, _Bs) -> ok. +assert_args_equivalence(X, Args) -> + rabbit_exchange:assert_args_equivalence(X, Args). diff -Nru rabbitmq-server-2.7.1/src/rabbit_exchange_type_topic.erl rabbitmq-server-2.8.0/src/rabbit_exchange_type_topic.erl --- rabbitmq-server-2.7.1/src/rabbit_exchange_type_topic.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_exchange_type_topic.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_exchange_type_topic). @@ -52,6 +52,7 @@ create(_Tx, _X) -> ok. delete(transaction, #exchange{name = X}, _Bs) -> + trie_remove_all_nodes(X), trie_remove_all_edges(X), trie_remove_all_bindings(X), ok; @@ -63,59 +64,26 @@ add_binding(none, _Exchange, _Binding) -> ok. -remove_bindings(transaction, #exchange{name = X}, Bs) -> - %% The remove process is split into two distinct phases. In the - %% first phase we gather the lists of bindings and edges to - %% delete, then in the second phase we process all the - %% deletions. This is to prevent interleaving of read/write - %% operations in mnesia that can adversely affect performance. - {ToDelete, Paths} = - lists:foldl( - fun(#binding{source = S, key = K, destination = D}, {Acc, PathAcc}) -> - Path = [{FinalNode, _} | _] = - follow_down_get_path(S, split_topic_key(K)), - {[{FinalNode, D} | Acc], - decrement_bindings(X, Path, maybe_add_path(X, Path, PathAcc))} - end, {[], gb_trees:empty()}, Bs), - - [trie_remove_binding(X, FinalNode, D) || {FinalNode, D} <- ToDelete], - [trie_remove_edge(X, Parent, Node, W) || - {Node, {Parent, W, {0, 0}}} <- gb_trees:to_list(Paths)], +remove_bindings(transaction, _X, Bs) -> + %% See rabbit_binding:lock_route_tables for the rationale for + %% taking table locks. + case Bs of + [_] -> ok; + _ -> [mnesia:lock({table, T}, write) || + T <- [rabbit_topic_trie_node, + rabbit_topic_trie_edge, + rabbit_topic_trie_binding]] + end, + [begin + Path = [{FinalNode, _} | _] = + follow_down_get_path(X, split_topic_key(K)), + trie_remove_binding(X, FinalNode, D), + remove_path_if_empty(X, Path) + end || #binding{source = X, key = K, destination = D} <- Bs], ok; remove_bindings(none, _X, _Bs) -> ok. -maybe_add_path(_X, [{root, none}], PathAcc) -> - PathAcc; -maybe_add_path(X, [{Node, W}, {Parent, _} | _], PathAcc) -> - case gb_trees:is_defined(Node, PathAcc) of - true -> PathAcc; - false -> gb_trees:insert(Node, {Parent, W, {trie_binding_count(X, Node), - trie_child_count(X, Node)}}, - PathAcc) - end. - -decrement_bindings(X, Path, PathAcc) -> - with_path_acc(X, fun({Bindings, Edges}) -> {Bindings - 1, Edges} end, - Path, PathAcc). - -decrement_edges(X, Path, PathAcc) -> - with_path_acc(X, fun({Bindings, Edges}) -> {Bindings, Edges - 1} end, - Path, PathAcc). - -with_path_acc(_X, _Fun, [{root, none}], PathAcc) -> - PathAcc; -with_path_acc(X, Fun, [{Node, _} | ParentPath], PathAcc) -> - {Parent, W, Counts} = gb_trees:get(Node, PathAcc), - NewCounts = Fun(Counts), - NewPathAcc = gb_trees:update(Node, {Parent, W, NewCounts}, PathAcc), - case NewCounts of - {0, 0} -> decrement_edges(X, ParentPath, - maybe_add_path(X, ParentPath, NewPathAcc)); - _ -> NewPathAcc - end. - - assert_args_equivalence(X, Args) -> rabbit_exchange:assert_args_equivalence(X, Args). @@ -183,6 +151,16 @@ error -> {error, Acc, Words} end. +remove_path_if_empty(_, [{root, none}]) -> + ok; +remove_path_if_empty(X, [{Node, W} | [{Parent, _} | _] = RestPath]) -> + case mnesia:read(rabbit_topic_trie_node, + #trie_node{exchange_name = X, node_id = Node}, write) of + [] -> trie_remove_edge(X, Parent, Node, W), + remove_path_if_empty(X, RestPath); + _ -> ok + end. + trie_child(X, Node, Word) -> case mnesia:read({rabbit_topic_trie_edge, #trie_edge{exchange_name = X, @@ -199,10 +177,30 @@ destination = '$1'}}, mnesia:select(rabbit_topic_trie_binding, [{MatchHead, [], ['$1']}]). +trie_update_node_counts(X, Node, Field, Delta) -> + E = case mnesia:read(rabbit_topic_trie_node, + #trie_node{exchange_name = X, + node_id = Node}, write) of + [] -> #topic_trie_node{trie_node = #trie_node{ + exchange_name = X, + node_id = Node}, + edge_count = 0, + binding_count = 0}; + [E0] -> E0 + end, + case setelement(Field, E, element(Field, E) + Delta) of + #topic_trie_node{edge_count = 0, binding_count = 0} -> + ok = mnesia:delete_object(rabbit_topic_trie_node, E, write); + EN -> + ok = mnesia:write(rabbit_topic_trie_node, EN, write) + end. + trie_add_edge(X, FromNode, ToNode, W) -> + trie_update_node_counts(X, FromNode, #topic_trie_node.edge_count, +1), trie_edge_op(X, FromNode, ToNode, W, fun mnesia:write/3). trie_remove_edge(X, FromNode, ToNode, W) -> + trie_update_node_counts(X, FromNode, #topic_trie_node.edge_count, -1), trie_edge_op(X, FromNode, ToNode, W, fun mnesia:delete_object/3). trie_edge_op(X, FromNode, ToNode, W, Op) -> @@ -214,9 +212,11 @@ write). trie_add_binding(X, Node, D) -> + trie_update_node_counts(X, Node, #topic_trie_node.binding_count, +1), trie_binding_op(X, Node, D, fun mnesia:write/3). trie_remove_binding(X, Node, D) -> + trie_update_node_counts(X, Node, #topic_trie_node.binding_count, -1), trie_binding_op(X, Node, D, fun mnesia:delete_object/3). trie_binding_op(X, Node, D, Op) -> @@ -227,23 +227,11 @@ destination = D}}, write). -trie_child_count(X, Node) -> - count(rabbit_topic_trie_edge, - #topic_trie_edge{trie_edge = #trie_edge{exchange_name = X, - node_id = Node, - _ = '_'}, - _ = '_'}). - -trie_binding_count(X, Node) -> - count(rabbit_topic_trie_binding, - #topic_trie_binding{ - trie_binding = #trie_binding{exchange_name = X, - node_id = Node, - _ = '_'}, - _ = '_'}). - -count(Table, Match) -> - length(mnesia:match_object(Table, Match, read)). +trie_remove_all_nodes(X) -> + remove_all(rabbit_topic_trie_node, + #topic_trie_node{trie_node = #trie_node{exchange_name = X, + _ = '_'}, + _ = '_'}). trie_remove_all_edges(X) -> remove_all(rabbit_topic_trie_edge, @@ -262,7 +250,7 @@ mnesia:match_object(Table, Pattern, write)). new_node_id() -> - rabbit_guid:guid(). + rabbit_guid:gen(). split_topic_key(Key) -> split_topic_key(Key, [], []). @@ -275,4 +263,3 @@ split_topic_key(Rest, [], [lists:reverse(RevWordAcc) | RevResAcc]); split_topic_key(<>, RevWordAcc, RevResAcc) -> split_topic_key(Rest, [C | RevWordAcc], RevResAcc). - diff -Nru rabbitmq-server-2.7.1/src/rabbit_file.erl rabbitmq-server-2.8.0/src/rabbit_file.erl --- rabbitmq-server-2.7.1/src/rabbit_file.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_file.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_file). diff -Nru rabbitmq-server-2.7.1/src/rabbit_framing.erl rabbitmq-server-2.8.0/src/rabbit_framing.erl --- rabbitmq-server-2.7.1/src/rabbit_framing.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_framing.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% TODO auto-generate diff -Nru rabbitmq-server-2.7.1/src/rabbit_guid.erl rabbitmq-server-2.8.0/src/rabbit_guid.erl --- rabbitmq-server-2.7.1/src/rabbit_guid.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_guid.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_guid). @@ -19,7 +19,7 @@ -behaviour(gen_server). -export([start_link/0]). --export([guid/0, string_guid/1, binstring_guid/1]). +-export([gen/0, gen_secure/0, string/2, binary/2]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -38,9 +38,10 @@ -type(guid() :: binary()). -spec(start_link/0 :: () -> rabbit_types:ok_pid_or_error()). --spec(guid/0 :: () -> guid()). --spec(string_guid/1 :: (any()) -> string()). --spec(binstring_guid/1 :: (any()) -> binary()). +-spec(gen/0 :: () -> guid()). +-spec(gen_secure/0 :: () -> guid()). +-spec(string/2 :: (guid(), any()) -> string()). +-spec(binary/2 :: (guid(), any()) -> binary()). -endif. @@ -65,11 +66,8 @@ end, Serial. -%% generate a GUID. -%% -%% The id is only unique within a single cluster and as long as the -%% serial store hasn't been deleted. -guid() -> +%% Generate an un-hashed guid. +fresh() -> %% 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 @@ -78,29 +76,74 @@ %% %% A persisted serial number, the node, and a unique reference %% (per node incarnation) uniquely identifies a process in space - %% and time. We combine that with a process-local counter to give - %% us a GUID. - G = case get(guid) of - undefined -> Serial = gen_server:call(?SERVER, serial, infinity), - {{Serial, node(), make_ref()}, 0}; + %% and time. + Serial = gen_server:call(?SERVER, serial, infinity), + {Serial, node(), make_ref()}. + +advance_blocks({B1, B2, B3, B4}, I) -> + %% To produce a new set of blocks, we create a new 32bit block + %% hashing {B5, I}. The new hash is used as last block, and the + %% other three blocks are XORed with it. + %% + %% Doing this is convenient because it avoids cascading conflits, + %% while being very fast. The conflicts are avoided by propagating + %% the changes through all the blocks at each round by XORing, so + %% the only occasion in which a collision will take place is when + %% all 4 blocks are the same and the counter is the same. + %% + %% The range (2^32) is provided explicitly since phash uses 2^27 + %% by default. + B5 = erlang:phash2({B1, I}, 4294967296), + {{(B2 bxor B5), (B3 bxor B5), (B4 bxor B5), B5}, I+1}. + +blocks_to_binary({B1, B2, B3, B4}) -> <>. + +%% generate a GUID. This function should be used when performance is a +%% priority and predictability is not an issue. Otherwise use +%% gen_secure/0. +gen() -> + %% We hash a fresh GUID with md5, split it in 4 blocks, and each + %% time we need a new guid we rotate them producing a new hash + %% with the aid of the counter. Look at the comments in + %% advance_blocks/2 for details. + {BS, I} = case get(guid) of + undefined -> <> = + erlang:md5(term_to_binary(fresh())), + {{B1,B2,B3,B4}, 0}; + {BS0, I0} -> advance_blocks(BS0, I0) + end, + put(guid, {BS, I}), + blocks_to_binary(BS). + +%% generate a non-predictable GUID. +%% +%% The id is only unique within a single cluster and as long as the +%% serial store hasn't been deleted. +%% +%% If you are not concerned with predictability, gen/0 is faster. +gen_secure() -> + %% Here instead of hashing once we hash the GUID and the counter + %% each time, so that the GUID is not predictable. + G = case get(guid_secure) of + undefined -> {fresh(), 0}; {S, I} -> {S, I+1} end, - put(guid, G), + put(guid_secure, G), erlang:md5(term_to_binary(G)). %% generate a readable string representation of a GUID. %% %% employs base64url encoding, which is safer in more contexts than %% plain base64. -string_guid(Prefix) -> +string(G, Prefix) -> Prefix ++ "-" ++ lists:foldl(fun ($\+, Acc) -> [$\- | Acc]; ($\/, Acc) -> [$\_ | Acc]; ($\=, Acc) -> Acc; (Chr, Acc) -> [Chr | Acc] - end, [], base64:encode_to_string(guid())). + end, [], base64:encode_to_string(G)). -binstring_guid(Prefix) -> - list_to_binary(string_guid(Prefix)). +binary(G, Prefix) -> + list_to_binary(string(G, Prefix)). %%---------------------------------------------------------------------------- diff -Nru rabbitmq-server-2.7.1/src/rabbit_heartbeat.erl rabbitmq-server-2.8.0/src/rabbit_heartbeat.erl --- rabbitmq-server-2.7.1/src/rabbit_heartbeat.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_heartbeat.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_heartbeat). diff -Nru rabbitmq-server-2.7.1/src/rabbit_limiter.erl rabbitmq-server-2.8.0/src/rabbit_limiter.erl --- rabbitmq-server-2.7.1/src/rabbit_limiter.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_limiter.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_limiter). diff -Nru rabbitmq-server-2.7.1/src/rabbit_log.erl rabbitmq-server-2.8.0/src/rabbit_log.erl --- rabbitmq-server-2.7.1/src/rabbit_log.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_log.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_log). @@ -23,8 +23,7 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --export([debug/1, debug/2, message/4, info/1, info/2, - warning/1, warning/2, error/1, error/2]). +-export([log/3, log/4, info/1, info/2, warning/1, warning/2, error/1, error/2]). -define(SERVER, ?MODULE). @@ -32,9 +31,15 @@ -ifdef(use_specs). +-export_type([level/0]). + +-type(category() :: atom()). +-type(level() :: 'info' | 'warning' | 'error'). + -spec(start_link/0 :: () -> rabbit_types:ok_pid_or_error()). --spec(debug/1 :: (string()) -> 'ok'). --spec(debug/2 :: (string(), [any()]) -> 'ok'). + +-spec(log/3 :: (category(), level(), string()) -> 'ok'). +-spec(log/4 :: (category(), level(), string(), [any()]) -> 'ok'). -spec(info/1 :: (string()) -> 'ok'). -spec(info/2 :: (string(), [any()]) -> 'ok'). -spec(warning/1 :: (string()) -> 'ok'). @@ -42,84 +47,47 @@ -spec(error/1 :: (string()) -> 'ok'). -spec(error/2 :: (string(), [any()]) -> 'ok'). --spec(message/4 :: (_,_,_,_) -> 'ok'). - -endif. %%---------------------------------------------------------------------------- - start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). +log(Category, Level, Fmt) -> log(Category, Level, Fmt, []). -debug(Fmt) -> - gen_server:cast(?SERVER, {debug, Fmt}). - -debug(Fmt, Args) when is_list(Args) -> - gen_server:cast(?SERVER, {debug, Fmt, Args}). - -message(Direction, Channel, MethodRecord, Content) -> - gen_server:cast(?SERVER, - {message, Direction, Channel, MethodRecord, Content}). +log(Category, Level, Fmt, Args) when is_list(Args) -> + gen_server:cast(?SERVER, {log, Category, Level, Fmt, Args}). -info(Fmt) -> - gen_server:cast(?SERVER, {info, Fmt}). - -info(Fmt, Args) when is_list(Args) -> - gen_server:cast(?SERVER, {info, Fmt, Args}). - -warning(Fmt) -> - gen_server:cast(?SERVER, {warning, Fmt}). - -warning(Fmt, Args) when is_list(Args) -> - gen_server:cast(?SERVER, {warning, Fmt, Args}). - -error(Fmt) -> - gen_server:cast(?SERVER, {error, Fmt}). - -error(Fmt, Args) when is_list(Args) -> - gen_server:cast(?SERVER, {error, Fmt, Args}). +info(Fmt) -> log(default, info, Fmt). +info(Fmt, Args) -> log(default, info, Fmt, Args). +warning(Fmt) -> log(default, warning, Fmt). +warning(Fmt, Args) -> log(default, warning, Fmt, Args). +error(Fmt) -> log(default, error, Fmt). +error(Fmt, Args) -> log(default, error, Fmt, Args). %%-------------------------------------------------------------------- -init([]) -> {ok, none}. +init([]) -> + {ok, CatLevelList} = application:get_env(log_levels), + CatLevels = [{Cat, level(Level)} || {Cat, Level} <- CatLevelList], + {ok, orddict:from_list(CatLevels)}. handle_call(_Request, _From, State) -> {noreply, State}. -handle_cast({debug, Fmt}, State) -> - io:format("debug:: "), io:format(Fmt), - error_logger:info_msg("debug:: " ++ Fmt), - {noreply, State}; -handle_cast({debug, Fmt, Args}, State) -> - io:format("debug:: "), io:format(Fmt, Args), - error_logger:info_msg("debug:: " ++ Fmt, Args), - {noreply, State}; -handle_cast({message, Direction, Channel, MethodRecord, Content}, State) -> - io:format("~s ch~p ~p~n", - [case Direction of - in -> "-->"; - out -> "<--" end, - Channel, - {MethodRecord, Content}]), - {noreply, State}; -handle_cast({info, Fmt}, State) -> - error_logger:info_msg(Fmt), - {noreply, State}; -handle_cast({info, Fmt, Args}, State) -> - error_logger:info_msg(Fmt, Args), - {noreply, State}; -handle_cast({warning, Fmt}, State) -> - error_logger:warning_msg(Fmt), - {noreply, State}; -handle_cast({warning, Fmt, Args}, State) -> - error_logger:warning_msg(Fmt, Args), - {noreply, State}; -handle_cast({error, Fmt}, State) -> - error_logger:error_msg(Fmt), - {noreply, State}; -handle_cast({error, Fmt, Args}, State) -> - error_logger:error_msg(Fmt, Args), - {noreply, State}; +handle_cast({log, Category, Level, Fmt, Args}, CatLevels) -> + CatLevel = case orddict:find(Category, CatLevels) of + {ok, L} -> L; + error -> level(info) + end, + case level(Level) =< CatLevel of + false -> ok; + true -> (case Level of + info -> fun error_logger:info_msg/2; + warning -> fun error_logger:warning_msg/2; + error -> fun error_logger:error_msg/2 + end)(Fmt, Args) + end, + {noreply, CatLevels}; handle_cast(_Msg, State) -> {noreply, State}. @@ -132,3 +100,9 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. +%%-------------------------------------------------------------------- + +level(info) -> 3; +level(warning) -> 2; +level(error) -> 1; +level(none) -> 0. diff -Nru rabbitmq-server-2.7.1/src/rabbit_memory_monitor.erl rabbitmq-server-2.8.0/src/rabbit_memory_monitor.erl --- rabbitmq-server-2.7.1/src/rabbit_memory_monitor.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_memory_monitor.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% @@ -178,11 +178,8 @@ %% Internal functions %%---------------------------------------------------------------------------- -zero_clamp(Sum) -> - case Sum < ?EPSILON of - true -> 0.0; - false -> Sum - end. +zero_clamp(Sum) when Sum < ?EPSILON -> 0.0; +zero_clamp(Sum) -> Sum. internal_deregister(Pid, Demonitor, State = #state { queue_duration_sum = Sum, @@ -240,26 +237,21 @@ fun (Proc = #process { reported = QueueDuration, sent = PrevSendDuration, callback = {M, F, A} }, true) -> - case (case {QueueDuration, PrevSendDuration} of - {infinity, infinity} -> - true; - {infinity, D} -> - DesiredDurationAvg1 < D; - {D, infinity} -> - DesiredDurationAvg1 < D; - {D1, D2} -> - DesiredDurationAvg1 < - lists:min([D1,D2]) - end) of - true -> - ok = erlang:apply( - M, F, A ++ [DesiredDurationAvg1]), - ets:insert( - Durations, - Proc #process {sent = DesiredDurationAvg1}); - false -> - true + case should_send(QueueDuration, PrevSendDuration, + DesiredDurationAvg1) of + true -> ok = erlang:apply( + M, F, A ++ [DesiredDurationAvg1]), + ets:insert( + Durations, + Proc #process { + sent = DesiredDurationAvg1}); + false -> true end end, true, Durations) end, State1. + +should_send(infinity, infinity, _) -> true; +should_send(infinity, D, DD) -> DD < D; +should_send(D, infinity, DD) -> DD < D; +should_send(D1, D2, DD) -> DD < lists:min([D1, D2]). diff -Nru rabbitmq-server-2.7.1/src/rabbit_mirror_queue_coordinator.erl rabbitmq-server-2.8.0/src/rabbit_mirror_queue_coordinator.erl --- rabbitmq-server-2.7.1/src/rabbit_mirror_queue_coordinator.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_mirror_queue_coordinator.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mirror_queue_coordinator). @@ -325,8 +325,7 @@ true = link(GM), GM end, - {ok, _TRef} = - timer:apply_interval(?ONE_SECOND, gm, broadcast, [GM1, heartbeat]), + ensure_gm_heartbeat(), {ok, #state { q = Q, gm = GM1, monitors = dict:new(), @@ -366,6 +365,11 @@ end, Monitors, Pids), noreply(State #state { monitors = Monitors1 }). +handle_info(send_gm_heartbeat, State = #state{gm = GM}) -> + gm:broadcast(GM, heartbeat), + ensure_gm_heartbeat(), + noreply(State); + handle_info({'DOWN', _MonitorRef, process, Pid, _Reason}, State = #state { monitors = Monitors, death_fun = DeathFun }) -> @@ -419,3 +423,6 @@ reply(Reply, State) -> {reply, Reply, State, hibernate}. + +ensure_gm_heartbeat() -> + erlang:send_after(?ONE_SECOND, self(), send_gm_heartbeat). diff -Nru rabbitmq-server-2.7.1/src/rabbit_mirror_queue_master.erl rabbitmq-server-2.8.0/src/rabbit_mirror_queue_master.erl --- rabbitmq-server-2.7.1/src/rabbit_mirror_queue_master.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_mirror_queue_master.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,17 +11,17 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mirror_queue_master). -export([init/3, terminate/2, delete_and_terminate/2, purge/1, publish/4, publish_delivered/5, fetch/2, ack/2, - requeue/2, len/1, is_empty/1, drain_confirmed/1, dropwhile/2, + requeue/2, len/1, is_empty/1, drain_confirmed/1, dropwhile/3, set_ram_duration_target/2, ram_duration/1, needs_timeout/1, timeout/1, handle_pre_hibernate/1, - status/1, invoke/3, is_duplicate/2, discard/3]). + status/1, invoke/3, is_duplicate/2, discard/3, fold/3]). -export([start/1, stop/0]). @@ -172,12 +172,13 @@ ensure_monitoring(ChPid, State #state { backing_queue_state = BQS1, ack_msg_id = AM1 })}. -dropwhile(Fun, State = #state { gm = GM, - backing_queue = BQ, - backing_queue_state = BQS, - set_delivered = SetDelivered }) -> +dropwhile(Pred, MsgFun, + State = #state{gm = GM, + backing_queue = BQ, + set_delivered = SetDelivered, + backing_queue_state = BQS }) -> Len = BQ:len(BQS), - BQS1 = BQ:dropwhile(Fun, BQS), + BQS1 = BQ:dropwhile(Pred, MsgFun, BQS), Dropped = Len - BQ:len(BQS1), SetDelivered1 = lists:max([0, SetDelivered - Dropped]), ok = gm:broadcast(GM, {set_length, BQ:len(BQS1)}), @@ -248,6 +249,13 @@ {MsgIds, State #state { backing_queue_state = BQS1, ack_msg_id = AM1 }}. +fold(MsgFun, State = #state { gm = GM, + backing_queue = BQ, + backing_queue_state = BQS}, AckTags) -> + BQS1 = BQ:fold(MsgFun, BQS, AckTags), + ok = gm:broadcast(GM, {fold, MsgFun, AckTags}), + State #state { backing_queue_state = BQS1 }. + requeue(AckTags, State = #state { gm = GM, backing_queue = BQ, backing_queue_state = BQS }) -> @@ -280,8 +288,10 @@ backing_queue_state = BQS }) -> State #state { backing_queue_state = BQ:handle_pre_hibernate(BQS) }. -status(#state { backing_queue = BQ, backing_queue_state = BQS }) -> - BQ:status(BQS). +status(State = #state { backing_queue = BQ, backing_queue_state = BQS }) -> + BQ:status(BQS) ++ + [ {mirror_seen, dict:size(State #state.seen_status)}, + {mirror_senders, sets:size(State #state.known_senders)} ]. invoke(?MODULE, Fun, State) -> Fun(?MODULE, State); diff -Nru rabbitmq-server-2.7.1/src/rabbit_mirror_queue_misc.erl rabbitmq-server-2.8.0/src/rabbit_mirror_queue_misc.erl --- rabbitmq-server-2.7.1/src/rabbit_mirror_queue_misc.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_mirror_queue_misc.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mirror_queue_misc). @@ -134,14 +134,17 @@ Queue, fun (#amqqueue { name = Name, pid = QPid, slave_pids = SPids } = Q) -> case [Pid || Pid <- [QPid | SPids], node(Pid) =:= MirrorNode] of - [] -> Result = rabbit_mirror_queue_slave_sup:start_child( - MirrorNode, [Q]), - rabbit_log:info( - "Adding mirror of queue ~s on node ~p: ~p~n", - [rabbit_misc:rs(Name), MirrorNode, Result]), - case Result of - {ok, _Pid} -> ok; - _ -> Result + [] -> case rabbit_mirror_queue_slave_sup:start_child( + MirrorNode, [Q]) of + {ok, undefined} -> %% Already running + ok; + {ok, SPid} -> + rabbit_log:info( + "Adding mirror of ~s on node ~p: ~p~n", + [rabbit_misc:rs(Name), MirrorNode, SPid]), + ok; + Other -> + Other end; [_] -> {error, {queue_already_mirrored_on_node, MirrorNode}} end diff -Nru rabbitmq-server-2.7.1/src/rabbit_mirror_queue_slave.erl rabbitmq-server-2.8.0/src/rabbit_mirror_queue_slave.erl --- rabbitmq-server-2.7.1/src/rabbit_mirror_queue_slave.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_mirror_queue_slave.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mirror_queue_slave). @@ -90,7 +90,7 @@ }). start_link(Q) -> - gen_server2:start_link(?MODULE, [Q], []). + gen_server2:start_link(?MODULE, Q, []). set_maximum_since_use(QPid, Age) -> gen_server2:cast(QPid, {set_maximum_since_use, Age}). @@ -98,59 +98,64 @@ info(QPid) -> gen_server2:call(QPid, info, infinity). -init([#amqqueue { name = QueueName } = Q]) -> - process_flag(trap_exit, true), %% amqqueue_process traps exits too. - {ok, GM} = gm:start_link(QueueName, ?MODULE, [self()]), - receive {joined, GM} -> - ok - end, +init(#amqqueue { name = QueueName } = Q) -> Self = self(), Node = node(), - {ok, MPid} = - rabbit_misc:execute_mnesia_transaction( - fun () -> - [Q1 = #amqqueue { pid = QPid, slave_pids = MPids }] = - mnesia:read({rabbit_queue, QueueName}), - %% ASSERTION - [] = [Pid || Pid <- [QPid | MPids], node(Pid) =:= Node], - MPids1 = MPids ++ [Self], - ok = rabbit_amqqueue:store_queue( - Q1 #amqqueue { slave_pids = MPids1 }), - {ok, QPid} - end), - erlang:monitor(process, MPid), - ok = file_handle_cache:register_callback( - rabbit_amqqueue, set_maximum_since_use, [Self]), - ok = rabbit_memory_monitor:register( - Self, {rabbit_amqqueue, set_ram_duration_target, [Self]}), - {ok, BQ} = application:get_env(backing_queue_module), - BQS = bq_init(BQ, Q, false), - State = #state { q = Q, - gm = GM, - master_pid = MPid, - backing_queue = BQ, - backing_queue_state = BQS, - rate_timer_ref = undefined, - sync_timer_ref = undefined, - - sender_queues = dict:new(), - msg_id_ack = dict:new(), - ack_num = 0, + case rabbit_misc:execute_mnesia_transaction( + fun () -> + [Q1 = #amqqueue { pid = QPid, slave_pids = MPids }] = + mnesia:read({rabbit_queue, QueueName}), + case [Pid || Pid <- [QPid | MPids], node(Pid) =:= Node] of + [] -> MPids1 = MPids ++ [Self], + ok = rabbit_amqqueue:store_queue( + Q1 #amqqueue { slave_pids = MPids1 }), + {new, QPid}; + [SPid] -> true = rabbit_misc:is_process_alive(SPid), + existing + end + end) of + {new, MPid} -> + process_flag(trap_exit, true), %% amqqueue_process traps exits too. + {ok, GM} = gm:start_link(QueueName, ?MODULE, [self()]), + receive {joined, GM} -> + ok + end, + erlang:monitor(process, MPid), + ok = file_handle_cache:register_callback( + rabbit_amqqueue, set_maximum_since_use, [Self]), + ok = rabbit_memory_monitor:register( + Self, {rabbit_amqqueue, set_ram_duration_target, [Self]}), + {ok, BQ} = application:get_env(backing_queue_module), + BQS = bq_init(BQ, Q, false), + State = #state { q = Q, + gm = GM, + master_pid = MPid, + backing_queue = BQ, + backing_queue_state = BQS, + rate_timer_ref = undefined, + sync_timer_ref = undefined, + + sender_queues = dict:new(), + msg_id_ack = dict:new(), + ack_num = 0, - msg_id_status = dict:new(), - known_senders = dict:new(), + msg_id_status = dict:new(), + known_senders = dict:new(), - synchronised = false + synchronised = false }, - rabbit_event:notify(queue_slave_created, - infos(?CREATION_EVENT_KEYS, State)), - ok = gm:broadcast(GM, request_length), - {ok, State, hibernate, - {backoff, ?HIBERNATE_AFTER_MIN, ?HIBERNATE_AFTER_MIN, ?DESIRED_HIBERNATE}}. - -handle_call({deliver_immediately, Delivery = #delivery {}}, From, State) -> - %% Synchronous, "immediate" delivery mode + rabbit_event:notify(queue_slave_created, + infos(?CREATION_EVENT_KEYS, State)), + ok = gm:broadcast(GM, request_length), + {ok, State, hibernate, + {backoff, ?HIBERNATE_AFTER_MIN, ?HIBERNATE_AFTER_MIN, + ?DESIRED_HIBERNATE}}; + existing -> + ignore + end. +handle_call({deliver, Delivery = #delivery { immediate = true }}, + From, State) -> %% It is safe to reply 'false' here even if a) we've not seen the %% msg via gm, or b) the master dies before we receive the msg via %% gm. In the case of (a), we will eventually receive the msg via @@ -166,8 +171,8 @@ gen_server2:reply(From, false), %% master may deliver it, not us noreply(maybe_enqueue_message(Delivery, false, State)); -handle_call({deliver, Delivery = #delivery {}}, From, State) -> - %% Synchronous, "mandatory" delivery mode +handle_call({deliver, Delivery = #delivery { mandatory = true }}, + From, State) -> gen_server2:reply(From, true), %% amqqueue throws away the result anyway noreply(maybe_enqueue_message(Delivery, true, State)); @@ -208,8 +213,12 @@ handle_cast({gm, Instruction}, State) -> handle_process_result(process_instruction(Instruction, State)); -handle_cast({deliver, Delivery = #delivery {}}, State) -> +handle_cast({deliver, Delivery = #delivery{sender = Sender}, Flow}, State) -> %% Asynchronous, non-"mandatory", non-"immediate" deliver mode. + case Flow of + flow -> credit_flow:ack(Sender); + noflow -> ok + end, noreply(maybe_enqueue_message(Delivery, true, State)); handle_cast({set_maximum_since_use, Age}, State) -> @@ -250,6 +259,10 @@ handle_info({'EXIT', _Pid, Reason}, State) -> {stop, Reason, State}; +handle_info({bump_credit, Msg}, State) -> + credit_flow:handle_bump_msg(Msg), + noreply(State); + handle_info(Msg, State) -> {stop, {unexpected_info, Msg}, State}. @@ -417,7 +430,7 @@ Acc end end, {gb_trees:empty(), MS}, MsgIds), - rabbit_misc:gb_trees_foreach(fun rabbit_channel:confirm/2, CMs), + rabbit_misc:gb_trees_foreach(fun rabbit_misc:confirm_to_sender/2, CMs), State #state { msg_id_status = MS1 }. handle_process_result({ok, State}) -> noreply(State); @@ -447,7 +460,7 @@ %% Everything that we're monitoring, we need to ensure our new %% coordinator is monitoring. - MonitoringPids = [begin true = erlang:demonitor(MRef), + MonitoringPids = [begin put({ch_publisher, Pid}, MRef), Pid end || {Pid, MRef} <- dict:to_list(KS)], ok = rabbit_mirror_queue_coordinator:ensure_monitoring( @@ -601,7 +614,8 @@ local_sender_death(ChPid, State = #state { known_senders = KS }) -> ok = case dict:is_key(ChPid, KS) of false -> ok; - true -> confirm_sender_death(ChPid) + true -> credit_flow:peer_down(ChPid), + confirm_sender_death(ChPid) end, State. @@ -651,7 +665,7 @@ {ok, {confirmed, ChPid}} -> %% BQ has confirmed it but we didn't know what the %% msg_seq_no was at the time. We do now! - ok = rabbit_channel:confirm(ChPid, [MsgSeqNo]), + ok = rabbit_misc:confirm_to_sender(ChPid, [MsgSeqNo]), SQ1 = remove_from_pending_ch(MsgId, ChPid, SQ), State1 #state { sender_queues = SQ1, msg_id_status = dict:erase(MsgId, MS) }; @@ -668,7 +682,7 @@ msg_id_status = dict:store(MsgId, {published, ChPid, MsgSeqNo}, MS) }; immediately -> - ok = rabbit_channel:confirm(ChPid, [MsgSeqNo]), + ok = rabbit_misc:confirm_to_sender(ChPid, [MsgSeqNo]), SQ1 = remove_from_pending_ch(MsgId, ChPid, SQ), State1 #state { msg_id_status = dict:erase(MsgId, MS), sender_queues = SQ1 } @@ -730,7 +744,7 @@ {MQ2, PendingCh, dict:store(MsgId, {published, ChPid, MsgSeqNo}, MS)}; immediately -> - ok = rabbit_channel:confirm(ChPid, [MsgSeqNo]), + ok = rabbit_misc:confirm_to_sender(ChPid, [MsgSeqNo]), {MQ2, PendingCh, MS} end; {{value, {#delivery {}, _EnqueueOnPromotion}}, _MQ2} -> @@ -829,6 +843,11 @@ [] = MsgIds1 -- MsgIds, %% ASSERTION {ok, State #state { msg_id_ack = MA1, backing_queue_state = BQS1 }}; +process_instruction({fold, MsgFun, AckTags}, + State = #state { backing_queue = BQ, + backing_queue_state = BQS }) -> + BQS1 = BQ:fold(AckTags, MsgFun, BQS), + {ok, State #state { backing_queue_state = BQS1 }}; process_instruction({requeue, MsgIds}, State = #state { backing_queue = BQ, backing_queue_state = BQS, diff -Nru rabbitmq-server-2.7.1/src/rabbit_mirror_queue_slave_sup.erl rabbitmq-server-2.8.0/src/rabbit_mirror_queue_slave_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_mirror_queue_slave_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_mirror_queue_slave_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2010-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2010-2012 VMware, Inc. All rights reserved. %% -module(rabbit_mirror_queue_slave_sup). diff -Nru rabbitmq-server-2.7.1/src/rabbit_misc.erl rabbitmq-server-2.8.0/src/rabbit_misc.erl --- rabbitmq-server-2.7.1/src/rabbit_misc.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_misc.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_misc). @@ -28,23 +28,26 @@ -export([enable_cover/0, report_cover/0]). -export([enable_cover/1, report_cover/1]). -export([start_cover/1]). +-export([confirm_to_sender/2]). -export([throw_on_error/2, with_exit_handler/2, filter_exit_map/2]). +-export([is_abnormal_termination/1]). -export([with_user/2, with_user_and_vhost/3]). -export([execute_mnesia_transaction/1]). -export([execute_mnesia_transaction/2]). -export([execute_mnesia_tx_with_tail/1]). -export([ensure_ok/2]). --export([makenode/1, nodeparts/1, cookie_hash/0, tcp_name/3]). +-export([tcp_name/3]). -export([upmap/2, map_in_order/2]). -export([table_filter/3]). -export([dirty_read_all/1, dirty_foreach_key/2, dirty_dump_log/1]). --export([format_stderr/2, with_local_io/1, local_info_msg/2]). +-export([format/2, format_stderr/2, with_local_io/1, local_info_msg/2]). -export([start_applications/1, stop_applications/1]). -export([unfold/2, ceil/1, queue_fold/3]). -export([sort_field_table/1]). -export([pid_to_string/1, string_to_pid/1]). -export([version_compare/2, version_compare/3]). --export([dict_cons/3, orddict_cons/3, gb_trees_cons/3]). +-export([dict_cons/3, orddict_cons/3, gb_trees_cons/3, + gb_trees_set_insert/3]). -export([gb_trees_fold/3, gb_trees_foreach/2]). -export([get_options/2]). -export([all_module_attributes/1, build_acyclic_graph/3]). @@ -55,6 +58,7 @@ -export([pget/2, pget/3, pget_or_die/2]). -export([format_message_queue/2]). -export([append_rpc_all_nodes/4]). +-export([multi_call/2]). -export([quit/1]). %%---------------------------------------------------------------------------- @@ -108,7 +112,6 @@ (rabbit_framing:amqp_table(), binary(), rabbit_framing:amqp_field_type(), rabbit_framing:amqp_value()) -> rabbit_framing:amqp_table()). - -spec(r/2 :: (rabbit_types:vhost(), K) -> rabbit_types:r3(rabbit_types:vhost(), K, '_') when is_subtype(K, atom())). @@ -131,6 +134,7 @@ (atom(), thunk(rabbit_types:error(any()) | {ok, A} | A)) -> A). -spec(with_exit_handler/2 :: (thunk(A), thunk(A)) -> A). -spec(filter_exit_map/2 :: (fun ((A) -> B), [A]) -> [B]). +-spec(is_abnormal_termination/1 :: (any()) -> boolean()). -spec(with_user/2 :: (rabbit_types:username(), thunk(A)) -> A). -spec(with_user_and_vhost/3 :: (rabbit_types:username(), rabbit_types:vhost(), thunk(A)) @@ -141,9 +145,6 @@ -spec(execute_mnesia_tx_with_tail/1 :: (thunk(fun ((boolean()) -> B))) -> B | (fun ((boolean()) -> B))). -spec(ensure_ok/2 :: (ok_or_error(), atom()) -> 'ok'). --spec(makenode/1 :: ({string(), string()} | string()) -> node()). --spec(nodeparts/1 :: (node() | string()) -> {string(), string()}). --spec(cookie_hash/0 :: () -> string()). -spec(tcp_name/3 :: (atom(), inet:ip_address(), rabbit_networking:ip_port()) -> atom()). @@ -155,6 +156,7 @@ -spec(dirty_foreach_key/2 :: (fun ((any()) -> any()), atom()) -> 'ok' | 'aborted'). -spec(dirty_dump_log/1 :: (file:filename()) -> ok_or_error()). +-spec(format/2 :: (string(), [any()]) -> string()). -spec(format_stderr/2 :: (string(), [any()]) -> 'ok'). -spec(with_local_io/1 :: (fun (() -> A)) -> A). -spec(local_info_msg/2 :: (string(), [any()]) -> 'ok'). @@ -174,6 +176,7 @@ -spec(dict_cons/3 :: (any(), any(), dict()) -> dict()). -spec(orddict_cons/3 :: (any(), any(), orddict:orddict()) -> orddict:orddict()). -spec(gb_trees_cons/3 :: (any(), any(), gb_tree()) -> gb_tree()). +-spec(gb_trees_set_insert/3 :: (any(), any(), gb_tree()) -> gb_tree()). -spec(gb_trees_fold/3 :: (fun ((any(), any(), A) -> A), A, gb_tree()) -> A). -spec(gb_trees_foreach/2 :: (fun ((any(), any()) -> any()), gb_tree()) -> 'ok'). @@ -198,6 +201,8 @@ -spec(pget_or_die/2 :: (term(), [term()]) -> term() | no_return()). -spec(format_message_queue/2 :: (any(), priority_queue:q()) -> term()). -spec(append_rpc_all_nodes/4 :: ([node()], atom(), atom(), [any()]) -> [any()]). +-spec(multi_call/2 :: + ([pid()], any()) -> {[{pid(), any()}], [{pid(), any()}]}). -spec(quit/1 :: (integer() | string()) -> no_return()). -endif. @@ -222,7 +227,7 @@ protocol_error(frame_error, "cannot decode ~w", [BinaryFields], MethodName). amqp_error(Name, ExplanationFormat, Params, Method) -> - Explanation = lists:flatten(io_lib:format(ExplanationFormat, Params)), + Explanation = format(ExplanationFormat, Params), #amqp_error{name = Name, explanation = Explanation, method = Method}. protocol_error(Name, ExplanationFormat, Params) -> @@ -276,8 +281,7 @@ true -> "~s"; false -> "~w" end, - lists:flatten(io_lib:format("the value '" ++ ValFmt ++ "' of type '~s'", - [Value, Type])). + format("the value '" ++ ValFmt ++ "' of type '~s'", [Value, Type]). %% Normally we'd call mnesia:dirty_read/1 here, but that is quite %% expensive due to general mnesia overheads (figuring out table types @@ -320,8 +324,7 @@ end. rs(#resource{virtual_host = VHostPath, kind = Kind, name = Name}) -> - lists:flatten(io_lib:format("~s '~s' in vhost '~s'", - [Kind, Name, VHostPath])). + format("~s '~s' in vhost '~s'", [Kind, Name, VHostPath]). enable_cover() -> enable_cover(["."]). @@ -337,7 +340,7 @@ end, ok, Dirs). start_cover(NodesS) -> - {ok, _} = cover:start([makenode(N) || N <- NodesS]), + {ok, _} = cover:start([rabbit_nodes:make(N) || N <- NodesS]), ok. report_cover() -> report_cover(["."]). @@ -376,6 +379,9 @@ end, Mod]). +confirm_to_sender(Pid, MsgSeqNos) -> + gen_server2:cast(Pid, {confirm, MsgSeqNos, self()}). + throw_on_error(E, Thunk) -> case Thunk() of {error, Reason} -> throw({E, Reason}); @@ -401,6 +407,12 @@ fun () -> Ref end, fun () -> F(I) end) || I <- L]). +is_abnormal_termination(Reason) + when Reason =:= noproc; Reason =:= noconnection; + Reason =:= normal; Reason =:= shutdown -> false; +is_abnormal_termination({shutdown, _}) -> false; +is_abnormal_termination(_) -> true. + with_user(Username, Thunk) -> fun () -> case mnesia:read({rabbit_user, Username}) of @@ -418,12 +430,25 @@ %% Making this a sync_transaction allows us to use dirty_read %% elsewhere and get a consistent result even when that read %% executes on a different node. - case worker_pool:submit({mnesia, sync_transaction, [TxFun]}) of - {atomic, Result} -> Result; - {aborted, Reason} -> throw({error, Reason}) + case worker_pool:submit( + fun () -> + case mnesia:is_transaction() of + false -> DiskLogBefore = mnesia_dumper:get_log_writes(), + Res = mnesia:sync_transaction(TxFun), + DiskLogAfter = mnesia_dumper:get_log_writes(), + case DiskLogAfter == DiskLogBefore of + true -> Res; + false -> {sync, Res} + end; + true -> mnesia:sync_transaction(TxFun) + end + end) of + {sync, {atomic, Result}} -> mnesia_sync:sync(), Result; + {sync, {aborted, Reason}} -> throw({error, Reason}); + {atomic, Result} -> Result; + {aborted, Reason} -> throw({error, Reason}) end. - %% Like execute_mnesia_transaction/1 with additional Pre- and Post- %% commit function execute_mnesia_transaction(TxFun, PrePostCommitFun) -> @@ -450,29 +475,10 @@ ensure_ok(ok, _) -> ok; ensure_ok({error, Reason}, ErrorTag) -> throw({error, {ErrorTag, Reason}}). -makenode({Prefix, Suffix}) -> - list_to_atom(lists:append([Prefix, "@", Suffix])); -makenode(NodeStr) -> - makenode(nodeparts(NodeStr)). - -nodeparts(Node) when is_atom(Node) -> - nodeparts(atom_to_list(Node)); -nodeparts(NodeStr) -> - case lists:splitwith(fun (E) -> E =/= $@ end, NodeStr) of - {Prefix, []} -> {_, Suffix} = nodeparts(node()), - {Prefix, Suffix}; - {Prefix, Suffix} -> {Prefix, tl(Suffix)} - end. - -cookie_hash() -> - base64:encode_to_string(erlang:md5(atom_to_list(erlang:get_cookie()))). - tcp_name(Prefix, IPAddress, Port) when is_atom(Prefix) andalso is_number(Port) -> list_to_atom( - lists:flatten( - io_lib:format("~w_~s:~w", - [Prefix, inet_parse:ntoa(IPAddress), Port]))). + format("~w_~s:~w", [Prefix, inet_parse:ntoa(IPAddress), Port])). %% This is a modified version of Luke Gorrie's pmap - %% http://lukego.livejournal.com/6753.html - that doesn't care about @@ -541,6 +547,8 @@ io:format("Bad Chunk, ~p: ~p~n", [BadBytes, Terms]), dirty_dump_log1(LH, disk_log:chunk(LH, K)). +format(Fmt, Args) -> lists:flatten(io_lib:format(Fmt, Args)). + format_stderr(Fmt, Args) -> case os:type() of {unix, _} -> @@ -636,7 +644,7 @@ <<131,103,100,NodeLen:16,NodeBin:NodeLen/binary,Id:32,Ser:32,Cre:8>> = term_to_binary(Pid), Node = binary_to_term(<<131,100,NodeLen:16,NodeBin:NodeLen/binary>>), - lists:flatten(io_lib:format("<~w.~B.~B.~B>", [Node, Cre, Id, Ser])). + format("<~w.~B.~B.~B>", [Node, Cre, Id, Ser]). %% inverse of above string_to_pid(Str) -> @@ -709,6 +717,15 @@ none -> gb_trees:insert(Key, [Value], Tree) end. +gb_trees_set_insert(Key, Value, Tree) -> + case gb_trees:lookup(Key, Tree) of + {value, Values} -> + Values1 = gb_sets:insert(Value, Values), + gb_trees:update(Key, Values1, Tree); + none -> + gb_trees:insert(Key, gb_sets:singleton(Value), Tree) + end. + gb_trees_fold(Fun, Acc, Tree) -> gb_trees_fold1(Fun, Acc, gb_trees:next(gb_trees:iterator(Tree))). @@ -728,13 +745,14 @@ %% [{"-q",true},{"-p","/"}]} get_options(Defs, As) -> lists:foldl(fun(Def, {AsIn, RsIn}) -> - {AsOut, Value} = case Def of - {flag, Key} -> - get_flag(Key, AsIn); - {option, Key, Default} -> - get_option(Key, Default, AsIn) - end, - {AsOut, [{Key, Value} | RsIn]} + {K, {AsOut, V}} = + case Def of + {flag, Key} -> + {Key, get_flag(Key, AsIn)}; + {option, Key, Default} -> + {Key, get_option(Key, Default, AsIn)} + end, + {AsOut, [{K, V} | RsIn]} end, {As, []}, Defs). get_option(K, _Default, [K, V | As]) -> @@ -865,6 +883,31 @@ _ -> Res end || Res <- ResL]). +%% A simplified version of gen_server:multi_call/2 with a sane +%% API. This is not in gen_server2 as there is no useful +%% infrastructure there to share. +multi_call(Pids, Req) -> + MonitorPids = [start_multi_call(Pid, Req) || Pid <- Pids], + receive_multi_call(MonitorPids, [], []). + +start_multi_call(Pid, Req) when is_pid(Pid) -> + Mref = erlang:monitor(process, Pid), + Pid ! {'$gen_call', {self(), Mref}, Req}, + {Mref, Pid}. + +receive_multi_call([], Good, Bad) -> + {lists:reverse(Good), lists:reverse(Bad)}; +receive_multi_call([{Mref, Pid} | MonitorPids], Good, Bad) -> + receive + {Mref, Reply} -> + erlang:demonitor(Mref, [flush]), + receive_multi_call(MonitorPids, [{Pid, Reply} | Good], Bad); + {'DOWN', Mref, _, _, noconnection} -> + receive_multi_call(MonitorPids, Good, [{Pid, nodedown} | Bad]); + {'DOWN', Mref, _, _, Reason} -> + receive_multi_call(MonitorPids, Good, [{Pid, Reason} | Bad]) + end. + %% the slower shutdown on windows required to flush stdout quit(Status) -> case os:type() of diff -Nru rabbitmq-server-2.7.1/src/rabbit_mnesia.erl rabbitmq-server-2.8.0/src/rabbit_mnesia.erl --- rabbitmq-server-2.7.1/src/rabbit_mnesia.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_mnesia.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% @@ -23,8 +23,8 @@ empty_ram_only_tables/0, copy_db/1, wait_for_tables/1, create_cluster_nodes_config/1, read_cluster_nodes_config/0, record_running_nodes/0, read_previously_running_nodes/0, - delete_previously_running_nodes/0, running_nodes_filename/0, - is_disc_node/0, on_node_down/1, on_node_up/1]). + running_nodes_filename/0, is_disc_node/0, on_node_down/1, + on_node_up/1]). -export([table_names/0]). @@ -64,7 +64,6 @@ -spec(read_cluster_nodes_config/0 :: () -> [node()]). -spec(record_running_nodes/0 :: () -> 'ok'). -spec(read_previously_running_nodes/0 :: () -> [node()]). --spec(delete_previously_running_nodes/0 :: () -> 'ok'). -spec(running_nodes_filename/0 :: () -> file:filename()). -spec(is_disc_node/0 :: () -> boolean()). -spec(on_node_up/1 :: (node()) -> 'ok'). @@ -98,12 +97,13 @@ init() -> ensure_mnesia_running(), ensure_mnesia_dir(), - ok = init_db(read_cluster_nodes_config(), true, - fun maybe_upgrade_local_or_record_desired/0), + Nodes = read_cluster_nodes_config(), + ok = init_db(Nodes, should_be_disc_node(Nodes)), %% We intuitively expect the global name server to be synced when %% Mnesia is up. In fact that's not guaranteed to be the case - let's %% make it so. ok = global:sync(), + ok = delete_previously_running_nodes(), ok. is_db_empty() -> @@ -174,8 +174,7 @@ %% Join the cluster start_mnesia(), try - ok = init_db(ClusterNodes, Force, - fun maybe_upgrade_local_or_record_desired/0), + ok = init_db(ClusterNodes, Force), ok = create_cluster_nodes_config(ClusterNodes) after stop_mnesia() @@ -268,6 +267,11 @@ {type, ordered_set}, {match, #reverse_route{reverse_binding = reverse_binding_match(), _='_'}}]}, + {rabbit_topic_trie_node, + [{record_name, topic_trie_node}, + {attributes, record_info(fields, topic_trie_node)}, + {type, ordered_set}, + {match, #topic_trie_node{trie_node = trie_node_match(), _='_'}}]}, {rabbit_topic_trie_edge, [{record_name, topic_trie_edge}, {attributes, record_info(fields, topic_trie_edge)}, @@ -314,12 +318,12 @@ _='_'}. binding_destination_match() -> resource_match('_'). +trie_node_match() -> + #trie_node{ exchange_name = exchange_name_match(), _='_'}. trie_edge_match() -> - #trie_edge{exchange_name = exchange_name_match(), - _='_'}. + #trie_edge{ exchange_name = exchange_name_match(), _='_'}. trie_binding_match() -> - #trie_binding{exchange_name = exchange_name_match(), - _='_'}. + #trie_binding{exchange_name = exchange_name_match(), _='_'}. exchange_name_match() -> resource_match(exchange). queue_name_match() -> @@ -496,6 +500,18 @@ FileName, Reason}}) end. +init_db(ClusterNodes, Force) -> + init_db( + ClusterNodes, Force, + fun () -> + case rabbit_upgrade:maybe_upgrade_local() of + ok -> ok; + %% If we're just starting up a new node we won't have a + %% version + version_not_available -> ok = rabbit_version:record_desired() + end + end). + %% Take a cluster node config and create the right kind of node - a %% standalone disk node, or disk or ram node connected to the %% specified cluster nodes. If Force is false, don't allow @@ -504,20 +520,12 @@ UClusterNodes = lists:usort(ClusterNodes), ProperClusterNodes = UClusterNodes -- [node()], case mnesia:change_config(extra_db_nodes, ProperClusterNodes) of + {ok, []} when not Force andalso ProperClusterNodes =/= [] -> + throw({error, {failed_to_cluster_with, ProperClusterNodes, + "Mnesia could not connect to any disc nodes."}}); {ok, Nodes} -> - case Force of - false -> FailedClusterNodes = ProperClusterNodes -- Nodes, - case FailedClusterNodes of - [] -> ok; - _ -> throw({error, {failed_to_cluster_with, - FailedClusterNodes, - "Mnesia could not connect " - "to some nodes."}}) - end; - true -> ok - end, - WantDiscNode = should_be_disc_node(ClusterNodes), WasDiscNode = is_disc_node(), + WantDiscNode = should_be_disc_node(ClusterNodes), %% We create a new db (on disk, or in ram) in the first %% two cases and attempt to upgrade the in the other two case {Nodes, WasDiscNode, WantDiscNode} of @@ -567,14 +575,6 @@ throw({error, {unable_to_join_cluster, ClusterNodes, Reason}}) end. -maybe_upgrade_local_or_record_desired() -> - case rabbit_upgrade:maybe_upgrade_local() of - ok -> ok; - %% If we're just starting up a new node we won't have a - %% version - version_not_available -> ok = rabbit_version:record_desired() - end. - schema_ok_or_move() -> case check_schema_integrity() of ok -> @@ -622,10 +622,9 @@ stop_mnesia(), MnesiaDir = filename:dirname(dir() ++ "/"), {{Year, Month, Day}, {Hour, Minute, Second}} = erlang:universaltime(), - BackupDir = lists:flatten( - io_lib:format("~s_~w~2..0w~2..0w~2..0w~2..0w~2..0w", - [MnesiaDir, - Year, Month, Day, Hour, Minute, Second])), + BackupDir = rabbit_misc:format( + "~s_~w~2..0w~2..0w~2..0w~2..0w~2..0w", + [MnesiaDir, Year, Month, Day, Hour, Minute, Second]), case file:rename(MnesiaDir, BackupDir) of ok -> %% NB: we cannot use rabbit_log here since it may not have @@ -733,16 +732,18 @@ false -> ok end, Node = node(), + Nodes = all_clustered_nodes() -- [Node], case Force of true -> ok; false -> ensure_mnesia_dir(), start_mnesia(), - {Nodes, RunningNodes} = + RunningNodes = try - ok = init(), - {all_clustered_nodes() -- [Node], - running_clustered_nodes() -- [Node]} + %% Force=true here so that reset still works when clustered + %% with a node which is down + ok = init_db(read_cluster_nodes_config(), true), + running_clustered_nodes() -- [Node] after stop_mnesia() end, @@ -750,6 +751,10 @@ rabbit_misc:ensure_ok(mnesia:delete_schema([Node]), cannot_delete_schema) end, + %% We need to make sure that we don't end up in a distributed + %% Erlang system with nodes while not being in an Mnesia cluster + %% with them. We don't handle that well. + [erlang:disconnect_node(N) || N <- Nodes], ok = delete_cluster_nodes_config(), %% remove persisted messages and any other garbage we find ok = rabbit_file:recursive_delete(filelib:wildcard(dir() ++ "/*")), diff -Nru rabbitmq-server-2.7.1/src/rabbit_msg_file.erl rabbitmq-server-2.8.0/src/rabbit_msg_file.erl --- rabbitmq-server-2.7.1/src/rabbit_msg_file.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_msg_file.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_msg_file). diff -Nru rabbitmq-server-2.7.1/src/rabbit_msg_store.erl rabbitmq-server-2.8.0/src/rabbit_msg_store.erl --- rabbitmq-server-2.7.1/src/rabbit_msg_store.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_msg_store.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_msg_store). @@ -21,7 +21,7 @@ -export([start_link/4, successfully_recovered_state/1, client_init/4, client_terminate/1, client_delete_and_terminate/1, client_ref/1, close_all_indicated/1, - write/3, read/2, contains/2, remove/2]). + write/3, write_flow/3, read/2, contains/2, remove/2]). -export([set_maximum_since_use/2, has_readers/2, combine_files/3, delete_file/2]). %% internal @@ -152,6 +152,7 @@ -spec(close_all_indicated/1 :: (client_msstate()) -> rabbit_types:ok(client_msstate())). -spec(write/3 :: (rabbit_types:msg_id(), msg(), client_msstate()) -> 'ok'). +-spec(write_flow/3 :: (rabbit_types:msg_id(), msg(), client_msstate()) -> 'ok'). -spec(read/2 :: (rabbit_types:msg_id(), client_msstate()) -> {rabbit_types:ok(msg()) | 'not_found', client_msstate()}). -spec(contains/2 :: (rabbit_types:msg_id(), client_msstate()) -> boolean()). @@ -436,7 +437,8 @@ {IState, IModule, Dir, GCPid, FileHandlesEts, FileSummaryEts, CurFileCacheEts, FlyingEts} = gen_server2:call( - Server, {new_client_state, Ref, MsgOnDiskFun, CloseFDsFun}, infinity), + Server, {new_client_state, Ref, self(), MsgOnDiskFun, CloseFDsFun}, + infinity), #client_msstate { server = Server, client_ref = Ref, file_handle_cache = dict:new(), @@ -460,12 +462,11 @@ client_ref(#client_msstate { client_ref = Ref }) -> Ref. -write(MsgId, Msg, - CState = #client_msstate { cur_file_cache_ets = CurFileCacheEts, - client_ref = CRef }) -> - ok = client_update_flying(+1, MsgId, CState), - ok = update_msg_cache(CurFileCacheEts, MsgId, Msg), - ok = server_cast(CState, {write, CRef, MsgId}). +write_flow(MsgId, Msg, CState = #client_msstate { server = Server }) -> + credit_flow:send(whereis(Server), ?CREDIT_DISC_BOUND), + client_write(MsgId, Msg, flow, CState). + +write(MsgId, Msg, CState) -> client_write(MsgId, Msg, noflow, CState). read(MsgId, CState = #client_msstate { cur_file_cache_ets = CurFileCacheEts }) -> @@ -500,6 +501,13 @@ server_cast(#client_msstate { server = Server }, Msg) -> gen_server2:cast(Server, Msg). +client_write(MsgId, Msg, Flow, + CState = #client_msstate { cur_file_cache_ets = CurFileCacheEts, + client_ref = CRef }) -> + ok = client_update_flying(+1, MsgId, CState), + ok = update_msg_cache(CurFileCacheEts, MsgId, Msg), + ok = server_cast(CState, {write, CRef, MsgId, Flow}). + client_read1(#msg_location { msg_id = MsgId, file = File } = MsgLocation, Defer, CState = #client_msstate { file_summary_ets = FileSummaryEts }) -> case ets:lookup(FileSummaryEts, File) of @@ -666,7 +674,8 @@ recover_index_and_client_refs(IndexModule, FileSummaryRecovered, ClientRefs, Dir, Server), Clients = dict:from_list( - [{CRef, {undefined, undefined}} || CRef <- ClientRefs1]), + [{CRef, {undefined, undefined, undefined}} || + CRef <- ClientRefs1]), %% CleanShutdown => msg location index and file_summary both %% recovered correctly. true = case {FileSummaryRecovered, CleanShutdown} of @@ -731,10 +740,10 @@ prioritise_call(Msg, _From, _State) -> case Msg of - successfully_recovered_state -> 7; - {new_client_state, _Ref, _MODC, _CloseFDsFun} -> 7; - {read, _MsgId} -> 2; - _ -> 0 + successfully_recovered_state -> 7; + {new_client_state, _Ref, _Pid, _MODC, _CloseFDsFun} -> 7; + {read, _MsgId} -> 2; + _ -> 0 end. prioritise_cast(Msg, _State) -> @@ -755,7 +764,7 @@ handle_call(successfully_recovered_state, _From, State) -> reply(State #msstate.successfully_recovered, State); -handle_call({new_client_state, CRef, MsgOnDiskFun, CloseFDsFun}, _From, +handle_call({new_client_state, CRef, CPid, MsgOnDiskFun, CloseFDsFun}, _From, State = #msstate { dir = Dir, index_state = IndexState, index_module = IndexModule, @@ -765,7 +774,7 @@ flying_ets = FlyingEts, clients = Clients, gc_pid = GCPid }) -> - Clients1 = dict:store(CRef, {MsgOnDiskFun, CloseFDsFun}, Clients), + Clients1 = dict:store(CRef, {CPid, MsgOnDiskFun, CloseFDsFun}, Clients), reply({IndexState, IndexModule, Dir, GCPid, FileHandlesEts, FileSummaryEts, CurFileCacheEts, FlyingEts}, State #msstate { clients = Clients1 }); @@ -789,11 +798,19 @@ handle_cast({client_delete, CRef}, State = #msstate { clients = Clients }) -> + {CPid, _, _} = dict:fetch(CRef, Clients), + credit_flow:peer_down(CPid), State1 = State #msstate { clients = dict:erase(CRef, Clients) }, noreply(remove_message(CRef, CRef, clear_client(CRef, State1))); -handle_cast({write, CRef, MsgId}, - State = #msstate { cur_file_cache_ets = CurFileCacheEts }) -> +handle_cast({write, CRef, MsgId, Flow}, + State = #msstate { cur_file_cache_ets = CurFileCacheEts, + clients = Clients }) -> + case Flow of + flow -> {CPid, _, _} = dict:fetch(CRef, Clients), + credit_flow:ack(CPid, ?CREDIT_DISC_BOUND); + noflow -> ok + end, true = 0 =< ets:update_counter(CurFileCacheEts, MsgId, {3, -1}), case update_flying(-1, MsgId, CRef, State) of process -> @@ -1204,10 +1221,10 @@ State = #msstate { clients = Clients, cref_to_msg_ids = CTM }) -> case dict:fetch(CRef, Clients) of - {undefined, _CloseFDsFun} -> State; - {MsgOnDiskFun, _CloseFDsFun} -> CTM1 = Fun(MsgOnDiskFun, CTM), - State #msstate { - cref_to_msg_ids = CTM1 } + {_CPid, undefined, _CloseFDsFun} -> State; + {_CPid, MsgOnDiskFun, _CloseFDsFun} -> CTM1 = Fun(MsgOnDiskFun, CTM), + State #msstate { + cref_to_msg_ids = CTM1 } end. record_pending_confirm(CRef, MsgId, State) -> @@ -1294,8 +1311,10 @@ case (ets:update_element(FileHandlesEts, Key, {2, close}) andalso Invoke) of true -> case dict:fetch(Ref, ClientRefs) of - {_MsgOnDiskFun, undefined} -> ok; - {_MsgOnDiskFun, CloseFDsFun} -> ok = CloseFDsFun() + {_CPid, _MsgOnDiskFun, undefined} -> + ok; + {_CPid, _MsgOnDiskFun, CloseFDsFun} -> + ok = CloseFDsFun() end; false -> ok end diff -Nru rabbitmq-server-2.7.1/src/rabbit_msg_store_ets_index.erl rabbitmq-server-2.8.0/src/rabbit_msg_store_ets_index.erl --- rabbitmq-server-2.7.1/src/rabbit_msg_store_ets_index.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_msg_store_ets_index.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_msg_store_ets_index). diff -Nru rabbitmq-server-2.7.1/src/rabbit_msg_store_gc.erl rabbitmq-server-2.8.0/src/rabbit_msg_store_gc.erl --- rabbitmq-server-2.7.1/src/rabbit_msg_store_gc.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_msg_store_gc.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_msg_store_gc). diff -Nru rabbitmq-server-2.7.1/src/rabbit_msg_store_index.erl rabbitmq-server-2.8.0/src/rabbit_msg_store_index.erl --- rabbitmq-server-2.7.1/src/rabbit_msg_store_index.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_msg_store_index.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_msg_store_index). diff -Nru rabbitmq-server-2.7.1/src/rabbit_net.erl rabbitmq-server-2.8.0/src/rabbit_net.erl --- rabbitmq-server-2.7.1/src/rabbit_net.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_net.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_net). @@ -19,7 +19,8 @@ -export([is_ssl/1, ssl_info/1, controlling_process/2, getstat/2, recv/1, async_recv/3, port_command/2, setopts/2, send/2, close/1, - sockname/1, peername/1, peercert/1]). + maybe_fast_close/1, sockname/1, peername/1, peercert/1, + connection_string/2]). %%--------------------------------------------------------------------------- @@ -53,6 +54,7 @@ binary()}]) -> ok_or_any_error()). -spec(send/2 :: (socket(), binary() | iolist()) -> ok_or_any_error()). -spec(close/1 :: (socket()) -> ok_or_any_error()). +-spec(maybe_fast_close/1 :: (socket()) -> ok_or_any_error()). -spec(sockname/1 :: (socket()) -> ok_val_or_error({inet:ip_address(), rabbit_networking:ip_port()})). @@ -62,6 +64,8 @@ -spec(peercert/1 :: (socket()) -> 'nossl' | ok_val_or_error(rabbit_ssl:certificate())). +-spec(connection_string/2 :: + (socket(), 'inbound' | 'outbound') -> ok_val_or_error(string())). -endif. @@ -133,6 +137,9 @@ close(Sock) when ?IS_SSL(Sock) -> ssl:close(Sock#ssl_socket.ssl); close(Sock) when is_port(Sock) -> gen_tcp:close(Sock). +maybe_fast_close(Sock) when ?IS_SSL(Sock) -> ok; +maybe_fast_close(Sock) when is_port(Sock) -> erlang:port_close(Sock), ok. + sockname(Sock) when ?IS_SSL(Sock) -> ssl:sockname(Sock#ssl_socket.ssl); sockname(Sock) when is_port(Sock) -> inet:sockname(Sock). @@ -141,3 +148,19 @@ peercert(Sock) when ?IS_SSL(Sock) -> ssl:peercert(Sock#ssl_socket.ssl); peercert(Sock) when is_port(Sock) -> nossl. + +connection_string(Sock, Direction) -> + {From, To} = case Direction of + inbound -> {fun peername/1, fun sockname/1}; + outbound -> {fun sockname/1, fun peername/1} + end, + case {From(Sock), To(Sock)} of + {{ok, {FromAddress, FromPort}}, {ok, {ToAddress, ToPort}}} -> + {ok, rabbit_misc:format("~s:~p -> ~s:~p", + [rabbit_misc:ntoab(FromAddress), FromPort, + rabbit_misc:ntoab(ToAddress), ToPort])}; + {{error, _Reason} = Error, _} -> + Error; + {_, {error, _Reason} = Error} -> + Error + end. diff -Nru rabbitmq-server-2.7.1/src/rabbit_networking.erl rabbitmq-server-2.8.0/src/rabbit_networking.erl --- rabbitmq-server-2.7.1/src/rabbit_networking.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_networking.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_networking). @@ -24,7 +24,7 @@ close_connection/2, force_connection_event_refresh/0]). %%used by TCP-based transports, e.g. STOMP adapter --export([check_tcp_listener_address/2, +-export([tcp_listener_addresses/1, tcp_listener_spec/6, ensure_ssl/0, ssl_transform_fun/1]). -export([tcp_listener_started/3, tcp_listener_stopped/3, @@ -47,12 +47,16 @@ -export_type([ip_port/0, hostname/0]). -type(hostname() :: inet:hostname()). --type(ip_port() :: inet:ip_port()). +-type(ip_port() :: inet:port_number()). -type(family() :: atom()). -type(listener_config() :: ip_port() | {hostname(), ip_port()} | {hostname(), ip_port(), family()}). +-type(address() :: {inet:ip_address(), ip_port(), family()}). +-type(name_prefix() :: atom()). +-type(protocol() :: atom()). +-type(label() :: string()). -spec(start/0 :: () -> 'ok'). -spec(start_tcp_listener/1 :: (listener_config()) -> 'ok'). @@ -76,8 +80,10 @@ -spec(force_connection_event_refresh/0 :: () -> 'ok'). -spec(on_node_down/1 :: (node()) -> 'ok'). --spec(check_tcp_listener_address/2 :: (atom(), listener_config()) - -> [{inet:ip_address(), ip_port(), family(), atom()}]). +-spec(tcp_listener_addresses/1 :: (listener_config()) -> [address()]). +-spec(tcp_listener_spec/6 :: + (name_prefix(), address(), [gen_tcp:listen_option()], protocol(), + label(), rabbit_types:mfargs()) -> supervisor:child_spec()). -spec(ensure_ssl/0 :: () -> rabbit_types:infos()). -spec(ssl_transform_fun/1 :: (rabbit_types:infos()) @@ -140,39 +146,6 @@ transient, infinity, supervisor, [rabbit_client_sup]}), ok. -%% inet_parse:address takes care of ip string, like "0.0.0.0" -%% inet:getaddr returns immediately for ip tuple {0,0,0,0}, -%% and runs 'inet_gethost' port process for dns lookups. -%% On Windows inet:getaddr runs dns resolver for ip string, which may fail. - -getaddr(Host, Family) -> - case inet_parse:address(Host) of - {ok, IPAddress} -> [{IPAddress, resolve_family(IPAddress, Family)}]; - {error, _} -> gethostaddr(Host, Family) - end. - -gethostaddr(Host, auto) -> - Lookups = [{Family, inet:getaddr(Host, Family)} || Family <- [inet, inet6]], - case [{IP, Family} || {Family, {ok, IP}} <- Lookups] of - [] -> host_lookup_error(Host, Lookups); - IPs -> IPs - end; - -gethostaddr(Host, Family) -> - case inet:getaddr(Host, Family) of - {ok, IPAddress} -> [{IPAddress, Family}]; - {error, Reason} -> host_lookup_error(Host, Reason) - end. - -host_lookup_error(Host, Reason) -> - error_logger:error_msg("invalid host ~p - ~p~n", [Host, Reason]), - throw({error, {invalid_host, Host, Reason}}). - -resolve_family({_,_,_,_}, auto) -> inet; -resolve_family({_,_,_,_,_,_,_,_}, auto) -> inet6; -resolve_family(IP, auto) -> throw({error, {strange_family, IP}}); -resolve_family(_, F) -> F. - ensure_ssl() -> ok = rabbit_misc:start_applications([crypto, public_key, ssl]), {ok, SslOptsConfig} = application:get_env(rabbit, ssl_options), @@ -191,8 +164,6 @@ fun (Sock) -> case catch ssl:ssl_accept(Sock, SslOpts, ?SSL_TIMEOUT * 1000) of {ok, SslSock} -> - rabbit_log:info("upgraded TCP connection ~p to SSL~n", - [self()]), {ok, #ssl_socket{tcp = Sock, ssl = SslSock}}; {error, Reason} -> {error, {ssl_upgrade_error, Reason}}; @@ -201,31 +172,36 @@ end end. -check_tcp_listener_address(NamePrefix, Port) when is_integer(Port) -> - check_tcp_listener_address_auto(NamePrefix, Port); - -check_tcp_listener_address(NamePrefix, {"auto", Port}) -> +tcp_listener_addresses(Port) when is_integer(Port) -> + tcp_listener_addresses_auto(Port); +tcp_listener_addresses({"auto", Port}) -> %% Variant to prevent lots of hacking around in bash and batch files - check_tcp_listener_address_auto(NamePrefix, Port); - -check_tcp_listener_address(NamePrefix, {Host, Port}) -> + tcp_listener_addresses_auto(Port); +tcp_listener_addresses({Host, Port}) -> %% auto: determine family IPv4 / IPv6 after converting to IP address - check_tcp_listener_address(NamePrefix, {Host, Port, auto}); + tcp_listener_addresses({Host, Port, auto}); +tcp_listener_addresses({Host, Port, Family0}) + when is_integer(Port) andalso (Port >= 0) andalso (Port =< 65535) -> + [{IPAddress, Port, Family} || + {IPAddress, Family} <- getaddr(Host, Family0)]; +tcp_listener_addresses({_Host, Port, _Family0}) -> + error_logger:error_msg("invalid port ~p - not 0..65535~n", [Port]), + throw({error, {invalid_port, Port}}). -check_tcp_listener_address(NamePrefix, {Host, Port, Family0}) -> - if is_integer(Port) andalso (Port >= 0) andalso (Port =< 65535) -> ok; - true -> error_logger:error_msg("invalid port ~p - not 0..65535~n", - [Port]), - throw({error, {invalid_port, Port}}) - end, - [{IPAddress, Port, Family, - rabbit_misc:tcp_name(NamePrefix, IPAddress, Port)} || - {IPAddress, Family} <- getaddr(Host, Family0)]. - -check_tcp_listener_address_auto(NamePrefix, Port) -> - lists:append([check_tcp_listener_address(NamePrefix, Listener) || +tcp_listener_addresses_auto(Port) -> + lists:append([tcp_listener_addresses(Listener) || Listener <- port_to_listeners(Port)]). +tcp_listener_spec(NamePrefix, {IPAddress, Port, Family}, SocketOpts, + Protocol, Label, OnConnect) -> + {rabbit_misc:tcp_name(NamePrefix, IPAddress, Port), + {tcp_listener_sup, start_link, + [IPAddress, Port, [Family | SocketOpts], + {?MODULE, tcp_listener_started, [Protocol]}, + {?MODULE, tcp_listener_stopped, [Protocol]}, + OnConnect, Label]}, + transient, infinity, supervisor, [tcp_listener_sup]}. + start_tcp_listener(Listener) -> start_listener(Listener, amqp, "TCP Listener", {?MODULE, start_client, []}). @@ -235,27 +211,26 @@ {?MODULE, start_ssl_client, [SslOpts]}). start_listener(Listener, Protocol, Label, OnConnect) -> - [start_listener0(Spec, Protocol, Label, OnConnect) || - Spec <- check_tcp_listener_address(rabbit_tcp_listener_sup, Listener)], + [start_listener0(Address, Protocol, Label, OnConnect) || + Address <- tcp_listener_addresses(Listener)], ok. -start_listener0({IPAddress, Port, Family, Name}, Protocol, Label, OnConnect) -> - {ok,_} = supervisor:start_child( - rabbit_sup, - {Name, - {tcp_listener_sup, start_link, - [IPAddress, Port, [Family | tcp_opts()], - {?MODULE, tcp_listener_started, [Protocol]}, - {?MODULE, tcp_listener_stopped, [Protocol]}, - OnConnect, Label]}, - transient, infinity, supervisor, [tcp_listener_sup]}). +start_listener0(Address, Protocol, Label, OnConnect) -> + Spec = tcp_listener_spec(rabbit_tcp_listener_sup, Address, tcp_opts(), + Protocol, Label, OnConnect), + case supervisor:start_child(rabbit_sup, Spec) of + {ok, _} -> ok; + {error, {shutdown, _}} -> {IPAddress, Port, _Family} = Address, + exit({could_not_start_tcp_listener, + {rabbit_misc:ntoa(IPAddress), Port}}) + end. stop_tcp_listener(Listener) -> - [stop_tcp_listener0(Spec) || - Spec <- check_tcp_listener_address(rabbit_tcp_listener_sup, Listener)], + [stop_tcp_listener0(Address) || + Address <- tcp_listener_addresses(Listener)], ok. -stop_tcp_listener0({IPAddress, Port, _Family, Name}) -> +stop_tcp_listener0({IPAddress, Port, _Family}) -> Name = rabbit_misc:tcp_name(rabbit_tcp_listener_sup, IPAddress, Port), ok = supervisor:terminate_child(rabbit_sup, Name), ok = supervisor:delete_child(rabbit_sup, Name). @@ -294,6 +269,16 @@ {ok, _Child, Reader} = supervisor:start_child(rabbit_tcp_client_sup, []), ok = rabbit_net:controlling_process(Sock, Reader), Reader ! {go, Sock, SockTransform}, + + %% In the event that somebody floods us with connections, the + %% reader processes can spew log events at error_logger faster + %% than it can keep up, causing its mailbox to grow unbounded + %% until we eat all the memory available and crash. So here is a + %% meaningless synchronous call to the underlying gen_event + %% mechanism. When it returns the mailbox is drained, and we + %% return to our caller to accept more connetions. + gen_event:which_handlers(error_logger), + Reader. start_client(Sock) -> @@ -363,6 +348,38 @@ {ok, Opts} = application:get_env(rabbit, tcp_listen_options), Opts. +%% inet_parse:address takes care of ip string, like "0.0.0.0" +%% inet:getaddr returns immediately for ip tuple {0,0,0,0}, +%% and runs 'inet_gethost' port process for dns lookups. +%% On Windows inet:getaddr runs dns resolver for ip string, which may fail. +getaddr(Host, Family) -> + case inet_parse:address(Host) of + {ok, IPAddress} -> [{IPAddress, resolve_family(IPAddress, Family)}]; + {error, _} -> gethostaddr(Host, Family) + end. + +gethostaddr(Host, auto) -> + Lookups = [{Family, inet:getaddr(Host, Family)} || Family <- [inet, inet6]], + case [{IP, Family} || {Family, {ok, IP}} <- Lookups] of + [] -> host_lookup_error(Host, Lookups); + IPs -> IPs + end; + +gethostaddr(Host, Family) -> + case inet:getaddr(Host, Family) of + {ok, IPAddress} -> [{IPAddress, Family}]; + {error, Reason} -> host_lookup_error(Host, Reason) + end. + +host_lookup_error(Host, Reason) -> + error_logger:error_msg("invalid host ~p - ~p~n", [Host, Reason]), + throw({error, {invalid_host, Host, Reason}}). + +resolve_family({_,_,_,_}, auto) -> inet; +resolve_family({_,_,_,_,_,_,_,_}, auto) -> inet6; +resolve_family(IP, auto) -> throw({error, {strange_family, IP}}); +resolve_family(_, F) -> F. + %%-------------------------------------------------------------------- %% There are three kinds of machine (for our purposes). diff -Nru rabbitmq-server-2.7.1/src/rabbit_node_monitor.erl rabbitmq-server-2.8.0/src/rabbit_node_monitor.erl --- rabbitmq-server-2.7.1/src/rabbit_node_monitor.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_node_monitor.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_node_monitor). @@ -55,29 +55,32 @@ {_, Bad} -> rabbit_log:info("failed to contact nodes ~p~n", [Bad]) end, %% register other active rabbits with this rabbit - [ rabbit_node_monitor:rabbit_running_on(N) || N <- Nodes ], + [ rabbit_running_on(N) || N <- Nodes ], ok. %%-------------------------------------------------------------------- init([]) -> - {ok, no_state}. + {ok, ordsets:new()}. handle_call(_Request, _From, State) -> {noreply, State}. -handle_cast({rabbit_running_on, Node}, State) -> - rabbit_log:info("rabbit on ~p up~n", [Node]), - erlang:monitor(process, {rabbit, Node}), - ok = handle_live_rabbit(Node), - {noreply, State}; +handle_cast({rabbit_running_on, Node}, Nodes) -> + case ordsets:is_element(Node, Nodes) of + true -> {noreply, Nodes}; + false -> rabbit_log:info("rabbit on node ~p up~n", [Node]), + erlang:monitor(process, {rabbit, Node}), + ok = handle_live_rabbit(Node), + {noreply, ordsets:add_element(Node, Nodes)} + end; handle_cast(_Msg, State) -> {noreply, State}. -handle_info({'DOWN', _MRef, process, {rabbit, Node}, _Reason}, State) -> - rabbit_log:info("node ~p lost 'rabbit'~n", [Node]), +handle_info({'DOWN', _MRef, process, {rabbit, Node}, _Reason}, Nodes) -> + rabbit_log:info("rabbit on node ~p down~n", [Node]), ok = handle_dead_rabbit(Node), - {noreply, State}; + {noreply, ordsets:del_element(Node, Nodes)}; handle_info(_Info, State) -> {noreply, State}. diff -Nru rabbitmq-server-2.7.1/src/rabbit_nodes.erl rabbitmq-server-2.8.0/src/rabbit_nodes.erl --- rabbitmq-server-2.7.1/src/rabbit_nodes.erl 1970-01-01 00:00:00.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_nodes.erl 2012-03-19 10:36:09.000000000 +0000 @@ -0,0 +1,94 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is VMware, Inc. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. +%% + +-module(rabbit_nodes). + +-export([names/1, diagnostics/1, make/1, parts/1, cookie_hash/0]). + +-define(EPMD_TIMEOUT, 30000). + +%%---------------------------------------------------------------------------- +%% Specs +%%---------------------------------------------------------------------------- + +-ifdef(use_specs). + +-spec(names/1 :: (string()) -> rabbit_types:ok_or_error2( + [{string(), integer()}], term())). +-spec(diagnostics/1 :: ([node()]) -> string()). +-spec(make/1 :: ({string(), string()} | string()) -> node()). +-spec(parts/1 :: (node() | string()) -> {string(), string()}). +-spec(cookie_hash/0 :: () -> string()). + +-endif. + +%%---------------------------------------------------------------------------- + +names(Hostname) -> + Self = self(), + process_flag(trap_exit, true), + Pid = spawn_link(fun () -> Self ! {names, net_adm:names(Hostname)} end), + timer:exit_after(?EPMD_TIMEOUT, Pid, timeout), + Res = receive + {names, Names} -> Names; + {'EXIT', Pid, Reason} -> {error, Reason} + end, + process_flag(trap_exit, false), + Res. + +diagnostics(Nodes) -> + Hosts = lists:usort([element(2, parts(Node)) || Node <- Nodes]), + NodeDiags = [{"~nDIAGNOSTICS~n===========~n~n" + "nodes in question: ~p~n~n" + "hosts, their running nodes and ports:", [Nodes]}] ++ + [diagnostics_host(Host) || Host <- Hosts] ++ + diagnostics0(), + lists:flatten([io_lib:format(F ++ "~n", A) || NodeDiag <- NodeDiags, + {F, A} <- [NodeDiag]]). + +diagnostics0() -> + [{"~ncurrent node details:~n- node name: ~w", [node()]}, + case init:get_argument(home) of + {ok, [[Home]]} -> {"- home dir: ~s", [Home]}; + Other -> {"- no home dir: ~p", [Other]} + end, + {"- cookie hash: ~s", [cookie_hash()]}]. + +diagnostics_host(Host) -> + case names(Host) of + {error, EpmdReason} -> + {"- unable to connect to epmd on ~s: ~w", + [Host, EpmdReason]}; + {ok, NamePorts} -> + {"- ~s: ~p", + [Host, [{list_to_atom(Name), Port} || + {Name, Port} <- NamePorts]]} + end. + +make({Prefix, Suffix}) -> list_to_atom(lists:append([Prefix, "@", Suffix])); +make(NodeStr) -> make(parts(NodeStr)). + +parts(Node) when is_atom(Node) -> + parts(atom_to_list(Node)); +parts(NodeStr) -> + case lists:splitwith(fun (E) -> E =/= $@ end, NodeStr) of + {Prefix, []} -> {_, Suffix} = parts(node()), + {Prefix, Suffix}; + {Prefix, Suffix} -> {Prefix, tl(Suffix)} + end. + +cookie_hash() -> + base64:encode_to_string(erlang:md5(atom_to_list(erlang:get_cookie()))). diff -Nru rabbitmq-server-2.7.1/src/rabbit_plugins.erl rabbitmq-server-2.8.0/src/rabbit_plugins.erl --- rabbitmq-server-2.7.1/src/rabbit_plugins.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_plugins.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved. %% -module(rabbit_plugins). @@ -55,17 +55,27 @@ CmdArgsAndOpts -> CmdArgsAndOpts end, Command = list_to_atom(Command0), + PrintInvalidCommandError = + fun () -> + print_error("invalid command '~s'", + [string:join([atom_to_list(Command) | Args], " ")]) + end, case catch action(Command, Args, Opts, PluginsFile, PluginsDir) of ok -> rabbit_misc:quit(0); {'EXIT', {function_clause, [{?MODULE, action, _} | _]}} -> - print_error("invalid command '~s'", - [string:join([atom_to_list(Command) | Args], " ")]), + PrintInvalidCommandError(), + usage(); + {'EXIT', {function_clause, [{?MODULE, action, _, _} | _]}} -> + PrintInvalidCommandError(), usage(); {error, Reason} -> print_error("~p", [Reason]), rabbit_misc:quit(2); + {error_string, Reason} -> + print_error("~s", [Reason]), + rabbit_misc:quit(2); Other -> print_error("~p", [Other]), rabbit_misc:quit(2) @@ -90,7 +100,7 @@ action(enable, ToEnable0, _Opts, PluginsFile, PluginsDir) -> case ToEnable0 of - [] -> throw("Not enough arguments for 'enable'"); + [] -> throw({error_string, "Not enough arguments for 'enable'"}); _ -> ok end, AllPlugins = find_plugins(PluginsDir), @@ -100,8 +110,9 @@ Missing = ToEnable -- plugin_names(AllPlugins), case Missing of [] -> ok; - _ -> throw(fmt_list("The following plugins could not be found:", - Missing)) + _ -> throw({error_string, + fmt_list("The following plugins could not be found:", + Missing)}) end, NewEnabled = lists:usort(Enabled ++ ToEnable), write_enabled_plugins(PluginsFile, NewEnabled), @@ -116,7 +127,7 @@ action(disable, ToDisable0, _Opts, PluginsFile, PluginsDir) -> case ToDisable0 of - [] -> throw("Not enough arguments for 'disable'"); + [] -> throw({error_string, "Not enough arguments for 'disable'"}); _ -> ok end, ToDisable = [list_to_atom(Name) || Name <- ToDisable0], @@ -231,7 +242,8 @@ {false, false} -> normal; {true, false} -> verbose; {false, true} -> minimal; - {true, true} -> throw("Cannot specify -m and -v together") + {true, true} -> throw({error_string, + "Cannot specify -m and -v together"}) end, OnlyEnabled = proplists:get_bool(?ENABLED_OPT, Opts), OnlyEnabledAll = proplists:get_bool(?ENABLED_ALL_OPT, Opts), @@ -289,7 +301,7 @@ fmt_list(Header, Plugins) -> lists:flatten( - [Header, $\n, [io_lib:format(" ~s~n", [P]) || P <- Plugins], $\n]). + [Header, $\n, [io_lib:format(" ~s~n", [P]) || P <- Plugins]]). usort_plugins(Plugins) -> lists:usort(fun plugins_cmp/2, Plugins). @@ -325,6 +337,9 @@ read_enabled_plugins(PluginsFile) -> case rabbit_file:read_term_file(PluginsFile) of {ok, [Plugins]} -> Plugins; + {ok, []} -> []; + {ok, [_|_]} -> throw({error, {malformed_enabled_plugins_file, + PluginsFile}}); {error, enoent} -> []; {error, Reason} -> throw({error, {cannot_read_enabled_plugins_file, PluginsFile, Reason}}) diff -Nru rabbitmq-server-2.7.1/src/rabbit_prelaunch.erl rabbitmq-server-2.8.0/src/rabbit_prelaunch.erl --- rabbitmq-server-2.7.1/src/rabbit_prelaunch.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_prelaunch.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_prelaunch). @@ -22,7 +22,6 @@ -define(BaseApps, [rabbit]). -define(ERROR_CODE, 1). --define(EPMD_TIMEOUT, 30000). %%---------------------------------------------------------------------------- %% Specs @@ -244,16 +243,15 @@ %% Ignore running node while installing windows service ok; duplicate_node_check(NodeStr) -> - Node = rabbit_misc:makenode(NodeStr), - {NodeName, NodeHost} = rabbit_misc:nodeparts(Node), - case names(NodeHost) of + Node = rabbit_nodes:make(NodeStr), + {NodeName, NodeHost} = rabbit_nodes:parts(Node), + case rabbit_nodes:names(NodeHost) of {ok, NamePorts} -> case proplists:is_defined(NodeName, NamePorts) of true -> io:format("node with name ~p " "already running on ~p~n", [NodeName, NodeHost]), - [io:format(Fmt ++ "~n", Args) || - {Fmt, Args} <- rabbit_control:diagnostics(Node)], + io:format(rabbit_nodes:diagnostics([Node]) ++ "~n"), terminate(?ERROR_CODE); false -> ok end; @@ -279,15 +277,3 @@ after infinity -> ok end end. - -names(Hostname) -> - Self = self(), - process_flag(trap_exit, true), - Pid = spawn_link(fun () -> Self ! {names, net_adm:names(Hostname)} end), - timer:exit_after(?EPMD_TIMEOUT, Pid, timeout), - Res = receive - {names, Names} -> Names; - {'EXIT', Pid, Reason} -> {error, Reason} - end, - process_flag(trap_exit, false), - Res. diff -Nru rabbitmq-server-2.7.1/src/rabbit_queue_collector.erl rabbitmq-server-2.8.0/src/rabbit_queue_collector.erl --- rabbitmq-server-2.7.1/src/rabbit_queue_collector.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_queue_collector.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_queue_collector). diff -Nru rabbitmq-server-2.7.1/src/rabbit_queue_index.erl rabbitmq-server-2.8.0/src/rabbit_queue_index.erl --- rabbitmq-server-2.7.1/src/rabbit_queue_index.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_queue_index.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,15 +11,17 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_queue_index). -export([init/2, shutdown_terms/1, recover/5, terminate/2, delete_and_terminate/1, - publish/5, deliver/2, ack/2, sync/1, sync/2, flush/1, read/3, - next_segment_boundary/1, bounds/1, recover/1]). + publish/5, deliver/2, ack/2, sync/1, needs_sync/1, flush/1, + read/3, next_segment_boundary/1, bounds/1, recover/1]). + +-export([scan/3]). -export([add_queue_ttl/0]). @@ -207,7 +209,8 @@ -> qistate()). -spec(deliver/2 :: ([seq_id()], qistate()) -> qistate()). -spec(ack/2 :: ([seq_id()], qistate()) -> qistate()). --spec(sync/2 :: ([seq_id()], qistate()) -> qistate()). +-spec(sync/1 :: (qistate()) -> qistate()). +-spec(needs_sync/1 :: (qistate()) -> boolean()). -spec(flush/1 :: (qistate()) -> qistate()). -spec(read/3 :: (seq_id(), seq_id(), qistate()) -> {[{rabbit_types:msg_id(), seq_id(), @@ -218,6 +221,12 @@ {non_neg_integer(), non_neg_integer(), qistate()}). -spec(recover/1 :: ([rabbit_amqqueue:name()]) -> {[[any()]], {walker(A), A}}). +-spec(scan/3 :: (file:filename(), + fun ((seq_id(), rabbit_types:msg_id(), + rabbit_types:message_properties(), boolean(), + ('del' | 'no_del'), ('ack' | 'no_ack'), A) -> A), + A) -> A). + -spec(add_queue_ttl/0 :: () -> 'ok'). -endif. @@ -283,20 +292,18 @@ ack(SeqIds, State) -> deliver_or_ack(ack, SeqIds, State). -%% This is only called when there are outstanding confirms and the -%% queue is idle. -sync(State = #qistate { unsynced_msg_ids = MsgIds }) -> - sync_if(not gb_sets:is_empty(MsgIds), State). - -sync(SeqIds, State) -> - %% The SeqIds here contains the SeqId of every publish and ack to - %% be sync'ed. Ideally we should go through these seqids and only - %% sync the journal if the pubs or acks appear in the - %% journal. However, this would be complex to do, and given that - %% the variable queue publishes and acks to the qi, and then - %% syncs, all in one operation, there is no possibility of the - %% seqids not being in the journal. - sync_if([] =/= SeqIds, State). +%% This is called when there are outstanding confirms or when the +%% queue is idle and the journal needs syncing (see needs_sync/1). +sync(State = #qistate { journal_handle = undefined }) -> + State; +sync(State = #qistate { journal_handle = JournalHdl }) -> + ok = file_handle_cache:sync(JournalHdl), + notify_sync(State). + +needs_sync(#qistate { journal_handle = undefined }) -> + false; +needs_sync(#qistate { journal_handle = JournalHdl }) -> + file_handle_cache:needs_sync(JournalHdl). flush(State = #qistate { dirty_count = 0 }) -> State; flush(State) -> flush_journal(State). @@ -379,7 +386,10 @@ %%---------------------------------------------------------------------------- blank_state(QueueName) -> - Dir = filename:join(queues_dir(), queue_name_to_dir_name(QueueName)), + blank_state_dir( + filename:join(queues_dir(), queue_name_to_dir_name(QueueName))). + +blank_state_dir(Dir) -> {ok, MaxJournal} = application:get_env(rabbit, queue_index_max_journal_entries), #qistate { dir = Dir, @@ -491,7 +501,7 @@ queue_name_to_dir_name(Name = #resource { kind = queue }) -> <> = erlang:md5(term_to_binary(Name)), - lists:flatten(io_lib:format("~.36B", [Num])). + rabbit_misc:format("~.36B", [Num]). queues_dir() -> filename:join(rabbit_mnesia:dir(), "queues"). @@ -524,19 +534,34 @@ end. queue_index_walker_reader(QueueName, Gatherer) -> - State = #qistate { segments = Segments, dir = Dir } = - recover_journal(blank_state(QueueName)), - [ok = segment_entries_foldr( - fun (_RelSeq, {{MsgId, _MsgProps, true}, _IsDelivered, no_ack}, - ok) -> - gatherer:in(Gatherer, {MsgId, 1}); - (_RelSeq, _Value, Acc) -> - Acc - end, ok, segment_find_or_new(Seg, Dir, Segments)) || - Seg <- all_segment_nums(State)], - {_SegmentCounts, _State} = terminate(State), + State = blank_state(QueueName), + ok = scan_segments( + fun (_SeqId, MsgId, _MsgProps, true, _IsDelivered, no_ack, ok) -> + gatherer:in(Gatherer, {MsgId, 1}); + (_SeqId, _MsgId, _MsgProps, _IsPersistent, _IsDelivered, + _IsAcked, Acc) -> + Acc + end, ok, State), ok = gatherer:finish(Gatherer). +scan(Dir, Fun, Acc) -> + scan_segments(Fun, Acc, blank_state_dir(Dir)). + +scan_segments(Fun, Acc, State) -> + State1 = #qistate { segments = Segments, dir = Dir } = + recover_journal(State), + Result = lists:foldr( + fun (Seg, AccN) -> + segment_entries_foldr( + fun (RelSeq, {{MsgId, MsgProps, IsPersistent}, + IsDelivered, IsAcked}, AccM) -> + Fun(reconstruct_seq_id(Seg, RelSeq), MsgId, MsgProps, + IsPersistent, IsDelivered, IsAcked, AccM) + end, AccN, segment_find_or_new(Seg, Dir, Segments)) + end, Acc, all_segment_nums(State1)), + {_SegmentCounts, _State} = terminate(State1), + Result. + %%---------------------------------------------------------------------------- %% expiry/binary manipulation %%---------------------------------------------------------------------------- @@ -707,14 +732,6 @@ add_to_journal(SeqId, Kind, StateN) end, State1, SeqIds)). -sync_if(false, State) -> - State; -sync_if(_Bool, State = #qistate { journal_handle = undefined }) -> - State; -sync_if(true, State = #qistate { journal_handle = JournalHdl }) -> - ok = file_handle_cache:sync(JournalHdl), - notify_sync(State). - notify_sync(State = #qistate { unsynced_msg_ids = UG, on_sync = OnSyncFun }) -> OnSyncFun(UG), State #qistate { unsynced_msg_ids = gb_sets:new() }. diff -Nru rabbitmq-server-2.7.1/src/rabbit_reader.erl rabbitmq-server-2.8.0/src/rabbit_reader.erl --- rabbitmq-server-2.7.1/src/rabbit_reader.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_reader.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_reader). @@ -27,11 +27,9 @@ -export([conserve_memory/2, server_properties/1]). --export([process_channel_frame/5]). %% used by erlang-client - -define(HANDSHAKE_TIMEOUT, 10). -define(NORMAL_TIMEOUT, 3). --define(CLOSING_TIMEOUT, 1). +-define(CLOSING_TIMEOUT, 30). -define(CHANNEL_TERMINATION_TIMEOUT, 3). -define(SILENT_CLOSE_DELAY, 3). @@ -40,13 +38,15 @@ -record(v1, {parent, sock, connection, callback, recv_len, pending_recv, connection_state, queue_collector, heartbeater, stats_timer, channel_sup_sup_pid, start_heartbeat_fun, buf, buf_len, - auth_mechanism, auth_state}). + auth_mechanism, auth_state, conserve_memory, + last_blocked_by, last_blocked_at}). -define(STATISTICS_KEYS, [pid, recv_oct, recv_cnt, send_oct, send_cnt, - send_pend, state, channels]). + send_pend, state, last_blocked_by, last_blocked_age, + channels]). --define(CREATION_EVENT_KEYS, [pid, address, port, peer_address, peer_port, ssl, - peer_cert_subject, peer_cert_issuer, +-define(CREATION_EVENT_KEYS, [pid, name, address, port, peer_address, peer_port, + ssl, peer_cert_subject, peer_cert_issuer, peer_cert_validity, auth_mechanism, ssl_protocol, ssl_key_exchange, ssl_cipher, ssl_hash, @@ -90,10 +90,6 @@ -spec(system_continue/3 :: (_,_,#v1{}) -> any()). -spec(system_terminate/4 :: (_,_,_,_) -> none()). --spec(process_channel_frame/5 :: - (rabbit_command_assembler:frame(), pid(), non_neg_integer(), pid(), - tuple()) -> tuple()). - -endif. %%-------------------------------------------------------------------------- @@ -177,25 +173,26 @@ server_capabilities(_) -> []. +log(Level, Fmt, Args) -> rabbit_log:log(connection, Level, Fmt, Args). + inet_op(F) -> rabbit_misc:throw_on_error(inet_error, F). socket_op(Sock, Fun) -> case Fun(Sock) of {ok, Res} -> Res; - {error, Reason} -> rabbit_log:error("error on TCP connection ~p:~p~n", - [self(), Reason]), - rabbit_log:info("closing TCP connection ~p~n", - [self()]), + {error, Reason} -> log(error, "error on AMQP connection ~p: ~p~n", + [self(), Reason]), exit(normal) end. +name(Sock) -> + socket_op(Sock, fun (S) -> rabbit_net:connection_string(S, inbound) end). + start_connection(Parent, ChannelSupSupPid, Collector, StartHeartbeatFun, Deb, Sock, SockTransform) -> process_flag(trap_exit, true), - {PeerAddress, PeerPort} = socket_op(Sock, fun rabbit_net:peername/1), - PeerAddressS = rabbit_misc:ntoab(PeerAddress), - rabbit_log:info("starting TCP connection ~p from ~s:~p~n", - [self(), PeerAddressS, PeerPort]), + ConnStr = name(Sock), + log(info, "accepting AMQP connection ~p (~s)~n", [self(), ConnStr]), ClientSock = socket_op(Sock, SockTransform), erlang:send_after(?HANDSHAKE_TIMEOUT * 1000, self(), handshake_timeout), @@ -220,27 +217,31 @@ buf = [], buf_len = 0, auth_mechanism = none, - auth_state = none}, + auth_state = none, + conserve_memory = false, + last_blocked_by = none, + last_blocked_at = never}, try recvloop(Deb, switch_callback(rabbit_event:init_stats_timer( State, #v1.stats_timer), - handshake, 8)) + handshake, 8)), + log(info, "closing AMQP connection ~p (~s)~n", [self(), ConnStr]) catch - 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]) + Ex -> log(case Ex of + connection_closed_abruptly -> warning; + _ -> error + end, "closing AMQP connection ~p (~s):~n~p~n", + [self(), ConnStr, Ex]) after - rabbit_log:info("closing TCP connection ~p from ~s:~p~n", - [self(), PeerAddressS, PeerPort]), - %% We don't close the socket explicitly. The reader is the - %% controlling process and hence its termination will close - %% the socket. Furthermore, gen_tcp:close/1 waits for pending - %% output to be sent, which results in unnecessary delays. + %% The reader is the controlling process and hence its + %% termination will close the socket. Furthermore, + %% gen_tcp:close/1 waits for pending output to be sent, which + %% results in unnecessary delays. However, to keep the + %% file_handle_cache accounting as accurate as possible it + %% would be good to close the socket immediately if we + %% can. But we can only do this for non-ssl sockets. %% - %% gen_tcp:close(ClientSock), + rabbit_net:maybe_fast_close(ClientSock), rabbit_event:notify(connection_closed, [{pid, self()}]) end, done. @@ -267,21 +268,20 @@ {data, Data} -> recvloop(Deb, State#v1{buf = [Data | Buf], buf_len = BufLen + size(Data), pending_recv = false}); - closed -> if State#v1.connection_state =:= closed -> - State; - true -> - throw(connection_closed_abruptly) + closed -> case State#v1.connection_state of + closed -> State; + _ -> throw(connection_closed_abruptly) end; {error, Reason} -> throw({inet_error, Reason}); {other, Other} -> handle_other(Other, Deb, State) end. handle_other({conserve_memory, Conserve}, Deb, State) -> - recvloop(Deb, internal_conserve_memory(Conserve, State)); + recvloop(Deb, control_throttle(State#v1{conserve_memory = Conserve})); handle_other({channel_closing, ChPid}, Deb, State) -> ok = rabbit_channel:ready_for_close(ChPid), channel_cleanup(ChPid), - mainloop(Deb, maybe_close(State)); + mainloop(Deb, maybe_close(control_throttle(State))); handle_other({'EXIT', Parent, Reason}, _Deb, State = #v1{parent = Parent}) -> terminate(io_lib:format("broker forced connection closure " "with reason '~w'", [Reason]), State), @@ -341,14 +341,13 @@ mainloop(Deb, emit_stats(State)); handle_other({system, From, Request}, Deb, State = #v1{parent = Parent}) -> sys:handle_system_msg(Request, From, Parent, ?MODULE, Deb, State); +handle_other({bump_credit, Msg}, Deb, State) -> + credit_flow:handle_bump_msg(Msg), + recvloop(Deb, control_throttle(State)); handle_other(Other, _Deb, _State) -> %% internal error -> something worth dying for exit({unexpected_message, Other}). -switch_callback(State = #v1{connection_state = blocked, - heartbeater = Heartbeater}, Callback, Length) -> - ok = rabbit_heartbeat:pause_monitor(Heartbeater), - State#v1{callback = Callback, recv_len = Length}; switch_callback(State, Callback, Length) -> State#v1{callback = Callback, recv_len = Length}. @@ -359,17 +358,30 @@ terminate(_Explanation, State) -> {force, State}. -internal_conserve_memory(true, State = #v1{connection_state = running}) -> - State#v1{connection_state = blocking}; -internal_conserve_memory(false, State = #v1{connection_state = blocking}) -> - State#v1{connection_state = running}; -internal_conserve_memory(false, State = #v1{connection_state = blocked, - heartbeater = Heartbeater}) -> - ok = rabbit_heartbeat:resume_monitor(Heartbeater), - State#v1{connection_state = running}; -internal_conserve_memory(_Conserve, State) -> +control_throttle(State = #v1{connection_state = CS, + conserve_memory = Mem}) -> + case {CS, Mem orelse credit_flow:blocked()} of + {running, true} -> State#v1{connection_state = blocking}; + {blocking, false} -> State#v1{connection_state = running}; + {blocked, false} -> ok = rabbit_heartbeat:resume_monitor( + State#v1.heartbeater), + State#v1{connection_state = running}; + {blocked, true} -> update_last_blocked_by(State); + {_, _} -> State + end. + +maybe_block(State = #v1{connection_state = blocking}) -> + ok = rabbit_heartbeat:pause_monitor(State#v1.heartbeater), + update_last_blocked_by(State#v1{connection_state = blocked, + last_blocked_at = erlang:now()}); +maybe_block(State) -> State. +update_last_blocked_by(State = #v1{conserve_memory = true}) -> + State#v1{last_blocked_by = mem}; +update_last_blocked_by(State = #v1{conserve_memory = false}) -> + State#v1{last_blocked_by = flow}. + close_connection(State = #v1{queue_collector = Collector, connection = #connection{ timeout_sec = TimeoutSec}}) -> @@ -380,34 +392,30 @@ rabbit_queue_collector:delete_all(Collector), %% We terminate the connection after the specified interval, but %% no later than ?CLOSING_TIMEOUT seconds. - TimeoutMillisec = - 1000 * if TimeoutSec > 0 andalso - TimeoutSec < ?CLOSING_TIMEOUT -> TimeoutSec; - true -> ?CLOSING_TIMEOUT - end, - erlang:send_after(TimeoutMillisec, self(), terminate_connection), + erlang:send_after((if TimeoutSec > 0 andalso + TimeoutSec < ?CLOSING_TIMEOUT -> TimeoutSec; + true -> ?CLOSING_TIMEOUT + end) * 1000, self(), terminate_connection), State#v1{connection_state = closed}. handle_dependent_exit(ChPid, Reason, State) -> - case termination_kind(Reason) of - controlled -> - channel_cleanup(ChPid), - maybe_close(State); - uncontrolled -> - case channel_cleanup(ChPid) of - undefined -> exit({abnormal_dependent_exit, ChPid, Reason}); - Channel -> rabbit_log:error( - "connection ~p, channel ~p - error:~n~p~n", - [self(), Channel, Reason]), - maybe_close( - handle_exception(State, Channel, Reason)) - end + case {channel_cleanup(ChPid), termination_kind(Reason)} of + {undefined, uncontrolled} -> + exit({abnormal_dependent_exit, ChPid, Reason}); + {_Channel, controlled} -> + maybe_close(control_throttle(State)); + {Channel, uncontrolled} -> + log(error, "AMQP connection ~p, channel ~p - error:~n~p~n", + [self(), Channel, Reason]), + maybe_close(handle_exception(control_throttle(State), + Channel, Reason)) end. channel_cleanup(ChPid) -> case get({ch_pid, ChPid}) of undefined -> undefined; - {Channel, MRef} -> erase({channel, Channel}), + {Channel, MRef} -> credit_flow:peer_down(ChPid), + erase({channel, Channel}), erase({ch_pid, ChPid}), erlang:demonitor(MRef, [flush]), Channel @@ -436,19 +444,16 @@ wait_for_channel_termination(N, TimerRef) -> receive {'DOWN', _MRef, process, ChPid, Reason} -> - case channel_cleanup(ChPid) of - undefined -> + case {channel_cleanup(ChPid), termination_kind(Reason)} of + {undefined, _} -> exit({abnormal_dependent_exit, ChPid, Reason}); - Channel -> - case termination_kind(Reason) of - controlled -> - ok; - uncontrolled -> - rabbit_log:error( - "connection ~p, channel ~p - " - "error while terminating:~n~p~n", - [self(), Channel, Reason]) - end, + {_Channel, controlled} -> + wait_for_channel_termination(N-1, TimerRef); + {Channel, uncontrolled} -> + log(error, + "AMQP connection ~p, channel ~p - " + "error while terminating:~n~p~n", + [self(), Channel, Reason]), wait_for_channel_termination(N-1, TimerRef) end; cancel_wait -> @@ -497,41 +502,38 @@ case rabbit_command_assembler:analyze_frame(Type, Payload, Protocol) of error -> throw({unknown_frame, Channel, Type, Payload}); heartbeat -> throw({unexpected_heartbeat_frame, Channel}); - AnalyzedFrame -> - case get({channel, Channel}) of - {ChPid, FramingState} -> - NewAState = process_channel_frame( - AnalyzedFrame, self(), - Channel, ChPid, FramingState), - put({channel, Channel}, {ChPid, NewAState}), - post_process_frame(AnalyzedFrame, ChPid, State); - undefined -> - case ?IS_RUNNING(State) of - true -> send_to_new_channel( - Channel, AnalyzedFrame, State); - false -> throw({channel_frame_while_starting, - Channel, State#v1.connection_state, - AnalyzedFrame}) - end - end + AnalyzedFrame -> process_frame(AnalyzedFrame, Channel, State) + end. + +process_frame(Frame, Channel, State) -> + case get({channel, Channel}) of + {ChPid, AState} -> + case process_channel_frame(Frame, ChPid, AState) of + {ok, NewAState} -> put({channel, Channel}, {ChPid, NewAState}), + post_process_frame(Frame, ChPid, State); + {error, Reason} -> handle_exception(State, Channel, Reason) + end; + undefined when ?IS_RUNNING(State) -> + ok = create_channel(Channel, State), + process_frame(Frame, Channel, State); + undefined -> + throw({channel_frame_while_starting, + Channel, State#v1.connection_state, Frame}) end. post_process_frame({method, 'channel.close_ok', _}, ChPid, State) -> channel_cleanup(ChPid), - State; + control_throttle(State); post_process_frame({method, MethodName, _}, _ChPid, State = #v1{connection = #connection{ protocol = Protocol}}) -> case Protocol:method_has_content(MethodName) of true -> erlang:bump_reductions(2000), - case State#v1.connection_state of - blocking -> State#v1{connection_state = blocked}; - _ -> State - end; - false -> State + maybe_block(control_throttle(State)); + false -> control_throttle(State) end; post_process_frame(_Frame, _ChPid, State) -> - State. + control_throttle(State). handle_input(frame_header, <>, State) -> ensure_stats_timer( @@ -699,10 +701,11 @@ ok = rabbit_access_control:check_vhost_access(User, VHostPath), NewConnection = Connection#connection{vhost = VHostPath}, ok = send_on_channel0(Sock, #'connection.open_ok'{}, Protocol), - State1 = internal_conserve_memory( - rabbit_alarm:register(self(), {?MODULE, conserve_memory, []}), + Conserve = rabbit_alarm:register(self(), {?MODULE, conserve_memory, []}), + State1 = control_throttle( State#v1{connection_state = running, - connection = NewConnection}), + connection = NewConnection, + conserve_memory = Conserve}), rabbit_event:notify(connection_created, [{type, network} | infos(?CREATION_EVENT_KEYS, State1)]), @@ -801,6 +804,8 @@ i(pid, #v1{}) -> self(); +i(name, #v1{sock = Sock}) -> + list_to_binary(name(Sock)); i(address, #v1{sock = Sock}) -> socket_info(fun rabbit_net:sockname/1, fun ({A, _}) -> A end, Sock); i(port, #v1{sock = Sock}) -> @@ -834,6 +839,12 @@ fun ([{_, I}]) -> I end); i(state, #v1{connection_state = S}) -> S; +i(last_blocked_by, #v1{last_blocked_by = By}) -> + By; +i(last_blocked_age, #v1{last_blocked_at = never}) -> + infinity; +i(last_blocked_age, #v1{last_blocked_at = T}) -> + timer:now_diff(erlang:now(), T) / 1000000; i(channels, #v1{}) -> length(all_channels()); i(protocol, #v1{connection = #connection{protocol = none}}) -> @@ -889,7 +900,7 @@ %%-------------------------------------------------------------------------- -send_to_new_channel(Channel, AnalyzedFrame, State) -> +create_channel(Channel, State) -> #v1{sock = Sock, queue_collector = Collector, channel_sup_sup_pid = ChanSupSup, connection = #connection{protocol = Protocol, @@ -899,26 +910,22 @@ capabilities = Capabilities}} = State, {ok, _ChSupPid, {ChPid, AState}} = rabbit_channel_sup_sup:start_channel( - ChanSupSup, {tcp, Sock, Channel, FrameMax, self(), Protocol, User, - VHost, Capabilities, Collector}), + ChanSupSup, {tcp, Sock, Channel, FrameMax, self(), name(Sock), + Protocol, User, VHost, Capabilities, Collector}), MRef = erlang:monitor(process, ChPid), - NewAState = process_channel_frame(AnalyzedFrame, self(), - Channel, ChPid, AState), - put({channel, Channel}, {ChPid, NewAState}), put({ch_pid, ChPid}, {Channel, MRef}), - State. + put({channel, Channel}, {ChPid, AState}), + ok. -process_channel_frame(Frame, ErrPid, Channel, ChPid, AState) -> +process_channel_frame(Frame, ChPid, AState) -> case rabbit_command_assembler:process(Frame, AState) of - {ok, NewAState} -> NewAState; + {ok, NewAState} -> {ok, NewAState}; {ok, Method, NewAState} -> rabbit_channel:do(ChPid, Method), - NewAState; - {ok, Method, Content, NewAState} -> rabbit_channel:do(ChPid, - Method, Content), - NewAState; - {error, Reason} -> ErrPid ! {channel_exit, Channel, - Reason}, - AState + {ok, NewAState}; + {ok, Method, Content, NewAState} -> rabbit_channel:do_flow( + ChPid, Method, Content), + {ok, NewAState}; + {error, Reason} -> {error, Reason} end. handle_exception(State = #v1{connection_state = closed}, _Channel, _Reason) -> diff -Nru rabbitmq-server-2.7.1/src/rabbit_registry.erl rabbitmq-server-2.8.0/src/rabbit_registry.erl --- rabbitmq-server-2.7.1/src/rabbit_registry.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_registry.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_registry). diff -Nru rabbitmq-server-2.7.1/src/rabbit_restartable_sup.erl rabbitmq-server-2.8.0/src/rabbit_restartable_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_restartable_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_restartable_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_restartable_sup). @@ -28,7 +28,8 @@ -ifdef(use_specs). --spec(start_link/2 :: (atom(), mfa()) -> rabbit_types:ok_pid_or_error()). +-spec(start_link/2 :: (atom(), rabbit_types:mfargs()) -> + rabbit_types:ok_pid_or_error()). -endif. diff -Nru rabbitmq-server-2.7.1/src/rabbit_router.erl rabbitmq-server-2.8.0/src/rabbit_router.erl --- rabbitmq-server-2.7.1/src/rabbit_router.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_router.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,28 +11,24 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_router). -include_lib("stdlib/include/qlc.hrl"). -include("rabbit.hrl"). --export([deliver/2, match_bindings/2, match_routing_key/2]). +-export([match_bindings/2, match_routing_key/2]). %%---------------------------------------------------------------------------- -ifdef(use_specs). --export_type([routing_key/0, routing_result/0, match_result/0]). +-export_type([routing_key/0, match_result/0]). -type(routing_key() :: binary()). --type(routing_result() :: 'routed' | 'unroutable' | 'not_delivered'). --type(qpids() :: [pid()]). -type(match_result() :: [rabbit_types:binding_destination()]). --spec(deliver/2 :: ([rabbit_amqqueue:name()], rabbit_types:delivery()) -> - {routing_result(), qpids()}). -spec(match_bindings/2 :: (rabbit_types:binding_source(), fun ((rabbit_types:binding()) -> boolean())) -> match_result()). @@ -44,38 +40,6 @@ %%---------------------------------------------------------------------------- -deliver([], #delivery{mandatory = false, - immediate = false}) -> - %% /dev/null optimisation - {routed, []}; - -deliver(QNames, Delivery = #delivery{mandatory = false, - immediate = false}) -> - %% optimisation: when Mandatory = false and Immediate = false, - %% rabbit_amqqueue:deliver will deliver the message to the queue - %% process asynchronously, and return true, which means all the - %% QPids will always be returned. It is therefore safe to use a - %% fire-and-forget cast here and return the QPids - the semantics - %% is preserved. This scales much better than the non-immediate - %% case below. - QPids = lookup_qpids(QNames), - delegate:invoke_no_result( - QPids, fun (Pid) -> rabbit_amqqueue:deliver(Pid, Delivery) end), - {routed, QPids}; - -deliver(QNames, Delivery = #delivery{mandatory = Mandatory, - immediate = Immediate}) -> - QPids = lookup_qpids(QNames), - {Success, _} = - delegate:invoke(QPids, - fun (Pid) -> - rabbit_amqqueue:deliver(Pid, Delivery) - end), - {Routed, Handled} = - lists:foldl(fun fold_deliveries/2, {false, []}, Success), - check_delivery(Mandatory, Immediate, {Routed, Handled}). - - %% 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) -> @@ -104,26 +68,6 @@ %%-------------------------------------------------------------------- -fold_deliveries({Pid, true},{_, Handled}) -> {true, [Pid|Handled]}; -fold_deliveries({_, false},{_, Handled}) -> {true, Handled}. - -%% check_delivery(Mandatory, Immediate, {WasRouted, QPids}) -check_delivery(true, _ , {false, []}) -> {unroutable, []}; -check_delivery(_ , true, {_ , []}) -> {not_delivered, []}; -check_delivery(_ , _ , {_ , Qs}) -> {routed, Qs}. - -%% Normally we'd call mnesia:dirty_read/1 here, but that is quite -%% expensive for the reasons explained in rabbit_misc:dirty_read/1. -lookup_qpids(QNames) -> - lists:foldl(fun (QName, QPids) -> - case ets:lookup(rabbit_queue, QName) of - [#amqqueue{pid = QPid, slave_pids = SPids}] -> - [QPid | SPids ++ QPids]; - [] -> - QPids - end - end, [], QNames). - %% Normally we'd call mnesia:dirty_select/2 here, but that is quite %% expensive for the same reasons as above, and, additionally, due to %% mnesia 'fixing' the table with ets:safe_fixtable/2, which is wholly diff -Nru rabbitmq-server-2.7.1/src/rabbit_sasl_report_file_h.erl rabbitmq-server-2.8.0/src/rabbit_sasl_report_file_h.erl --- rabbitmq-server-2.7.1/src/rabbit_sasl_report_file_h.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_sasl_report_file_h.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_sasl_report_file_h). diff -Nru rabbitmq-server-2.7.1/src/rabbit_ssl.erl rabbitmq-server-2.8.0/src/rabbit_ssl.erl --- rabbitmq-server-2.7.1/src/rabbit_ssl.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_ssl.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_ssl). @@ -21,7 +21,7 @@ -include_lib("public_key/include/public_key.hrl"). -export([peer_cert_issuer/1, peer_cert_subject/1, peer_cert_validity/1]). --export([peer_cert_subject_item/2]). +-export([peer_cert_subject_items/2, peer_cert_auth_name/1]). %%-------------------------------------------------------------------------- @@ -34,8 +34,10 @@ -spec(peer_cert_issuer/1 :: (certificate()) -> string()). -spec(peer_cert_subject/1 :: (certificate()) -> string()). -spec(peer_cert_validity/1 :: (certificate()) -> string()). --spec(peer_cert_subject_item/2 :: - (certificate(), tuple()) -> string() | 'not_found'). +-spec(peer_cert_subject_items/2 :: + (certificate(), tuple()) -> [string()] | 'not_found'). +-spec(peer_cert_auth_name/1 :: + (certificate()) -> binary() | 'not_found' | 'unsafe'). -endif. @@ -59,8 +61,8 @@ format_rdn_sequence(Subject) end, Cert). -%% Return a part of the certificate's subject. -peer_cert_subject_item(Cert, Type) -> +%% Return the parts of the certificate's subject. +peer_cert_subject_items(Cert, Type) -> cert_info(fun(#'OTPCertificate' { tbsCertificate = #'OTPTBSCertificate' { subject = Subject }}) -> @@ -72,11 +74,47 @@ cert_info(fun(#'OTPCertificate' { tbsCertificate = #'OTPTBSCertificate' { validity = {'Validity', Start, End} }}) -> - lists:flatten( - io_lib:format("~s - ~s", [format_asn1_value(Start), - format_asn1_value(End)])) + rabbit_misc:format("~s - ~s", [format_asn1_value(Start), + format_asn1_value(End)]) end, Cert). +%% Extract a username from the certificate +peer_cert_auth_name(Cert) -> + {ok, Mode} = application:get_env(rabbit, ssl_cert_login_from), + peer_cert_auth_name(Mode, Cert). + +peer_cert_auth_name(distinguished_name, Cert) -> + case auth_config_sane() of + true -> iolist_to_binary(peer_cert_subject(Cert)); + false -> unsafe + end; + +peer_cert_auth_name(common_name, Cert) -> + %% If there is more than one CN then we join them with "," in a + %% vaguely DN-like way. But this is more just so we do something + %% more intelligent than crashing, if you actually want to escape + %% things properly etc, use DN mode. + case auth_config_sane() of + true -> case peer_cert_subject_items(Cert, ?'id-at-commonName') of + not_found -> not_found; + CNs -> list_to_binary(string:join(CNs, ",")) + end; + false -> unsafe + end. + +auth_config_sane() -> + {ok, Opts} = application:get_env(rabbit, ssl_options), + case {proplists:get_value(fail_if_no_peer_cert, Opts), + proplists:get_value(verify, Opts)} of + {true, verify_peer} -> + true; + {F, V} -> + rabbit_log:warning("SSL certificate authentication disabled, " + "fail_if_no_peer_cert=~p; " + "verify=~p~n", [F, V]), + false + end. + %%-------------------------------------------------------------------------- cert_info(F, Cert) -> @@ -89,8 +127,8 @@ case [V || #'AttributeTypeAndValue'{type = T, value = V} <- lists:flatten(RDNs), T == Type] of - [Val] -> format_asn1_value(Val); - [] -> not_found + [] -> not_found; + L -> [format_asn1_value(V) || V <- L] end. %%-------------------------------------------------------------------------- @@ -150,11 +188,12 @@ escape_rdn_value([C | S], middle) when C =:= $"; C =:= $+; C =:= $,; C =:= $;; C =:= $<; C =:= $>; C =:= $\\ -> [$\\, C | escape_rdn_value(S, middle)]; -escape_rdn_value([C | S], middle) when C < 32 ; C =:= 127 -> - %% only U+0000 needs escaping, but for display purposes it's handy - %% to escape all non-printable chars - lists:flatten(io_lib:format("\\~2.16.0B", [C])) ++ - escape_rdn_value(S, middle); +escape_rdn_value([C | S], middle) when C < 32 ; C >= 126 -> + %% Of ASCII characters only U+0000 needs escaping, but for display + %% purposes it's handy to escape all non-printable chars. All non-ASCII + %% characters get converted to UTF-8 sequences and then escaped. We've + %% already got a UTF-8 sequence here, so just escape it. + rabbit_misc:format("\\~2.16.0B", [C]) ++ escape_rdn_value(S, middle); escape_rdn_value([C | S], middle) -> [C | escape_rdn_value(S, middle)]. @@ -167,6 +206,10 @@ Min1, Min2, S1, S2, $Z]}) -> io_lib:format("20~c~c-~c~c-~c~cT~c~c:~c~c:~c~cZ", [Y1, Y2, M1, M2, D1, D2, H1, H2, Min1, Min2, S1, S2]); +%% We appear to get an untagged value back for an ia5string +%% (e.g. domainComponent). +format_asn1_value(V) when is_list(V) -> + V; format_asn1_value(V) -> io_lib:format("~p", [V]). diff -Nru rabbitmq-server-2.7.1/src/rabbit_sup.erl rabbitmq-server-2.8.0/src/rabbit_sup.erl --- rabbitmq-server-2.7.1/src/rabbit_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_sup). diff -Nru rabbitmq-server-2.7.1/src/rabbit_tests.erl rabbitmq-server-2.8.0/src/rabbit_tests.erl --- rabbitmq-server-2.7.1/src/rabbit_tests.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_tests.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tests). @@ -35,6 +35,7 @@ passed = mirrored_supervisor_tests:all_tests(), application:set_env(rabbit, file_handles_high_watermark, 10, infinity), ok = file_handle_cache:set_limit(10), + passed = test_multi_call(), passed = test_file_handle_cache(), passed = test_backing_queue(), passed = test_priority_queue(), @@ -59,7 +60,7 @@ passed. maybe_run_cluster_dependent_tests() -> - SecondaryNode = rabbit_misc:makenode("hare"), + SecondaryNode = rabbit_nodes:make("hare"), case net_adm:ping(SecondaryNode) of pong -> passed = run_cluster_dependent_tests(SecondaryNode); @@ -71,10 +72,13 @@ run_cluster_dependent_tests(SecondaryNode) -> SecondaryNodeS = atom_to_list(SecondaryNode), + cover:stop(SecondaryNode), ok = control_action(stop_app, []), ok = control_action(reset, []), ok = control_action(cluster, [SecondaryNodeS]), ok = control_action(start_app, []), + cover:start(SecondaryNode), + ok = control_action(start_app, SecondaryNode, [], []), io:format("Running cluster dependent tests with node ~p~n", [SecondaryNode]), passed = test_delegates_async(SecondaryNode), @@ -104,6 +108,26 @@ passed. +test_multi_call() -> + Fun = fun() -> + receive + {'$gen_call', {From, Mref}, request} -> + From ! {Mref, response} + end, + receive + never -> ok + end + end, + Pid1 = spawn(Fun), + Pid2 = spawn(Fun), + Pid3 = spawn(Fun), + exit(Pid2, bang), + {[{Pid1, response}, {Pid3, response}], [{Pid2, _Fail}]} = + rabbit_misc:multi_call([Pid1, Pid2, Pid3], request), + exit(Pid1, bang), + exit(Pid3, bang), + passed. + test_priority_queue() -> false = priority_queue:is_queue(not_a_queue), @@ -859,7 +883,7 @@ "invalid2@invalid"]), ok = assert_ram_node(), - SecondaryNode = rabbit_misc:makenode("hare"), + SecondaryNode = rabbit_nodes:make("hare"), case net_adm:ping(SecondaryNode) of pong -> passed = test_cluster_management2(SecondaryNode); pang -> io:format("Skipping clustering tests with node ~p~n", @@ -889,6 +913,14 @@ ok = control_action(stop_app, []), ok = assert_ram_node(), + %% ram node will not start by itself + ok = control_action(stop_app, []), + ok = control_action(stop_app, SecondaryNode, [], []), + {error, _} = control_action(start_app, []), + ok = control_action(start_app, SecondaryNode, [], []), + ok = control_action(start_app, []), + ok = control_action(stop_app, []), + %% change cluster config while remaining in same cluster ok = control_action(force_cluster, ["invalid2@invalid", SecondaryNodeS]), ok = control_action(start_app, []), @@ -897,8 +929,7 @@ %% join non-existing cluster as a ram node ok = control_action(force_cluster, ["invalid1@invalid", "invalid2@invalid"]), - ok = control_action(start_app, []), - ok = control_action(stop_app, []), + {error, _} = control_action(start_app, []), ok = assert_ram_node(), %% join empty cluster as a ram node (converts to disc) @@ -953,7 +984,9 @@ ok = control_action(cluster, [SecondaryNodeS, NodeS]), ok = control_action(start_app, []), ok = control_action(stop_app, []), + cover:stop(SecondaryNode), ok = control_action(reset, []), + cover:start(SecondaryNode), %% attempt to leave cluster when no other node is alive ok = control_action(cluster, [SecondaryNodeS, NodeS]), @@ -970,7 +1003,15 @@ %% leave system clustered, with the secondary node as a ram node ok = control_action(force_reset, []), ok = control_action(start_app, []), - ok = control_action(force_reset, SecondaryNode, [], []), + %% Yes, this is rather ugly. But since we're a clustered Mnesia + %% node and we're telling another clustered node to reset itself, + %% we will get disconnected half way through causing a + %% badrpc. This never happens in real life since rabbitmqctl is + %% not a clustered Mnesia node. + cover:stop(SecondaryNode), + {badrpc, nodedown} = control_action(force_reset, SecondaryNode, [], []), + pong = net_adm:ping(SecondaryNode), + cover:start(SecondaryNode), ok = control_action(cluster, SecondaryNode, [NodeS], []), ok = control_action(start_app, SecondaryNode, [], []), @@ -1059,7 +1100,7 @@ %% create a few things so there is some useful information to list Writer = spawn(fun () -> receive shutdown -> ok end end), {ok, Ch} = rabbit_channel:start_link( - 1, self(), Writer, self(), rabbit_framing_amqp_0_9_1, + 1, self(), Writer, self(), "", rabbit_framing_amqp_0_9_1, user(<<"user">>), <<"/">>, [], self(), rabbit_limiter:make_token(self())), [Q, Q2] = [Queue || Name <- [<<"foo">>, <<"bar">>], @@ -1130,7 +1171,7 @@ Me = self(), Writer = spawn(fun () -> test_writer(Me) end), {ok, Ch} = rabbit_channel:start_link( - 1, Me, Writer, Me, rabbit_framing_amqp_0_9_1, + 1, Me, Writer, Me, "", rabbit_framing_amqp_0_9_1, user(<<"guest">>), <<"/">>, [], Me, rabbit_limiter:make_token(self())), ok = rabbit_channel:do(Ch, #'channel.open'{}), @@ -1779,10 +1820,10 @@ restart_msg_store_empty(), MsgIds = [msg_id_bin(M) || M <- lists:seq(1,100)], {MsgIds1stHalf, MsgIds2ndHalf} = lists:split(length(MsgIds) div 2, MsgIds), - Ref = rabbit_guid:guid(), + Ref = rabbit_guid:gen(), {Cap, MSCState} = msg_store_client_init_capture( ?PERSISTENT_MSG_STORE, Ref), - Ref2 = rabbit_guid:guid(), + Ref2 = rabbit_guid:gen(), {Cap2, MSC2State} = msg_store_client_init_capture( ?PERSISTENT_MSG_STORE, Ref2), %% check we don't contain any of the msgs we're about to publish @@ -1934,7 +1975,7 @@ passed. test_msg_store_confirm_timer() -> - Ref = rabbit_guid:guid(), + Ref = rabbit_guid:gen(), MsgId = msg_id_bin(1), Self = self(), MSCState = rabbit_msg_store:client_init( @@ -1963,7 +2004,7 @@ test_msg_store_client_delete_and_terminate() -> restart_msg_store_empty(), MsgIds = [msg_id_bin(M) || M <- lists:seq(1, 10)], - Ref = rabbit_guid:guid(), + Ref = rabbit_guid:gen(), MSCState = msg_store_client_init(?PERSISTENT_MSG_STORE, Ref), ok = msg_store_write(MsgIds, MSCState), %% test the 'dying client' fast path for writes @@ -1979,7 +2020,7 @@ init_test_queue() -> TestQueue = test_queue(), Terms = rabbit_queue_index:shutdown_terms(TestQueue), - PRef = proplists:get_value(persistent_ref, Terms, rabbit_guid:guid()), + PRef = proplists:get_value(persistent_ref, Terms, rabbit_guid:gen()), PersistentClient = msg_store_client_init(?PERSISTENT_MSG_STORE, PRef), Res = rabbit_queue_index:recover( TestQueue, Terms, false, @@ -2013,7 +2054,7 @@ rabbit:start(). queue_index_publish(SeqIds, Persistent, Qi) -> - Ref = rabbit_guid:guid(), + Ref = rabbit_guid:gen(), MsgStore = case Persistent of true -> ?PERSISTENT_MSG_STORE; false -> ?TRANSIENT_MSG_STORE @@ -2022,7 +2063,7 @@ {A, B = [{_SeqId, LastMsgIdWritten} | _]} = lists:foldl( fun (SeqId, {QiN, SeqIdsMsgIdsAcc}) -> - MsgId = rabbit_guid:guid(), + MsgId = rabbit_guid:gen(), QiM = rabbit_queue_index:publish( MsgId, SeqId, #message_properties{}, Persistent, QiN), ok = rabbit_msg_store:write(MsgId, MsgId, MSCState), @@ -2045,7 +2086,7 @@ test_queue_index_props() -> with_empty_test_queue( fun(Qi0) -> - MsgId = rabbit_guid:guid(), + MsgId = rabbit_guid:gen(), Props = #message_properties{expiry=12345}, Qi1 = rabbit_queue_index:publish(MsgId, 1, Props, true, Qi0), {[{MsgId, 1, Props, _, _}], Qi2} = @@ -2222,17 +2263,29 @@ #amqqueue { durable = Durable }. with_fresh_variable_queue(Fun) -> - ok = empty_test_queue(), - VQ = variable_queue_init(test_amqqueue(true), false), - S0 = rabbit_variable_queue:status(VQ), - assert_props(S0, [{q1, 0}, {q2, 0}, - {delta, {delta, undefined, 0, undefined}}, - {q3, 0}, {q4, 0}, - {len, 0}]), - _ = rabbit_variable_queue:delete_and_terminate(shutdown, Fun(VQ)), + Ref = make_ref(), + Me = self(), + %% Run in a separate process since rabbit_msg_store will send + %% bump_credit messages and we want to ignore them + spawn_link(fun() -> + ok = empty_test_queue(), + VQ = variable_queue_init(test_amqqueue(true), false), + S0 = rabbit_variable_queue:status(VQ), + assert_props(S0, [{q1, 0}, {q2, 0}, + {delta, + {delta, undefined, 0, undefined}}, + {q3, 0}, {q4, 0}, + {len, 0}]), + _ = rabbit_variable_queue:delete_and_terminate( + shutdown, Fun(VQ)), + Me ! Ref + end), + receive + Ref -> ok + end, passed. -publish_and_confirm(QPid, Payload, Count) -> +publish_and_confirm(Q, Payload, Count) -> Seqs = lists:seq(1, Count), [begin Msg = rabbit_basic:message(rabbit_misc:r(<<>>, exchange, <<>>), @@ -2240,7 +2293,7 @@ Payload), Delivery = #delivery{mandatory = false, immediate = false, sender = self(), message = Msg, msg_seq_no = Seq}, - true = rabbit_amqqueue:deliver(QPid, Delivery) + {routed, _} = rabbit_amqqueue:deliver([Q], Delivery) end || Seq <- Seqs], wait_for_confirms(gb_sets:from_list(Seqs)). @@ -2334,7 +2387,7 @@ VQ2 = rabbit_variable_queue:dropwhile( fun(#message_properties { expiry = Expiry }) -> Expiry =< 5 - end, VQ1), + end, undefined, VQ1), %% fetch five now VQ3 = lists:foldl(fun (_N, VQN) -> @@ -2351,10 +2404,11 @@ test_dropwhile_varying_ram_duration(VQ0) -> VQ1 = variable_queue_publish(false, 1, VQ0), VQ2 = rabbit_variable_queue:set_ram_duration_target(0, VQ1), - VQ3 = rabbit_variable_queue:dropwhile(fun(_) -> false end, VQ2), + VQ3 = rabbit_variable_queue:dropwhile( + fun(_) -> false end, undefined, VQ2), VQ4 = rabbit_variable_queue:set_ram_duration_target(infinity, VQ3), VQ5 = variable_queue_publish(false, 1, VQ4), - rabbit_variable_queue:dropwhile(fun(_) -> false end, VQ5). + rabbit_variable_queue:dropwhile(fun(_) -> false end, undefined, VQ5). test_variable_queue_dynamic_duration_change(VQ0) -> SegmentSize = rabbit_queue_index:next_segment_boundary(0), @@ -2477,7 +2531,7 @@ Count = 2 * rabbit_queue_index:next_segment_boundary(0), {new, #amqqueue { pid = QPid, name = QName } = Q} = rabbit_amqqueue:declare(test_queue(), true, false, [], none), - publish_and_confirm(QPid, <<>>, Count), + publish_and_confirm(Q, <<>>, Count), exit(QPid, kill), MRef = erlang:monitor(process, QPid), @@ -2507,7 +2561,7 @@ rabbit_amqqueue:declare(test_queue(), true, false, [], none), Payload = <<0:8388608>>, %% 1MB Count = 30, - publish_and_confirm(QPid, Payload, Count), + publish_and_confirm(Q, Payload, Count), rabbit_amqqueue:set_ram_duration_target(QPid, 0), diff -Nru rabbitmq-server-2.7.1/src/rabbit_tests_event_receiver.erl rabbitmq-server-2.8.0/src/rabbit_tests_event_receiver.erl --- rabbitmq-server-2.7.1/src/rabbit_tests_event_receiver.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_tests_event_receiver.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_tests_event_receiver). diff -Nru rabbitmq-server-2.7.1/src/rabbit_trace.erl rabbitmq-server-2.8.0/src/rabbit_trace.erl --- rabbitmq-server-2.7.1/src/rabbit_trace.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_trace.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_trace). diff -Nru rabbitmq-server-2.7.1/src/rabbit_types.erl rabbitmq-server-2.8.0/src/rabbit_types.erl --- rabbitmq-server-2.7.1/src/rabbit_types.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_types.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_types). @@ -28,12 +28,9 @@ binding/0, binding_source/0, binding_destination/0, amqqueue/0, exchange/0, connection/0, protocol/0, user/0, internal_user/0, - username/0, password/0, password_hash/0, ok/1, error/1, - ok_or_error/1, ok_or_error2/2, ok_pid_or_error/0, channel_exit/0, - connection_exit/0]). - --type(channel_exit() :: no_return()). --type(connection_exit() :: no_return()). + username/0, password/0, password_hash/0, + ok/1, error/1, ok_or_error/1, ok_or_error2/2, ok_pid_or_error/0, + channel_exit/0, connection_exit/0, mfargs/0]). -type(maybe(T) :: T | 'none'). -type(vhost() :: binary()). @@ -156,4 +153,9 @@ -type(ok_or_error2(A, B) :: ok(A) | error(B)). -type(ok_pid_or_error() :: ok_or_error2(pid(), any())). +-type(channel_exit() :: no_return()). +-type(connection_exit() :: no_return()). + +-type(mfargs() :: {atom(), atom(), [any()]}). + -endif. % use_specs diff -Nru rabbitmq-server-2.7.1/src/rabbit_upgrade.erl rabbitmq-server-2.8.0/src/rabbit_upgrade.erl --- rabbitmq-server-2.7.1/src/rabbit_upgrade.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_upgrade.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_upgrade). diff -Nru rabbitmq-server-2.7.1/src/rabbit_upgrade_functions.erl rabbitmq-server-2.8.0/src/rabbit_upgrade_functions.erl --- rabbitmq-server-2.7.1/src/rabbit_upgrade_functions.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_upgrade_functions.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_upgrade_functions). @@ -35,6 +35,7 @@ -rabbit_upgrade({gm, mnesia, []}). -rabbit_upgrade({exchange_scratch, mnesia, [trace_exchanges]}). -rabbit_upgrade({mirrored_supervisor, mnesia, []}). +-rabbit_upgrade({topic_trie_node, mnesia, []}). %% ------------------------------------------------------------------- @@ -54,6 +55,7 @@ -spec(gm/0 :: () -> 'ok'). -spec(exchange_scratch/0 :: () -> 'ok'). -spec(mirrored_supervisor/0 :: () -> 'ok'). +-spec(topic_trie_node/0 :: () -> 'ok'). -endif. @@ -177,6 +179,12 @@ [{record_name, mirrored_sup_childspec}, {attributes, [key, mirroring_pid, childspec]}]). +topic_trie_node() -> + create(rabbit_topic_trie_node, + [{record_name, topic_trie_node}, + {attributes, [trie_node, edge_count, binding_count]}, + {type, ordered_set}]). + %%-------------------------------------------------------------------- transform(TableName, Fun, FieldList) -> diff -Nru rabbitmq-server-2.7.1/src/rabbit_variable_queue.erl rabbitmq-server-2.8.0/src/rabbit_variable_queue.erl --- rabbitmq-server-2.7.1/src/rabbit_variable_queue.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_variable_queue.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,18 +11,18 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_variable_queue). -export([init/3, terminate/2, delete_and_terminate/2, purge/1, publish/4, publish_delivered/5, drain_confirmed/1, - dropwhile/2, fetch/2, ack/2, requeue/2, len/1, is_empty/1, + dropwhile/3, fetch/2, ack/2, requeue/2, len/1, is_empty/1, set_ram_duration_target/2, ram_duration/1, needs_timeout/1, timeout/1, handle_pre_hibernate/1, status/1, invoke/3, is_duplicate/2, discard/3, - multiple_routing_keys/0]). + multiple_routing_keys/0, fold/3]). -export([start/1, stop/0]). @@ -434,7 +434,7 @@ Terms = rabbit_queue_index:shutdown_terms(QueueName), {PRef, Terms1} = case proplists:get_value(persistent_ref, Terms) of - undefined -> {rabbit_guid:guid(), []}; + undefined -> {rabbit_guid:gen(), []}; PRef1 -> {PRef1, Terms} end, PersistentClient = msg_store_client_init(?PERSISTENT_MSG_STORE, PRef, @@ -581,15 +581,23 @@ confirmed = gb_sets:new() }} end. -dropwhile(Pred, State) -> +dropwhile(Pred, MsgFun, State) -> case queue_out(State) of {empty, State1} -> a(State1); {{value, MsgStatus = #msg_status { msg_props = MsgProps }}, State1} -> - case Pred(MsgProps) of - true -> {_, State2} = internal_fetch(false, MsgStatus, State1), - dropwhile(Pred, State2); - false -> a(in_r(MsgStatus, State1)) + case {Pred(MsgProps), MsgFun} of + {true, undefined} -> + {_, State2} = internal_fetch(false, MsgStatus, State1), + dropwhile(Pred, MsgFun, State2); + {true, _} -> + {{_, _, AckTag, _}, State2} = + internal_fetch(true, MsgStatus, State1), + {MsgStatus, State3} = read_msg(MsgStatus, State2), + MsgFun(MsgStatus#msg_status.msg, AckTag), + dropwhile(Pred, MsgFun, State3); + {false, _} -> + a(in_r(MsgStatus, State1)) end end. @@ -628,11 +636,22 @@ persistent_count = PCount1, ack_out_counter = AckOutCount + length(AckTags) })}. -requeue(AckTags, #vqstate { delta = Delta, - q3 = Q3, - q4 = Q4, - in_counter = InCounter, - len = Len } = State) -> +fold(undefined, State, _AckTags) -> + State; +fold(MsgFun, State = #vqstate{pending_ack = PA}, AckTags) -> + lists:foldl( + fun(SeqId, State1) -> + {MsgStatus, State2} = + read_msg(gb_trees:get(SeqId, PA), State1), + MsgFun(MsgStatus#msg_status.msg, SeqId), + State2 + end, State, AckTags). + +requeue(AckTags, #vqstate { delta = Delta, + q3 = Q3, + q4 = Q4, + in_counter = InCounter, + len = Len } = State) -> {SeqIds, Q4a, MsgIds, State1} = queue_merge(lists:sort(AckTags), Q4, [], beta_limit(Q3), fun publish_alpha/2, State), @@ -731,21 +750,27 @@ ram_msg_count_prev = RamMsgCount, ram_ack_count_prev = RamAckCount }}. -needs_timeout(State) -> - case needs_index_sync(State) of - false -> case reduce_memory_use( - fun (_Quota, State1) -> {0, State1} end, - fun (_Quota, State1) -> State1 end, - fun (_Quota, State1) -> {0, State1} end, - State) of - {true, _State} -> idle; - {false, _State} -> false - end; - true -> timed +needs_timeout(State = #vqstate { index_state = IndexState }) -> + case must_sync_index(State) of + true -> timed; + false -> + case rabbit_queue_index:needs_sync(IndexState) of + true -> idle; + false -> case reduce_memory_use( + fun (_Quota, State1) -> {0, State1} end, + fun (_Quota, State1) -> State1 end, + fun (_Quota, State1) -> {0, State1} end, + State) of + {true, _State} -> idle; + {false, _State} -> false + end + end end. -timeout(State) -> - a(reduce_memory_use(confirm_commit_index(State))). +timeout(State = #vqstate { index_state = IndexState }) -> + IndexState1 = rabbit_queue_index:sync(IndexState), + State1 = State #vqstate { index_state = IndexState1 }, + a(reduce_memory_use(State1)). handle_pre_hibernate(State = #vqstate { index_state = IndexState }) -> State #vqstate { index_state = rabbit_queue_index:flush(IndexState) }. @@ -860,7 +885,8 @@ Res. msg_store_client_init(MsgStore, MsgOnDiskFun, Callback) -> - msg_store_client_init(MsgStore, rabbit_guid:guid(), MsgOnDiskFun, Callback). + msg_store_client_init(MsgStore, rabbit_guid:gen(), MsgOnDiskFun, + Callback). msg_store_client_init(MsgStore, Ref, MsgOnDiskFun, Callback) -> CloseFDsFun = msg_store_close_fds_fun(MsgStore =:= ?PERSISTENT_MSG_STORE), @@ -870,17 +896,23 @@ msg_store_write(MSCState, IsPersistent, MsgId, Msg) -> with_immutable_msg_store_state( MSCState, IsPersistent, - fun (MSCState1) -> rabbit_msg_store:write(MsgId, Msg, MSCState1) end). + fun (MSCState1) -> + rabbit_msg_store:write_flow(MsgId, Msg, MSCState1) + end). msg_store_read(MSCState, IsPersistent, MsgId) -> with_msg_store_state( MSCState, IsPersistent, - fun (MSCState1) -> rabbit_msg_store:read(MsgId, MSCState1) end). + fun (MSCState1) -> + rabbit_msg_store:read(MsgId, MSCState1) + end). msg_store_remove(MSCState, IsPersistent, MsgIds) -> with_immutable_msg_store_state( MSCState, IsPersistent, - fun (MCSState1) -> rabbit_msg_store:remove(MsgIds, MCSState1) end). + fun (MCSState1) -> + rabbit_msg_store:remove(MsgIds, MCSState1) + end). msg_store_close_fds(MSCState, IsPersistent) -> with_msg_store_state( @@ -1255,13 +1287,6 @@ %% Internal plumbing for confirms (aka publisher acks) %%---------------------------------------------------------------------------- -confirm_commit_index(State = #vqstate { index_state = IndexState }) -> - case needs_index_sync(State) of - true -> State #vqstate { - index_state = rabbit_queue_index:sync(IndexState) }; - false -> State - end. - record_confirms(MsgIdSet, State = #vqstate { msgs_on_disk = MOD, msg_indices_on_disk = MIOD, unconfirmed = UC, @@ -1271,8 +1296,8 @@ unconfirmed = gb_sets:difference(UC, MsgIdSet), confirmed = gb_sets:union (C, MsgIdSet) }. -needs_index_sync(#vqstate { msg_indices_on_disk = MIOD, - unconfirmed = UC }) -> +must_sync_index(#vqstate { msg_indices_on_disk = MIOD, + unconfirmed = UC }) -> %% If UC is empty then by definition, MIOD and MOD are also empty %% and there's nothing that can be pending a sync. diff -Nru rabbitmq-server-2.7.1/src/rabbit_version.erl rabbitmq-server-2.8.0/src/rabbit_version.erl --- rabbitmq-server-2.7.1/src/rabbit_version.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_version.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_version). diff -Nru rabbitmq-server-2.7.1/src/rabbit_vhost.erl rabbitmq-server-2.8.0/src/rabbit_vhost.erl --- rabbitmq-server-2.7.1/src/rabbit_vhost.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_vhost.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_vhost). diff -Nru rabbitmq-server-2.7.1/src/rabbit_writer.erl rabbitmq-server-2.8.0/src/rabbit_writer.erl --- rabbitmq-server-2.7.1/src/rabbit_writer.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/rabbit_writer.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(rabbit_writer). @@ -129,6 +129,9 @@ ok = internal_send_command_async(MethodRecord, Content, State), rabbit_amqqueue:notify_sent(QPid, ChPid), State; +handle_message({'DOWN', _MRef, process, QPid, _Reason}, State) -> + rabbit_amqqueue:notify_sent_queue_down(QPid), + State; handle_message({inet_reply, _, ok}, State) -> State; handle_message({inet_reply, _, Status}, _State) -> @@ -169,12 +172,10 @@ %%--------------------------------------------------------------------------- assemble_frame(Channel, MethodRecord, Protocol) -> - ?LOGMESSAGE(out, Channel, MethodRecord, none), rabbit_binary_generator:build_simple_method_frame( Channel, MethodRecord, Protocol). assemble_frames(Channel, MethodRecord, Content, FrameMax, Protocol) -> - ?LOGMESSAGE(out, Channel, MethodRecord, Content), MethodName = rabbit_misc:method_record_type(MethodRecord), true = Protocol:method_has_content(MethodName), % assertion MethodFrame = rabbit_binary_generator:build_simple_method_frame( diff -Nru rabbitmq-server-2.7.1/src/supervisor2.erl rabbitmq-server-2.8.0/src/supervisor2.erl --- rabbitmq-server-2.7.1/src/supervisor2.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/supervisor2.erl 2012-03-19 10:36:09.000000000 +0000 @@ -41,7 +41,7 @@ %% 5) normal, and {shutdown, _} exit reasons are all treated the same %% (i.e. are regarded as normal exits) %% -%% All modifications are (C) 2010-2011 VMware, Inc. +%% All modifications are (C) 2010-2012 VMware, Inc. %% %% %CopyrightBegin% %% @@ -717,8 +717,8 @@ ok; {error, normal} -> case Child#child.restart_type of - permanent -> ReportError(normal); - {permanent, _Delay} -> ReportError(normal); + permanent -> ReportError(normal, Child); + {permanent, _Delay} -> ReportError(normal, Child); _ -> ok end; {error, OtherReason} -> diff -Nru rabbitmq-server-2.7.1/src/tcp_acceptor.erl rabbitmq-server-2.8.0/src/tcp_acceptor.erl --- rabbitmq-server-2.7.1/src/tcp_acceptor.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/tcp_acceptor.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(tcp_acceptor). @@ -54,28 +54,9 @@ {ok, Mod} = inet_db:lookup_socket(LSock), inet_db:register_socket(Sock, Mod), - try - %% report - {Address, Port} = inet_op(fun () -> inet:sockname(LSock) end), - {PeerAddress, PeerPort} = inet_op(fun () -> inet:peername(Sock) end), - error_logger:info_msg("accepted TCP connection on ~s:~p from ~s:~p~n", - [rabbit_misc:ntoab(Address), Port, - rabbit_misc:ntoab(PeerAddress), PeerPort]), - %% In the event that somebody floods us with connections we can spew - %% the above message at error_logger faster than it can keep up. - %% So error_logger's mailbox grows unbounded until we eat all the - %% memory available and crash. So here's a meaningless synchronous call - %% to the underlying gen_event mechanism - when it returns the mailbox - %% is drained. - gen_event:which_handlers(error_logger), - %% handle - file_handle_cache:transfer(apply(M, F, A ++ [Sock])), - ok = file_handle_cache:obtain() - catch {inet_error, Reason} -> - gen_tcp:close(Sock), - error_logger:error_msg("unable to accept TCP connection: ~p~n", - [Reason]) - end, + %% handle + file_handle_cache:transfer(apply(M, F, A ++ [Sock])), + ok = file_handle_cache:obtain(), %% accept more accept(State); @@ -86,6 +67,10 @@ %% know this will fail. {stop, normal, State}; +handle_info({inet_async, LSock, Ref, {error, Reason}}, + State=#state{sock=LSock, ref=Ref}) -> + {stop, {accept_failed, Reason}, State}; + handle_info(_Info, State) -> {noreply, State}. @@ -97,8 +82,6 @@ %%-------------------------------------------------------------------- -inet_op(F) -> rabbit_misc:throw_on_error(inet_error, F). - accept(State = #state{sock=LSock}) -> case prim_inet:async_accept(LSock, -1) of {ok, Ref} -> {noreply, State#state{ref=Ref}}; diff -Nru rabbitmq-server-2.7.1/src/tcp_acceptor_sup.erl rabbitmq-server-2.8.0/src/tcp_acceptor_sup.erl --- rabbitmq-server-2.7.1/src/tcp_acceptor_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/tcp_acceptor_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(tcp_acceptor_sup). @@ -25,7 +25,11 @@ %%---------------------------------------------------------------------------- -ifdef(use_specs). --spec(start_link/2 :: (atom(), mfa()) -> rabbit_types:ok_pid_or_error()). + +-type(mfargs() :: {atom(), atom(), [any()]}). + +-spec(start_link/2 :: (atom(), mfargs()) -> rabbit_types:ok_pid_or_error()). + -endif. %%---------------------------------------------------------------------------- diff -Nru rabbitmq-server-2.7.1/src/tcp_listener.erl rabbitmq-server-2.8.0/src/tcp_listener.erl --- rabbitmq-server-2.7.1/src/tcp_listener.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/tcp_listener.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(tcp_listener). @@ -28,9 +28,14 @@ %%---------------------------------------------------------------------------- -ifdef(use_specs). + +-type(mfargs() :: {atom(), atom(), [any()]}). + -spec(start_link/8 :: - (gen_tcp:ip_address(), integer(), rabbit_types:infos(), integer(), - atom(), mfa(), mfa(), string()) -> rabbit_types:ok_pid_or_error()). + (inet:ip_address(), inet:port_number(), [gen_tcp:listen_option()], + integer(), atom(), mfargs(), mfargs(), string()) -> + rabbit_types:ok_pid_or_error()). + -endif. %%-------------------------------------------------------------------- @@ -67,8 +72,9 @@ label = Label}}; {error, Reason} -> error_logger:error_msg( - "failed to start ~s on ~s:~p - ~p~n", - [Label, rabbit_misc:ntoab(IPAddress), Port, Reason]), + "failed to start ~s on ~s:~p - ~p (~s)~n", + [Label, rabbit_misc:ntoab(IPAddress), Port, + Reason, inet:format_error(Reason)]), {stop, {cannot_listen, IPAddress, Port, Reason}} end. diff -Nru rabbitmq-server-2.7.1/src/tcp_listener_sup.erl rabbitmq-server-2.8.0/src/tcp_listener_sup.erl --- rabbitmq-server-2.7.1/src/tcp_listener_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/tcp_listener_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(tcp_listener_sup). @@ -26,12 +26,16 @@ -ifdef(use_specs). +-type(mfargs() :: {atom(), atom(), [any()]}). + -spec(start_link/7 :: - (gen_tcp:ip_address(), integer(), rabbit_types:infos(), mfa(), mfa(), - mfa(), string()) -> rabbit_types:ok_pid_or_error()). + (inet:ip_address(), inet:port_number(), [gen_tcp:listen_option()], + mfargs(), mfargs(), mfargs(), string()) -> + rabbit_types:ok_pid_or_error()). -spec(start_link/8 :: - (gen_tcp:ip_address(), integer(), rabbit_types:infos(), mfa(), mfa(), - mfa(), integer(), string()) -> rabbit_types:ok_pid_or_error()). + (inet:ip_address(), inet:port_number(), [gen_tcp:listen_option()], + mfargs(), mfargs(), mfargs(), integer(), string()) -> + rabbit_types:ok_pid_or_error()). -endif. diff -Nru rabbitmq-server-2.7.1/src/test_sup.erl rabbitmq-server-2.8.0/src/test_sup.erl --- rabbitmq-server-2.7.1/src/test_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/test_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(test_sup). diff -Nru rabbitmq-server-2.7.1/src/vm_memory_monitor.erl rabbitmq-server-2.8.0/src/vm_memory_monitor.erl --- rabbitmq-server-2.7.1/src/vm_memory_monitor.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/vm_memory_monitor.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% %% In practice Erlang shouldn't be allowed to grow to more than a half diff -Nru rabbitmq-server-2.7.1/src/worker_pool.erl rabbitmq-server-2.8.0/src/worker_pool.erl --- rabbitmq-server-2.7.1/src/worker_pool.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/worker_pool.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(worker_pool). @@ -37,10 +37,11 @@ -ifdef(use_specs). +-type(mfargs() :: {atom(), atom(), [any()]}). + -spec(start_link/0 :: () -> {'ok', pid()} | {'error', any()}). --spec(submit/1 :: (fun (() -> A) | {atom(), atom(), [any()]}) -> A). --spec(submit_async/1 :: - (fun (() -> any()) | {atom(), atom(), [any()]}) -> 'ok'). +-spec(submit/1 :: (fun (() -> A) | mfargs()) -> A). +-spec(submit_async/1 :: (fun (() -> any()) | mfargs()) -> 'ok'). -spec(idle/1 :: (any()) -> 'ok'). -endif. diff -Nru rabbitmq-server-2.7.1/src/worker_pool_sup.erl rabbitmq-server-2.8.0/src/worker_pool_sup.erl --- rabbitmq-server-2.7.1/src/worker_pool_sup.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/worker_pool_sup.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(worker_pool_sup). diff -Nru rabbitmq-server-2.7.1/src/worker_pool_worker.erl rabbitmq-server-2.8.0/src/worker_pool_worker.erl --- rabbitmq-server-2.7.1/src/worker_pool_worker.erl 2011-12-16 12:24:15.000000000 +0000 +++ rabbitmq-server-2.8.0/src/worker_pool_worker.erl 2012-03-19 10:36:09.000000000 +0000 @@ -11,7 +11,7 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is VMware, Inc. -%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved. +%% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% -module(worker_pool_worker). @@ -29,12 +29,12 @@ -ifdef(use_specs). +-type(mfargs() :: {atom(), atom(), [any()]}). + -spec(start_link/1 :: (any()) -> {'ok', pid()} | {'error', any()}). --spec(submit/2 :: (pid(), fun (() -> A) | {atom(), atom(), [any()]}) -> A). --spec(submit_async/2 :: - (pid(), fun (() -> any()) | {atom(), atom(), [any()]}) -> 'ok'). --spec(run/1 :: (fun (() -> A)) -> A; - ({atom(), atom(), [any()]}) -> any()). +-spec(submit/2 :: (pid(), fun (() -> A) | mfargs()) -> A). +-spec(submit_async/2 :: (pid(), fun (() -> any()) | mfargs()) -> 'ok'). +-spec(run/1 :: (fun (() -> A)) -> A; (mfargs()) -> any()). -spec(set_maximum_since_use/2 :: (pid(), non_neg_integer()) -> 'ok'). -endif.